/* Mistook: the speaking screens.
 *
 * Every one of them is the same three things: something to say, the round microphone, and what
 * came of it. On a phone they follow each other down the page. From 840px the thing to say and the
 * microphone keep one column and what came of it has the column beside, so the microphone never
 * moves when the marks arrive.
 *
 * The marks themselves are in app.css, section 15. Nothing here changes what a mark means.
 */

/* ---- 1. The stage: say it on one side, see it on the other ---- */

/* The way back is not offered part way through a step, but its place is kept, so the page does not jump up. */
.back-slot { min-height: 2.25rem; }
.back-slot .back { vertical-align: top; }

/* On a phone the two sides are one column, and the buttons that move me on come last, after the marks. */
.say-stage > .say-side { display: contents; }
.say-stage > .say-side > * { min-width: 0; }
.say-stage > .say-result { order: 2; display: grid; gap: .8rem; align-content: start; }
.say-stage > .say-result > * { min-width: 0; }
.say-stage .say-actions { order: 3; display: grid; gap: .5rem; }
.say-stage > .say-side > .notice, .say-stage > .say-result > .notice, .say-stage > .say-result > .stats { margin-bottom: 0; }

@media (min-width: 840px) {
    .say-stage > .say-side { display: grid; gap: .8rem; align-content: start; }
    .say-stage > .say-result { gap: 1rem; }
}

/* With room to spare the marks get the larger share: they hold more than the sentence does. */
@media (min-width: 1100px) {
    .cols.halves.say-stage:not(.even) { grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); }
}

/* The side that stays put never grows past the window: with the text set large it scrolls by itself,
   so the button under the microphone can always be reached. */
@media (min-width: 840px) {
    .say-stage > .say-side.sticky { max-height: calc(100dvh - 3rem); overflow-y: auto; scrollbar-width: thin; margin: -4px; padding: 4px; }

    /* Talk: the topic keeps a share of the page, not a width in letters, so large text cannot squeeze the results. */
    .cols.side-main.say-stage { grid-template-columns: minmax(0, 4fr) minmax(0, 7fr); }
}

/* A window too short to hold the card lets it scroll with the page instead. */
@media (min-width: 840px) and (max-height: 640px) {
    .say-stage > .say-side.sticky { position: static; max-height: none; overflow: visible; }
}

/* What will be here once I have spoken. Only where there is a second column to fill. */
.say-wait { display: none; }

@media (min-width: 840px) {
    .say-wait {
        display: grid;
        justify-items: center;
        align-content: center;
        gap: .45rem;
        min-height: 19rem;
        padding: 2rem 1.5rem;
        text-align: center;
        color: var(--ink-2);
        border: 1.5px dashed var(--line-strong);
        border-radius: var(--r-card);
    }
    .say-wait .face { width: 4.6rem; height: 4.6rem; color: var(--ink); margin-bottom: .3rem; }
    .say-wait strong { font-family: var(--display); font-size: 1.2rem; line-height: 1.2; color: var(--ink); }
    .say-wait p { margin: 0; max-width: 26ch; }
}

/* A short list of what is coming, each line with its picture. */
.wait-list { list-style: none; margin: .5rem 0 0; padding: 0; display: grid; gap: .55rem; text-align: left; }
.wait-list li { display: flex; align-items: center; gap: .65rem; font-weight: 600; color: var(--ink-2); }
.wait-list .pic { width: 2.2rem; height: 2.2rem; border-radius: 11px; }
.wait-list .pic .icon { width: 1.25rem; height: 1.25rem; }

/* The card that holds the thing to say and the microphone. */
.say-card { display: grid; gap: .2rem; }
.say-card > * { min-width: 0; }
/* Room for two lines of the sentence, so a short one and a long one leave the microphone in one place. */
.say-prompt { display: grid; align-content: center; min-height: calc(2 * 1.35 * 1.5rem); }
@media (min-width: 840px) { .say-prompt { min-height: calc(2 * 1.35 * 1.8rem); } }
.say-hear { display: flex; flex-wrap: wrap; justify-content: center; gap: .25rem .5rem; margin: .1rem 0 .5rem; }
.say-note { text-align: center; margin-top: .2rem; }
.say-step { display: flex; align-items: center; gap: .6rem; }
.say-step .dots { padding: 0; }

/* ---- 2. The microphone ---- */

.recorder { display: grid; justify-items: center; padding: .7rem 0 .1rem; }
.recorder > * { min-width: 0; max-width: 100%; }

.recorder-label { min-height: 1.4em; margin-top: .75rem; line-height: 1.4; text-wrap: balance; }

/* A long take shows its time under the label. Two lines are kept, so the time arriving moves nothing below it. */
.recorder.long .recorder-label { min-height: 3.1rem; }
.recorder-hint { font-weight: 400; font-size: .92rem; color: var(--ink-2); }
.take-time { width: 16rem; max-width: 100%; margin-top: .35rem; font-size: .95rem; }
.take-time span { white-space: nowrap; }

