/* Practice: reading, writing, the spelling rooms and the games. Everything here stands on app.css
 * and uses its tokens. Nothing in this file is a colour of its own. */

/* ---- 1. Small things several of these screens share ---- */

/* A heading that starts a column sits level with the column beside it. */
.h-top { margin-top: 0; }
@media (min-width: 840px) { .h-top-wide { margin-top: 0; } }

.page-actions { margin-top: 1rem; }

/* Things the dark card did not yet know how to hold: a chosen chip, a link, a spinner, a fold
   and a count on its yellow button. Without these they are ink on ink. */
.hero .chip.on { background: var(--on-hero); border-color: var(--on-hero); color: var(--hero); }
.hero .link { min-height: 0; padding: 0 .1rem; color: inherit; text-decoration: underline; text-underline-offset: .18em; }
.hero .spinner { border-color: color-mix(in srgb, currentColor 30%, transparent); border-top-color: currentColor; }
.hero .fold-inner { margin-top: .5rem; }
.hero .fold-inner > summary { color: inherit; opacity: .85; }
.hero .btn-primary .count { background: var(--on-yellow); color: var(--yellow); }
.hero .btn .count { margin-left: .15rem; }

/* One card of practice: a column of its own, in the middle when the window is wide. */
.play { max-width: 34rem; margin-inline: auto; }

/* On a tablet held upright there is one column, and a button should still not run right across it. */
@media (min-width: 600px) and (max-width: 839.98px) {
    .reading-side > .btn-block, .stack > .btn-block { max-width: 24rem; }
}

/* ---- 2. A page of a book ---- */

.book {
    background: var(--paper);
    border: 1px solid var(--line);
    border-radius: var(--r-card);
    padding: 1.25rem 1.2rem 1.4rem;
}
@media (min-width: 600px) { .book { padding: 1.8rem 2rem 2rem; } }

.book .passage, .book .gap-text {
    max-width: var(--prose);
    margin-inline: auto;
    font-size: 1.2rem;
    line-height: 1.9;
    word-spacing: .06em;
}

/* Every word can be tapped. */
.passage .w { cursor: pointer; padding: .1em .12em; margin: 0 -.12em; border-radius: 4px; }
@media (hover: hover) { .passage .w:hover { background: var(--sunken); } }

/* One of my own words: it rests on the wavy line of a word I am not sure of yet. */
.passage .w.mine { text-decoration: underline wavy var(--coral); text-decoration-thickness: .08em; text-underline-offset: .26em; }

/* The sentence being read to me. The shadow carries the colour across the space to the next word. */
.passage .w.now { background: var(--yellow-soft); border-radius: 0; box-shadow: .32em 0 0 var(--yellow-soft); }

/* The word I tapped: a swipe of highlighter. */
.passage .w.picked, .tapped-word {
    background: linear-gradient(transparent 14%, var(--yellow) 14%, var(--yellow) 90%, transparent 90%);
    color: var(--on-yellow);
    box-shadow: none;
}

/* The text, and what goes with it. On a phone they follow one another, and the word I tapped
   rides at the bottom of the screen so it can be reached without scrolling past the text. */
.reading { display: block; }
.reading > .book { margin-bottom: .8rem; }
.reading-side { display: contents; }

.tap-hint { display: flex; align-items: center; gap: .45rem; margin: 0 .2rem .8rem; color: var(--ink-3); font-size: .95rem; }
.tap-hint .icon { width: 1.2rem; height: 1.2rem; }

.reading .tapped {
    position: sticky;
    bottom: calc(var(--tabbar) + env(safe-area-inset-bottom, 0px) + .6rem);
    z-index: 5;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .5rem .7rem;
    padding: .7rem .8rem;
    border-color: var(--line-strong);
    box-shadow: var(--lift);
}
.tapped-word { flex: 0 1 auto; min-width: 0; padding: 0 .15em; border-radius: 3px; font-family: var(--display); font-weight: 800; font-size: 1.4rem; line-height: 1.2; overflow-wrap: anywhere; }
.tapped .btn-row { flex: 1 0 auto; justify-content: flex-end; flex-wrap: nowrap; }
.tapped .long { display: none; }
.tapped .tapped-hear { min-width: 2.9rem; padding: 0; border-radius: 50%; }

