/* Add and Subtract to 100 activity styles.
 * 1em = 1/50th of activity width (800px / 50 = 16px).
 * Available height: 450px ≈ 28.125em (minus nav ~2em → ~26em usable).
 * Tens block SVG aspect ratio: 40.45 × 350.4 ≈ 1 : 8.66
 */

/* -------------------------------------------------------------------------
   Options form — suppress borders on inner (nested) fieldsets
   The outer Activity / Accessibility fieldsets keep their default browser
   border; the inner fieldsets (Operation, Questions, Number range, etc.)
   that sit inside the options table do not have visible borders in Flash.
   ------------------------------------------------------------------------- */
fieldset fieldset {
    border: none;
    padding: 0;
    margin: 0;
}

/* -------------------------------------------------------------------------
   Welcome screen
   -------------------------------------------------------------------------
   Flash welcome: "77 in blocks". 10 ten-columns (3 dashed phantoms + 7 solid
   blue), with the overall block ~square. Right column: a 10-row units stack
   with 3 dashed-empty at the TOP (9,8,7) and 7 solid orange below (6..0),
   so the orange stack sits at the bottom. A horizontal blue rule above and
   a vertical blue rule between tens and units. Number labels (0-9) align to
   the BOTTOM of each cell (the "line"), not the gap between cells. */

/* "Doorway" brand label on the welcome screen.
   Shared style sets color:#555 (grey) — override to black to match
   Flash. */
body.dw-screen-welcome #dwWelcomeScreen .dw-app-label {
    color: #000;
}

/* tenBlue.svg native aspect ratio 1:8.66 (40.45 × 350.4). To make the
   10-ten block visually square we need height ≈ 10× column-width.
   Each ten-image stretches modestly (8.66→10) but stays recognisable.
   Unit cells are sized so 10 of them stack to exactly the tens height,
   keeping the units column's bottom aligned with the tens column's bottom. */
.aat100-welcome-demo {
    --aat100-ten-w: 1.27em;            /* ~15% smaller than 1.5em */
    --aat100-ten-h: calc(var(--aat100-ten-w) * 10);
    --aat100-unit-h: calc(var(--aat100-ten-h) / 10);
    --aat100-phantom-border: 0.1em;    /* thinner dashed outline */
    --aat100-blue: #1d4ec4;            /* brighter blue to match activity screen */
    --aat100-rule: 0.18em;

    display: flex;
    flex-direction: column;
    align-items: center;
    margin: var(--dw-space-tight) auto var(--dw-space-narrow);
    width: max-content;
    max-width: 100%;
    max-height: 19em;
}

/* Horizontal blue rule above the composition. Rounded ends: border-radius
   = half the border thickness so the line-caps become semicircles. */
.aat100-welcome-rules {
    border-top: var(--aat100-rule) solid var(--aat100-blue);
    border-top-left-radius: calc(var(--aat100-rule) / 2);
    border-top-right-radius: calc(var(--aat100-rule) / 2);
}

/* Cross row: left col (numeral + tens) | (vertical rule) | right col
   (numeral + units). Vertical rule = right border of the left column,
   so it spans the full row height up to the horizontal rule. */
.aat100-welcome-cross-row {
    display: flex;
    align-items: flex-end;
    gap: 0;
}

.aat100-welcome-left-col {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    border-right: var(--aat100-rule) solid var(--aat100-blue);
    /* Rounded caps on the vertical rule (top-right + bottom-right corners of
       the left column own the visible right border). */
    border-top-right-radius: calc(var(--aat100-rule) / 2);
    border-bottom-right-radius: calc(var(--aat100-rule) / 2);
}

.aat100-welcome-right-col {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
}

/* "7 7" numerals sit on top of their column's blocks (inside the cross). */
.aat100-welcome-numeral {
    font-size: var(--dw-font-size-subheading);
    line-height: 1.1;
    font-weight: normal;
    color: #000;
    padding: 0 0.15em;
}

.aat100-welcome-numeral-tens  { align-self: flex-end;   margin-right: 0.1em; }
.aat100-welcome-numeral-units { align-self: flex-start; margin-left: 0.1em; }

/* TENS row — 10 cells (3 dashed phantoms + 7 solid bars), zero gap. */
.aat100-welcome-tens-col {
    display: flex;
    align-items: flex-end;
    gap: 0;
    height: var(--aat100-ten-h);
}

/* Higher-specificity selector defeats shared/doorway.css's
   `div.welcome_image img { width: 100%; height: 100% }` rule. */
div.welcome_image img.aat100-welcome-ten {
    width: var(--aat100-ten-w);
    height: var(--aat100-ten-h);
    display: block;
    flex: 0 0 auto;
}

/* Phantom (empty) tens-bar: same footprint as a tenBlue, dashed outline.
   Adjacent phantoms overlap by one border-width so the dashed strokes
   collapse onto each other rather than leaving a visible gap. The first
   solid blue ten also pulls left by the same amount to butt against the
   last phantom's dashed edge. */
.aat100-welcome-ten-phantom {
    width: var(--aat100-ten-w);
    height: var(--aat100-ten-h);
    border: var(--aat100-phantom-border) dashed var(--dw-color-border-muted);
    box-sizing: border-box;
    flex: 0 0 auto;
}

.aat100-welcome-ten-phantom + .aat100-welcome-ten-phantom,
.aat100-welcome-tens-col img.aat100-welcome-ten:first-of-type {
    margin-left: calc(var(--aat100-phantom-border) * -1);
}

/* UNITS column — 10 rows, top→bottom = 9..0. */
.aat100-welcome-unitstack {
    display: flex;
    flex-direction: column;
    gap: 0;
}

.aat100-welcome-unit-row {
    display: flex;
    align-items: flex-end;          /* anchor label to cell baseline (line) */
    gap: 0.18em;
    height: var(--aat100-unit-h);
}

.aat100-welcome-unit-cell {
    width: var(--aat100-ten-w);
    height: 100%;
    box-sizing: border-box;
    flex: 0 0 auto;
}

/* Label sits at the bottom edge of the cell — aligns with the "line"
   between two cells rather than centred in the gap. */
.aat100-welcome-unit-label {
    font-size: 0.7em;
    font-weight: normal;
    line-height: 1;
    color: #000;
    transform: translateY(0.3em);   /* half-cell shift down */
}

/* Empty (dashed grey) units — positions 9, 8, 7. */
.aat100-welcome-unit-empty {
    border: var(--aat100-phantom-border) dashed var(--dw-color-border-muted);
}

/* Solid orange units (unitOrange palette: fill #ff9b06, stroke #d55500). */
.aat100-welcome-unit-lit {
    background: #ff9b06;
    border: 0.2em solid #d55500;
}

/* -------------------------------------------------------------------------
   Activity screen — new layout
   -------------------------------------------------------------------------
   Top row: back-pencil + "Make the Number" title (left), "Question: 1 of 10"
   (right). Subtitle row: "Make 20" with a small mouth icon to the right.
   Work area: 2-column grid (tens | units) with vertical blue divider running
   through the t/u header and the working area. Below the work area: +/-
   buttons under each column, plus Done bottom-right. */

/* Flex-column skeleton (display / direction / width / height / box-sizing)
   comes from .dw-activity-screen in shared/doorway.css. This rule keeps
   only what's specific to add-and-subtract-100. */