.recorder .notice { margin: .4rem 0 .3rem; text-align: left; justify-self: stretch; }
.recorder .notice .btn { margin: .5rem 0 0; display: flex; }

.mic-options { margin-top: 0; }
.mic-options summary { gap: .35rem; min-height: 2.6rem; font-size: .92rem; color: var(--ink-2); list-style: none; }
.mic-options summary::-webkit-details-marker { display: none; }
.mic-options summary:hover { color: var(--ink); }
.mic-options summary .icon { width: 1.1rem; height: 1.1rem; }
.mic-options .btn-row { justify-content: center; align-items: center; padding-bottom: .4rem; }

/* Not there while I am talking, but its place is kept. */
.mic-options.is-away { visibility: hidden; }

/* ---- 3. What came of it: the number, the words, one word's sounds ---- */

.clarity-row { margin-bottom: .7rem; }
.clarity-line { font-weight: 700; line-height: 1.3; }
.clarity-row .sub { margin-top: .1rem; }
.count-anyway { margin: 0 0 .8rem; }

.spoken .mark { width: 1.2em; height: 1.2em; stroke-width: 3; vertical-align: -.2em; }

/* The same lines, named once, so nobody has to guess what a wave means. */
.spoken-key { display: flex; flex-wrap: wrap; gap: .1rem 1.1rem; margin: .55rem .5rem 0; font-size: .84rem; font-weight: 600; color: var(--ink-2); }
.spoken-key span { position: relative; padding: 0 .05rem .5rem; display: inline-flex; align-items: center; gap: .15rem; }
.spoken-key span::after { content: ""; position: absolute; left: 0; right: 0; bottom: .22rem; height: 3px; border-radius: 3px; background: var(--green); }
.spoken-key .close::after, .spoken-key .wrong::after {
    height: .36rem;
    bottom: .1rem;
    border-radius: 0;
    -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 13 7'%3E%3Cpath d='M0 4.500q3.250-5 6.500 0t6.500 0' fill='none' stroke='%23000' stroke-width='2.400' stroke-linecap='round'/%3E%3C/svg%3E") left center / auto 100% repeat-x;
    mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 13 7'%3E%3Cpath d='M0 4.500q3.250-5 6.500 0t6.500 0' fill='none' stroke='%23000' stroke-width='2.400' stroke-linecap='round'/%3E%3C/svg%3E") left center / auto 100% repeat-x;
}
.spoken-key .close::after { background: var(--amber); }
.spoken-key .wrong::after { background: var(--coral); }
.spoken-key .wrong { color: var(--wrong); }
.spoken-key .icon { width: .95em; height: .95em; stroke-width: 3; }

.word-detail { margin-top: .9rem; padding-top: .85rem; display: grid; gap: .55rem; }
.word-detail > * { min-width: 0; margin: 0; }
.word-detail-head { display: flex; align-items: center; flex-wrap: wrap; gap: .2rem .6rem; }
.word-detail-word { font-family: var(--display); font-size: 1.35rem; font-weight: 800; line-height: 1.2; overflow-wrap: anywhere; }
.word-detail .sounds { margin-bottom: 0; }
.word-detail .notice { padding: .6rem .85rem; }

.sound { border-width: 2px; }

/* Beside the sentence on a laptop the marks should fit without scrolling, so they sit a little closer. */
@media (min-width: 840px) {
    :is(.say-result, .marks-card) .clarity-score { width: 3.5rem; height: 3.5rem; font-size: 1.35rem; }
    :is(.say-result, .marks-card) .word-detail { gap: .5rem; margin-top: .75rem; padding-top: .75rem; }
    :is(.say-result, .marks-card) .word-detail .notice { padding: .5rem .8rem; font-size: .93rem; }
    :is(.say-result, .marks-card) .sound { min-width: 3.1rem; min-height: 2.7rem; padding: .2rem .45rem; }
    :is(.say-result, .marks-card) .sounds { gap: .35rem; }
}
.sound .sound-name { display: flex; align-items: center; justify-content: center; gap: .2rem; white-space: nowrap; }
.sound .sound-name .icon { width: .95em; height: .95em; stroke-width: 3; }
.sound.picked { border-color: currentColor; }
.sound:disabled { cursor: default; }
button.sound:not(:disabled):hover { border-color: color-mix(in srgb, currentColor 45%, transparent); }
button.sound.picked:hover { border-color: currentColor; }

/* Two buttons that share a row equally: mine beside the right one. */
.btn-row.even > .btn { flex: 1 1 8rem; }

/* ---- 4. Groups of results ---- */

.say-group { display: grid; gap: .6rem; align-content: start; }
.say-group > * { min-width: 0; }
.say-group .card, .say-group .notice, .say-group .fold { margin-bottom: 0; }
.say-group-head { display: flex; align-items: center; gap: .6rem; margin-top: .35rem; }
.say-group-head h2, .say-group-head h3 { margin: 0; }
.say-group-head .pic { width: 2.2rem; height: 2.2rem; border-radius: 11px; }
.say-group-head .pic .icon { width: 1.25rem; height: 1.25rem; }
.say-waiting { display: flex; align-items: center; gap: .6rem; color: var(--ink-2); }
.say-waiting .spinner { flex: 0 0 auto; }