@media (min-width: 600px) { .reading .tapped { bottom: .9rem; } }

@media (min-width: 840px) {
    .reading { display: grid; grid-template-columns: minmax(0, 1.7fr) minmax(16.5rem, 1fr); gap: 1.4rem; align-items: start; }
    .reading > .book { margin-bottom: 0; }
    .reading-side { display: grid; gap: .8rem; position: sticky; top: 1.5rem; }
    .reading-side > * { min-width: 0; margin-bottom: 0; }

    .reading .tapped { position: static; display: block; padding: 1.15rem; border-color: var(--line); box-shadow: none; }
    .tapped-word { display: inline-block; font-size: 1.7rem; margin-bottom: .7rem; }
    .tapped .btn-row { justify-content: flex-start; flex-wrap: wrap; }
    .tapped .long { display: inline; }
    .tapped .tapped-hear { padding: 0 1.1rem; border-radius: var(--r-control); }

    .tap-hint { margin: 0; padding: 1.15rem; border: 1px dashed var(--line-strong); border-radius: var(--r-card); color: var(--ink-2); }
}

/* ---- 3. Read ---- */

/* Today's paragraph, on the one dark card. */
.read-today h2 { padding-right: 0; margin-bottom: .7rem; }
.read-today .chips { padding-bottom: .35rem; }
.read-today .spinner { margin-right: .3rem; }
.read-suggest { margin: .2rem 0 .1rem; }
.read-today-note { margin: .9rem 0 0; }

.read-mine { margin: .1rem 0 .1rem .35rem; }
.row .meta .read-mine { vertical-align: baseline; }

/* What goes with the text while I read. */
.read-tools { display: grid; gap: .85rem; justify-items: start; }
.read-notes { list-style: none; margin: 0; padding: 0; display: grid; gap: .45rem; color: var(--ink-2); font-size: .92rem; }
.read-notes li { display: grid; grid-template-columns: 1.5rem minmax(0, 1fr); gap: .45rem; align-items: start; }
.read-notes .icon { width: 1.2rem; height: 1.2rem; margin-top: .12rem; color: var(--ink-3); }
.wave-key {
    height: .42rem;
    margin-top: .5rem;
    background: var(--coral);
    -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;
}

/* A gap to fill: a blank on the page, marked with the highlighter. */
.book .gap-text { line-height: 2.6; }
.book .gap-input {
    width: 7.2em;
    min-height: 2.5rem;
    padding: 0 .45rem;
    border: 0;
    border-bottom: 2px solid var(--ink-3);
    border-radius: 8px 8px 0 0;
    background: var(--yellow-soft);
    font-weight: 600;
}
.book .gap-input:focus { outline: none; border-bottom-color: var(--focus); box-shadow: 0 0 0 3px color-mix(in srgb, var(--focus) 22%, transparent); }

textarea.answer-box { min-height: 5.5rem; }

/* The marks. */
.gap-marks { display: grid; }
.gap-mark { display: flex; align-items: baseline; gap: .55rem; padding: .45rem 0; border-top: 1px solid var(--line); }
.gap-mark:first-child { border-top: 0; padding-top: 0; }
.gap-mark:last-child { padding-bottom: 0; }
.gap-mark .tag { flex: 0 0 auto; min-width: 4.7rem; justify-content: center; margin: 0; }
.gap-word { font-family: var(--letters); font-weight: 600; }
.gap-mark .diff { font-size: 1.15rem; }
.gap-mark .diff-row .who { min-width: 3.3rem; text-align: left; }

.answer .card-head { align-items: flex-start; flex-wrap: wrap; gap: .3rem 1rem; }
.answer .card-head h3 { flex: 1 1 13rem; }
.answer .card-head .tag { flex: 0 0 auto; margin: 0; }
.answer > .link { margin-bottom: -.55rem; }

.points { list-style: none; margin: 0 0 .5rem; padding: 0; display: grid; gap: .3rem; }
.points li { display: grid; grid-template-columns: 1.4rem minmax(0, 1fr); gap: .45rem; align-items: start; }
.points .found .icon { margin-top: .12em; color: var(--green); stroke-width: 2.6; }
.points .missed { color: var(--ink-2); }
.points .missed i { width: .85rem; height: .85rem; margin: .38em 0 0 .25rem; border: 2px solid var(--ink-3); border-radius: 50%; }