.aat100-screen {
    /* Padding-top is minimal — title sits flush adjacent to the navigation
       header (settings/fullscreen icons). Instructions sit below the title
       with their own top padding so they clear the nav bar without forcing
       the title down. */
    padding: var(--dw-space-tight) 0.8em var(--dw-space-snug);
    overflow: hidden;
    position: relative;
    /* Blue rule colour — Flash uses ~#1d4ec4 for the horizontal/vertical
       guides. Same variable drives the t/u divider and the horizontal
       rule below the t/u header band. */
    --aat100-blue: #1d4ec4;
    --aat100-rule: 0.17em;
    /* Tens column width tuned so the 10-column grid is comparable in width
       to Flash's tens block (~57% of stage). With 50em stage and a 7fr/3fr
       work split, the tens column gets ~33em; 10 × 2.55em + 9 × 0.12em ≈
       26.6em fills most of it (with the grid anchored flush against the
       central divider via align-self: flex-end). */
    /* Unit cell side = tens column width = 1 unit square. The 10-unit tall
       tens grid and 10-cell units stack must fit vertically inside the
       activity work area (~17em after chrome). 1.6em × 10 = 16em fits. */
    --aat100-ten-w: 1.6em;            /* tens column width = 1 unit square */
    --aat100-unit-size: 1.6em;        /* units cell side (height = width) */
    --aat100-ten-h: calc(var(--aat100-unit-size) * 10);
    --aat100-work-cols-ratio: 6fr 4fr;
    /* Thinner dashed strokes for the phantom slots / units ruler. */
    --aat100-dash: 0.1em;
    /* Shared button palette. Used by the block-builder +/- controls, the
       writtensums +/- controls, and the Done button. Grey gradient with
       a dark neutral outline — replaces the earlier lavender/blue Flash
       sprite match. All +/- variants share one size + one radius so they
       read as the same control. Done keeps its own radius. */
    --aat100-btn-size:      2em;
    --aat100-btn-font-size: 2em;
    --aat100-btn-radius:    0.08em;
    --aat100-btn-border:    0.08em solid #555;
    /* Lighter than pure grey, with a whisper of blue in the highlight and
       bottom shadow — reads as neutral chrome, not a coloured chip. */
    --aat100-btn-bg:        linear-gradient(180deg, #f7f9fe 0%, #eef1f9 15%, #d6dbe9 85%, #b0b8ce 100%);
    --aat100-btn-bg-hover:  linear-gradient(180deg, #ffffff 0%, #e6ebf5 60%, #c0c8dd 100%);
    --aat100-done-radius:   0.18em;
    --aat100-done-padding:  0.25em 0.9em;
}

/* Top row: back pencil + title (left), question counter (right). Top
   padding leaves room for the absolute-positioned nav-bar icons (gear /
   fullscreen / audio), which occupy ~6em on the left. The title shifts
   right by that amount so it doesn't overlap them. */
.aat100-top-row {
    display: flex;
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
    flex-shrink: 0;
    gap: 0.8em;
    min-height: 2em;
    padding-left: 10em;
}

.aat100-top-left {
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: var(--dw-space-comfy);
}

.aat100-back-btn {
    /* shared .pencil_btn already sized; keep ~2em high to fit the top row */
    transform: scale(0.85);
    transform-origin: left center;
}

/* Activity title — same size across all sub-activities (Explore / Make /
   What's / Sums) so the top row is visually consistent. */
.aat100-screen-title {
    margin: 0;
    font-size: var(--dw-font-size-subheading);
    font-family: "Jotter Primary", sans-serif;
    font-weight: normal;
    color: var(--dw-color-text-primary);
    line-height: 1.1;
    white-space: nowrap;
}

.aat100-question-counter {
    margin: 0;
    font-size: 1em;
    font-family: "Jotter Primary", sans-serif;
    color: var(--dw-color-text-primary);
    white-space: nowrap;
}

/* Instructions row — sits below the title and now hosts the replay-mouth
   icon to the right of the subtitle text (matches Flash composition: the
   prompt text and the speaker glyph share a single row, both above the
   blue rule). The row stays a flex container so the mouth tracks the end
   of the text rather than floating at a fixed x-position. */
.aat100-subtitle-row {
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: var(--dw-space-default);
    margin-top: var(--dw-space-snug);
    min-height: 1.6em;
    flex-shrink: 0;
    /* Align with the title above (which sits behind the nav-bar icons via
       .aat100-top-row's padding-left: 10em). */
    padding-left: 10em;
}

.aat100-subtitle {
    margin: 0;
    font-size: 1em;
    font-family: "Jotter Primary", sans-serif;
    font-weight: normal;
    color: var(--dw-color-text-primary);
    line-height: 1.15;
    white-space: normal;
    /* Cap width so text doesn't run past the t|u divider (max-width is
       set explicitly on .aat100-subtitle later in this file). */
    box-sizing: border-box;
}
.aat100-subtitle:empty + .aat100-replay-inline { display: none; }

/* Replay-mouth, inline variant. Sits immediately to the right of the
   subtitle text. The button itself is just a clickable wrapper around the
   small mouth glyph (mouth.png) — no border/background. */
.aat100-replay-inline {
    width: 1.8em;
    height: 1.4em;
    flex-shrink: 0;
    /* Establish stacking context so the sums-mode transforms (which
       overlay the visible mouth on top of the work area / horizontal
       rule) don't leave the button hit-target sitting behind a
       higher-z-index sibling pseudo (`.aat100-work::before` uses z-index:
       1). Without this the visible mouth is unclickable in writtensums
       because the horiz rule pseudo overlaps its transformed footprint. */
    position: relative;
    z-index: 5;
}

/* Sum text (sums modes) sits above the work area. */
.aat100-sum-text {
    font-size: var(--dw-font-size-subheading);
    font-weight: bold;
    color: #224;
    text-align: center;
    margin: 0;
    min-height: 0;
    flex-shrink: 0;
}
.aat100-sum-text:empty { min-height: 0; }

/* -------------------------------------------------------------------------
   Work area: 2-column grid (tens | units) with vertical blue divider that
   spans the t/u header band and the working area.
   ------------------------------------------------------------------------- */
.aat100-work {
    flex: 1;
    min-height: 0;
    display: grid;
    grid-template-columns: var(--aat100-work-cols-ratio);
    grid-template-rows: 1fr auto;
    column-gap: 0;
    row-gap: 0;
    position: relative;
    /* Horizontal blue rule below the t/u header band (drawn as the column
       background — see .aat100-work-tens / .aat100-work-units). */
}

/* Vertical blue rule (between tens/units columns) — pseudo-element pinned
   to the right edge of the LEFT column. Wider than the horizontal rule per
   Flash. Rounded caps. `.aat100-work-tens` inherits `position: relative`
   from `.aat100-work-col`, so the absolute pseudo anchors to the column.
   Negative `top` overshoots into the t/u header band so the rule visually
   crosses the letters (Flash faithful). */
.aat100-work-tens::before {
    content: "";
    position: absolute;
    top:    -2.7em;
    bottom: 0em;
    right:  -0.1em;
    width:  var(--aat100-rule);
    background: var(--aat100-blue);
    border-radius: calc(var(--aat100-rule) / 2);
    pointer-events: none;
    z-index: 1;
}

/* Horizontal blue rule (below the t/u header band) — pseudo-element on the
   .aat100-work container. One continuous line running across the working
   area; anchored to .aat100-work (position: relative) whose full width
   matches the .aat100-screen content-box. Vertical position sits just
   below the t/u header row (header height ≈ 0.25em + 1.4em). */
.aat100-work::before {
    content: "";
    position: absolute;
    top:    calc(0.25em + var(--dw-font-size-large));
    left:   10.5em;
    right:  14em;
    height: var(--aat100-rule);
    background: var(--aat100-blue);
    border-radius: calc(var(--aat100-rule) / 2);
    pointer-events: none;
    z-index: 1;
}

.aat100-work-col {
    display: flex;
    flex-direction: column;
    align-items: center;
    position: relative;
    min-height: 0;
    min-width: 0;
    padding: 0;
    box-sizing: border-box;
}

/* "t" / "u" header row — Jotter handwriting font, NOT italic per Flash
   (the original glyphs sit upright). The horizontal blue rule below this
   band is drawn separately as `.aat100-work::before`. Each glyph is
   centred horizontally over its column's visual midline (the block area
   plus +/− controls underneath), not biased toward the central divider. */
.aat100-tu-header {
    font-family: "Jotter Primary", sans-serif;
    font-style: normal;
    font-size: var(--dw-font-size-large);
    color: var(--dw-color-text-primary);
    line-height: 1;
    width: 100%;
    padding: 0.1em 0 0.15em;
    text-align: center;
    box-sizing: border-box;
}

/* Per-column horizontal offset for the "t" / "u" glyphs. Positive shifts
   the tens glyph rightward toward the central divider; the units glyph
   uses a negative shift to mirror. translateX keeps the header's
   text-align: center intact. */
.aat100-work-tens  .aat100-tu-label {
    display: inline-block;
    transform: translateX(9.7em);
}
.aat100-work-units .aat100-tu-label {
    display: inline-block;
    transform: translateX(-6.2em);
}

/* Big-digit row: large "0" current value (+ mouthTotal icon on the units side).
   Tens-column instance right-aligns toward the central divider; units-column
   instance left-aligns toward it — so both digits sit close to the divider. */
.aat100-units-digit-row {
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: var(--dw-space-comfy);
    padding: 0.1em 0;
    min-height: 1.6em;
    width: 100%;
}
.aat100-work-tens  .aat100-units-digit-row { justify-content: flex-end;   padding-right: 0.3em; }
.aat100-work-units .aat100-units-digit-row { justify-content: flex-start; padding-left:  0.3em; }

.aat100-units-big-digit {
    /* Borderless, Jotter handwriting font — the digit reads as the
       handwritten "t"/"u" headers above it, with no visible cell outline
       (per Flash, which set the running-total textfield's border to false). */
    font-family: "Jotter Primary", sans-serif;
    font-size: var(--dw-font-size-heading);
    line-height: 1;
    color: var(--dw-color-text-primary);
    text-align: center;
    min-width: 1em;
    padding: 0.05em var(--dw-space-tight);
    border: none;
    background: transparent;
    box-sizing: border-box;
}

.aat100-tens-digit-row {
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: 0.25em;
    min-height: 2em;
    justify-content: flex-end;
    width: 100%;
}
.aat100-tens-digit-row.hidden_panel { display: none; }

/* -------------------------------------------------------------------------
   Tens column — 10 dashed phantom slots side-by-side (the "empty board").
   Each slot is a tall narrow column with 9 internal horizontal segment
   lines (showing the 10 unit-rows inside a ten). Live tens blocks render
   on top via absolute positioning (#aat100TensCol).
   ------------------------------------------------------------------------- */
.aat100-tens-grid {
    display: grid;
    grid-template-columns: repeat(10, 1fr);
    grid-template-rows: 1fr;
    column-gap: 0;
    align-items: stretch;
    /* Right-aligned against the central vertical divider so the rightmost
       phantom column butts up against the blue rule (matches Flash). */
    align-self: flex-end;
    margin: var(--dw-space-narrow) 0 0 0;
    /* Each phantom column is a tall narrow bar with 1:10 aspect (width:height).
       With 10 columns of 1fr each, the overall grid is 10 unit-widths wide and
       10 unit-heights tall — i.e. square. Driving the grid via aspect-ratio +
       fluid height means the grid fills the available vertical space and the
       width derives from that, guaranteeing each column stays 1:10. */
    flex: 0 1 auto;
    height: 18em;
    max-height: 100%;
    min-height: 0;
    aspect-ratio: 1 / 1;
    width: auto;
    max-width: 100%;
    position: relative;
    box-sizing: border-box;
    /* No CSS border — see the units-col-wrapper comment for the same
       reason: a border would shrink the content area so 10 columns at
       1fr each would no longer line up with the percentage-positioned
       dashed lines, and a live ten-block (width: 10%) would render off
       the column it represents. Draw the outer rectangle as background
       dashed lines at 0% and 100% instead, and keep the 9 internal
       verticals at 10-90%. */
    background:
        linear-gradient(to bottom, var(--dw-color-border-muted) 50%, transparent 50%) 0%   0 / var(--aat100-dash) 0.75em repeat-y,
        linear-gradient(to bottom, var(--dw-color-border-muted) 50%, transparent 50%) 10%  0 / var(--aat100-dash) 0.75em repeat-y,
        linear-gradient(to bottom, var(--dw-color-border-muted) 50%, transparent 50%) 20%  0 / var(--aat100-dash) 0.75em repeat-y,
        linear-gradient(to bottom, var(--dw-color-border-muted) 50%, transparent 50%) 30%  0 / var(--aat100-dash) 0.75em repeat-y,
        linear-gradient(to bottom, var(--dw-color-border-muted) 50%, transparent 50%) 40%  0 / var(--aat100-dash) 0.75em repeat-y,
        linear-gradient(to bottom, var(--dw-color-border-muted) 50%, transparent 50%) 50%  0 / var(--aat100-dash) 0.75em repeat-y,
        linear-gradient(to bottom, var(--dw-color-border-muted) 50%, transparent 50%) 60%  0 / var(--aat100-dash) 0.75em repeat-y,
        linear-gradient(to bottom, var(--dw-color-border-muted) 50%, transparent 50%) 70%  0 / var(--aat100-dash) 0.75em repeat-y,
        linear-gradient(to bottom, var(--dw-color-border-muted) 50%, transparent 50%) 80%  0 / var(--aat100-dash) 0.75em repeat-y,
        linear-gradient(to bottom, var(--dw-color-border-muted) 50%, transparent 50%) 90%  0 / var(--aat100-dash) 0.75em repeat-y,
        linear-gradient(to bottom, var(--dw-color-border-muted) 50%, transparent 50%) 100% 0 / var(--aat100-dash) 0.75em repeat-y,
        /* Top and bottom horizontals — match the units-wrapper edges so
           the two rulers feel like a single composition. */
        linear-gradient(to right, var(--dw-color-border-muted) 50%, transparent 50%) 0 0%   / 0.75em var(--aat100-dash) repeat-x,
        linear-gradient(to right, var(--dw-color-border-muted) 50%, transparent 50%) 0 100% / 0.75em var(--aat100-dash) repeat-x;
}

/* Slots are invisible scaffolding now — the grid container itself draws
   both outer border and internal vertical lines (above). The slot must NOT
   pin a min-width (e.g. `width: var(--aat100-ten-w)`); otherwise its
   intrinsic min-content beats the grid's `aspect-ratio: 1` and the grid
   ends up wider than it is tall. Let the `1fr` columns size the slots
   fluidly so the grid stays a true square. */
.aat100-tens-slot {
    min-width: 0;
    height: 100%;
    border: 0;
    background: transparent;
    box-sizing: border-box;
}

/* Live tens column — absolutely positioned inside the dashed grid so
   live blocks visually replace the dashed phantoms. With row-reverse +
   flex-start, the first appended ten sits at the right edge (against the
   central divider) and each subsequent ten stacks to its LEFT. */
.aat100-tens-col {
    display: flex;
    flex-direction: row-reverse;
    align-items: flex-end;
    justify-content: flex-start;
    gap: 0;
    position: absolute;
    inset: 0;
    pointer-events: none;
}

/* -------------------------------------------------------------------------
   Units column — single dashed slot acting as a "ruler" with 10 unit-cells.
   Number labels (9..0) align to the BOTTOM of each cell (the line). Live
   units blocks render in front (#aat100UnitsCol).
   ------------------------------------------------------------------------- */
.aat100-units-stack {
    display: flex;
    flex-direction: row;
    align-items: stretch;
    gap: var(--dw-space-tight);
    margin-top: var(--dw-space-narrow);
    /* Fluid height: matches the tens-grid sizing rule so both columns share
       a baseline regardless of available vertical space. */
    height: 18em;
    max-height: 100%;
    flex: 0 1 auto;
    min-height: 0;
    transition: transform 0.4s ease-in-out;
    /* Left-aligned in the units column so the ruler sits flush against
       the central blue divider, matching Flash. */
    align-self: flex-start;
}

.aat100-units-stack.aat100-units-shifted {
    transform: translateX(1.75em);
}

.aat100-units-col-wrapper {
    position: relative;
    display: flex;
    align-items: flex-end;
    flex: 0 0 auto;
    /* Each ruler cell is 1:1 (unit width:unit height). Wrapper is 1 cell
       wide and 10 tall ⇒ aspect-ratio 1:10, with width derived from height
       so the ruler stays in lockstep with the (fluid) tens grid. */
    height: 100%;
    aspect-ratio: 1 / 10;
    width: auto;
    box-sizing: border-box;
    /* No CSS border: a real border would shrink the content-area aspect
       ratio away from 1:10, and the unit blocks (sized as 100% × 10% of
       the inner box) would no longer be square. Instead, draw both the
       outer rectangle and the 9 internal segments as background dashed
       lines — 11 horizontal lines at 0%, 10%, … 100% give the same
       visual ruler-box without eating into the geometry. */
    background:
        linear-gradient(to right, var(--dw-color-border-muted) 50%, transparent 50%) 0 0%   / 0.75em var(--aat100-dash) repeat-x,
        linear-gradient(to right, var(--dw-color-border-muted) 50%, transparent 50%) 0 10%  / 0.75em var(--aat100-dash) repeat-x,
        linear-gradient(to right, var(--dw-color-border-muted) 50%, transparent 50%) 0 20%  / 0.75em var(--aat100-dash) repeat-x,
        linear-gradient(to right, var(--dw-color-border-muted) 50%, transparent 50%) 0 30%  / 0.75em var(--aat100-dash) repeat-x,
        linear-gradient(to right, var(--dw-color-border-muted) 50%, transparent 50%) 0 40%  / 0.75em var(--aat100-dash) repeat-x,
        linear-gradient(to right, var(--dw-color-border-muted) 50%, transparent 50%) 0 50%  / 0.75em var(--aat100-dash) repeat-x,
        linear-gradient(to right, var(--dw-color-border-muted) 50%, transparent 50%) 0 60%  / 0.75em var(--aat100-dash) repeat-x,
        linear-gradient(to right, var(--dw-color-border-muted) 50%, transparent 50%) 0 70%  / 0.75em var(--aat100-dash) repeat-x,
        linear-gradient(to right, var(--dw-color-border-muted) 50%, transparent 50%) 0 80%  / 0.75em var(--aat100-dash) repeat-x,
        linear-gradient(to right, var(--dw-color-border-muted) 50%, transparent 50%) 0 90%  / 0.75em var(--aat100-dash) repeat-x,
        linear-gradient(to right, var(--dw-color-border-muted) 50%, transparent 50%) 0 100% / 0.75em var(--aat100-dash) repeat-x,
        /* Left & right edge verticals — same dash cadence as the tens-grid
           verticals so the two rulers visually tile. */
        linear-gradient(to bottom, var(--dw-color-border-muted) 50%, transparent 50%) 0%   0 / var(--aat100-dash) 0.75em repeat-y,
        linear-gradient(to bottom, var(--dw-color-border-muted) 50%, transparent 50%) 100% 0 / var(--aat100-dash) 0.75em repeat-y;
}

.aat100-units-col {
    display: flex;
    flex-direction: column-reverse;
    align-items: stretch;
    gap: 0;
    flex-shrink: 0;
    width: 100%;
    /* No min-width: the wrapper's aspect-ratio (1:10) drives the column
       width from its height; pinning a min-width here would beat that and
       leave the cell wider than 1/10th of the ruler height. */
    min-width: 0;
    height: 100%;
    position: relative;
}

/* Ruler labels: 9..0 — each label aligned to the BOTTOM edge of its
   own cell (the line between cells), NOT centred in the gap between
   adjacent cell lines.
   Layout: 10-row CSS grid where each row matches one unit cell; each
   <span> is anchored to the BOTTOM of its row so it visually sits on
   the line that separates that cell from the one below. */
.aat100-units-numbers {
    display: grid;
    /* Fluid rows: 10 equal-fraction rows match the ruler wrapper's segments. */
    grid-template-rows: repeat(10, 1fr);
    align-items: end;
    height: 100%;
    font-family: "Jotter Primary", sans-serif;
    color: var(--dw-color-text-secondary);
    line-height: 1;
    box-sizing: border-box;
    padding: 0;
}

.aat100-units-numbers span {
    display: block;
    font-size: 0.65em;
    /* Centre the digit vertically on the line between cells (rather than
       sit it above or below). Each <span> is anchored to the BOTTOM of
       its row (align-items: end); translating down by 50% of its own
       height places the digit's vertical centre on the cell's bottom
       edge — i.e. on the dashed line itself. */
    transform: translateY(50%);
}

/* +/- block controls — sit BELOW each column. */
.aat100-block-controls {
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: var(--dw-space-snug);
    margin-top: var(--dw-space-narrow);
    flex-shrink: 0;
}
/* What's-the-Number mode hides the block-builder +/− pair entirely (input
   moves to the inline t/u row above). Use visibility: hidden — NOT
   display: none — so the row still occupies its ~2em of vertical space
   below each column. Otherwise the .aat100-tens-grid + .aat100-units-stack
   (which have `height: 18em; max-height: 100%`) absorb the freed vertical
   room in WTN mode and render visibly taller than in Explore/Make/sums
   modes. Buttons under visibility:hidden are removed from tab order + the
   a11y tree, so keyboard/switch users still can't reach them. This selector
   only matches block-controls, and block-controls are only hidden in WTN
   — so the vertical-space preservation is naturally WTN-scoped. */
.aat100-block-controls.hidden_panel { display: flex; visibility: hidden; }

.aat100-tens-controls {
    /* Right-align under the tens block (which is right-anchored against
       the central divider — see .aat100-tens-grid margin: 0 0 0 auto). */
    align-self: flex-end;
    margin-right: 0;
}

.aat100-units-controls {
    /* Left-align under the units column (which sits flush left in the
       narrow right pane — see .aat100-units-stack default flex layout). */
    align-self: flex-start;
}

/* Done button — bottom-right of the activity screen, beside (not on top of)
   the units +/- controls. Shares the +/- palette (--aat100-btn-*) but
   keeps its own softer corner radius and horizontal padding. */
.aat100-done-btn {
    position: absolute;
    /* Shifted up so we clear the bottom-right scan-hud chip
       (.dw-scan-hud--bottom-right at bottom:0.35em, ~0.6em tall). */
    bottom: 1.3em;
    right: 0.6em;
    z-index: 2;
    background: var(--aat100-btn-bg);
    border: var(--aat100-btn-border);
    border-radius: var(--aat100-done-radius);
    padding: var(--aat100-done-padding);
    font-family: "Jotter Primary", sans-serif;
    font-size: var(--dw-font-size-subheading);
    color: var(--dw-color-text-primary);
}
@media (hover: hover) {
    .aat100-done-btn:hover:not(:disabled) {
        background: var(--aat100-btn-bg-hover);
    }
}

/* -------------------------------------------------------------------------
   Block images
   ------------------------------------------------------------------------- */
.aat100-ten-block {
    /* Fill one column of the 10-column tens grid. The grid is square and
       its columns are 1fr each, so a block at 10% width × 100% height
       matches the dashed phantom slot underneath exactly. Sizing by % of
       the parent (not by --aat100-ten-w em hint) means the block tracks
       the actual rendered column width, which is now driven by
       aspect-ratio rather than the em variable. */
    height: 100%;
    width: 10%;
    display: block;
    flex-shrink: 0;
    opacity: 1;
}

.aat100-ten-block.aat100-fading-in {
    animation: aat100FadeIn 0.25s ease-in-out;
}

.aat100-ten-block.aat100-fading-out {
    animation: aat100FadeOut 0.2s ease-in-out forwards;
    pointer-events: none;
}

.aat100-unit-block {
    /* Each unit block fills exactly 1/10 of the parent ruler height — the
       ruler is 10 cells tall and this block must occupy one cell regardless
       of how many other blocks are stacked above. */
    width: 100%;
    height: 10%;
    flex: 0 0 10%;
    display: block;
    opacity: 1;
}

.aat100-unit-block.aat100-fading-in {
    animation: aat100FadeIn 0.18s ease-in-out;
}

.aat100-unit-block.aat100-fading-out {
    animation: aat100FadeOut 0.15s ease-in-out forwards;
    pointer-events: none;
}

@keyframes aat100FadeIn {
    from { opacity: 0; }
    to   { opacity: 1; }
}

@keyframes aat100FadeOut {
    from { opacity: 1; }
    to   { opacity: 0; }
}

/* Trade animations — sideways slide + fade for the units↔tens borrow visual. */
.aat100-ten-block.aat100-trading-out {
    animation: aat100TradeOutTen 0.7s ease-in-out forwards;
    pointer-events: none;
}

/* Trade-out displaces the block by ~2 ten-column widths so the visual
   carry feels distinct at any column-width tuning. */
@keyframes aat100TradeOutTen {
    0%   { transform: translateX(0);                              opacity: 1; }
    55%  { transform: translateX(calc(var(--aat100-ten-w) * 2));  opacity: 1; }
    100% { transform: translateX(calc(var(--aat100-ten-w) * 2));  opacity: 0; }
}

.aat100-ten-block.aat100-trading-in {
    animation: aat100TradeInTen 0.7s ease-in-out;
}

@keyframes aat100TradeInTen {
    0%   { transform: translateX(calc(var(--aat100-ten-w) * 2));  opacity: 0.5; }
    40%  { transform: translateX(calc(var(--aat100-ten-w) * 2));  opacity: 1;   }
    100% { transform: translateX(0);                              opacity: 1;   }
}

/* Original blocks — darkened when the sums-mode child moves from step 1
   (build the first number) to step 2 (PLUS branch only — see below for
   MINUS). New blocks that appear during step 2 stay full-colour so the
   child can distinguish what they've added or what remains.

   Flash uses a 40% black overlay (see comboBlockShaded.svg's
   #000000 / fill-opacity="0.4" fills). `filter: brightness(0.6)`
   reproduces that exactly: 0.6 × colour === 0.6 × colour + 0.4 × black. */
.aat100-ten-block.aat100-block-original,
.aat100-unit-block.aat100-block-original {
    filter: brightness(0.6);
}

/* MINUS-mode fade-in-place: blocks the child subtracts don't leave the
   DOM — they get `.aat100-block-consumed` and render as the same block
   minus its fill (stroke-only "-ghost.svg" sibling per palette,
   generated by scripts/utils/make_ghost_block_svgs.py). Stroke width,
   colour and corner rounding come from the SVG itself, so live and
   consumed blocks stay in visual lockstep automatically. Alpha fades
   the whole element to read as "removed" rather than "dimmed".
   Matches Flash's fadeOutAnim with tm / um shadow at _alpha=45
   (frame_05.as:1869-1873, 375-382). */
.aat100-ten-block.aat100-block-consumed[src*="tenBlue"]      { content: url('pictures/tenBlue-ghost.svg'); }
.aat100-ten-block.aat100-block-consumed[src*="tenOrange"]    { content: url('pictures/tenOrange-ghost.svg'); }
.aat100-ten-block.aat100-block-consumed[src*="tenLightBlue"] { content: url('pictures/tenLightBlue-ghost.svg'); }
.aat100-unit-block.aat100-block-consumed[src*="unitOrange"]  { content: url('pictures/unitOrange-ghost.svg'); }
.aat100-unit-block.aat100-block-consumed[src*="unitGreen"]   { content: url('pictures/unitGreen-ghost.svg'); }
.aat100-unit-block.aat100-block-consumed[src*="unitGrey"]    { content: url('pictures/unitGrey-ghost.svg'); }
.aat100-unit-block.aat100-block-consumed[src*="unitWhite"]   { content: url('pictures/unitWhite-ghost.svg'); }
.aat100-ten-block.aat100-block-consumed,
.aat100-unit-block.aat100-block-consumed {
    opacity: 0.55;
    filter: none;
}

/* Carried ten — a stack of 10 tens-coloured mini-unit cells, so the
   child reads "10 units bundled" while keeping the ten's colour identity.
   Cells that originated from darkened step-1 units keep the same darken
   overlay via .aat100-block-original — see .aat100-ten-carried-cell. */
.aat100-ten-block.aat100-ten-carried {
    display: flex;
    flex-direction: column-reverse;
    padding: 0;
    background: none;
    box-sizing: border-box;
}
.aat100-ten-carried-cell {
    /* Match the unit-block stroke visually: unitOrange.svg has stroke
       ~17% of its side, so with each cell = --aat100-ten-w (≈1.6em), a
       border of 0.22em reads as roughly the same weight. Fill / stroke
       colours are tenBlue.svg's exact values. */
    flex: 0 0 10%;
    width: 100%;
    background-color: #2c40f4;
    border: 0.22em solid #00136a;
    box-sizing: border-box;
}
.aat100-ten-carried-cell.aat100-block-original {
    filter: brightness(0.6);
}

/* Extra units column — appears to the LEFT of the units column when the
   child triggers a borrow in minus step 2. Holds 10 real solid unit-blocks
   (populated by populateBorrowExtraColumn); child then consumes them one
   at a time on subsequent -Unit presses. Wrapper is empty (children hidden)
   outside of borrow, so nothing renders until populate. */
.aat100-extra-units-col {
    display: flex;
    flex-direction: column-reverse;
    align-items: stretch;
    gap: 0;
    position: absolute;
    bottom: 0;
    /* Sit immediately to the LEFT of the units-col wrapper, with a small
       visible gap. -100% = one wrapper-width to the left (flush); the
       -0.15em nudge leaves a hair of daylight between extra and real. */
    left: calc(-100% - 0.15em);
    width: 100%;
    height: 100%;
    pointer-events: none;
}
/* Combo block: 1×10 outlined unit strip during ±Unit trade. Fills the
   units column exactly via fluid % geometry so it scales with the
   actual rendered column. */
.aat100-combo-block {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    display: block;
    pointer-events: none;
    opacity: 0.85;
}

.aat100-combo-block.aat100-combo-fading {
    animation: aat100ComboFade 0.7s ease-in-out forwards;
}

@keyframes aat100ComboFade {
    0%   { opacity: 0.85; transform: translateY(0); }
    40%  { opacity: 0.7;  transform: translateY(0); }
    100% { opacity: 0;    transform: translateY(-0.3em); }
}

/* -------------------------------------------------------------------------
   Digit boxes (kept for written-sums mode)
   ------------------------------------------------------------------------- */
.aat100-digit-box {
    width: 1.7em;
    height: 1.7em;
    border: 0.12em solid var(--dw-color-border-muted);
    border-radius: 0.15em;
    background: #fff;
    box-sizing: border-box;
    display: flex;
    align-items: center;
    justify-content: center;
    font-family: Georgia, "Times New Roman", serif;
    font-size: var(--dw-font-size-subheading);
    font-weight: normal;
    color: var(--dw-color-text-primary);
    line-height: 1;
    flex-shrink: 0;
}

.aat100-digit-box.aat100-digit-running {
    border-color: #000;
    border-width: 0.16em;
    font-weight: bold;
}
.aat100-digit-box.aat100-digit-tens.aat100-digit-running { border-color: #1d3f7a; }
.aat100-digit-box.aat100-digit-units.aat100-digit-running { border-color: #1d3f7a; }

/* Row-3 +/- buttons (writtensums answer input). Shares every visual with
   .aat100-block-btn and the WTN inline +/- — all three read as one
   control via the --aat100-btn-* tokens. Font-size stays 1em on the
   button so width/height are decoupled from the glyph size (glyph lives
   in .aat100-btn-glyph). */
.aat100-digit-pm-btn {
    width:  var(--aat100-btn-size);
    height: var(--aat100-btn-size);
    aspect-ratio: 1 / 1;
    border-radius: var(--aat100-btn-radius);
    border: var(--aat100-btn-border);
    background: var(--aat100-btn-bg);
    padding: 0;
    margin: 0 0.1em;
    font-family: "Jotter Primary", sans-serif;
    font-size: 1em;
    font-weight: normal;
    line-height: 1;
    color: var(--dw-color-text-primary);
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transition: background 0.15s, transform 0.1s;
    flex-shrink: 0;
}
@media (hover: hover) {
    .aat100-digit-pm-btn:hover:not(:disabled) {
        background: var(--aat100-btn-bg-hover);
        transform: scale(1.05);
    }
}
.aat100-digit-pm-btn:active:not(:disabled) { transform: scale(0.95); }
.aat100-digit-pm-btn:focus-visible {
    outline: 0.18em dotted black;
    outline-offset: 0.1em;
}
.aat100-digit-pm-btn:disabled {
    opacity: 0.35;
    cursor: default;
}
.aat100-digit-pm-btn.hidden_panel { display: none; }

/* Written sums layout — three-row column notation positioned to the right
   of the block grid. Each row is "operator tb ub"; +/- buttons next to
   row-3 digits are revealed only in the guess steps. */
.aat100-written-display.hidden_panel { display: none; }

.aat100-written-display {
    display: flex;
    flex-direction: column;
    gap: 0.15em;
    align-items: flex-start;
    flex-shrink: 0;
    position: absolute;
    /* Upper-right of the activity area, clear of the praise/feedback
       which sits below it. Left expressed as % of stage width so em
       resolving against the element's own (larger) font-size doesn't
       push the column off-screen. */
    top: 4.5em;
    left: 68%;
    z-index: 4;
}

.aat100-written-row {
    display: flex;
    align-items: center;
    gap: 0.25em;
}

.aat100-written-op {
    font-size: var(--dw-font-size-large);
    font-weight: bold;
    min-width: 1em;
    text-align: center;
    color: var(--dw-color-text-primary);
}

.aat100-written-divider {
    border-top: 0.12em solid var(--dw-color-text-strong);
    /* Width spans the two digit boxes + the operator slot. */
    width: 4.3em;
    margin: 0.1em 0 0.1em var(--dw-space-loose);
}

/* Shaded placeholder state for tb1/ub1/tb2/ub2 before they're filled. */
.aat100-digit-box.aat100-wsum-shaded {
    opacity: 0.7;
}

/* Row-2 tens wrapper — keeps the small carry "1" glyph anchored above the
   tens digit box without disturbing the row's flex baseline. Width of the
   wrapper is set from the digit box itself so the glyph sits in the same
   column as the tens digit. */
.aat100-wsum-tens-wrap {
    position: relative;
    display: inline-block;
    line-height: 0;
}

/* Small carry "1" glyph — sits just above the row-2 tens box, fades in
   via animation when JS toggles `.aat100-wsum-carry-visible`. Absolute
   positioning keeps the row-2 flex baseline unaffected. Offset from the
   centred-above anchor nudges the glyph into the top-left corner of the
   ten it labels (Flash-faithful placement). */
.aat100-wsum-carry {
    position: absolute;
    left: 50%;
    bottom: 100%;
    transform: translate(calc(-50% + 1.16em), 2.7em);
    font-family: "Jotter Primary", sans-serif;
    font-size: 0.7em;
    font-weight: normal;
    color: var(--dw-color-text-primary);
    line-height: 1;
    padding-bottom: 0.05em;
    opacity: 0;
    pointer-events: none;
}
.aat100-wsum-carry.aat100-wsum-carry-visible {
    animation: aat100CarryFadeIn 0.3s ease-in-out forwards;
}
@keyframes aat100CarryFadeIn {
    from { opacity: 0; }
    to   { opacity: 1; }
}

/* Row-1 borrow notation — three glyphs shown when the child borrows a
   ten in step 2 of a minus writtensums problem. Staggered fade-ins
   (0/500/1000 ms). Wrappers are inline-block so the row-1 flex baseline
   is unaffected; position:relative anchors the absolutely-positioned
   glyphs to the digit box beneath them (fluid percentage sizing). */
.aat100-wsum-row1-tens-wrap,
.aat100-wsum-row1-units-wrap {
    position: relative;
    display: inline-block;
    line-height: 0;
}

/* Decremented tens numeral (above the crossed-out tens digit) + the
   small "1" borrowed into the units column. Same sizing as the carry "1".
   Both glyphs share the same offset from their centred-above anchor —
   sitting to the top-left of their digit box (Flash-faithful placement). */
.aat100-wsum-borrow-tn1,
.aat100-wsum-borrow-un1 {
    position: absolute;
    left: 50%;
    bottom: 100%;
    transform: translate(calc(-50% + -0.8em), 0.9em);
    font-family: "Jotter Primary", sans-serif;
    font-size: 0.7em;
    font-weight: normal;
    color: var(--dw-color-text-primary);
    line-height: 1;
    padding-bottom: 0.05em;
    opacity: 0;
    pointer-events: none;
    white-space: nowrap;
}

/* Diagonal strike through the row-1 tens digit — a thin dark line drawn
   by a CSS gradient inside the wrapper, sized as a percentage of the
   digit box so it scales with column width. */
.aat100-wsum-borrow-slash {
    position: absolute;
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
    pointer-events: none;
    opacity: 0;
    background: linear-gradient(
        to bottom right,
        transparent 0%,
        transparent calc(50% - 0.06em),
        var(--dw-color-text-primary) calc(50% - 0.06em),
        var(--dw-color-text-primary) calc(50% + 0.06em),
        transparent calc(50% + 0.06em),
        transparent 100%
    );
}

/* Staggered fade-in delays (0 / 500 / 1000 ms). Same 300 ms fade
   duration as the plus-carry glyph for consistency. */
.aat100-wsum-borrow-slash.aat100-wsum-borrow-visible {
    animation: aat100CarryFadeIn 0.3s ease-in-out 0s forwards;
}
.aat100-wsum-borrow-tn1.aat100-wsum-borrow-visible {
    animation: aat100CarryFadeIn 0.3s ease-in-out 0.5s forwards;
}
.aat100-wsum-borrow-un1.aat100-wsum-borrow-visible {
    animation: aat100CarryFadeIn 0.3s ease-in-out 1s forwards;
}

/* The +/- buttons inside the row-3 units/tens inputs sit to the RIGHT
   of the digit box (DOM order: digit → + → −). The whole tens-input +
   units-input cluster in row 3 stays inline so the digits stay aligned
   with rows 1 and 2. */
.aat100-wsum-tens-input,
.aat100-wsum-units-input {
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: 0.1em;
}

/* --- wsum row-3 input (writtensums only) ---------------------------------
   Scoped to writtensums so the geometry doesn't bleed into WTN / other
   modes that share `.aat100-digit-pm-btn`. */
.aat100-screen.aat100-mode-writtensums #aat100WrittenDisplay .aat100-wsum-tens-input,
.aat100-screen.aat100-mode-writtensums #aat100WrittenDisplay .aat100-wsum-units-input {
    flex-direction: row;
    gap: 0.1em;
}
/* Per-widget position — tens and units shift independently. */
.aat100-screen.aat100-mode-writtensums #aat100WrittenDisplay .aat100-wsum-tens-input {
    transform: translate(-4.8em, 0.15em);
}
.aat100-screen.aat100-mode-writtensums #aat100WrittenDisplay .aat100-wsum-units-input {
    transform: translate(-4.75em, 0.15em);
}
.aat100-screen.aat100-mode-writtensums #aat100WrittenDisplay .aat100-wsum-tens-input .aat100-digit-box,
.aat100-screen.aat100-mode-writtensums #aat100WrittenDisplay .aat100-wsum-units-input .aat100-digit-box {
    width:  1.7em;
    height: 1.7em;
}
/* Units input: [digit][+][-] — offset pushes buttons to the right of digit. */
.aat100-screen.aat100-mode-writtensums #aat100WrittenDisplay .aat100-wsum-units-input .aat100-digit-box {
    margin-right: 0.05em;
}
/* Tens input: [+][-][digit] — offset pushes buttons to the left of digit. */
.aat100-screen.aat100-mode-writtensums #aat100WrittenDisplay .aat100-wsum-tens-input .aat100-digit-box {
    margin-left: 0.05em;
}
.aat100-screen.aat100-mode-writtensums #aat100WrittenDisplay .aat100-wsum-tens-input .aat100-digit-pm-btn,
.aat100-screen.aat100-mode-writtensums #aat100WrittenDisplay .aat100-wsum-units-input .aat100-digit-pm-btn {
    width:  1.7em;
    height: 1.7em;
    font-size: var(--dw-font-size-subheading);
}
/* Hidden +/- keep their flex footprint so the digit stays anchored in
   the [+][−][digit] / [digit][+][−] cluster after step 3 confirms and
   the buttons vanish — otherwise the tens digit collapses leftward. */
