/* Checking an answer with the inverse operation.

   One scroll-led figure and one still one. The scroll-led figure writes a check
   three times over, from a subtraction, a division and a power, and leaves each
   calculation standing above the statement that tests it. The still figure is
   47 counters as seven columns of six with five left loose, which is the whole
   of why a remainder has to go back into its own check.

   Everything else comes from lesson.css. */

/* THE SCROLL-LED CARD ---------------------------------------------------- */

.inv-scene {
    position: relative;
    min-height: min(628px, calc(100vh - 104px));
    margin: 26px 0 8px;
    overflow-anchor: none;
}

.inv-scene.is-ready { height: var(--scene-height); min-height: var(--scene-min-height); }

.inv-scene__sticky {
    position: absolute;
    top: 0;
    right: 0;
    left: 0;
    display: grid;
    height: min(628px, calc(100vh - 104px));
    min-height: 470px;
    box-sizing: border-box;
    /* board, caption, progress. There is no heading row: this scene works three
       statements, and a single heading over them could only describe the figure
       rather than name what it shows. */
    grid-template-rows: minmax(0, 1fr) auto auto;
    overflow: hidden;
    border: 2px solid #c9dce8;
    border-radius: 22px;
    background: linear-gradient(180deg, #fbfdff 0%, #f2f8fc 100%);
    box-shadow: 0 12px 30px rgba(20, 57, 78, .14);
    contain: layout paint;
    overflow-anchor: none;
    will-change: transform;
}

.inv-scene__sticky.is-pinned { position: fixed; right: auto; z-index: 900; transform-origin: top left; }

.inv-board { position: relative; display: grid; min-height: 0; padding: 6px 24px 0; place-items: center; }
.inv-board__paper { position: relative; display: grid; justify-items: center; width: 100%; }

/* h3 under a card that has a worked title above it, h2 under one that does
   not, so the heading order holds either way. Both read the same. */
.inv-scene__caption h2,
.inv-scene__caption h3 { margin: 0 0 5px; color: #09539d; font-size: 1.1rem; }

.inv-scene__caption {
    display: grid;
    align-content: center;
    height: 6.6em;
    box-sizing: border-box;
    padding: 14px 28px 6px;
    text-align: center;
}

.inv-scene__caption p { margin: 0; color: #243a45; font-size: .97rem; line-height: 1.5; }

.inv-scene__progress { display: flex; gap: 8px; padding: 0 22px 18px; justify-content: center; }

.inv-scene__dot {
    width: 9px;
    height: 9px;
    border-radius: 999px;
    background: #c6d4dc;
    transition: width .25s ease, background-color .25s ease;
}

.inv-scene__dot.is-past { background: #6c9bb0; }
.inv-scene__dot.is-current { width: 28px; background: #116e93; }

/* WHAT UNDOES WHAT -------------------------------------------------------

   A calculation on the left and the statement that tests it on the right. This
   used to be a sentence listing the pairings, which is exactly the kind of prose
   that should be shown: the reader wants to find their own calculation's shape
   and read off the check, not parse a list. */

.undoes {
    display: grid;
    gap: 0;
    margin: 22px 0;
    padding: 6px 0;
    border: 2px solid #d9e2ec;
    border-radius: 18px;
    background: #f8fbfd;
    list-style: none;
}

.undoes li {
    display: grid;
    align-items: baseline;
    padding: 11px 24px;
    gap: 18px;
    grid-template-columns: 1fr auto 1fr;
}

.undoes li + li { border-top: 1px solid #e4edf3; }

.undoes__from { color: #173849; text-align: right; }
.undoes__to { color: #09539d; text-align: left; }

.undoes__from,
.undoes__to { font-size: 1.06rem; font-weight: 700; }

/* The arrow reads "is checked by". It is decorative: each statement carries
   that in words in its own label. */
.undoes__arrow { color: #b86821; font-size: 1.12rem; }

/* THE ENDS SWAP, THE SIGN TURNS ------------------------------------------

   Three pairs down the board, each a calculation still being asked about with
   the check that answers it standing underneath. The check is a copy of the
   calculation: it starts exactly on top of it and falls away, its two end
   numbers crossing on the way down, so what the reader watches is one statement
   becoming another and both being readable at the end of it.

   The rows keep their space from the first frame, whether or not they have been
   reached, so the board never reflows under a pinned card. */

.cross {
    display: grid;
    align-content: center;
    justify-items: center;
    gap: 16px;
    width: 100%;
}

/* The pair shares one cell, so the copy can start on top of the original. The
   row is taller than the pair it holds, and that surplus plus the gap is what
   separates one pair from the next — it has to beat the drop inside a pair, or
   the six lines group the wrong way. */
.cross__row {
    display: grid;
    align-content: center;
    justify-items: center;
    height: 134px;
}

.cross__line {
    display: flex;
    grid-area: 1 / 1;
    align-items: baseline;
    gap: 10px;
    font: 700 1.62rem/1.2 ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace;
    font-variant-numeric: tabular-nums;
}

/* The calculation that has been left behind, still holding its question. Dark
   enough to survive a finished pair stepping back: at a lighter grey it dropped
   out of the card altogether and the reader was left with three checks and
   nothing to read them against. */
.cross__line--ghost { color: #55707f; }
.cross__line--live { color: #123244; }

/* Nothing is padded out to a common width. Each mark is let go from the place
   it is copied from, so the slots can be exactly as wide as what they hold.

   The one exception is the slot the root grows into, which is held at the width
   the root will need so the line does not reflow as the sign is drawn. Centring
   is what keeps the radicand under the mark it is copied from while that slot is
   still wider than the number in it. */
.cross__end { position: relative; z-index: 2; text-align: center; }
.cross__mid { color: inherit; }

/* A MARK THAT TURNS INTO ANOTHER -----------------------------------------

   Both faces are present from the start, stacked in one slot, and the change is
   a crossfade between them. Rewriting the character at a threshold put the
   change between two scroll events, which read as a glitch rather than a turn.

   The face the mark rests on is written into the element and the face it turns
   from is drawn by the stylesheet, so the line that survives the stylesheet
   being stripped is the finished check rather than a mark of each. */

.cross__slot {
    display: inline-grid;
    z-index: 1;
    justify-items: center;
}

.cross__face { grid-area: 1 / 1; }
/* only where a mark was named — the questioning equals draws its own */
.cross__face--from[data-face]::before { content: attr(data-face); }

/* The sign the check is written with, and so the one worth marking. The
   calculation's own sign is not marked: on the line above, the sign is what the
   reader is being asked to accept, not what has changed. */
.cross__line--live .cross__op .cross__face:first-child { color: #b86821; }
.cross__op { min-width: 1ch; }

.cross__eq { padding: 0 5px; }

/* THE QUESTIONING EQUALS — drawn, not typed.

   The character is there in the source, clipped, so a stripped page still says
   the line is asking. It is not what gets shown: no face in this monospace stack
   carries it, and the fallback that does sets the question mark at half the size
   and most of a line above the bar, so the mark reads as an equals with
   something else floating over it. Drawn from an equals and a question mark of
   its own, both in the face the numerals are set in, the two parts sit together
   as one sign. */

.cross__ask { position: relative; display: inline-block; }
.cross__ask::before { content: "="; }

.cross__ask::after {
    content: "?";
    position: absolute;
    /* Per cent of the slot's height, not em. An em on this rule resolves against
       the font-size declared beside it — half the line's — so every em offset
       written here is silently worth half of what it reads as, and the question
       mark comes to rest on the bar it is supposed to stand over. */
    bottom: 68%;
    left: 50%;
    font-size: .5em;
    line-height: 1;
    transform: translateX(-50%);
}

/* the index rides on its base, so it takes no width of its own in the row */
.cross__index { position: relative; z-index: 3; }
.cross__index sup { font-size: .62em; }

/* The order in flight. It is drawn for the same reason the root's own order is:
   it is one mark moving between two places rather than a digit of the number it
   passes over, and as text it flattened into that number. And an inline box
   cannot be transformed, so the mark that slides has to be one that can. */
.cross__index--flying {
    display: inline-block;
    font-size: .58em;
    vertical-align: super;
}

.cross__index--flying::before { content: attr(data-order); }

/* THE ROOT, GROWN RATHER THAN SWITCHED ON --------------------------------

   The radical is built around its number from the start and written as the swap
   lands, in the order a pen writes it: --room slides the radicand right to open
   the space, --sign then uncovers the sign from its own left tick, and --bar
   runs the bar out across the number. Each runs 0 to 1 in turn.

   Its own order is never drawn. The order that ends up over the sign is the one
   that slid off the base, so a second one faded in underneath it would be the
   same mark twice — the slot is kept only to say where the sliding one lands. */

.cross__end--rooted .rad { display: inline-block; padding-left: calc(1.1em * var(--room, 0)); }
.rad__index--slot { opacity: 0; }

/* The sign is uncovered from its own left tick rather than faded up whole: the
   path is one unit long, and --sign is how much of it has been written. */
.cross__end--rooted .rad__sign path {
    stroke-dasharray: 1;
    stroke-dashoffset: calc(1 - var(--sign, 0));
}

/* The bar over the radicand is normally the top border of .rad__over, and a
   border cannot be faded without fading the number underneath it. Here it is
   drawn as its own mark in the border's place instead. */
.cross__end--rooted .rad__over { position: relative; border-top-color: transparent; }

/* and the bar runs out from where the sign finishes, across the radicand */
.cross__bar {
    position: absolute;
    top: -.1em;
    right: 0;
    left: 0;
    height: .1em;
    background: currentColor;
    transform: scaleX(var(--bar, 0));
    transform-origin: left center;
}

/* SEVEN SIXES, AS A RECTANGLE -------------------------------------------

   A static figure. The whole groups are a 7 by 6 rectangle of unit squares and
   the remainder is five more that cannot make an eighth column; the picture is
   the statement 7 x 6 + 5 = 47 with nothing left to animate. It is laid out by
   the grid algorithm rather than positioned, because nothing here has to move. */

.grid {
    margin: 24px 0;
    padding: 22px 26px;
    border: 2px solid #d9e2ec;
    border-radius: 18px;
    background: #f8fbfd;
}

.grid__figure { display: flex; gap: 18px; align-items: center; justify-content: center; }

/* seven across, six down — the shape of 7 x 6 */
.grid__rect {
    display: grid;
    gap: 5px;
    grid-template-columns: repeat(7, 34px);
    grid-auto-rows: 34px;
}

/* the five that will not fill an eighth column, stacked as the start of one */
.grid__spares {
    display: grid;
    gap: 5px;
    grid-template-columns: 34px;
    grid-auto-rows: 34px;
    align-self: start;
}

.grid__cell {
    box-sizing: border-box;
    border: 2px solid #5d91b0;
    border-radius: 3px;
    background: #dfeaf2;
}

/* The remainder is a different colour and a different position — never colour
   alone, since it also stands outside the rectangle and the caption names it. */
.grid__cell--spare { border-color: #b86821; background: #fbeeda; }

.grid__plus {
    color: #b86821;
    font: 700 1.6rem/1 ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace;
}

.grid__caption {
    margin: 16px auto 0;
    max-width: 34em;
    color: #243a45;
    font-size: .95rem;
    line-height: 1.55;
    text-align: center;
}

/* REDUCED MOTION ---------------------------------------------------------

   The card is never pinned and never scrubbed: it draws its finished state and
   stays where it sits in the page. */

@media (prefers-reduced-motion: reduce) {
    .inv-scene.is-ready { height: auto; min-height: 0; }

    .inv-scene__sticky {
        position: relative;
        height: auto;
        transform: none !important;
    }

    .inv-scene__dot { transition: none; }
}