.model-answer { margin: .7rem 0 .2rem; padding: .65rem .85rem; border-radius: var(--r-control); background: var(--sunken); color: var(--ink-2); font-size: .96rem; }

/* ---- 4. Write ---- */

/* A task to choose. It keeps the old tile's name, which the scripts know, and takes the look of a feature. */
.feature.hub-item { column-gap: .85rem; row-gap: .1rem; padding: .95rem 1.05rem; align-content: center; }
.feature.hub-item .ttl .tag { margin: 0 0 0 .3rem; vertical-align: .08em; }
.write-tasks { align-content: start; }

.tallies { display: grid; }
.tally { display: flex; align-items: center; gap: .8rem; min-height: 2.2rem; }
.tally .grow { color: var(--ink-2); font-weight: 600; }
.tally .tag { margin: 0; min-width: 2rem; justify-content: center; font-variant-numeric: tabular-nums; }
.write-keep { margin: .8rem 0 .1rem; padding-top: .8rem; border-top: 1px solid var(--line); }
.fix .sub { margin-left: auto; font-family: var(--text); }

/* The task, and the box to write in. */
.write-task { display: flex; align-items: center; gap: .8rem; margin-bottom: .9rem; font-weight: 600; line-height: 1.35; }
.write-box textarea.input { min-height: 12rem; }
.write-box > .sub { margin-top: .3rem; }
.write-actions { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: .4rem 1rem; margin-top: .6rem; }
.write-actions .btn { flex: 1 1 12rem; }
.write-box .write-note { margin: .7rem 0 0; }
.write-maybes { margin-bottom: .6rem; }
.write-waiting { min-height: 20rem; align-content: center; border: 1px dashed var(--line-strong); border-radius: var(--r-card); }

@media (min-width: 840px) {
    .write-box textarea.input { min-height: 17rem; }
    .write-actions .btn { flex: 0 0 auto; }
}

/* One suggestion: what kind it is, the change in its sentence, why, and what to do with it. What
   goes is struck out in red pen, and what comes in is in green. */
.suggestion .tag { margin: 0 0 .35rem; }
.suggestion .change { display: block; font-size: 1.08rem; line-height: 1.65; color: var(--ink-2); }
.change s { padding: 0 .12em; border-radius: 4px; background: var(--wrong-bg); color: var(--wrong); text-decoration-thickness: .1em; }
.change strong { padding: 0 .12em; border-radius: 4px; background: var(--right-bg); color: var(--right); box-shadow: inset 0 -.14em 0 var(--green); font-weight: 700; }
.change strong:empty { display: none; }
.suggestion .sub { margin-top: .25rem; }
.suggestion .btn-row { margin-top: .55rem; }
.suggestion .btn { min-height: 2.6rem; }

/* ---- 5. Spelling, and the packs ---- */

.spell-hero h2 { font-size: 2.1rem; }
/* A pack: its name, its rule in a line, and how many words it holds. */
.pack { grid-template-rows: auto auto 1fr; align-items: start; }
.pack .pic { grid-row: 1 / span 3; align-self: start; }
.pack .ttl, .pack .meta { align-self: start; }
.pack .tag { grid-column: 2; justify-self: start; align-self: end; margin: .55rem 0 0; }

/* ---- 6. Hear it, type it ---- */

.drill-head { margin-bottom: .7rem; }
.lives { display: inline-flex; gap: .15rem; color: var(--coral); }
.lives .icon { width: 1.35rem; height: 1.35rem; }
.lives .full { fill: var(--coral); }
.lives .lost { color: var(--line-strong); }

/* On a laptop the bar is one row: where I am, the bar, then the score. */
@media (min-width: 840px) {
    .drill-head .session-bar { order: 1; }
    .drill-head .tag, .drill-head .lives { order: 2; margin-right: 0; }
}

/* The words I missed, at the end of a round. */
.empty .finish-words { justify-content: center; margin: 0; }
.missed-words { font-family: var(--letters); font-weight: 600; color: var(--ink); }

/* ---- 7. Dictation ---- */

.heard { max-width: none; font-size: 1.25rem; line-height: 1.9; }
.heard-fixes { display: grid; gap: .6rem; }
.heard-fixes > * { min-width: 0; margin: 0; }
.heard-fixes .diff { font-size: 1.3rem; }