/* What I said, and how to say it: one above the other, so the change is easy to see. */
.fix-list { list-style: none; margin: 0; padding: 0; }
.fix-item { display: grid; gap: .2rem; padding: .85rem 1.15rem; }
.fix-item + .fix-item { border-top: 1px solid var(--line); }
.fix-item.on { background: var(--sunken); box-shadow: inset 3px 0 0 var(--coral); }
.fix-said, .fix-better { display: grid; grid-template-columns: 1.3rem minmax(0, 1fr); gap: .5rem; align-items: start; margin: 0; line-height: 1.4; }
.fix-said { color: var(--wrong); }
.fix-said s { text-decoration-thickness: .08em; }
.fix-said .icon, .fix-better .icon { width: 1.25rem; height: 1.25rem; margin-top: .12rem; stroke-width: 2.6; }
.fix-better .icon { color: var(--green); }
.fix-why { padding-left: 1.8rem; }
.fix-item .tag { justify-self: start; margin: .2rem 0 0 1.8rem; }

/* ---- 5. Talk about a topic ---- */

.topic-card { display: grid; }
.topic-card > * { min-width: 0; }
.topic-prompts { margin: .55rem 0 .8rem; }
.topic-prompts li::marker { color: var(--ink-3); }
.try-words { display: flex; flex-wrap: wrap; align-items: center; gap: .3rem .35rem; padding-bottom: .85rem; }
.try-words .sub { margin-right: .2rem; }
.try-word { margin: 0; gap: .3rem; padding: .15rem .65rem .15rem .5rem; }
.try-mark { width: 1em; height: 1em; display: inline-grid; place-items: center; flex: 0 0 auto; }
.try-mark:empty::before { content: ""; width: .55em; height: .55em; border-radius: 50%; border: 2px solid var(--ink-3); }
.try-mark .icon { width: 1em; height: 1em; stroke-width: 3.2; }
.topic-card .recorder { border-top: 1px solid var(--line); padding-top: 1.1rem; }

.talk-results .tip-pic { background: var(--sunken); }
.talk-edit { display: grid; gap: .6rem; justify-items: start; }
.talk-edit .input { min-height: 8rem; }
.heard-text { font-size: 1rem; line-height: 1.65; max-width: var(--prose); }
.talk-results .card > .link:last-child { margin-bottom: -.4rem; }
.coach-note { margin-top: .6rem; }
.clearer-actions { margin-top: .7rem; }

/* ---- 6. Speaking: five sentences ---- */

.say-step .dot.done { background: var(--ink-3); }
.speak-more h2 { margin-top: .8rem; }
.done-list .row { padding-left: 0; padding-right: 0; }
.done-card { display: grid; justify-items: center; gap: .6rem; text-align: center; }
.done-card .face { width: 4.6rem; height: 4.6rem; color: var(--ink); }
.done-actions { display: grid; gap: .5rem; width: 100%; margin-top: .4rem; }

@media (min-width: 840px) {
    .speak-more h2 { margin-top: 0; }
}

/* ---- 7. One of two: ear training, say one of two ---- */

/* Two big cards side by side. Each is the whole target for a thumb. */
.duo { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: .7rem; }
.duo-card {
    position: relative;
    display: grid;
    justify-items: center;
    align-content: center;
    gap: .15rem;
    width: 100%;
    min-height: 7.5rem;
    padding: 1.9rem .5rem;
    background: var(--paper);
    color: var(--ink);
    border: 1.5px solid var(--line-strong);
    border-bottom-width: 4px;
    border-radius: var(--r-card);
    font: inherit;
    cursor: pointer;
    transition: background .12s ease, border-color .12s ease, transform .06s ease;
}
.duo-card:hover { background: var(--sunken); }
.duo-card:active { transform: translateY(2px); }
.duo-word { font-family: var(--display); font-size: 1.7rem; font-weight: 800; line-height: 1.15; overflow-wrap: anywhere; }

/* The small speaker sits at the foot of the card, so the word stays in the middle before and after the answer. */
.duo-note { position: absolute; left: 0; right: 0; bottom: .65rem; display: grid; place-items: center; color: var(--ink-2); }
.duo-note .icon { width: 1.2rem; height: 1.2rem; }

/* Right and wrong are a colour, a thicker edge and a drawn mark, never the colour alone. */
.duo-card.is-right { border-color: var(--green); background: var(--right-bg); color: var(--right); }
.duo-card.is-wrong { border-color: var(--coral); background: var(--wrong-bg); color: var(--wrong); }
.duo-card.is-right .duo-note, .duo-card.is-wrong .duo-note { color: inherit; }
.duo-mark { position: absolute; top: .5rem; right: .5rem; width: 1.75rem; height: 1.75rem; border-radius: 50%; display: grid; place-items: center; background: var(--green); color: var(--paper); }
.duo-card.is-wrong .duo-mark { background: var(--coral); color: var(--on-coral); }
.duo-mark .icon { width: 1.1rem; height: 1.1rem; stroke-width: 3; }