.aat100-screen.aat100-mode-writtensums #aat100WrittenDisplay .aat100-wsum-tens-input .aat100-digit-pm-btn.hidden_panel,
.aat100-screen.aat100-mode-writtensums #aat100WrittenDisplay .aat100-wsum-units-input .aat100-digit-pm-btn.hidden_panel {
    display: inline-flex;
    visibility: hidden;
    pointer-events: none;
}

/* -------------------------------------------------------------------------
   +/- block controls
   ------------------------------------------------------------------------- */
.aat100-block-btn {
    /* Square Jotter +/- glyph on the shared grey button palette. Sizing
       (--aat100-btn-*) is uniform across every +/- variant so the block-
       builder, writtensums, and WTN inline +/- all read as one control.
       The button keeps font-size at 1em so width/height em units stay
       parent-relative (independent of the glyph size). The glyph itself
       is wrapped in .aat100-btn-glyph and takes --aat100-btn-font-size. */
    width:  var(--aat100-btn-size);
    height: var(--aat100-btn-size);
    aspect-ratio: 1 / 1;
    border-radius: var(--aat100-btn-radius);
    border: var(--aat100-btn-border);
    background: var(--aat100-btn-bg);
    font-family: "Jotter Primary", sans-serif;
    font-size: 1em;
    font-weight: normal;
    line-height: 1;
    color: var(--dw-color-text-primary);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: background 0.15s, transform 0.1s;
    flex-shrink: 0;
}
.aat100-btn-glyph {
    font-size: var(--aat100-btn-font-size);
    line-height: 1;
    /* Optical nudge: '+' / '−' glyphs sit slightly above the geometric
       centre in the Jotter font — lift by half a pixel-ish so the box
       reads as centred. */
    margin-top: -0.05em;
}
@media (hover: hover) {
    .aat100-block-btn:hover:not(:disabled) {
        background: var(--aat100-btn-bg-hover);
        transform: scale(1.05);
    }
}
.aat100-block-btn:active:not(:disabled) { transform: scale(0.95); }
.aat100-block-btn:disabled {
    opacity: 0.35;
    cursor: default;
}