/* ---- 8. Stories ---- */

.choices { display: grid; gap: .5rem; }
.btn.choice { justify-content: space-between; min-height: 3.2rem; height: auto; padding: .7rem 1rem; text-align: left; line-height: 1.35; }
.choice .icon { color: var(--ink-3); }
.choices .btn-ghost { justify-self: start; }
.story-end { display: flex; align-items: center; gap: .7rem; margin: .2rem 0 .3rem; }
.story-end .face { width: 3rem; height: 3rem; }
.story-end strong { font-family: var(--display); font-size: 1.25rem; }

/* ---- 9. Word builder ---- */

/* The board: where the pieces go on top, the pieces to choose from in a tray under them. Pieces
   are large, because they are picked up with a thumb. */
.board { display: grid; gap: 1rem; justify-items: center; text-align: center; }
.board .ask { padding-bottom: 0; }
.board > * { min-width: 0; margin: 0; }
.board h3 { color: var(--ink-3); font-family: var(--text); font-size: .92rem; }
.board .slots, .board .pieces { width: 100%; justify-content: center; }
.board .slot { min-width: 4.6rem; min-height: 3.9rem; }
.board .tile, .tile.tile-ghost { min-height: 3.2rem; padding: .3rem 1rem; font-size: 1.3rem; }
.board .pieces { min-height: 4.6rem; padding: .7rem; border-radius: var(--r-control); background: var(--sunken); }
.board .notice { width: 100%; text-align: left; }
.play > .btn-ghost { display: flex; margin: .5rem auto 0; }

/* ---- 10. Typing race ---- */

.race { display: grid; gap: .9rem; justify-items: center; text-align: center; }
.race > * { min-width: 0; margin: 0; }
.race .stats, .race-clock { width: 100%; max-width: 20rem; }
.race-clock > div { background: var(--coral); transition: width 1s linear; }
.race-word { min-height: 1.2em; font-family: var(--letters); font-weight: 700; }
.race-again { min-height: 2.9rem; }
.race .input-answer { width: 100%; }
.race .face { width: 5rem; height: 5rem; color: var(--ink); }
.race-pic { width: 4.2rem; height: 4.2rem; border-radius: 18px; }
.race-pic .icon { width: 2.2rem; height: 2.2rem; }
.race .btn-row { justify-content: center; }
.race .btn-primary { min-width: 11rem; }

/* The games' own cards take the same room inside as the practice card does. */
@media (min-width: 840px) { .board, .race, .confusion { padding: 1.6rem 1.75rem 1.5rem; } }

/* ---- 11. Mixed-up words ---- */

.confusion { display: grid; gap: 1rem; }
.confusion > * { min-width: 0; margin: 0; }
.confusion > .tag { justify-self: start; }
.confusion-sentence { font-family: var(--display); font-size: 1.5rem; font-weight: 600; line-height: 1.55; text-wrap: balance; }

/* The gap in the sentence, drawn as a gap. Once I have chosen, the right word is written into it. */
.blank {
    display: inline-block;
    min-width: 3.2em;
    min-height: 1.1em;
    margin: 0 .1em;
    padding: 0 .25em;
    border-bottom: 3px solid var(--ink);
    border-radius: 6px 6px 0 0;
    background: var(--yellow-soft);
    line-height: 1.25;
    text-align: center;
    vertical-align: -.14em;
}
.blank.filled { min-width: 0; vertical-align: baseline; border-bottom-color: transparent; border-radius: 3px; background: linear-gradient(transparent 14%, var(--yellow) 14%, var(--yellow) 90%, transparent 90%); color: var(--on-yellow); }

.options { display: grid; grid-template-columns: repeat(auto-fit, minmax(7rem, 1fr)); gap: .6rem; }
.options .btn { min-height: 3.6rem; font-family: var(--letters); font-size: 1.2rem; }
.confusion .notice strong { margin-right: .3rem; }

@media (min-width: 840px) { .confusion-sentence { font-size: 1.7rem; } }

/* ---- 12. Handwriting ---- */