.pick-card { display: grid; gap: .2rem; }
.pick-card > * { min-width: 0; }
.pick-count { text-align: center; font-weight: 600; }
.pick-card .ask { padding-bottom: .9rem; }
.pick-card > .notice.after { margin: .8rem 0 0; }
.pick-card > .btn-block.btn-lg { margin-top: .7rem; }
.pick-stage .so-far { margin-bottom: .8rem; }

/* Say one of two: the word to say is in highlighter, the other is set back. */
.duo-slot { display: grid; gap: .3rem; align-content: start; }
.duo-cap { text-align: center; font-size: .9rem; font-weight: 700; color: var(--ink-2); }
.duo-card.say-this { border-color: var(--ink); }
.duo-card.say-this .duo-word { background: linear-gradient(transparent 58%, var(--yellow) 58%, var(--yellow) 92%, transparent 92%); padding: 0 .12em; }
.duo-card.not-this { border-style: dashed; border-bottom-style: solid; }
.duo-card.not-this .duo-word { color: var(--ink-2); font-weight: 700; }
.duo-card.is-right, .duo-card.say-this.is-right { border-color: var(--green); }
.duo-card.is-wrong, .duo-card.not-this.is-wrong { border-color: var(--coral); border-style: solid; }
.duo-card.is-right .duo-word, .duo-card.is-wrong .duo-word { color: inherit; }
.say-card.pick-card .duo { margin: .5rem 0 .3rem; }

/* What the laptop made of it: the face first, then the words. */
.say-verdict { display: flex; align-items: center; gap: .9rem; }
.say-verdict .face { width: 3.4rem; height: 3.4rem; flex: 0 0 auto; color: var(--ink); }
.say-verdict-line { font-family: var(--display); font-weight: 700; font-size: 1.15rem; line-height: 1.3; }
.say-verdict-line .icon { margin-right: .35rem; stroke-width: 2.6; }
.say-verdict.is-right { background: var(--right-bg); border-color: transparent; }
.say-verdict.is-right .say-verdict-line { color: var(--right); }
.say-verdict.is-wrong { background: var(--wrong-bg); border-color: transparent; }
.say-verdict.is-wrong .say-verdict-line { color: var(--wrong); }

@media (min-width: 840px) {
    .duo-card { min-height: 9rem; }
    .duo-word { font-size: 2rem; }
    .say-result > .say-verdict { flex-direction: column; justify-content: center; text-align: center; min-height: 19rem; padding: 2rem 1.5rem; }
    .say-result > .say-verdict .face { width: 5.5rem; height: 5.5rem; }
    .say-result > .say-verdict .say-verdict-line { font-size: 1.4rem; }
}

/* The sounds to train: a card each, with its two words and how I am doing. */
.contrast-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(18rem, 100%), 1fr)); gap: .7rem; }
.contrast {
    display: flex;
    align-items: center;
    gap: .8rem;
    min-height: 4.6rem;
    padding: .8rem 1rem;
    background: var(--paper);
    border: 1px solid var(--line);
    border-radius: var(--r-card);
    color: inherit;
    font: inherit;
    text-align: left;
    cursor: pointer;
}
.contrast:hover { border-color: var(--line-strong); }
.contrast .ttl { display: block; font-weight: 700; line-height: 1.25; }
.contrast .meta { display: block; font-size: .92rem; color: var(--ink-2); line-height: 1.3; }
.contrast .tag { margin: 0; flex: 0 0 auto; }

/* ---- 8. See and say, inside the daily review ---- */

.say-one .shown-word { padding-bottom: .4rem; gap: .5rem; }
.say-one .recorder { padding-top: .4rem; }
.say-marks { margin-top: 0; }

/* Where the microphone sits in a row beside its label, such as on the save screen, what follows takes a row of its own. */
.recorder > .notice, .recorder > .mic-options { flex: 1 1 100%; }

/* ---- 9. Repeat after a speaker ---- */

.say-card .ask { padding: .8rem 0 .6rem; }
.tune-card .card-head { align-items: center; }
.tune-card .tag, .say-result .card-head .tag { margin: 0; }
.melody { height: 120px; }
.legend { flex-wrap: wrap; }

/* ---- 10. Scene reader ---- */