/* -------------------------------------------------------------------------
   Subtitle animations: praise reveal + try-again pulse
   -------------------------------------------------------------------------
   Flash writes both prompt and feedback/praise into the single
   instructTextBox and calls fadeInItem to redraw it on each change. We
   mirror that here by animating the subtitle element directly rather than
   using a separate feedback/praise box. Uses opacity only (not transform)
   so the sums-mode subtitle offset stays intact. */
.aat100-subtitle.aat100-praise-reveal {
    animation: aat100PraiseReveal 0.45s ease-out;
}

@keyframes aat100PraiseReveal {
    from { opacity: 0; }
    to   { opacity: 1; }
}

.aat100-subtitle.aat100-feedback-shake {
    animation: aat100FeedbackShake 0.3s ease-in-out;
}

@keyframes aat100FeedbackShake {
    0%, 100% { opacity: 1;   }
    25%      { opacity: 0.4; }
    50%      { opacity: 1;   }
    75%      { opacity: 0.4; }
}

/* -------------------------------------------------------------------------
   What's the Number feedback panel — "Try again" / "Well done, that is N".
   Rendered as a right-hand-side sibling of .aat100-work so the main
   subtitle prompt ("What number are the blocks showing") remains visible
   above the working blocks. Absolute-positioned inside the WTN-scoped
   screen root; hidden entirely in every other mode. Top offset aligns
   the feedback with the sums-mode subtitle position (right column,
   below the replay mouth) so the two modes share a visual anchor —
   font-size is --dw-font-size-large (1.4em base), so 11.2em ≈ 15.6em
   in base units, matching the sums subtitle's translate(_, 12em) landing.
   ------------------------------------------------------------------------- */