/* A line to write on, as in a notebook. The page stays white in both looks, because the ink is dark. */
.handwrite .draw {
    height: 14rem;
    background-image: linear-gradient(to bottom, transparent calc(70% - 1px), var(--line-strong) calc(70% - 1px), var(--line-strong) calc(70% + 1px), transparent calc(70% + 1px));
}
.handwrite > .btn-row { margin-bottom: .8rem; }
.read-back { display: grid; gap: .6rem; margin-top: .9rem; }
.read-back .word-big { text-align: center; }
.verdict .btn { flex: 1 1 9rem; }
.handwrite .notice strong { margin-right: .3rem; }

/* ---- 13. From a photo ---- */

.photo-ways .btn { flex: 1 1 8rem; }
.photo-note { display: flex; align-items: center; gap: .4rem; margin-top: .7rem; }
.photo-note .icon { width: 1.1rem; height: 1.1rem; color: var(--ink-3); }
.photo-error { margin: .7rem 0 0; }
.photo-waiting { min-height: 22rem; align-content: center; border: 1px dashed var(--line-strong); border-radius: var(--r-card); }
.photo-frame { border: 1px solid var(--line); }
.photo-cols .btn .tag { margin: 0 0 0 .2rem; }

@media (max-width: 839.98px) {
    .photo-cols { gap: 0; }
    .photo-cols .photo-frame { margin-bottom: .8rem; }
}

/* ---- 14. Words offered after reading aloud ---- */

.offer-words .chips { padding-bottom: 0; }
.offer-words .chip .icon { width: 1.1em; height: 1.1em; }

/* ---- 15. How practice moves ----
   Everything here stands on section 27 of app.css: the same times, the same curves, the same
   keyframes. Four things are new, because nothing there could do them:
   - from-right-again, a second name for from-right, so the next card can arrive again without
     the card being thrown away (the box I type in keeps its place, and a phone keeps its keyboard);
   - pen-strike, a red line that is drawn through words that may run over two lines;
   - count-up, a number that counts up once;
   - hop, one small jump of the face for a right answer. */

@keyframes pen-strike { from { background-size: 0% .12em; } to { background-size: 100% .12em; } }
@keyframes hop {
    0%, 100% { transform: translateY(0); }
    40% { transform: translateY(-5px); }
}

/* The next card in a run of cards arrives from the right. Adding "again" plays it once more.
   It lets go when it has arrived, so nothing inside it is held in place by a finished movement. */
.arrives { animation: from-right var(--t) var(--ease-out) backwards; }
.arrives.again { animation-name: from-right-again; }

/* A card on its way in must not make the page wider than the window. */
.page:has(.arrives) { overflow-x: clip; }

/* A list or a grid arrives one after another. The first twelve wait their turn; the rest come with
   the twelfth. "one-by-one" goes on the list itself; "in-turn" goes around a list this file cannot
   reach into, such as the grid of things to choose from. */
:is(.one-by-one, .in-turn > .feature-grid) > * { animation: rise var(--t) var(--ease-out) backwards; animation-delay: calc(var(--i, 0) * 40ms); }
:is(.one-by-one, .in-turn > .feature-grid) > :nth-child(2) { --i: 1; }
:is(.one-by-one, .in-turn > .feature-grid) > :nth-child(3) { --i: 2; }
:is(.one-by-one, .in-turn > .feature-grid) > :nth-child(4) { --i: 3; }
:is(.one-by-one, .in-turn > .feature-grid) > :nth-child(5) { --i: 4; }
:is(.one-by-one, .in-turn > .feature-grid) > :nth-child(6) { --i: 5; }
:is(.one-by-one, .in-turn > .feature-grid) > :nth-child(7) { --i: 6; }
:is(.one-by-one, .in-turn > .feature-grid) > :nth-child(8) { --i: 7; }
:is(.one-by-one, .in-turn > .feature-grid) > :nth-child(9) { --i: 8; }
:is(.one-by-one, .in-turn > .feature-grid) > :nth-child(10) { --i: 9; }
:is(.one-by-one, .in-turn > .feature-grid) > :nth-child(11) { --i: 10; }
:is(.one-by-one, .in-turn > .feature-grid) > :nth-child(n+12) { --i: 11; }