.scene-grid { display: grid; gap: .7rem; }
.scene-card {
    display: flex;
    align-items: center;
    gap: .9rem;
    padding: 1rem 1.05rem;
    background: var(--paper);
    border: 1px solid var(--line);
    border-radius: var(--r-card);
    color: inherit;
    font: inherit;
    text-align: left;
    cursor: pointer;
}
.scene-card:hover { border-color: var(--line-strong); }
.scene-card .pic { width: 3rem; height: 3rem; }
.scene-card .ttl { display: block; font-family: var(--display); font-weight: 700; font-size: 1.15rem; line-height: 1.25; }
.scene-card .meta { display: block; margin-top: .15rem; font-size: .92rem; line-height: 1.4; color: var(--ink-2); }

@media (min-width: 840px) {
    .scene-grid { grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr)); gap: 1rem; }
    .scene-card { flex-direction: column; align-items: flex-start; gap: 1.1rem; min-height: 12rem; padding: 1.3rem; }
    .scene-card .pic { width: 3.4rem; height: 3.4rem; }
    .scene-card .pic .icon { width: 1.8rem; height: 1.8rem; }
    .scene-card .ttl { font-size: 1.3rem; }
    .scene-card .meta { font-size: .98rem; }
}

.scene-who { display: flex; align-items: center; justify-content: center; gap: .45rem; margin-bottom: .3rem; font-weight: 700; color: var(--ink-2); }
.scene-who .tag { margin: 0; }
.scene-how { display: flex; justify-content: center; margin: .5rem 0 .3rem; }
.scene-how .tag { margin: 0; white-space: normal; text-align: center; }
.expression-note { margin-top: .45rem; }

/* ---- 11. Speaking diary ---- */

.diary-ask { font-family: var(--display); font-size: 1.35rem; font-weight: 700; line-height: 1.3; text-align: center; text-wrap: balance; }
.diary-heard { display: grid; gap: .6rem; }
.diary-heard > * { min-width: 0; }
.diary-heard .input { min-height: 9rem; }
.diary-side h3 { margin-bottom: .2rem; }
.wait-list li.on { color: var(--ink); font-weight: 700; }
.wait-list li.on .pic { background: var(--yellow); color: var(--on-yellow); }
.say-group-count { margin-left: auto; font-weight: 700; }
.diary-fixes .done-card { padding: 2rem 1.15rem; }

/* ---- 12. Clarity check ---- */

.clarity-card .passage { max-width: none; }
.clarity-so-far { display: grid; gap: .7rem; }
.clarity-so-far > * { min-width: 0; }
.clarity-so-far h3 { margin: 0; }
.clarity-so-far .trend { max-width: 26rem; }
.clarity-so-far .stats { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: .5rem; }
.clarity-so-far .stat .n { font-size: 1.6rem; }
@media (min-width: 840px) {
    .clarity-card .passage { font-size: 1.05rem; line-height: 1.65; }

    /* Large text can make the passage taller than the window. The microphone then keeps to the foot of what can be seen. */
    .clarity-card .recorder { position: sticky; bottom: 0; z-index: 2; margin: .5rem -1.15rem -1.15rem; padding: .9rem 1.15rem .7rem; background: var(--paper); border-top: 1px solid var(--line); border-radius: 0 0 var(--r-card) var(--r-card); }
}
.say-result > .notice > .icon:first-child { vertical-align: -.3em; }

/* On a phone the passage is longer than the screen, so the microphone rides at the foot of the card while I read. */
@media (max-width: 839.98px) {
    .clarity-card .recorder {
        position: sticky;
        bottom: calc(var(--tabbar) + env(safe-area-inset-bottom, 0px));
        z-index: 2;
        margin: .6rem -1.15rem -1.15rem;
        padding: .7rem 1.15rem .5rem;
        background: var(--paper);
        border-top: 1px solid var(--line);
        border-radius: 0 0 var(--r-card) var(--r-card);
    }
    .clarity-card .recorder { grid-template-columns: auto minmax(0, 1fr); column-gap: .9rem; align-items: center; justify-items: start; text-align: left; }
    .clarity-card .mic { width: 4rem; height: 4rem; }
    .clarity-card .mic .icon { width: 1.7rem; height: 1.7rem; }
    .clarity-card .recorder.long .recorder-label { display: grid; align-content: center; min-height: 4rem; margin-top: 0; text-wrap: wrap; }
    .clarity-card .take-time { width: 100%; margin: .25rem 0 0; }
    .clarity-card .recorder > .notice, .clarity-card .recorder > .mic-options { grid-column: 1 / -1; }
    .clarity-card .mic-options { justify-self: center; }
    .clarity-card .mic-options summary { min-height: 2.2rem; }
}

@media (min-width: 600px) and (max-width: 839.98px) {
    .clarity-card .recorder { bottom: 0; }
}

/* ---- 13. A word said to save it, read back ---- */

.said-check { flex: 1 1 100%; margin-top: .8rem; padding: .9rem 1rem; background: var(--page); border-radius: var(--r-control); text-align: left; }
.said-check h3 { margin: 0 0 .3rem; }
.said-check h3 + .said-others, .said-check .sub + h3 { margin-top: .8rem; }
.said-word { display: flex; align-items: center; gap: .3rem; }
.said-word strong { font-family: var(--letters); font-size: 1.35rem; font-weight: 600; letter-spacing: .03em; overflow-wrap: anywhere; }
.said-others { display: grid; gap: .45rem; }
.said-other { display: flex; align-items: center; flex-wrap: wrap; gap: .3rem .7rem; }
.said-other .btn { font-family: var(--letters); font-weight: 600; letter-spacing: .03em; }