.aat100-wtn-feedback { display: none; }
.aat100-screen.aat100-mode-whatsthenumber .aat100-wtn-feedback {
    display: block;
    position: absolute;
    top: 11.2em;
    right: 1em;
    width: 10.5em;
    margin: 0;
    font-family: "Jotter Primary", sans-serif;
    font-size: var(--dw-font-size-large);
    color: var(--dw-color-text-primary);
    line-height: 1.2;
    text-align: left;
    z-index: 2;
}
.aat100-wtn-feedback.aat100-praise-reveal {
    animation: aat100PraiseReveal 0.45s ease-out;
}
.aat100-wtn-feedback.aat100-feedback-shake {
    animation: aat100FeedbackShake 0.3s ease-in-out;
}

/* -------------------------------------------------------------------------
   What's the Number input — inline +/- next to the t and u digit displays.
   ------------------------------------------------------------------------- */
.aat100-wtn-input-row.hidden_panel { display: none; }
/* Spacing between the +/- buttons and the digit in the WTN inline input
   row (also applies between the two adjacent buttons themselves — flex
   `gap` is uniform). */
.aat100-wtn-input-row { gap: 0.22em; }
.aat100-wtn-input-btn.hidden_panel { display: none; }

/* WTN inline +/- inherits the shared --aat100-btn-* palette from
   .aat100-block-btn — no per-variant overrides. */