/* The end of a round: the face, then the score with a small bounce, then what to do next. */
.ending > .face { animation: pop var(--t-slow) var(--ease-spring) both; }
.ending > strong { animation: pop var(--t) var(--ease-spring) .22s both; }
.ending > p, .ending > .sub { animation: rise var(--t) var(--ease-out) .34s both; }
.ending > .finish-words > * { animation-delay: calc(.4s + var(--i, 0) * 40ms); }
.ending > .btn-row { animation: rise var(--t) var(--ease-out) .5s both; }

/* A number that is the point of a screen counts up to itself, once. The number is written beside
   it for a screen reader, and a browser that cannot count simply shows it. */

/* The red pen through what I wrote. It is a background, so it follows the words over a line end. */
.pen-struck {
    background: linear-gradient(var(--coral), var(--coral)) left 56% / 100% .12em no-repeat;
    animation: pen-strike .34s var(--ease-out) .16s both;
}

/* Words the pen writes in: they appear from left to right. */
.written { animation: squiggle-in var(--t-slow) var(--ease-out) .12s both; }

/* Right: the tick in a notice draws itself, and the face at its end smiles. */
.notice-face { float: right; width: 1.7rem; height: 1.7rem; margin: -.08rem 0 0 .6rem; color: currentColor; }
.notice-good .notice-face .mouth { stroke: currentColor; }

/* For a moment after a right answer, what I pressed to hear the word gives its place to what
   the answer earned: the plant, or a smile. It takes the same room, so nothing under it moves. */
.ask.is-over { position: relative; }
.ask.is-over > :not(.ask-over) { visibility: hidden; }
.ask-over { position: absolute; inset: 0; display: grid; align-content: center; justify-items: center; gap: .3rem; text-align: center; }
.ask-over > .face { width: 5.4rem; height: 5.4rem; color: var(--ink); animation: pop var(--t) var(--ease-spring) both; }

/* ---- 16. Where a word stands, after an answer ----
   The stage moment: the plant grows, its stage is named, and the three steps show how far it has
   come. It is drawn only once the answer has been checked and has counted. */

/* The plant with its name beside it, then the steps and the day it comes back, each on a line of
   its own, so the three steps never have to break in two on a phone. */
.stage-moment {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    align-items: center;
    gap: .4rem .8rem;
    margin: .1rem 0 .2rem;
    padding: .75rem .9rem .8rem;
    border-radius: var(--r-control);
    background: var(--page);
    text-align: left;
    animation: rise var(--t) var(--ease-out) .2s both;
}
.stage-moment > .took-steps, .stage-moment > .next-due { grid-column: 1 / -1; }
.stage-moment .sprout { width: 2.5rem; height: 3.1rem; }
.stage-moment .sprout .grow { animation-delay: .34s; }
.stage-name { font-family: var(--display); font-weight: 800; font-size: 1.2rem; line-height: 1.2; }
.stage-say { color: var(--ink-2); line-height: 1.3; }
.stage-moment .took-steps { font-size: .88rem; gap: .2rem; }
.stage-moment .took-steps li { gap: .2rem; }
.stage-moment .took-steps span { padding: .12rem .55rem; }
.stage-moment .took-steps .now span { animation-delay: .5s; }
.stage-moment .next-due { justify-content: flex-start; margin-top: 0; font-size: .92rem; }
.stage-moment.took { background: var(--right-bg); }
.stage-moment.took .sprout { width: 3.2rem; height: 4rem; }
.stage-moment.took .next-due { color: var(--right); }
.spell-card > .stage-moment { margin-top: .8rem; }

/* Where there is room, the plant stands beside all three lines. */
@media (min-width: 600px) {
    .stage-moment { column-gap: 1rem; padding: .85rem 1.1rem; }
    .stage-moment > .sprout { grid-row: 1 / span 3; width: 3.2rem; height: 4rem; }
    .stage-moment > .took-steps, .stage-moment > .next-due { grid-column: 2; }
    .stage-moment.took > .sprout { width: 3.8rem; height: 4.75rem; }
}

/* In the moment a right answer stays on screen, it stands where the button to hear the word was. */
.stage-moment.ask-over { grid-template-columns: minmax(0, 1fr); gap: .3rem; margin: 0; padding: 0; background: none; text-align: center; animation: none; }
.stage-moment.ask-over > * { grid-column: 1; grid-row: auto; }
.stage-moment.ask-over > .sprout { width: 3.6rem; height: 4.5rem; }
.stage-moment.ask-over .sprout .grow { animation-delay: 0s; }
.stage-moment.ask-over .stage-name { animation: rise var(--t) var(--ease-out) .12s both; }
.stage-moment.ask-over .took-steps { justify-content: center; animation: rise var(--t) var(--ease-out) .2s both; }
.stage-moment.ask-over .took-steps .now span { animation-delay: .34s; }