/* A word's sounds on its own page. */
.sound-row { margin-bottom: .3rem; }

/* ---- 14. Things the shared sheet does not cover yet ---- */

/* In the dark look the highlighter must not run through pale letters, so it drops to a swipe under the word. */
:root[data-theme="dark"] .say-sentence strong, :root[data-theme="dark"] .duo-card.say-this .duo-word {
    background: linear-gradient(transparent 76%, var(--yellow) 76%, var(--yellow) 96%, transparent 96%);
}
@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) .say-sentence strong, :root:not([data-theme="light"]) .duo-card.say-this .duo-word {
        background: linear-gradient(transparent 76%, var(--yellow) 76%, var(--yellow) 96%, transparent 96%);
    }
}

/* On a tablet the topic card is wide, so the microphone sits beside the topic and not under it. */
@media (min-width: 600px) and (max-width: 839.98px) {
    .topic-card { grid-template-columns: minmax(0, 1fr) minmax(12rem, 15rem); column-gap: 1.5rem; align-items: start; }
    .topic-card > * { grid-column: 1; }
    .topic-card > .recorder { grid-column: 2; grid-row: 1; border-top: 0; border-left: 1px solid var(--line); padding: .3rem 0 .3rem 1.5rem; }
    .topic-card > .say-note { grid-column: 1 / -1; margin-top: .7rem; }
    .topic-card .try-words { padding-bottom: 0; }
}

@media (max-width: 599.98px) {
    .contrast-grid { gap: .5rem; }
    .contrast { min-height: 3.9rem; padding: .6rem .85rem; gap: .7rem; border-radius: 16px; }
    .contrast .pic { width: 2.5rem; height: 2.5rem; border-radius: 12px; }
    .contrast .pic .icon { width: 1.35rem; height: 1.35rem; }
}

/* A quiet button under a column keeps the column's width, whatever a wide page does to buttons elsewhere. */
.diary-fixes .stack > .btn-block, .diary-side > .btn-block { max-width: none; }

/* ---- 15. How the speaking screens move ----
   The app is listening, so its movement is a listener's: the microphone breathes while I talk, the
   squiggle writes itself while my take is marked, and the marks arrive the way a pen makes them, one
   word after another. Whatever I have to press next keeps its place while all of this happens.
   Every animation here ends on the finished picture and runs once, except while the app waits. */

/* The next thing to say arrives from the right: a sentence, a line, a pair, a topic. Where the thing
   is kept and only its words change, "again" is set on every other one, and the change of name is
   what replays the arrival. */
.next-in { animation: from-right var(--t) var(--ease-out) backwards; }
.next-in.again { animation-name: from-right-again; }

/* What came of it arrives in groups, one after another, never in one flash. */
.say-result > * { animation: rise var(--t) var(--ease-out) backwards; }
.say-result > :nth-child(2) { animation-delay: 90ms; }
.say-result > :nth-child(3) { animation-delay: 180ms; }
.say-result > :nth-child(4) { animation-delay: 270ms; }
.say-result > :nth-child(5) { animation-delay: 360ms; }
.say-result > :nth-child(n + 6) { animation-delay: 450ms; }

/* A button that arrives can still be pressed down afterwards. */
:is(.say-stage, .pick-card, .diary-fixes) .btn.rises { animation-fill-mode: backwards; }
.say-next { animation: rise var(--t) var(--ease-out) .2s backwards; }

/* A number that is the point of a screen counts up once. The real number stays in the page for
   anyone who cannot see it, and the one that is seen is drawn from it. */
.count-real { display: inline-block; width: 1px; height: 1px; margin-right: -1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }

/* The pen's own marks, drawn stroke by stroke. A cross is two strokes, one after the other. */
.pen-mark path + path { animation-delay: .16s; }

/* Lists of things to choose from arrive one after another, and give a little under the finger. */
.contrast, .scene-card { animation: rise var(--t) var(--ease-out) backwards; animation-delay: calc(var(--i, 0) * 40ms); transition: border-color var(--t-fast) ease, transform var(--t-fast) var(--ease-out); }
.contrast:active, .scene-card:active { transform: scale(.98); }
.done-list .row { animation: rise var(--t) var(--ease-out) backwards; animation-delay: calc(var(--i, 0) * 60ms); }
.clarity-so-far .stat { animation: pop var(--t) var(--ease-spring) backwards; animation-delay: calc(var(--i, 0) * 50ms + 120ms); }

/* ---- 16. The microphone listens ----
   Idle it is calm. While it records, a ring breathes around it for as long as it is listening, and
   the soft halo still follows my voice. While the take is worked on, the squiggle writes itself
   inside it. The button never moves or changes size: only what is around it and inside it does. */