.aat100-wtn-input-btn { /* intentionally empty — see .aat100-block-btn */ }

/* Wrapper around each column's WTN inline +/- pair — a single DOM anchor
   for the group .scan_highlight ring so switch users see a visible L1
   ring on "tens input" and "units input". Hidden entirely outside WTN
   mode so the digit-row layout in explore / make / sums modes is
   unchanged (the row's only visible child is the digit display, sitting
   at flex-start or flex-end per column as before). */
.aat100-wtn-btn-pair {
    display: flex;
    flex-direction: row;
    gap: 0.22em;
    align-items: center;
}
.aat100-screen:not(.aat100-mode-whatsthenumber) .aat100-wtn-btn-pair {
    display: none;
}

/* Push the WTN answer-input row (outlined tens + units digit boxes plus
   inline +/-) down slightly so the outlined boxes don't butt against
   the horizontal blue rule directly above. Row padding gives the whole
   row breathing space so digit and buttons stay vertically centred with
   each other via align-items: center. */
.aat100-screen.aat100-mode-whatsthenumber .aat100-wtn-input-row {
    padding-top: 0.4em;
}

/* When the WTN inline input is active, both digit displays (tens + units)
   get a black square outline — they read as the user's editable answer
   box, matching the Flash digit-box appearance. Toggled via JS by adding
   `aat100-wtn-active` to the tens + units `.aat100-units-big-digit`
   elements when WTN is showing, removed otherwise.

   Width is PINNED (not min-width) so the box stays a fixed size as the
   digit cycles 0→9. Jotter Primary numerals aren't tabular, so a purely
   content-sized box shifts a fraction of an em each time the user hits +/−
   — enough to nudge the inline +/- buttons visibly. 1.5em comfortably
   fits any single digit and matches the surrounding +/- button footprint
   (.aat100-wtn-input-btn is 1.35em wide). Scope is WTN-only: the class is
   toggled off in Explore/MakeTheNumber/sums modes so those shared digit
   displays keep their fluid width. */