/* ---- 17. The daily review ---- */

/* The face says how the last answer went: a hop for right, eyes down for a miss. */
.session-side .so-far .face.smile, .head-face.smile { animation: hop .5s var(--ease-out) both; }
.head-face { flex: 0 0 auto; width: 2rem; height: 2rem; color: var(--ink); }

/* The marks: the newest one pops in and draws itself, and the ring moves on to the next. */
.marks .mark.newest, .marks .mark.now { animation: pop var(--t) var(--ease-spring) both; }

/* The ending arrives in order: the face, the line, the marks one after another, then what grew. */
.finish-main .face { animation: pop var(--t-slow) var(--ease-spring) both; }
.finish-main h1 { animation: rise var(--t) var(--ease-out) .16s both; }
.finish-main .finish-line { animation: rise var(--t) var(--ease-out) .28s both; }
.finish-main .marks .mark { animation: pop var(--t) var(--ease-spring) both; animation-delay: calc(.42s + var(--i, 0) * 40ms); }
.finish-main .marks .mark path { stroke-dasharray: 100; animation: draw var(--t-slow) var(--ease-out) both; animation-delay: calc(.46s + var(--i, 0) * 40ms); }
.finish-main .finish-actions { animation: rise var(--t) var(--ease-out) 1s both; }
.finish > .stack > .card { animation: rise var(--t) var(--ease-out) both; animation-delay: calc(1.05s + var(--i, 0) * 130ms); }

/* Each word of the session beside what it is now: a flower if it took root, a seed if I mistook it. */
.finish-words.grown { gap: .5rem 1.3rem; align-items: flex-end; }
.finish-word { display: inline-flex; align-items: flex-end; gap: .4rem; }
.finish-word .sprout { width: 1.9rem; height: 2.4rem; }
.finish-word .word-mark { line-height: 1.7; }
.finish .finish-word .sprout .grow { animation-delay: calc(1.3s + var(--i, 0) * 90ms); }

/* ---- 18. A spelling card ---- */

/* My attempt against the right spelling arrives as a pen correction: what I wrote is struck
   through, then the right spelling is written under it. Under the pen's line a letter that does
   not belong keeps its red block, so it can still be told from the letters that do. */
.diff { animation: rise var(--t) var(--ease-out) both; }
.diff .pen-struck .d-extra { text-decoration: none; background: color-mix(in srgb, var(--coral) 20%, transparent); }
.diff .diff-row + .diff-row { animation: rise var(--t) var(--ease-out) .42s both; }

/* A wrong answer: the card shakes its head once, and what there is to study follows the pen. */
.spell-card.studying > h3, .spell-card.studying > .syllables, .spell-card.studying > .notice-tip, .spell-card.studying > .trouble-line { animation: rise var(--t) var(--ease-out) .5s both; }

/* From memory, three times: a mark for each, ticked as it is done. */
.retype-marks { display: inline-flex; flex-wrap: nowrap; vertical-align: -.22em; margin-left: .35rem; }
.retype-marks .mark { width: 1.3rem; height: 1.3rem; }

/* The word I chose and should not have, with the pen through it. */
.chosen-wrong { margin-right: .55rem; font-family: var(--letters); font-weight: 600; text-decoration: none; }

/* The word, once it may be seen. */
.spell-card > .shown-word { animation: rise var(--t) var(--ease-out) .08s both; }
.spell-card .pick { transition: background var(--t-fast) ease, border-color var(--t-fast) ease, transform var(--t-fast) var(--ease-out); }
.spell-card .pick:active { transform: scale(.98); }

/* ---- 19. Lives ---- */

/* A life that has just been lost pops, so the eye catches which one went. */
.lives .lost { animation: pop var(--t) var(--ease-spring) both; }

/* ---- 20. Word builder: pieces that lift and settle ----
   Two movements of their own: tile-lift for the piece that follows the finger (it has to keep
   its place under the finger while it tilts), and tile-settle for a piece that is put down. */