.mic { position: relative; transition: box-shadow .08s linear, transform .06s ease, background-color var(--t) ease, color var(--t) ease; }
.mic::before {
    content: "";
    position: absolute;
    inset: -.5rem;
    border: 3px solid var(--coral);
    border-radius: 50%;
    opacity: 0;
    transform: scale(.88);
    pointer-events: none;
    transition: opacity var(--t) ease, transform var(--t) var(--ease-out);
}
@keyframes mic-breathe {
    from { transform: scale(1); opacity: .9; }
    to { transform: scale(1.15); opacity: .3; }
}
.mic-on::before { opacity: .9; transform: none; animation: mic-breathe 1.7s ease-in-out .26s infinite alternate; }

/* The picture inside the button, and the words under it, arrive softly with each change. */
.mic-ico { animation: pop var(--t) var(--ease-spring) backwards; }
.mic .spinner { font-size: 1.3rem; }
.mic-busy .spinner { color: var(--coral); }
.recorder-say { animation: fade var(--t) ease backwards; }
.recorder-label { transition: color var(--t) ease; }
.mic-on + .recorder-label { color: var(--ink); }

/* Where there is a second column, the face that waits there looks towards the microphone while I talk. */
@media (min-width: 840px) {
    .say-stage:has(.mic-on) .say-wait .face .eye { translate: -2.6px 0; }
}

/* ---- 17. What came of it, marked by the pen ----
   The number counts up and the face beside it shows how it went. Then the words arrive one after
   another, and under each the pen draws its mark: a straight line for right, a wave for close, a
   wave and a cross for wrong. The marks mean what they meant before. Only their arrival is new. */

/* One take. It takes no room of its own, and is new for each take, so every take is marked afresh. */
.spoken-take { display: contents; }

.clarity-score { animation: pop var(--t) var(--ease-spring) backwards; }
.clarity-row > .grow { animation: rise var(--t) var(--ease-out) 70ms backwards; }
.clarity-face { flex: 0 0 auto; width: 3rem; height: 3rem; color: var(--ink); animation: pop var(--t) var(--ease-spring) 140ms backwards; }
@media (min-width: 840px) { .clarity-face { width: 3.4rem; height: 3.4rem; } }

/* On a phone the number and the face share the first line, and the words get the whole width under them. */
@media (max-width: 599.98px) {
    .clarity-row { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: .55rem .8rem; }
    .clarity-row > .grow { grid-column: 1 / -1; grid-row: 2; }
    .clarity-face { grid-column: 2; grid-row: 1; justify-self: end; align-self: center; width: 3.4rem; height: 3.4rem; }
}

.spoken { animation: rise var(--t) var(--ease-out) backwards; animation-delay: calc(var(--i, 0) * 55ms + 150ms); transition: background var(--t-fast) ease, box-shadow var(--t-fast) ease; }
.spoken::after { animation: squiggle-in .4s var(--ease-out) backwards; animation-delay: calc(var(--i, 0) * 55ms + 330ms); }
.spoken .mark path { animation-duration: var(--t); animation-delay: calc(var(--i, 0) * 55ms + 520ms); }
.spoken .mark path + path { animation-delay: calc(var(--i, 0) * 55ms + 660ms); }
.spoken-key { animation: fade var(--t-slow) ease backwards; animation-delay: calc(var(--n, 0) * 55ms + 420ms); }

/* One word's sounds. The first word opens by itself once the marks are down; a word I tap opens at once. */
.word-detail { --wait: 0ms; animation: rise var(--t) var(--ease-out) var(--wait) backwards; }
.word-detail.opens-itself { --wait: calc(var(--n, 0) * 55ms + 520ms); }
.word-detail .sound { animation: pop var(--t) var(--ease-spring) backwards; animation-delay: calc(var(--wait) + var(--i, 0) * 35ms + 90ms); }
.word-detail > .notice, .word-detail > .mouth-tip { animation: rise var(--t) var(--ease-out) backwards; animation-delay: calc(var(--wait) + 200ms); }

/* ---- 18. The vowel mouths ----
   A vowel is made with the mouth, so the face shows the shape: small on a vowel's tile, and larger
   beside a few plain words when a vowel was the sound I missed. The mouth is in the blue of speaking. */

/* A word's sounds on its own page: every name sits on one line, and a vowel carries its face above it. */
.sound-row .sound { display: flex; flex-direction: column; align-items: center; justify-content: flex-end; animation: rise var(--t) var(--ease-out) backwards; animation-delay: calc(var(--i, 0) * 40ms); }
.sound-face { width: 2rem; height: 2rem; margin: .1rem 0; color: var(--ink); }
/* A row of faces does not blink as one. */
.sound-face .eye { animation-delay: calc(var(--i, 0) * -1.3s); }
/* Tapping a vowel lets go of its mouth, so it bounces back as the sound is said. */
button.sound:active .sound-face .mouth { animation: none; }