.aat100-units-big-digit.aat100-wtn-active {
    border: 0.08em solid #000;
    border-radius: 0;
    background: #fff;
    /* Match the adjacent .aat100-wtn-input-btn footprint exactly.
       Buttons use `.aat100-block-btn { font-size: 1em; width/height:
       var(--aat100-btn-size) }` so their box side = 2 × parent-em. Here
       we bump font-size to 2em (so the digit character reads large) and
       set width/height to 1em (own em) — 1 × 2 × parent-em = same 2 ×
       parent-em box as the button. The tens display is blank for targets
       < 10 (tensText(0) → ""); the fixed dimensions keep the outlined
       box from collapsing when the content is empty. */
    font-size: var(--aat100-btn-font-size);
    width: 1em;
    height: 1em;
    padding: 0;
    line-height: 1;
    display: flex;
    align-items: center;
    justify-content: center;
}

/* -------------------------------------------------------------------------
   Results screen
   ------------------------------------------------------------------------- */
/* Flex-column skeleton comes from .dw-activity-screen. */
.aat100-results-screen {
    /* Top padding kept tight so 20Q (two tables × 10 rows + header + score +
       actions) fits inside the 506px aspect-locked stage without the tables
       overrunning the score row. */
    padding: var(--dw-space-loose) var(--dw-space-loose);
    overflow-y: auto;
}

.aat100-results-title {
    /* ~10% smaller than the previous 1.8em to give the two-table layout more
       vertical breathing room inside the 450px activity area. */
    font-size: 1.6em;
    text-align: center;
    margin: 0 0 var(--dw-space-narrow) 0;
}

.aat100-results-header {
    display: flex;
    flex-direction: row;
    justify-content: space-around;
    font-size: 0.9em;
    color: var(--dw-color-text-secondary);
    margin-bottom: var(--dw-space-narrow);
    flex-shrink: 0;
}

/* Two side-by-side tables (questions 1–10 | 11–20). Equal-width halves via
   flex 1 1 0; column-gap gives visual separation. When maxQ ≤ 10 the right
   table is hidden and .aat100-results-columns--single centres the left
   table at exactly half of the row width so 10Q ↔ 20Q swaps don't jump. */
.aat100-results-columns {
    display: flex;
    flex-direction: row;
    gap: var(--dw-space-loose);
    align-items: flex-start;
    justify-content: center;
    flex: 1;
    min-height: 0;
}

.aat100-results-columns--single .aat100-results-table {
    /* Match the visual width the left table would have in the two-table
       layout: half of the row minus half the gap. */
    flex: 0 0 calc(50% - (var(--dw-space-loose) / 2));
}

.aat100-results-table {
    border-collapse: collapse;
    font-size: 0.95em;
    flex: 1 1 0;
    /* Equal-width halves regardless of the number of populated rows. */
    table-layout: fixed;
    width: 100%;
}

.aat100-results-table th,
.aat100-results-table td {
    border: 0.06em solid var(--dw-color-border-light);
    padding: 0.05em var(--dw-space-narrow);
    text-align: center;
}

.aat100-results-table th {
    background: #eef;
    font-weight: bold;
}

.aat100-score-text {
    /* One step down from --dw-font-size-large so it reads as a supporting
       summary line rather than a second heading. */
    font-size: var(--dw-font-size-subheading);
    font-weight: bold;
    text-align: center;
    margin: var(--dw-space-tight) 0;
    color: #225500;
    flex-shrink: 0;
}

.aat100-results-actions {
    display: flex;
    flex-direction: row;
    justify-content: center;
    gap: var(--dw-space-loose);
    flex-shrink: 0;
    padding: var(--dw-space-narrow) 0;
}

/* -------------------------------------------------------------------------
   Options grid + description
   ------------------------------------------------------------------------- */
/* Base grid comes from the shared .dw-options-activity-grid class;
   only the activity-specific top-margin tweak lives here. */
.aat100-activity-grid {
    margin-top: var(--dw-space-narrow);
}

/* "Description: <text>" paragraph: prefix stays static, the second span
   live-updates from translations. */
.aat100-activity-description {
    margin: var(--dw-space-narrow) 0 0;
    font-size: 0.95em;
    color: var(--dw-color-text-secondary);
    min-height: 1.2em;
}

.aat100-description-prefix {
    font-weight: bold;
    color: var(--dw-color-text-primary);
    margin-right: var(--dw-space-snug);
}

.aat100-activity-description-value {
    font-style: italic;
}

/* Mode (Learning/Assessment) row sits inside the activity fieldset, beneath
   the description. The legend ("Mode") is visually hidden — divergence
   noted: the visible labels remain "Learning" / "Assessment". */
.aat100-mode-group {
    border: none;
    padding: var(--dw-space-narrow) 0 0;
    margin: 0;
}

.aat100-mode-description {
    margin: var(--dw-space-narrow) 0 0;
    font-size: 0.9em;
    color: var(--dw-color-text-secondary);
    font-style: italic;
    min-height: 1.1em;
}

/* Dimmed state for locked-by-activity radios. */
.aat100-dimmed {
    opacity: 0.4;
    pointer-events: none;
}

/* -------------------------------------------------------------------------
   Colour-set picker (options screen, mirrors Flash leftButton/rightButton +
   colourOptionsBox in frame_03.as). Two arrow buttons flank a small swatch
   showing the active tens-block and unit-stack at chosen colour.
   ------------------------------------------------------------------------- */
.aat100-colour-picker {
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: var(--dw-space-comfy);
    margin-top: var(--dw-space-snug);
}