@keyframes tile-lift { from { transform: translate(-50%, -50%) scale(1); } to { transform: translate(-50%, -50%) scale(1.08) rotate(-3deg); } }
@keyframes tile-settle { from { transform: translateY(-7px) scale(1.08); box-shadow: var(--lift); } to { transform: none; box-shadow: 0 0 0 transparent; } }

/* A piece rises a little under the hand, and comes to rest where it lands. The settling does not
   hold on afterwards, so the piece can still rise the next time it is touched. */
.board .tile { transition: transform var(--t-fast) var(--ease-out), box-shadow var(--t-fast) ease; animation: tile-settle var(--t) var(--ease-spring); }
@media (hover: hover) { .board .tile:hover { transform: translateY(-2px); box-shadow: var(--shadow); } }
.board .tile:active { transform: translateY(-3px) scale(1.05); box-shadow: var(--lift); }

/* The piece being carried lifts right off the board and tilts. */
.tile.tile-ghost { animation: tile-lift var(--t-fast) var(--ease-out) both; }

/* The place a piece is held over opens up for it. */
.board .slot { transition: background var(--t-fast) ease, border-color var(--t-fast) ease, transform var(--t-fast) var(--ease-out); }
.board .slot.slot-over { transform: scale(1.06); }

/* Built: the pieces hop one after another, left to right. */
.board .slot-right .tile { animation: hop .5s var(--ease-out) calc(var(--i, 0) * 70ms) both; }

/* ---- 21. Typing race: the end ---- */

.race.ended > .face { animation: pop var(--t-slow) var(--ease-spring) both; }
.race.ended > .word-big { animation: pop var(--t) var(--ease-spring) .2s both; }
.race.ended > .sub { animation: rise var(--t) var(--ease-out) .34s both; }
.race.ended > .btn-row { animation: rise var(--t) var(--ease-out) .5s both; }

/* ---- 22. Reading: the word I tapped ---- */

/* A word I save is planted. In the text it gets the wavy line of my own words at once. Where the
   panel is a card of its own, a seed drops in beside the word; on a phone the panel is one slim
   row with no room for it, and the green tick says it. */
.tapped-seed { display: none; }
@media (min-width: 840px) { .tapped-seed { display: inline-block; width: 1.8rem; height: 2.25rem; vertical-align: bottom; margin: 0 0 .7rem .6rem; } }

/* A gap I got wrong: what I wrote, with the pen through it. */
.wrote-wrong { text-decoration: none; }

/* ---- 23. Writing: the pen's corrections ---- */

/* A suggestion is marked the way a pen would mark the page: a line is drawn through what goes,
   and what comes in appears after it. In a list, each waits for its own turn. */
.change s {
    text-decoration: none;
    background: linear-gradient(var(--wrong), var(--wrong)) left 56% / 100% .12em no-repeat var(--wrong-bg);
    animation: pen-strike .34s var(--ease-out) calc(.2s + var(--i, 0) * 40ms) backwards;
}
.change strong { animation: fade var(--t) ease calc(.5s + var(--i, 0) * 40ms) backwards; }

/* The fix I just accepted, shown once more as the correction it was. */
.fixed-line { display: flex; align-items: baseline; gap: .5rem; padding: .6rem .9rem; border-radius: var(--r-control); background: var(--right-bg); color: var(--right); animation: rise var(--t) var(--ease-out) both; }
.fixed-line .icon { flex: 0 0 auto; align-self: center; }
.fixed-line .change { color: var(--ink); font-size: 1.05rem; line-height: 1.5; }

/* ---- 24. From a photo: the wait, and the words found ---- */

/* While the picture is read, the squiggle writes itself across it. */
.photo-reading { position: absolute; inset: 0; display: grid; place-items: center; background: color-mix(in srgb, var(--paper) 55%, transparent); color: var(--ink); font-size: 2.4rem; line-height: 1; }

/* Each word that is found pops up where it is in the picture. */
.photo-word { animation: pop var(--t) var(--ease-spring) backwards; animation-delay: calc(.1s + var(--i, 0) * 40ms); transition: background var(--t-fast) ease; }
@media (hover: hover) { .photo-word:hover { background: color-mix(in srgb, var(--yellow) 60%, transparent); } }