.mouth-tip { display: flex; align-items: center; gap: .85rem; padding: .5rem .9rem; border-radius: var(--r-control); background: var(--blue-soft); color: var(--ink); animation: rise var(--t) var(--ease-out) backwards; }
.mouth-tip .face { flex: 0 0 auto; width: 3.6rem; height: 3.6rem; color: var(--ink); }
.mouth-tip-words { display: grid; line-height: 1.3; }
.mouth-tip-sound { font-family: var(--display); font-size: 1.2rem; font-weight: 800; }
.mouth-tip-say { font-weight: 700; }
.mouth-tip.after { margin-top: .6rem; animation-delay: .25s; }

/* ---- 19. One of two, answered at once ----
   Right: the pen ticks the card and the face smiles. Wrong: the card I chose shakes its head once,
   and the face shows the squiggle, which writes itself. */

.duo-mark { animation: pop var(--t) var(--ease-spring) backwards; }
.duo-mark .pen-mark path { animation-delay: .1s; }
.duo-mark .pen-mark path + path { animation-delay: .24s; }
.duo-card.is-wrong { animation: shake .4s ease-in-out; }

.pick-verdict { display: flex; align-items: center; gap: .7rem; }
.pick-face { flex: 0 0 auto; width: 2.6rem; height: 2.6rem; color: var(--ink); }
.pick-face.mistook .mouth { stroke-dasharray: 100; animation: draw var(--t-slow) var(--ease-out) .1s backwards; }
.pick-icon { display: none; }
.pick-side .bar > div { transition: width .45s var(--ease-out); }

/* With room, the face beside the card says how the answer went, so the line under the cards keeps to the pen's mark. */
@media (min-width: 840px) {
    .pick-stage .pick-face { display: none; }
    .pick-stage .pick-icon { display: inline-block; }
    .pick-stage .pick-verdict { gap: .45rem; }
}

/* What the laptop made of it arrives with a small bounce, and its squiggle writes itself. */
.say-result > .say-verdict { animation-name: pop; animation-timing-function: var(--ease-spring); }
.say-verdict .face.mistook .mouth { stroke-dasharray: 100; animation: draw var(--t-slow) var(--ease-out) .15s backwards; }
.say-verdict-line .pen-mark { margin-right: .35rem; stroke-width: 2.6; }
.say-verdict-line .pen-mark path { animation-delay: .2s; }
.say-verdict-line .pen-mark path + path { animation-delay: .34s; }

/* ---- 20. Fixes, tunes and other results ---- */

/* Each fix arrives in its turn. The pen strikes what I said, from the first letter to the last even
   over two lines, and then ticks the better way. */
@keyframes pen-strike-thin { from { background-size: 0% max(.09em, 2px); } }
.fix-item { animation: rise var(--t) var(--ease-out) backwards; animation-delay: calc(var(--i, 0) * 90ms); transition: background var(--t) ease, box-shadow var(--t) ease; }
.fix-said s { text-decoration: none; }
.fix-said s > span {
    background: linear-gradient(currentColor, currentColor) no-repeat 0 58% / 100% max(.09em, 2px);
    animation: pen-strike-thin .45s var(--ease-out) backwards;
    animation-delay: calc(var(--i, 0) * 90ms + 220ms);
}
.fix-better .pen-mark path { animation-delay: calc(var(--i, 0) * 90ms + 520ms); }
.notice > .pen-mark:first-child { margin-right: .4rem; }
.fix-item .tag .pen-mark { width: 1em; height: 1em; margin-right: .1rem; stroke-width: 3; }
/* Where the system draws its own colours, a background cannot be relied on, so the plain line comes back. */
@media (forced-colors: active) { .fix-said s { text-decoration: line-through; } .fix-said s > span { background: none; } }

.try-mark .pen-mark { width: 1em; height: 1em; stroke-width: 3.2; }
.talk-results .tip { animation: rise var(--t) var(--ease-out) backwards; animation-delay: calc(var(--i, 0) * 70ms + 100ms); }
.stat .n .spinner { font-size: .55em; vertical-align: .3em; color: var(--ink-3); }

/* The tune: the speaker's line is drawn first, from left to right, then mine after it. */
.melody-window { transform-origin: 0 0; animation: strike .9s var(--ease-out) .2s backwards; }
.melody-window.after { animation-duration: 1s; animation-delay: .85s; }

/* Expression: the bar fills to its number. */
.expression-card .bar > div { transform-origin: 0 50%; animation: strike var(--t-slow) var(--ease-out) .15s backwards; }

/* A word said to save it: its place is kept while it is looked up, then the word pops in. */
.said-looking { display: flex; align-items: center; justify-content: center; min-height: 4rem; color: var(--ink-2); }
.said-word strong { display: inline-block; }
.said-other { animation: rise var(--t) var(--ease-out) backwards; animation-delay: calc(var(--i, 0) * 60ms + 150ms); }