.aat100-colour-arrow {
    width: 2.4em;
    height: 2em;
    border-radius: 0.18em;
    border: 0.08em solid #7e86de;
    background: linear-gradient(180deg, #ededf6 0%, #f0f0f7 15%, #dadef1 85%, #abb1e0 100%);
    color: var(--dw-color-text-primary);
    font-family: "Jotter Primary", sans-serif;
    font-size: 1.1em;
    font-weight: bold;
    cursor: pointer;
    line-height: 1;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}
@media (hover: hover) {
    .aat100-colour-arrow:hover:not(:disabled) {
        background: linear-gradient(180deg, #f7f7fc 0%, #e5e8f5 60%, #c6cee9 100%);
    }
}

/* Colour-set swatch (Flash colourOptionsBox in frame_03.as):
   one tall tens-block on the left + a vertical stack of 10 unit-squares on
   the right. Flash equalises the two heights visually — the units stack and
   tens block are the same height, even though that means each unit cell is
   slightly compressed (10 cubes ÷ tens-height < tens-width). Sizing by
   matching heights (rather than matching unit-cube-width to tens-column-
   width) is what the Flash reference shows. */
.aat100-colour-swatch {
    --aat100-swatch-h: 4.5em;
    display: flex;
    flex-direction: row;
    align-items: flex-end;
    gap: 0.25em;
    height: var(--aat100-swatch-h);
}

.aat100-colour-swatch-ten {
    /* Full swatch height to match the units stack. */
    height: 100%;
    width: auto;
    display: block;
}

/* Vertical stack of 10 unit squares — full swatch height (matches the
   tens block on the left). Width derives from the tens-block's column
   width so the cubes don't visually dominate the swatch. */
.aat100-colour-swatch-units {
    height: 100%;
    /* Width matches the tens-block column width (tens native aspect
       40.45 / 350.4 = 0.1155, so width = swatch-h × 0.1155). */
    width: calc(var(--aat100-swatch-h) * 0.1155);
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
}

.aat100-colour-swatch-units img {
    width: 100%;
    /* Square cubes: 1/10 of the stack height. */
    height: 10%;
    flex: 0 0 10%;
    display: block;
}

/* -------------------------------------------------------------------------
   Scanning controls: layout comes from shared dw-scan-* classes in doorway.css.
   ------------------------------------------------------------------------- */

/* -------------------------------------------------------------------------
   Replay-instruction mouth icons (Flash mouthGuide / mouthTotal).
   Both use about-time's mouth.png — a small red mouth glyph. The <button>
   is transparent; the <img> is the visual.
   ------------------------------------------------------------------------- */
.aat100-replay-btn {
    width: 1.8em;
    height: 1.4em;
    padding: 0;
    border: none;
    background: transparent;
    cursor: pointer;
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}
.aat100-replay-btn img {
    width: 100%;
    height: 100%;
    object-fit: contain;
    display: block;
}

@media (hover: hover) {
    .aat100-replay-btn:hover { filter: brightness(0.92); }
}
.aat100-replay-btn:active { filter: brightness(0.82); }
.aat100-replay-btn:focus-visible {
    outline: 0.2em solid var(--dw-color-focus-ring);
    outline-offset: 0.15em;
}
/* Inline replay-mouth gets a more prominent hover cue than the shared
   filter — a pale-blue background + blue outline, matching the mouth
   affordance used by first-sounds/first-words. Base transform (set on
   `.aat100-replay-inline` further down) must stay untouched by `:hover`,
   so we express hover via non-transform properties (background/outline)
   that compose cleanly with the sums-mode transform. */
.aat100-replay-btn.aat100-replay-inline:focus-visible {
    background: #d8eeff;
    outline: 0.15em solid #0066cc;
    outline-offset: 0.05em;
    border-radius: 0.25em;
    filter: none;
}
@media (hover: hover) {
    .aat100-replay-btn.aat100-replay-inline:hover {
        background: #d8eeff;
        outline: 0.15em solid #0066cc;
        outline-offset: 0.05em;
        border-radius: 0.25em;
        filter: none;
    }
}
.aat100-replay-btn.hidden_panel { display: none; }

/* mouthTotal sits as a direct child of .aat100-work (ahead of the tens/units
   columns in DOM order so keyboard tab reaches it before the block-builder
   +/− buttons). Positioned absolutely over the central divider; the final
   `transform` (further down) composes translateX(-50%) with the tuneable
   mouth-total offset + scale. */
.aat100-replay-total {
    position: absolute;
    top: 1.65em;
    left: 50%;
    z-index: 2;
}

/* Hide the t/u big-digit displays + mouthTotal in Make-the-Number Assessment.
   visibility:hidden (not display:none) so the row keeps its baseline —
   the units stack underneath is positioned relative to it. */
.aat100-screen.aat100-assessment-hide-digits .aat100-units-big-digit,
.aat100-screen.aat100-assessment-hide-digits .aat100-mouth-total {
    visibility: hidden;
}

/* Info text (subtitle) width. */
.aat100-subtitle {
    max-width: 10.5em;
}

/* Symmetric slot margin — pushes the tens-grid right edge left and the
   units-stack left edge right, both by the same amount. Also applied to
   the +/− block-controls row underneath so the buttons line up with the
   columns they operate on. */
.aat100-tens-grid,
.aat100-tens-controls  { margin-right: 0.3em; }
.aat100-units-stack,
.aat100-units-controls { margin-left:  0.3em; }

.aat100-tu-label {
    display: inline-block;
    transform-origin: center center;
}

/* Mouth buttons. The inline replay button sits to the right of the
   subtitle text; mouthTotal is absolutely positioned over the vertical
   divider. */
.aat100-replay-inline {
    transform: translate(1.1em, -0.15em) scale(1.5);
    transform-origin: left center;
}
.aat100-replay-total {
    /* Rightward offset places the mouth over the units-column digit box;
       the trailing +1em is half a `.aat100-block-btn` width, biasing the
       icon slightly further right so it reads as centred on that box
       rather than the vertical divider. */
    transform: translate(calc(-50% + 12.9em + 1em), 0.1em) scale(1.5);
    transform-origin: center center;
}

/* -------------------------------------------------------------------------
   Sums-mode overrides — scoped by `.aat100-mode-sumswithblocks` /
   `.aat100-mode-writtensums` on the screen root, toggled by
   `_applyModeClass()` in add-and-subtract-100.js.
   ------------------------------------------------------------------------- */

/* --- shared across both sums modes ------------------------------------ */
.aat100-screen.aat100-mode-sumswithblocks .aat100-sum-text,
.aat100-screen.aat100-mode-writtensums   .aat100-sum-text {
    transform: translateX(-8.6em);
}
/* Subtitle transform targets only the text element — the inline replay
   mouth (which sits in the same .aat100-subtitle-row flex container)
   stays put. */
.aat100-screen.aat100-mode-sumswithblocks .aat100-subtitle,
.aat100-screen.aat100-mode-writtensums   .aat100-subtitle {
    transform: translate(24em, 12em);
    /* Pin width so the flex-row layout of the subtitle-row is invariant
       across steps — subtitle text can change from "First make 98" (short,
       one line) to "Well done! Now take away 39. Take away the units
       first." (long, wraps to two lines) without the flex parent growing
       taller or the trailing mouth reflowing left/right. Width matches the
       shared .aat100-subtitle max-width so long strings still wrap the
       same way, but the box no longer shrink-fits shorter strings. */
    width: 10.5em;
}
/* Lock the subtitle-row's vertical box so wrapping subtitle text doesn't
   push the work area (and the horizontal blue rule) down at step 1→2.
   Height reserves room for the longest expected 2-line prompt within the
   10.5em max-width — height (not min-height) so the row is invariant
   even when text wraps to a single line ("First make 98") or a longer
   two-line prompt ("Well done! Now take away 39. Take away the units
   first."). The subtitle text and inline mouth are then anchored to a
   stable row baseline, so the .aat100-work grid below (and the
   horizontal blue rule that anchors to it) doesn't jump at step
   transitions. */
.aat100-screen.aat100-mode-sumswithblocks  .aat100-subtitle-row,
.aat100-screen.aat100-mode-writtensums    .aat100-subtitle-row,
.aat100-screen.aat100-mode-whatsthenumber .aat100-subtitle-row {
    height: 3.4em;
    min-height: 3.4em;
}
/* Inline replay-mouth — overrides the base transform (translate(1.1em,
   -0.15em) scale(1.5)) with a sums-mode offset. Transforms don't stack
   across matching rules, so this fully replaces the base. */
.aat100-screen.aat100-mode-sumswithblocks .aat100-replay-inline,
.aat100-screen.aat100-mode-writtensums   .aat100-replay-inline {
    transform: translate(-0.5em, 2.55em) scale(1.5);
}

/* --- writtensums-only ------------------------------------------------- */

/* Column-notation block position. */
.aat100-screen.aat100-mode-writtensums #aat100WrittenDisplay {
    transform: translate(-8em, 0.3em);
}

/* Hide the top-of-column big-digit displays in writtensums — the running
   total lives in the column-notation block instead. Use visibility (not
   display: none) so the .aat100-units-digit-row keeps its baseline and
   the tens-grid / units-stack below don't reflow taller. Same reasoning
   as the .aat100-block-controls visibility trick. */
.aat100-screen.aat100-mode-writtensums #aat100WtnTensDisplay,
.aat100-screen.aat100-mode-writtensums #aat100DigitUnits {
    visibility: hidden;
}

/* Strip the grey border and white fill on the six column-notation digit
   cells so the digits sit on the writing line without visible input
   boxes. Cell dimensions preserved — only the outline + background are
   removed. Font-family reverts to the Doorway default (Jotter Primary)
   rather than the digit-box Georgia serif, matching the on-screen sum
   text elsewhere on the writing line. */
.aat100-screen.aat100-mode-writtensums #aat100WrittenDisplay .aat100-digit-box {
    border-color: transparent;
    background: transparent;
    font-family: inherit;
}

/* Row 1 (top addend) reads as pre-printed text — a shade paler than the
   fresh ink of row 2 (bottom addend + operator) and row 3 (running
   guess). Signals "this number is already there; you're adding to it". */
.aat100-screen.aat100-mode-writtensums #aat100WrittenDisplay .aat100-wsum-row1 .aat100-digit-box {
    color: #555;
}

/* Row-3 typing target — the cell currently accepting the user's +/-
   input gets a solid black border so it reads as an editable answer
   box. JS toggles `aat100-wsum-row3-active` on the active cell; removed
   once the guess is finalised so the digit reads as fresh ink. */
.aat100-screen.aat100-mode-writtensums #aat100WrittenDisplay .aat100-digit-box.aat100-wsum-row3-active {
    border: 0.08em solid #000;
    background: #fff;
}

/* mouthTotal is hidden in writtensums — the guide mouth (in the subtitle
   row) is the only speech replay in this mode. `visibility: hidden` keeps
   the layout footprint stable in case anything else absolute-positions
   relative to it. */
.aat100-screen.aat100-mode-writtensums .aat100-mouth-total {
    visibility: hidden;
}

/* Divider between row-2 and row-3 is redundant — the horizontal blue rule
   above already separates the addends from the guess. Hide entirely. */
.aat100-written-divider { display: none; }

/* Row-2 operator glyph — kept inline-block to match the &nbsp; placeholders
   in rows 1 and 3. visibility (not display:none) so revealing the op at
   step 1→2 doesn't reflow row 2. JS toggles `aat100-wsum-op-visible` on
   the writtenDisplay root once the second addend / subtrahend is introduced. */
.aat100-screen.aat100-mode-writtensums #aat100WbOp {
    display: inline-block;
    visibility: hidden;
}
.aat100-screen.aat100-mode-writtensums #aat100WrittenDisplay.aat100-wsum-op-visible #aat100WbOp {
    visibility: visible;
}

/* Writtensums override for the horizontal blue rule y — nudged up slightly
   so it clears the (now translated) column-notation block above. */
.aat100-screen.aat100-mode-writtensums .aat100-work::before {
    top: calc(0.25em + var(--dw-font-size-large) - 0.45em);
}

/* Writtensums lifts the t/u labels above the column-notation sum block
   (absolutely positioned near top: 4.5em). X positions match the shared
   default so the glyphs sit at the same absolute x as the other sub-
   activities. */
.aat100-screen.aat100-mode-writtensums .aat100-work-tens .aat100-tu-label {
    transform: translate(9.7em, -3.7em);
}
.aat100-screen.aat100-mode-writtensums .aat100-work-units .aat100-tu-label {
    transform: translate(-6.2em, -3.7em);
}

/* -------------------------------------------------------------------------
   Reduced-motion fallback.
   ------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: 0.01ms !important;
        transition-duration: 0.01ms !important;
    }
}
