/* ============================================================================
   MATHS SPEED BUILDER — redesign on the design system (2026-09-19, Phase 3)
   Target: docs/mockups/msb-redesign.png.

   Moved OUT of css/styles.css into its own file, loaded after css/skin.css:
   the Speed Builder is one self-contained engine (js/19-speed-builder.js), and
   styles.css is shared by every area's chat.

   Rules of this file:
   - Fredoka (numbers, titles) + Lexend (words), via --font-display/--font-body.
   - Colours are tokens, plus ONE identity colour per operation (--msb-c, with a
     soft tint --msb-soft and a text-safe ink --msb-ink). None is green (success),
     clay (error) or violet (action), so an operation can never read as feedback.
   - Fixed zones: top bar / level strip / one card. Inside the card: the content,
     then a control bar that is always in the same place.
   - UI motion uses the token durations. The INTRO's own pace is the user's and
     lives in the JS (MSB_*_MS) — do not speed it up.
   ============================================================================ */

/* ---- identity colours -------------------------------------------------- */
.msb-add{ --msb-c:#23789b; --msb-soft:#e3f1f6; --msb-ink:#1a5c77; }
.msb-sub{ --msb-c:#c0620f; --msb-soft:#fbeedd; --msb-ink:#8f4506; }
.msb-mul{ --msb-c:#8b3f8e; --msb-soft:#f4e6f4; --msb-ink:#6d2f70; }
.msb-div{ --msb-c:#1c7a70; --msb-soft:#e0f2ef; --msb-ink:#155d55; }
.msb-money{ --msb-c:#4a7d1e; --msb-soft:#eaf3dd; --msb-ink:#365c14; }
.msb-frac{ --msb-c:#b23a5c; --msb-soft:#fbe6ec; --msb-ink:#862a45; }
.msb-meas{ --msb-c:#3f4ea6; --msb-soft:#e7e9f8; --msb-ink:#2e3a80; }
/* two letters in the sign circle: a size down so "cm" sits inside it */
.msb-meas .msb-sign{ font-size:28px; letter-spacing:-.02em; }
.msb-time{ --msb-c:#8b5a2b; --msb-soft:#f5ebe0; --msb-ink:#6b4220; }
.msb-nums{ --msb-c:#a67c00; --msb-soft:#f7edd0; --msb-ink:#6f5300; }
/* three figures in the sign circle */
.msb-nums .msb-sign{ font-size:24px; letter-spacing:-.04em; }
#screen-msbgroup .msb-sign-sm .ns-sign, .msb-zoom-sign .ns-sign{ font-size:.62em; }
/* GEOMETRY (js/42-43): magenta — green, red and purple already mean right, wrong and chosen on the tiles */
.msb-geo{ --msb-c:#b3337d; --msb-soft:#f8e4ef; --msb-ink:#86245c; }
.geo-sign{ display:block; }
/* a picture tile holds one shape, all four in one colour so colour is never the clue */
#screen-msbgroup .msb-choice .geo-tile{ display:block; width:100%; max-width:110px; height:clamp(46px, 8.4vh, 80px); margin:0 auto; }
@media (max-width:719px){ #screen-msbgroup .msb-choice .geo-tile{ height:48px; } }
/* the example is a ROW of four shapes (520 x 200): at the fraction size (300px) the numbered sides were ~9px
   badges on 80px shapes — the wide size makes the emphasis big enough to see */
#screen-msbgroup.msb-geo .fr-pic.fr-ex{ max-width:440px; }
@media (min-width:1100px) and (min-height:780px){ #screen-msbgroup.msb-geo .fr-pic.fr-ex{ max-width:520px; } }
/* the nets intro pictures are 300 x 210 (not the wide 520 x 200 rows): at 440px they run over the box */
#screen-msbgroup.msb-geo .fr-pic.fr-ex.geo-sq{ max-width:350px; }
/* THE DRAG-THE-NAME MODE (js/21 msbMDraw): six shapes with a box each in the question, the names where the tiles go */
#msb-sq .msb-mgrid{ display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); gap:8px; width:100%; margin:0 0 8px; }
#msb-sq .msb-mcard{ background:#fffdf7; border:2px solid #efe4d2; border-radius:16px; padding:4px 4px 6px; display:flex; flex-direction:column; align-items:center; gap:4px; }
#msb-sq .msb-mcard svg{ width:100%; height:clamp(56px, 10vh, 92px); display:block; }
.msb-mbox{ width:100%; min-height:38px; border:2.5px dashed #cdbfa6; border-radius:12px; display:flex; align-items:center; justify-content:center; background:#fbf6ea; cursor:pointer; }
.msb-mbox.hot{ border-color:#5b3fb0; background:#efeafb; }
.msb-mbox.ok{ border:2.5px solid #2e8b57; background:#e6f4ea; }
.msb-mbox.wrong{ border:2.5px solid #c0392b; background:#fbe9e7; }
.msb-mbox .msb-mright{ font:700 15px var(--font-display); color:#1f6b40; }
.msb-mchip{ font:700 clamp(15px, 2.3vh, 19px) var(--font-display); color:#2c2340; min-height:clamp(40px, 6.6vh, 54px); border-radius:14px; border:3px solid #e2d6bf; background:#fffdf7;
  box-shadow:0 4px 0 #d8cbb1; padding:4px 8px; touch-action:none; cursor:grab; user-select:none; -webkit-user-select:none; }
.msb-mchip.on{ border-color:#5b3fb0; background:#efeafb; box-shadow:0 4px 0 #3f2a86; }
.msb-mbox .msb-mchip{ min-height:30px; width:calc(100% - 6px); font-size:clamp(13px, 1.9vh, 16px); box-shadow:0 2px 0 #d8cbb1; padding:2px 4px; border-width:2px; display:flex; align-items:center; justify-content:center; }
.msb-mbox .msb-mchip.long{ font-size:clamp(11px, 1.6vh, 14px); letter-spacing:-.02em; }
.msb-mchip.gone{ visibility:hidden; }
.msb-mghost{ position:fixed; z-index:9999; pointer-events:none; transform:translate(-50%,-60%) rotate(-4deg) scale(1.06); box-shadow:0 10px 22px rgba(58,45,92,.28); border-color:#5b3fb0; background:#efeafb; }
#screen-msbgroup .msb-keys.msb-choices.match{ grid-template-columns:repeat(2,minmax(0,1fr)); }
@media (max-width:719px){ #screen-msbgroup .msb-keys.msb-choices.match{ grid-template-columns:repeat(3,minmax(0,1fr)); } #msb-sq .msb-mcard svg{ height:58px; } .msb-mbox .msb-mchip.long{ font-size:11.5px; }
  /* three names across a phone: "parallelogram" and "semicircle" overflowed their card at the full size */
  #screen-msbgroup .msb-choices.match .msb-mchip{ font-size:15px; padding:4px 3px; } #screen-msbgroup .msb-choices.match .msb-mchip.long{ font-size:12px; letter-spacing:-.02em; } }
/* MAPS AND DIRECTIONS (js/44): a map needs room for its labels — its own size, bigger than a question picture
   (.fr-pic.fr-q is 176px on a phone, too small to read a street name) */
#screen-msbgroup.msb-geo .fr-pic.geo-map.fr-q{ max-width:420px; }
@media (min-width:1100px) and (min-height:780px){ #screen-msbgroup.msb-geo .fr-pic.geo-map.fr-q{ max-width:470px; } }
/* …but capped by HEIGHT, because the shapes differ (a compass is square, a street of shops is wide): the intro box
   is ~340px on a laptop and ~308px on an iPad, and a full-width compass ran 200px over it */
@media (min-width:720px){ #screen-msbgroup.msb-geo .fr-pic.geo-map.fr-ex{ width:auto; max-width:100%; height:min(228px, calc(100vh - 575px)); }
  /* a question's compass at 420px wide was 420px TALL and covered the "Question 1 of 10" bar */
  #screen-msbgroup.msb-geo .fr-pic.geo-map.fr-q{ width:auto; max-width:100%; height:min(300px, calc(100vh - 500px)); } }
@media (max-width:719px){ #screen-msbgroup.msb-geo .fr-pic.geo-map.fr-q{ width:auto; max-width:100%; height:min(180px, 22vh); }
  /* a keypad question has the keypad under it: its map is a little shorter (the key count, the scale, the warehouse) */
  #screen-msbgroup.msb-geo .fr-pic.geo-map.geo-kp.fr-q{ height:min(150px, 18vh); } }
/* TURNS AND ANGLES (js/45): an angle picture carries no labels to make room for, and its captions are short, so its
   intro picture is taller than a map's (measured: every step still fits the scene on a laptop and an iPad) */
@media (min-width:720px){ #screen-msbgroup.msb-geo .fr-pic.geo-map.geo-ang.fr-ex{ height:min(272px, calc(100vh - 528px)); } }
/* every intro picture is drawn twice (js/42 geEqRow): a wide row, and two rows for phones (the user's choice) */
#screen-msbgroup svg.geo-tall{ display:none; }
@media (max-width:719px){ #screen-msbgroup svg.geo-wide{ display:none; } #screen-msbgroup svg.geo-tall{ display:block; max-width:340px; } }
/* STATISTICS (js/47-48): slate blue (no other game uses it; green, red and purple mean right, wrong and chosen).
   A graph is read for its NUMBERS, so a statistics picture has its own size, capped by HEIGHT like a map… */
.msb-stat{ --msb-c:#46607c; --msb-soft:#e6ecf2; --msb-ink:#31465c; }
#screen-msbgroup.msb-stat .fr-pic.st-pic.fr-q{ max-width:440px; }
@media (min-width:720px){ #screen-msbgroup.msb-stat .fr-pic.st-pic.fr-ex{ width:auto; max-width:100%; height:min(240px, calc(100vh - 565px)); }
  #screen-msbgroup.msb-stat .fr-pic.st-pic.fr-q{ width:auto; max-width:100%; height:min(290px, calc(100vh - 500px)); } }
@media (max-width:719px){ #screen-msbgroup.msb-stat .fr-pic.st-pic.fr-q{ width:auto; max-width:100%; height:min(190px, 23vh); }
  /* a keypad question has the keypad under it: its picture is shorter (measured on a 390 x 844 phone: at 158px a
     two-line question ran the box 5px over; a keypad stem is at most STA_KP characters, two lines) */
  #screen-msbgroup.msb-stat .fr-pic.st-pic.st-kp.fr-q{ height:min(148px, 17.5vh); } }
/* …except a FLAT picture (a list of answers, two graphs side by side, a row of dice): a fixed height would letterbox
   it, so it is sized by its width */
#screen-msbgroup.msb-stat .fr-pic.st-pic.st-flat.fr-q, #screen-msbgroup.msb-stat .fr-pic.st-pic.st-flat.fr-ex{ height:auto; width:100%; max-width:440px; }
/* a picture TILE: tally marks, a spinner, a jar; .st-tall = a small graph or picture graph, which needs more room */
#screen-msbgroup .msb-choice .st-tile{ display:block; width:100%; max-width:150px; height:clamp(50px, 9vh, 84px); margin:0 auto; }
#screen-msbgroup .msb-choice .st-tile.st-tall{ max-width:200px; height:clamp(76px, 13vh, 118px); }
@media (max-width:719px){ #screen-msbgroup .msb-choice .st-tile{ height:56px; } #screen-msbgroup .msb-choice .st-tile.st-tall{ height:84px; } }
/* the drag cards hold a column with its numbers, or a jar: taller than a shape's card */
#screen-msbgroup.msb-stat #msb-sq .msb-mcard svg{ height:clamp(64px, 11.5vh, 104px); }
@media (max-width:719px){ #screen-msbgroup.msb-stat #msb-sq .msb-mcard svg{ height:80px; } }   /* measured: 90px ran a two-line drag question 12px over */
/* THE TAP-THE-ANSWER MODE (js/21 msbCDraw): four answer tiles where the keypad was; long answers in one
   column; the chosen tile PURPLE like Check (never yellow: the user removed yellow highlights) */
#screen-msbgroup .msb-keys[hidden]{ display:none !important; }
#screen-msbgroup .msb-keys.msb-choices{ display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:10px; max-width:420px; align-self:center; }
#screen-msbgroup .msb-keys.msb-choices.one{ grid-template-columns:1fr; }
#screen-msbgroup .msb-choice{ font-family:var(--font-display); font-weight:700; font-size:clamp(17px, 2.5vh, 21px); color:#2c2340; min-height:clamp(44px, 7.6vh, 62px);
  border-radius:16px; border:3px solid #e2d6bf; background:#fffdf7; box-shadow:0 4px 0 #d8cbb1; padding:6px 10px; cursor:pointer; line-height:1.15; }
#screen-msbgroup .msb-choice:hover{ background:#fff; }
#screen-msbgroup .msb-choice:focus-visible{ outline:3px solid var(--focus-ring); outline-offset:2px; }
#screen-msbgroup .msb-choice.on{ border-color:#5b3fb0; background:#efeafb; box-shadow:0 4px 0 #3f2a86; }
#screen-msbgroup .msb-choice.ok{ border-color:#2e8b57; background:#e6f4ea; box-shadow:0 4px 0 #1f6b40; }
#screen-msbgroup .msb-choice.wrong{ border-color:#c0392b; background:#fbe9e7; box-shadow:0 4px 0 #8e2a1f; }
#screen-msbgroup .msb-choices .msb-choice-check{ grid-column:1 / -1; min-height:clamp(44px, 7vh, 56px); background:var(--action); color:var(--text-on-action);
  border-color:transparent; box-shadow:var(--elev-2); font-size:var(--text-lg); }
#screen-msbgroup .msb-choices .msb-choice-check:hover{ background:var(--action-hover); }
/* phones: long answers stay in TWO columns — stacked, 4 tiles and Check ran the question box 8px over (measured) */
@media (max-width:719px){ #screen-msbgroup .msb-keys.msb-choices, #screen-msbgroup .msb-keys.msb-choices.one{ grid-template-columns:repeat(2,minmax(0,1fr)); gap:8px; }
  #screen-msbgroup .msb-choice{ font-size:15px; min-height:46px; padding:4px 6px; } }
/* a number-sense answer line: a sum or a sentence with its one box; a long one a size down (5000 + 300 + 20 + 7
   was clipped on an iPad) */
.ns-line{ display:inline-flex; align-items:center; gap:.18em; white-space:nowrap; }
#screen-msbgroup .msb-sq-line .ns-line{ font-size:.84em; }
#screen-msbgroup .msb-sq-line .ns-line.ns-long{ font-size:.68em; }
@media (max-width:719px){ #screen-msbgroup .msb-sq-line .ns-line.ns-long{ font-size:.58em; } }
/* time (js/38, js/39): the sign is a small clock drawn in the text colour; a time is written the way a
   clock shows it, 3 : [ ], with the one box for the hour OR the minutes */
.tm-sign{ display:block; }
.tm-time, .tm-fact, .tm-date{ display:inline-flex; align-items:center; white-space:nowrap; font-variant-numeric:tabular-nums; }
.tm-colon{ margin:0 .14em; }
.tm-ap{ margin-left:.3em; font-size:.82em; }
/* the example's emphasis (js/38 tmClock o.focus / o.from): the named hand or number glows and pulses; the hands
   TURN on from the last time shown (the long hand going half way round for half past) */
.tm-glow{ animation:tmGlow 1.1s ease-in-out infinite alternate; }
@keyframes tmGlow{ from{ opacity:.35; } to{ opacity:1; } }
.tm-move{ transform-box:view-box; transform-origin:var(--ox) var(--oy); animation:tmMove 1.8s cubic-bezier(.45,.05,.3,1) .5s both; }
@keyframes tmMove{ from{ transform:rotate(var(--tm-from)); } to{ transform:rotate(0deg); } }
@media (prefers-reduced-motion:reduce){ .tm-glow, .tm-move{ animation:none; } }
/* the example's clock must be big enough to SEE the emphasis (at the fraction size it was 250px in a card with
   room to spare, 2026-09-27) */
#screen-msbgroup.msb-time .ms-pic.fr-ex.tm-big{ max-width:220px; }
@media (min-width:1100px) and (min-height:780px){ #screen-msbgroup.msb-time .ms-pic.fr-ex.tm-big{ max-width:260px; } }
/* a wide example picture (two clocks side by side) */
#screen-msbgroup.msb-time .ms-pic.fr-ex.tm-wide{ max-width:320px; }
@media (min-width:1100px) and (min-height:780px){ #screen-msbgroup.msb-time .ms-pic.fr-ex.tm-wide{ max-width:380px; } }
/* a unit fact ("4 min 20 s = [ ] seconds") and a date's month are longer than a time: a size down, or the
   fact ran off the left of the question box (seen on a laptop screenshot, 2026-09-27) */
#screen-msbgroup .msb-sq-line .tm-fact{ font-size:.66em; }
#screen-msbgroup .msb-sq-line .tm-date{ font-size:.8em; }
/* phones: at the fraction size (176px) a timetable's and a calendar's type read at 6-7px. A question of up to
   two lines has room for 220px (measured on every level, both years, the longest wordings forced in, 2026-09-27);
   one that runs to three lines (tm-long, js/39 TM_PHONE_2) keeps the smaller size */
@media (max-width:719px){ #screen-msbgroup.msb-time .ms-pic.fr-q:not(.tm-long){ max-width:220px; }
  /* "1 year 5 months = [ ] months" was clipped on a phone at .66em (test-msb-time, 2026-09-27) */
  #screen-msbgroup .msb-sq-line .tm-fact{ font-size:.54em; }
  /* a question's time line is short and wide (340 x 118): full width it is still shorter than a clock at 176px */
  #screen-msbgroup.msb-time .ms-pic.fr-q.tm-lineq{ max-width:290px; } }

/* ---- fractions (js/34, js/35) ------------------------------------------
   A fraction is written the way a child writes it: top, a bar, bottom — in the example's task
   line and around the question's answer box. The counting badges pop one at a time (--d). */
.fr-frac{ display:inline-flex; flex-direction:column; align-items:center; vertical-align:middle; line-height:1.05; margin:0 .12em; }
.fr-frac .fr-bar{ align-self:stretch; min-width:1.3em; height:.11em; border-radius:.06em; background:currentColor; margin:.1em 0; }
.fr-frac .msb-eq-ans{ margin:0; }
/* a wide box: a narrow one read as a zero */
#screen-msbgroup .msb-sq-line .fr-frac .msb-sq-box{ font-size:.92em; display:inline-block; min-width:1.9em; box-sizing:border-box; }
.msb-rows .fr-frac{ font-size:.82em; }
.fr-badge, .fr-pop{ transform-box:fill-box; transform-origin:center; animation:frPop .38s var(--ease-out,ease-out) both; animation-delay:var(--d,0s); }
@keyframes frPop{ from{ transform:scale(0); opacity:0; } 70%{ transform:scale(1.12); opacity:1; } to{ transform:scale(1); opacity:1; } }
/* sizes MEASURED 2026-09-25 so every example step and every question fits a laptop (1280x800),
   an iPad (1024x768) and a phone (390x844) */
.fr-pic.fr-q{ max-width:260px; }
.fr-pic.fr-ex{ max-width:240px; }
.fr-pic.fr-open{ max-width:440px; }
/* level 2's wide example pictures: the counters shared into groups, the bar model */
.fr-pic.fr-wide{ max-width:460px; }
/* a laptop has the room: bigger pictures */
@media (min-width:1100px) and (min-height:780px){ .fr-pic.fr-q{ max-width:320px; } .fr-pic.fr-ex{ max-width:300px; } .fr-pic.fr-wide{ max-width:520px; } .fr-pic.fr-scene{ max-width:300px; } }
#screen-msbgroup .msb-sq-line .fr-frac{ font-size:.8em; }
/* level 2's line, "1/4 of 12 = ?": a size smaller, so the stacked fraction keeps the box inside the question */
#screen-msbgroup .msb-sq-line .fr-ofline{ display:inline-flex; align-items:center; gap:.2em; font-size:.84em; }
/* measurement (js/36): a scale must be READ, so its pictures run bigger than the fraction ones (a ruler's
   millimetres were 3px apart at the fraction size, measured 2026-09-26) */
.ms-pic.fr-q{ max-width:340px; }
@media (min-width:1100px) and (min-height:780px){ .ms-pic.fr-q{ max-width:420px; } }
@media (max-width:719px){ .ms-pic.fr-q{ max-width:188px; } }
/* a Measurement EXAMPLE picture fills its box (the user, 2026-10-03: "lots of space but everything is just squeezed
   in the middle very small"): sized by the HEIGHT the scene has left at the example's fullest step (the task line,
   a 3-line caption, and --msb-pic-rows working rows, set by js/21 msbSFrame), so it is the same size on every step */
@media (min-width:720px){ #screen-msbgroup.msb-meas #msb-scene .ms-pic.fr-ex:not(.fr-flat){ width:auto; max-width:100%;
  height:min(330px, calc(100vh - 518px - var(--msb-pic-rows, 0) * 42px)); } }
/* WHAT DO WE MEASURE?: each page GROWS out of its row on the board, the page before it shrinking back into its own
   row first (js/36 msWhatFrameSvg; the user, 2026-10-03: "the Length box should smoothly expand and show the next
   screen"). The box's x/y/width/height are animated (SVG geometry in css), the words inside fade in once it is open.
   Only on the step that draws it (.live/.new, js/21); a still frame is the end: the new page whole, the old gone. */
#screen-msbgroup .ms-xout{ opacity:0; }
#screen-msbgroup .msb-pic:is(.live, .new) .ms-xout{ animation:msXoutVis .8s linear both; }
#screen-msbgroup .msb-pic:is(.live, .new) .ms-xout .ms-xbg{ animation:msXshrink .6s .1s cubic-bezier(.5,0,.3,1) both; }
#screen-msbgroup .msb-pic:is(.live, .new) .ms-xin .ms-xbg{ animation:msXgrow .7s var(--xd, .3s) cubic-bezier(.3,.7,.2,1) both; }
/* every part of the card travels between its place on the row and its place on the card (js/36 msKindCardInner) */
#screen-msbgroup .ms-mv{ transform-box:view-box; transform-origin:var(--ox) var(--oy); }
.ms-rowcopy{ opacity:0; }
#screen-msbgroup .msb-pic:is(.live, .new) .ms-xin .ms-mv{ animation:msMvIn .75s var(--xd, .3s) cubic-bezier(.3,.7,.2,1) both; }
#screen-msbgroup .msb-pic:is(.live, .new) .ms-xin .ms-rowcopy{ animation:msFadeOut .4s var(--xd, .3s) ease both; }
#screen-msbgroup .msb-pic:is(.live, .new) .ms-xin .ms-in1{ animation:msFadeIn .4s var(--xd, .3s) ease both; }
#screen-msbgroup .msb-pic:is(.live, .new) .ms-xin .ms-late{ animation:msFadeIn .4s calc(var(--xd, .3s) + .6s) ease both; }
#screen-msbgroup .msb-pic:is(.live, .new) .ms-xout .ms-mv{ animation:msMvOut .6s .1s cubic-bezier(.5,0,.3,1) both; }
#screen-msbgroup .msb-pic:is(.live, .new) .ms-xout .ms-rowcopy{ animation:msFadeIn .35s .35s ease both; }
#screen-msbgroup .msb-pic:is(.live, .new) .ms-xout .ms-in1{ animation:msFadeOut .35s .3s ease both; }
#screen-msbgroup .msb-pic:is(.live, .new) .ms-xout .ms-late{ animation:msFadeOut .2s ease both; }
/* the ring MOVING between rows on the "which tool" pages (js/36 msBoardInner hlFrom) */
#screen-msbgroup .msb-pic:is(.live, .new) .ms-hl-on{ animation:msHlOn .5s .15s ease both; }
#screen-msbgroup .msb-pic:is(.live, .new) .ms-hl-off{ animation:msHlOff .5s .15s ease both; }
#screen-msbgroup .msb-pic:is(.live, .new) .ms-ring-on{ animation:msFadeIn .5s .15s ease both; }
#screen-msbgroup .msb-pic:is(.live, .new) .ms-ring-off{ animation:msFadeOut .5s .15s ease both; }
@keyframes msHlOn{ from{ opacity:.28; } to{ opacity:1; } }
@keyframes msHlOff{ from{ opacity:1; } to{ opacity:.28; } }
@keyframes msMvIn{ from{ transform:translate(var(--tx), var(--ty)) scale(var(--ts)); } }
@keyframes msMvOut{ to{ transform:translate(var(--tx), var(--ty)) scale(var(--ts)); } }
@keyframes msFadeIn{ from{ opacity:0; } to{ opacity:1; } }
@keyframes msFadeOut{ from{ opacity:1; } to{ opacity:0; } }
#screen-msbgroup .ms-xin.ms-xlate{ --xd:.85s; }
@keyframes msXgrow{ 0%{ x:var(--rx); y:var(--ry); width:var(--rw); height:var(--rh); opacity:0; } 30%{ opacity:1; } }   /* the row shows through for a moment, never a blank box */
@keyframes msXshrink{ to{ x:var(--rx); y:var(--ry); width:var(--rw); height:var(--rh); } }
@keyframes msXshow{ from{ opacity:0; } }
@keyframes msXhide{ to{ opacity:0; } }
@keyframes msXoutVis{ 0%{ opacity:1; } 92%{ opacity:var(--xo, 1); } 100%{ opacity:0; } }
/* a level with capBelow (js/21): the words UNDER the picture, the task line stays on top (the user, 2026-10-03) */
#screen-msbgroup .msb-intro.cap-below .msb-coach{ order:2; padding:var(--space-2) calc(26px + var(--space-2) * 2); }
/* …and SMALLER there (the user: "writing box is very big"): one size down, a small bulb, no two-line minimum */
#screen-msbgroup .msb-intro.cap-below .msb-intro-cap{ font-size:var(--text-base); min-height:0; }
#screen-msbgroup .msb-intro.cap-below .msb-coach-av{ width:26px; height:26px; font-size:13px; left:var(--space-2); top:50%; transform:translateY(-50%); }
/* a phone has the height to spare, not the width: the full width of the box (a short phone still keeps it on screen) */
@media (max-width:719px){ #screen-msbgroup.msb-meas #msb-scene .ms-pic.fr-ex:not(.fr-flat){ max-width:100%;
  max-height:calc(100vh - 480px - var(--msb-pic-rows, 0) * 42px); } }
/* levels 3-9: the signs between fractions, a decimal's "0." before its box */
.fr-op{ margin:0 .22em; }
.fr-ofline{ white-space:nowrap; }
.fr-ofline .fr-frac{ margin:0 .06em; }
/* a line in two pieces that may wrap between them (the word-problem example's "? → half → 1 more → 5 left" and
   "start: ?"): on one line a phone cut it off at both ends */
.fr-ofline.fr-wrap{ display:inline-flex; flex-wrap:wrap; justify-content:center; align-items:center; column-gap:1.1em; row-gap:0; white-space:normal; }
.fr-ofline.fr-wrap > span{ white-space:nowrap; }
.fr-dec{ display:inline-flex; align-items:center; gap:.05em; }
/* phones: the fraction sits BESIDE the question, not under it — stacked, a two-line question ran
   the box 13px over; beside, the picture keeps a readable size */
@media (max-width:719px){ .fr-pic.fr-q{ max-width:176px; } #screen-msbgroup .msb-sq-line .fr-frac{ font-size:.7em; }
  /* only a line that IS a fraction (level 1): level 2's "1/4 of 12 = ?" beside the question squeezed it to one word a line */
  #screen-msbgroup .msb-sq:has(.msb-sq-line > .fr-frac:only-child){ display:grid; grid-template-columns:minmax(0,1fr) auto; align-items:center; align-content:center; justify-items:center; column-gap:var(--space-2); }
  #screen-msbgroup .msb-sq:has(.msb-sq-line > .fr-frac:only-child) .msb-pic{ grid-column:1 / -1; }
  #screen-msbgroup .msb-sq-line .fr-ofline{ font-size:.72em; }
  /* levels 3-9 (measured 2026-09-26): a line of two or three stacked fractions under a three-line
     question ran the box 4-10px over; a tighter gap and a smaller line of fractions keep it in */
  #screen-msbgroup.msb-frac .msb-sgame.has-pic .msb-sq, #screen-msbgroup.msb-meas .msb-sgame.has-pic .msb-sq, #screen-msbgroup.msb-time .msb-sgame.has-pic .msb-sq{ gap:4px; }
  #screen-msbgroup .msb-sq-line .fr-ofline:has(.fr-frac ~ .fr-frac){ font-size:.7em; }
  .fr-pic.fr-scene{ max-width:180px; } }
/* FLAT pictures (2026-10-02: a fraction number line, a row of counting boxes, a pencil over a row of paper clips):
   sized by their WIDTH. At the square pictures' width a phone drew a number line 176px wide with 11px numbers and
   nine paper clips 15px each (seen in the screenshots). A flat picture this wide is no taller than a square one. */
.fr-pic.fr-flat.fr-q, .fr-pic.fr-flat.fr-ex{ max-width:400px; }
@media (min-width:1100px) and (min-height:780px){ .fr-pic.fr-flat.fr-q, .fr-pic.fr-flat.fr-ex{ max-width:460px; } }
@media (max-width:719px){ .fr-pic.fr-flat.fr-q{ max-width:300px; } }
/* a TAP-THE-ANSWER picture (the fraction wall, the tray of buttons) has no answer line under it and four tiles
   instead of the keypad, so a phone has the room to draw it bigger */
@media (max-width:719px){ .fr-pic.fr-tap.fr-q{ max-width:250px; } }

/* ---- a picture a level draws itself (money, js/32) ----------------------
   A rounded card on the page's own cream, no backdrop behind the money (the user
   removed it, 2026-09-25). Popped-out things (a child's head, the money box) stay
   whole: the SVG is overflow:visible and the card does not clip. */
#screen-msbgroup .msb-pic{ width:100%; max-width:560px; border-radius:24px; background:var(--sand-50,#fffdf7);
  box-shadow:inset 0 0 0 1px var(--sand-300,#e3d9c8); padding:6px 8px 0; box-sizing:border-box; flex:0 0 auto; }
#screen-msbgroup .msb-pic.new{ animation:msbFade .4s ease both; }
/* a TOOL TILE (Measurement's What do we measure?, 2026-10-03): the tool drawn with its name */
#screen-msbgroup .msb-choice .ms-tile{ display:block; width:100%; max-width:150px; height:clamp(62px, 11vh, 100px); margin:0 auto; }
@media (max-width:719px){ #screen-msbgroup .msb-choice .ms-tile{ height:66px; } }
.msb-pic-svg{ display:block; width:100%; max-width:540px; height:auto; overflow:visible; margin:0 auto; }
.msb-pic-q{ max-width:420px; }
#screen-msbgroup .msb-sq .msb-pic{ max-width:440px; padding:6px 8px; }
/* the question's picture BESIDE the keypad from 720px — the column games' layout */
@media (min-width:720px){
  #screen-msbgroup .msb-sgame.has-pic .msb-body{ max-width:820px; display:grid;
    grid-template-columns:minmax(0,1fr) minmax(250px,300px); grid-template-rows:auto minmax(0,1fr) auto;
    column-gap:var(--space-6); row-gap:var(--space-2); align-items:center; }
  #screen-msbgroup .msb-sgame.has-pic .msb-status{ grid-column:1 / -1; grid-row:1; }
  #screen-msbgroup .msb-sgame.has-pic .msb-sq{ grid-column:1; grid-row:2; }
  #screen-msbgroup .msb-sgame.has-pic .msb-fb{ grid-column:1; grid-row:3; }
  #screen-msbgroup .msb-sgame.has-pic .msb-keys{ grid-column:2; grid-row:2 / span 2; align-self:center; max-width:none; }
}
#screen-msbgroup .msb-sgame.has-pic .msb-sq-text{ font-size:var(--text-base); }
/* phones: a two-line question ("… spilled out of the treasure chest?") overflowed the
   question box by 8px at 340px (measured 2026-09-25); 296px leaves room for it */
@media (max-width:719px){ #screen-msbgroup .msb-sq .msb-pic{ max-width:296px; padding:2px 4px; } }
/* phones: the real papers' questions are full sentences, up to three lines (2026-09-26, the
   wording banks in js/33) — tighter type and gaps keep a three-line question inside the box (measured) */
@media (max-width:719px){
  #screen-msbgroup .msb-sgame.has-pic .msb-sq{ gap:var(--space-2); }
  #screen-msbgroup .msb-sgame.has-pic .msb-sq-text{ font-size:16px; line-height:1.36; padding:6px 12px; }
}


/* ---- Your Quest: the two bonus banners ---------------------------------
   They sit side by side where there is room and stack on a phone. Each opens
   its own drawer, so the row aligns to the top and an open drawer never
   stretches its neighbour. */
.bonus-row{display:grid;grid-template-columns:1fr;gap:0 var(--space-3);align-items:start;}
@media(min-width:760px){ .bonus-row{grid-template-columns:1fr 1fr;} }
/* While both are closed they match in size: "Vocabulary" wraps the title onto a third
   line, so stretch the shorter banner to its neighbour and centre its row. Once a
   drawer opens the row goes back to top-aligned, so the closed one stays compact. */
.bonus-row:not(:has(.bonus-banner.open)){align-items:stretch;}
.bonus-row .bonus-banner{display:flex;flex-direction:column;justify-content:center;}
/* same banner, its own teal -> blue -> violet colours so the two read as different games */
.bonus-banner.bonus-maths{background:linear-gradient(135deg,#0f9488,#2563eb 55%,#6d28d9);
  box-shadow:0 8px 22px rgba(37,99,235,.36),0 5px 0 rgba(30,58,138,.28);animation:none;}
.bonus-banner.bonus-maths .bonus-title{text-shadow:0 1px 2px rgba(15,40,110,.3);}


/* ---- screen 1: pick an operation --------------------------------------- */
#screen-msb .msb-lead{ text-align:center; font-family:var(--font-body); font-weight:var(--weight-body);
  font-size:var(--text-base); color:var(--text-secondary); margin:var(--space-1) 0 var(--space-4); }
/* THREE games a row, narrower, so all FOUR rows (10 games) fit the screen without scrolling (the user, 2026-09-28:
   "make it 3 games in each row… 4 rows can fit nicely in the screen"). The card's padding and sign shrink with the
   screen HEIGHT; the lone 10th game sits in the middle column. */
#screen-msb .msb-groups{ display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); gap:var(--space-3); max-width:780px; margin:0 auto; }
#screen-msb .msb-group:last-child:nth-child(3n+1){ grid-column:2; }
#screen-msb .msb-lead{ margin-bottom:var(--space-3); }
#screen-msb .msb-group{
  display:flex; flex-direction:column; align-items:center; justify-content:center; gap:clamp(4px, 0.9vh, 8px); text-align:center; min-width:0;
  padding:clamp(10px, 2vh, 18px) var(--space-2) clamp(10px, 1.8vh, 16px); cursor:pointer;
  background:var(--bg-surface); color:var(--text-primary);
  border:1px solid var(--border-subtle); border-radius:var(--radius-xl); box-shadow:var(--elev-2);
  font-family:var(--font-body);
  transition:transform var(--duration-base) var(--ease-out), box-shadow var(--duration-base) var(--ease-out);
}
#screen-msb .msb-group:hover{ transform:translateY(-2px); box-shadow:var(--elev-3); }
#screen-msb .msb-group:active{ transform:scale(.98); }
#screen-msb .msb-group:focus-visible{ outline:3px solid var(--focus-ring); outline-offset:3px; }
.msb-sign{ width:60px; height:60px; border-radius:50%; display:grid; place-items:center;
  background:var(--msb-c); color:#fff; font-family:var(--font-display); font-weight:var(--weight-display);
  font-size:38px; line-height:1; }
#screen-msb .msb-group-name{ font-family:var(--font-display); font-weight:var(--weight-display);
  font-size:var(--text-lg); line-height:var(--leading-tight); }
/* 12 small bars: one per level, green once passed */
.msb-mini{ display:flex; gap:2px; width:100%; max-width:180px; }
.msb-mini i{ flex:1; height:5px; border-radius:3px; background:var(--sand-300); }
.msb-mini i.d{ background:var(--state-correct); }
#screen-msb .msb-group-meta{ font-size:var(--text-sm); font-weight:var(--weight-medium); color:var(--text-secondary); }
/* the home sign is smaller than the play screen's; its font follows by the same ratio (money / measurement /
   number sense set their own glyph size, so it is a zoom, not a font-size) */
#screen-msb .msb-sign{ zoom:0.87; }
@media(max-height:820px){ #screen-msb .msb-sign{ zoom:0.72; } #screen-msb .msb-group{ padding-top:10px; padding-bottom:10px; } }
@media(max-height:700px){ #screen-msb .msb-sign{ zoom:0.58; } #screen-msb .msb-group{ padding-top:7px; padding-bottom:7px; gap:3px; }
  #screen-msb .msb-lead{ margin:0 0 var(--space-2); font-size:var(--text-sm); } }
#screen-msb .msb-mini{ max-width:150px; width:82%; }
@media(max-width:560px){
  #screen-msb .msb-groups{ gap:var(--space-2); }
  #screen-msb .msb-group{ padding-left:4px; padding-right:4px; }
  #screen-msb .msb-group-name{ font-size:14.5px; }
  #screen-msb .msb-group-meta{ font-size:11.5px; line-height:1.25; }
  #screen-msb .msb-sign{ zoom:0.7; }
}
@media(max-width:380px){ #screen-msb .msb-group-name{ font-size:13.5px; } #screen-msb .msb-group-meta{ font-size:11px; } }


/* ---- screen 2: one operation ------------------------------------------- */
#screen-msbgroup{ overflow-x:clip; }
#screen-msbgroup .topbar{ margin-bottom:var(--space-2); }
#screen-msbgroup .msb-play-title{ display:inline-flex; align-items:center; justify-content:center; gap:var(--space-2);
  min-width:0; flex:1 1 auto; font-family:var(--font-display); font-weight:var(--weight-display);
  font-size:var(--text-xl); color:var(--text-primary); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
#screen-msbgroup .msb-sign-sm{ flex:0 0 auto; width:30px; height:30px; border-radius:50%; display:grid; place-items:center;
  background:var(--msb-c); color:#fff; font-size:22px; line-height:1; }
@media(max-width:420px){
  /* ⚠ the header must hold the LONGEST name, "Multiplication". At --text-lg it
     overflowed its box on every common phone (375: Subtraction by 3px,
     Multiplication by 13px) and overflow:hidden sliced the sign circle in half
     as well, because the row is centred. Measured: all four names fit at 360px. */
  #screen-msbgroup .msb-play-title{ font-size:var(--text-base); gap:var(--space-1); }
  #screen-msbgroup .msb-sign-sm{ width:24px; height:24px; font-size:18px; }
  #screen-msbgroup .topbar .grade-badge{ padding:var(--space-1) var(--space-2); font-size:var(--text-xs); }
  #screen-msbgroup .topbar .back{ padding:var(--space-1) var(--space-2); font-size:var(--text-sm); }
}

/* the level strip: a label, then 12 bars that share the width */
#screen-msbgroup .msb-track{ display:flex; align-items:center; gap:var(--space-3);
  height:36px; margin:0 2px var(--space-3); }
.msb-strip-lbl{ flex:0 0 auto; white-space:nowrap; font-family:var(--font-display); font-weight:var(--weight-display);
  font-size:var(--text-base); color:var(--msb-ink); }
.msb-strip-lbl small{ font-family:var(--font-body); font-weight:var(--weight-body); font-size:var(--text-sm);
  color:var(--text-secondary); }
.msb-segs{ flex:1; display:flex; align-items:center; gap:3px; min-width:0; }
.msb-seg{ position:relative; flex:1; min-width:0; height:8px; padding:0; border:0; border-radius:4px;
  background:var(--sand-300); cursor:pointer; font:inherit; line-height:1; transform-origin:left center;
  transition:background var(--duration-fast) var(--ease-out); }
.msb-seg.done{ background:var(--state-correct); }
.msb-seg.locked{ cursor:default; background:var(--sand-200); box-shadow:inset 0 0 0 1px var(--sand-300); }
.msb-seg:not(.locked):not(.cur):hover{ background:var(--sand-400); }
.msb-seg.done:hover{ background:var(--green-700); }
/* the level being played: a wider pill in the operation's colour, with its number */
.msb-seg.cur{ flex:0 0 28px; height:24px; border-radius:12px; background:var(--msb-c); color:#fff;
  font-family:var(--font-display); font-weight:var(--weight-display); font-size:var(--text-sm);
  box-shadow:0 0 0 4px color-mix(in srgb,var(--msb-c) 22%,transparent); cursor:default; }
/* each bar is pressable over the full 44px height of the strip */
.msb-seg::after{ content:""; position:absolute; left:-1px; right:-1px; top:-18px; bottom:-18px; }
.msb-seg:focus-visible{ outline:3px solid var(--focus-ring); outline-offset:2px; }

/* Tapping an operation: a copy of its card travels to exactly where the play
   card will be (msbZoomCard in js/19). ⚠ It must look like BOTH cards — the same
   surface, border, 26px radius and shadow — or it flashes as it takes over. */
.msb-zoom{ position:fixed; z-index:9000; display:flex; flex-direction:column; align-items:center; justify-content:center;
  gap:var(--space-2); background:var(--bg-surface); border:1px solid var(--border-subtle);
  border-radius:var(--radius-xl); box-shadow:var(--elev-2); overflow:hidden; pointer-events:none; }
/* while the copy is still travelling, the screen it is arriving on holds its peace */
#screen-msbgroup.msb-arriving .topbar, #screen-msbgroup.msb-arriving .msb-track{ opacity:0; pointer-events:none; }
.msb-zoom-sign{ width:60px; height:60px; border-radius:50%; display:grid; place-items:center; color:#fff;
  background:var(--msb-c); font-family:var(--font-display); font-weight:var(--weight-display); font-size:38px; line-height:1; }
.msb-zoom-name{ font-family:var(--font-display); font-weight:var(--weight-display); font-size:var(--text-lg);
  color:var(--text-primary); }


/* ---- the card: content, then one control bar --------------------------
   Sized to the window so every screen of the game fits WITHOUT SCROLLING
   (the user's rule): the window, less the page padding, top bar and strip. */
#screen-msbgroup .msb-stage{ display:flex; flex-direction:column; overflow:hidden;
  background:var(--bg-surface); border:1px solid var(--border-subtle); border-radius:var(--radius-xl);
  box-shadow:var(--elev-2); height:calc(100vh - 196px); height:calc(100dvh - 196px); min-height:500px; }
#screen-msbgroup .msb-intro, #screen-msbgroup .msb-game, #screen-msbgroup .msb-result{
  flex:1; min-height:0; display:flex; flex-direction:column; }
/* the content column: centred, and no wider than a calm reading width */
#screen-msbgroup .msb-body{ flex:1; min-height:0; width:100%; max-width:560px; margin:0 auto;
  display:flex; flex-direction:column; align-items:center; gap:var(--space-3);
  padding:var(--space-4) var(--space-4) var(--space-3); }
#screen-msbgroup .msb-result .msb-body, #screen-msbgroup .msb-empty .msb-body{ justify-content:center; text-align:center; }
#screen-msbgroup .msb-ctrl{ flex:0 0 auto; display:flex; align-items:center; gap:var(--space-3);
  padding:var(--space-3) var(--space-4); border-top:1px solid var(--border-subtle); background:var(--bg-surface); }
#screen-msbgroup .msb-ctrl.center{ justify-content:center; }

/* coach bubble: the words live in a tinted box, not loose text */
/* The words are CENTRED across the whole bubble (user, 2026-09-19): the 💡 is
   pinned to the left edge, and the text keeps equal room on both sides, so it
   sits on the true centre of the box rather than the centre of what is left. */
#screen-msbgroup .msb-coach{ position:relative; align-self:stretch; display:flex; justify-content:center; align-items:center;
  background:var(--msb-soft); border-radius:var(--radius-lg); padding:var(--space-3) calc(36px + var(--space-3) * 2); text-align:center; }
#screen-msbgroup .msb-coach-av{ position:absolute; left:var(--space-3); top:var(--space-3); width:36px; height:36px; border-radius:50%; background:var(--msb-c);
  display:grid; place-items:center; font-size:18px; line-height:1; }
#screen-msbgroup .msb-coach-txt{ flex:1; min-width:0; }
/* ▶▶ the level heading, ABOVE the script bubble (user rule 2026-09-20).
   It was inside the bubble, first as a 12px uppercase tag and then at 17px —
   both smaller than the 20px script line below them, so it read as script.
   It is the title of the screen: 24px Fredoka in the operation's colour, on the
   card rather than on the bubble, with the step count beside it smaller and
   lighter. Anything that keeps it inside the bubble brings the problem back. */
#screen-msbgroup .msb-lvl-head{ align-self:stretch; display:flex; align-items:baseline;
  justify-content:center; gap:var(--space-2); flex-wrap:wrap; min-height:1.4em; }
#screen-msbgroup .msb-coach-strat{ font-family:var(--font-display); font-weight:var(--weight-display);
  font-size:var(--text-xl); line-height:var(--leading-snug); color:var(--msb-ink); }
#screen-msbgroup .msb-coach-n{ font-family:var(--font-body); font-weight:var(--weight-body);
  font-size:var(--text-sm); line-height:var(--leading-snug); color:var(--text-secondary); }
#screen-msbgroup .msb-coach-dot{ color:var(--ink-300); }
/* the step count wrapped under a long name: no dot opening the line (msbCoachSet) */
#screen-msbgroup .wrapped .msb-coach-dot{ display:none; }
/* the words: big, above the sum (user rule). min-height holds two lines so the
   sum never jumps as the caption changes length. */
#screen-msbgroup .msb-intro-cap{ margin:0; min-height:2.7em; font-family:var(--font-body);
  font-weight:var(--weight-strong); font-size:var(--text-lg); line-height:var(--leading-snug); color:var(--text-primary); }
#screen-msbgroup .msb-result .msb-intro-cap{ min-height:0; font-size:var(--text-base); }
#screen-msbgroup .msb-intro-cap.pop{ animation:msbFade var(--duration-slow) var(--ease-out) both; }
#screen-msbgroup .msb-cap-part{ font-weight:var(--weight-strong); }
#screen-msbgroup .msb-cap-ans{ color:var(--msb-ink); }

/* control bar parts */
#screen-msbgroup .msb-round{ flex:0 0 auto; width:var(--tap-min); height:var(--tap-min); border-radius:50%; padding:0;
  display:grid; place-items:center; cursor:pointer; background:var(--bg-raised); color:var(--ink-700);
  border:1px solid var(--border-subtle); font-family:var(--font-body); font-size:var(--text-base); line-height:1;
  transition:background var(--duration-fast) var(--ease-out); }
#screen-msbgroup .msb-round:hover:not(:disabled){ background:var(--sand-200); }
#screen-msbgroup .msb-round:disabled{ opacity:.45; cursor:default; }
#screen-msbgroup .msb-round:focus-visible{ outline:3px solid var(--focus-ring); outline-offset:3px; }
#screen-msbgroup .msb-intro-dots{ flex:1; display:flex; gap:0; justify-content:center; flex-wrap:wrap; min-width:0; }
/* each dot is a BUTTON that jumps to its step: a 15 x 22px target round a small dot, which grows on hover */
#screen-msbgroup .msb-intro-dots .msb-dot{ width:15px; height:22px; padding:0; border:0; background:none; cursor:pointer; display:flex; align-items:center; justify-content:center; }
#screen-msbgroup .msb-intro-dots .msb-dot::before{ content:""; width:7px; height:7px; border-radius:50%; background:var(--sand-300);
  transition:background var(--duration-base) var(--ease-out), transform var(--duration-fast) var(--ease-out); }
#screen-msbgroup .msb-intro-dots .msb-dot.on::before{ background:var(--msb-c); }
#screen-msbgroup .msb-intro-dots .msb-dot.now::before{ transform:scale(1.35); }
#screen-msbgroup .msb-intro-dots .msb-dot:hover::before{ transform:scale(1.7); }
#screen-msbgroup .msb-intro-dots .msb-dot:focus-visible{ outline:3px solid var(--focus-ring); outline-offset:-2px; border-radius:6px; }
/* primary = violet, the one action colour (the op colour is identity, not action) */
#screen-msbgroup .msb-start{ flex:0 0 auto; min-height:48px; padding:0 var(--space-5); border:0; border-radius:var(--radius-pill);
  background:var(--action); color:var(--text-on-action); cursor:pointer; white-space:nowrap;
  font-family:var(--font-display); font-weight:var(--weight-display); font-size:var(--text-base);
  box-shadow:var(--elev-2); transition:background var(--duration-fast) var(--ease-out), transform var(--duration-fast) var(--ease-out); }
#screen-msbgroup .msb-start:hover{ background:var(--action-hover); transform:translateY(-2px); }
#screen-msbgroup .msb-start:active{ transform:none; box-shadow:var(--elev-1); }
#screen-msbgroup .msb-start:focus-visible{ outline:3px solid var(--focus-ring); outline-offset:3px; }
/* the intro has ended: the button to play invites a press, gently */
#screen-msbgroup .msb-start.ready{ animation:msbReady 1.6s ease-in-out infinite; }
#screen-msbgroup .msb-btn2{ flex:0 0 auto; min-height:48px; padding:0 var(--space-5); border-radius:var(--radius-pill); cursor:pointer;
  background:var(--bg-surface); color:var(--text-primary); border:1px solid var(--border-control);
  font-family:var(--font-display); font-weight:var(--weight-display); font-size:var(--text-base); }
#screen-msbgroup .msb-btn2:hover{ background:var(--bg-raised); }
#screen-msbgroup .msb-btn2:focus-visible{ outline:3px solid var(--focus-ring); outline-offset:3px; }
@keyframes msbFade{ from{ opacity:0; transform:translateY(4px); } to{ opacity:1; transform:none; } }
@keyframes msbReady{ 0%,100%{ box-shadow:var(--elev-2), 0 0 0 0 rgba(91,63,168,0); }
                     50%{ box-shadow:var(--elev-2), 0 0 0 7px rgba(91,63,168,.18); } }


/* ---- intro scene: the sum written out, then the columns ----------------
   First frame: the written sum sits big where the columns will be (JS sets the
   transform), then glides up to become the task line while copies of its
   digits fly into the columns. Its ? turns into the answer at the end. */
#screen-msbgroup .msb-scene{ position:relative; flex:1; min-height:0; width:100%;
  display:flex; flex-direction:column; align-items:center; gap:var(--space-3); }
#screen-msbgroup .msb-eq{ display:flex; align-items:baseline; gap:0; position:relative; z-index:2;
  font-family:var(--font-display); font-weight:var(--weight-display); font-size:var(--text-2xl); line-height:1.1;
  color:var(--text-primary); background:var(--bg-raised); border-radius:var(--radius-pill); padding:var(--space-1) var(--space-4);
  transform-origin:center center; transition:transform .9s cubic-bezier(.45,0,.2,1); }
#screen-msbgroup .msb-scene.eq-only .msb-eq{ background:transparent; }
#screen-msbgroup .msb-eq.no-anim{ transition:none; }
#screen-msbgroup .msb-eqd{ display:inline-block; line-height:1; }
#screen-msbgroup .msb-eqop{ margin:0 .3em; }
#screen-msbgroup .msb-eq-ans{ display:inline-block; min-width:1em; text-align:center; line-height:1; color:var(--msb-c); }
#screen-msbgroup .msb-eq-ans.got{ color:var(--state-correct); }
/* the ? in the question pulses softly until the answer arrives */
#screen-msbgroup .msb-eq-ans:not(.got){ animation:msbQ 2s ease-in-out infinite; }
@keyframes msbQ{ 0%,100%{ transform:none; } 50%{ transform:scale(1.15); } }
#screen-msbgroup .msb-eq-ans.pop{ animation:msbPop .5s cubic-bezier(.3,1.6,.5,1) both; }
/* the column being worked on: its numbers bob gently so the eye goes there */
#msb-intro-board .msb-c.hl.msb-top .msb-dig,
#msb-intro-board .msb-c.hl.msb-bot .msb-dig,
#msb-intro-board .msb-c.hl .msb-new{ animation:msbBob 1.5s ease-in-out infinite; }
@keyframes msbBob{ 0%,100%{ transform:none; } 50%{ transform:translateY(-3px) scale(1.06); } }
#screen-msbgroup .msb-scene.eq-only .msb-board-wrap{ visibility:hidden; }
#screen-msbgroup .msb-fly{ position:absolute; z-index:3; display:flex; align-items:center; justify-content:center;
  font-family:var(--font-display); font-weight:var(--weight-display); line-height:1; color:var(--text-primary);
  pointer-events:none; transform-origin:center center; }
/* "Write 27 under 52": the empty columns come in as tinted lanes */
#screen-msbgroup .msb-board.lanes .msb-c:not(.msb-gut){ background:color-mix(in srgb,var(--msb-c) 13%,transparent); }
#screen-msbgroup .msb-board.lanes .msb-head{ color:var(--msb-ink); border-radius:14px 14px 0 0; }
#screen-msbgroup .msb-board.lanes .msb-ans{ border-radius:0 0 14px 14px; margin:0 0 4px; }
#screen-msbgroup .msb-board.no-digs .msb-dig{ visibility:hidden; }
#screen-msbgroup .msb-board.lanes-in{ animation:msbFade .7s ease .55s both; }


/* ---- the column sum: a gutter for the minus sign, one column per place -- */
#screen-msbgroup .msb-board-wrap{ display:flex; justify-content:center; }
#screen-msbgroup .msb-board{ display:grid; grid-template-columns:34px repeat(var(--cols),64px); column-gap:6px;
  font-family:var(--font-display); font-weight:var(--weight-display); color:var(--text-primary); }
#screen-msbgroup .msb-c{ display:flex; align-items:center; justify-content:center; position:relative;
  transition:background var(--duration-base) var(--ease-out); }
/* the working column: a tinted band from the heading to the answer */
#screen-msbgroup .msb-c.hl{ background:color-mix(in srgb,var(--msb-c) 13%,transparent); }
#screen-msbgroup .msb-c.hl.msb-head{ border-radius:14px 14px 0 0; }
#screen-msbgroup .msb-c.hl.msb-ans{ border-radius:0 0 14px 14px; }
#screen-msbgroup .msb-c.warn .msb-dig{ color:var(--state-wrong); }
#screen-msbgroup .msb-head{ height:22px; font-family:var(--font-body); font-size:var(--text-sm);
  font-weight:var(--weight-strong); color:var(--text-secondary); }
#screen-msbgroup .msb-trow{ height:30px; }
#screen-msbgroup .msb-top, #screen-msbgroup .msb-bot{ height:58px; font-size:50px; line-height:1; }
#screen-msbgroup .msb-minus{ font-size:44px; height:58px; }
#screen-msbgroup .msb-rule{ grid-column:1 / -1; height:4px; border-radius:2px; background:var(--text-primary); margin:4px 0 8px; }
#screen-msbgroup .msb-dig{ position:relative; display:inline-block; }
/* a traded digit is crossed out; its new value is written small above it */
#screen-msbgroup .msb-dig.crossed{ color:var(--sand-500); }
#screen-msbgroup .msb-dig.crossed::after{ content:""; position:absolute; left:-4px; right:-4px; top:50%; height:4px;
  margin-top:-2px; background:var(--state-wrong); border-radius:2px; transform:rotate(-24deg); }
#screen-msbgroup .msb-new{ font-size:26px; line-height:1; color:var(--state-wrong); }
#screen-msbgroup .msb-trow .msb-tw{ font-size:20px; margin-right:3px; }
#screen-msbgroup .msb-new.pop, #screen-msbgroup .msb-ans.pop{ animation:msbPop .45s cubic-bezier(.3,1.6,.5,1) both; }
@keyframes msbPop{ 0%{ transform:scale(.3); opacity:0; } 100%{ transform:none; opacity:1; } }
#screen-msbgroup .msb-ans{ height:58px; margin:0 4px 4px; font-size:46px; border-radius:14px; border:2.5px solid transparent; }
#screen-msbgroup .msb-ans.active{ border-color:var(--msb-c); background:#fff; animation:msbBlink 1.4s ease-in-out infinite; }
/* every other box still to be answered: open, so no column looks locked */
#screen-msbgroup .msb-ans.open{ border:2.5px dashed color-mix(in srgb,var(--msb-c) 55%,transparent); background:#fff; cursor:pointer; }
#screen-msbgroup .msb-ans.ok, #screen-msbgroup .msb-board.done .msb-ans{ color:var(--state-correct); }
/* an answer the app had to show (two misses): gold, not green — it was not earned */
#screen-msbgroup .msb-ans.shown, #screen-msbgroup .msb-board.done .msb-ans.shown{ color:var(--accent-ink); }
#screen-msbgroup .msb-ans.wrong{ animation:msbShake .4s ease; border-color:var(--state-wrong); }

/* ---- the carry box (short multiplication) ------------------------------
   ▶ USER RULE 2026-09-20: a column whose product is two digits opens BOTH
   places to write, so the child writes "15", not the 5 and then the 1. The
   empty box has to be visible BEFORE anything is typed, or only one of the
   two is on screen and the rule is not kept. Same look as the answer box,
   scaled to the small carry row. */
#screen-msbgroup .msb-cbox{ display:inline-grid; place-items:center; min-width:26px; height:26px;
  padding:0 3px; border-radius:8px; border:2px solid var(--msb-c); background:#fff;
  font-family:var(--font-display); font-weight:var(--weight-display); font-size:19px; line-height:1;
  color:var(--msb-ink); animation:msbBlink 1.4s ease-in-out infinite; }
#screen-msbgroup .msb-cbox.has{ animation:none; }

/* the "r" in a remainder question (division level 8) */
.msb-rem{ margin:0 .28em; font-family:var(--font-body); font-weight:var(--weight-strong);
  font-size:.62em; color:var(--text-secondary); }
@media(max-width:420px){ #screen-msbgroup .msb-cbox{ min-width:22px; height:22px; font-size:16px; } }
@keyframes msbBlink{ 0%,100%{ box-shadow:0 0 0 0 transparent; }
                     50%{ box-shadow:0 0 0 5px color-mix(in srgb,var(--msb-c) 20%,transparent); } }
@keyframes msbShake{ 0%,100%{ transform:none; } 25%{ transform:translateX(-6px); } 75%{ transform:translateX(6px); } }


/* ---- working it out by hand (level 12 game) ----------------------------
   Answer / Cross / Trade, used freely; only the answers are marked. */
#screen-msbgroup .msb-board.tgame .msb-trow{ height:42px; }
#screen-msbgroup .msb-twrap{ display:inline-flex; align-items:center; gap:3px; }
#screen-msbgroup .msb-twbox{ display:inline-flex; align-items:center; justify-content:center; min-width:40px; height:32px;
  padding:0 3px; margin:0; border:2px dashed color-mix(in srgb,var(--msb-c) 45%,transparent); border-radius:9px;
  background:transparent; cursor:pointer; touch-action:manipulation;
  font-family:var(--font-display); font-weight:var(--weight-display); font-size:22px; line-height:1; color:var(--state-wrong); }
#screen-msbgroup .msb-twbox.filled{ border-color:transparent; }
#screen-msbgroup .msb-board[data-tool="trade"] .msb-twbox{ border-color:color-mix(in srgb,var(--msb-c) 70%,transparent); }
#screen-msbgroup .msb-twbox.active{ border:2px solid var(--msb-c); background:#fff;
  box-shadow:0 0 0 4px color-mix(in srgb,var(--msb-c) 18%,transparent); }
#screen-msbgroup .msb-twbox:focus-visible{ outline:3px solid var(--focus-ring); outline-offset:2px; }
#screen-msbgroup .msb-tw{ position:relative; display:inline-block; padding:0 2px; margin:0; background:none; border:0;
  cursor:pointer; border-radius:6px; font-family:var(--font-display); font-weight:var(--weight-display);
  font-size:22px; line-height:1; color:var(--sand-500); }
#screen-msbgroup .msb-tw.crossed::after{ content:""; position:absolute; left:-2px; right:-2px; top:50%; height:3px;
  margin-top:-2px; background:var(--state-wrong); border-radius:2px; transform:rotate(-24deg); }
#screen-msbgroup .msb-xbtn{ background:none; border:0; padding:0 4px; margin:0; font:inherit; color:inherit;
  line-height:1; cursor:pointer; border-radius:10px; touch-action:manipulation; }
/* with Cross on, the numbers that can be crossed out show it */
#screen-msbgroup .msb-board[data-tool="cross"] .msb-xbtn,
#screen-msbgroup .msb-board[data-tool="cross"] .msb-twbox.filled{ outline:2px dashed color-mix(in srgb,var(--state-wrong) 50%,transparent); outline-offset:1px; }
#screen-msbgroup .msb-xbtn:hover, #screen-msbgroup .msb-tw:hover{ background:var(--state-wrong-soft); }
#screen-msbgroup .msb-xbtn:focus-visible, #screen-msbgroup .msb-tw:focus-visible{ outline:3px solid var(--focus-ring); outline-offset:2px; }
#screen-msbgroup .msb-xbtn.crossed{ color:var(--sand-500); }


/* ---- the game ----------------------------------------------------------- */
#screen-msbgroup .msb-game .msb-body{ gap:var(--space-3); padding-bottom:var(--space-4); }
#screen-msbgroup .msb-status{ align-self:stretch; display:flex; align-items:center; gap:var(--space-3);
  font-size:var(--text-sm); font-weight:var(--weight-strong); color:var(--text-secondary); }
#screen-msbgroup .msb-qn{ white-space:nowrap; }
#screen-msbgroup .msb-qbar{ flex:1; height:6px; border-radius:3px; background:var(--sand-300); overflow:hidden; }
#screen-msbgroup .msb-qbar span{ display:block; height:100%; background:var(--msb-c); border-radius:3px;
  transition:width var(--duration-slow) var(--ease-out); }
#screen-msbgroup .msb-time{ white-space:nowrap; font-variant-numeric:tabular-nums; background:var(--bg-raised);
  border-radius:var(--radius-pill); padding:2px var(--space-3); }
#screen-msbgroup .msb-time::before{ content:"\23F1\00a0"; }
#screen-msbgroup .msb-game .msb-board-wrap{ flex:1; min-height:0; align-items:center; }
/* feedback + hints: one tinted box, always the same place and height */
#screen-msbgroup .msb-fb{ align-self:stretch; margin:0; min-height:2.9em; display:flex; align-items:center; justify-content:center;
  text-align:center; padding:var(--space-2) var(--space-3); border-radius:var(--radius-md);
  font-size:var(--text-sm); font-weight:var(--weight-medium); line-height:var(--leading-snug);
  background:var(--msb-soft); color:var(--text-primary); }
#screen-msbgroup .msb-fb:empty{ background:transparent; }
#screen-msbgroup .msb-fb.bad{ background:var(--state-wrong-soft); color:var(--state-wrong-ink); }
#screen-msbgroup .msb-fb.good{ background:var(--state-correct-soft); color:var(--state-correct-ink); font-weight:var(--weight-strong); }
#screen-msbgroup .msb-fb.show{ background:var(--accent-soft); color:var(--accent-ink); font-weight:var(--weight-strong); }
/* Answer / Cross / Trade: a segmented switch, the mode in use filled */
#screen-msbgroup .msb-modes{ align-self:stretch; display:flex; gap:4px; padding:4px;
  background:var(--bg-raised); border-radius:var(--radius-pill); }
#screen-msbgroup .msb-mode{ flex:1; min-height:40px; border:0; border-radius:var(--radius-pill); cursor:pointer;
  background:transparent; color:var(--ink-700); font-family:var(--font-body); font-weight:var(--weight-strong);
  font-size:var(--text-base); transition:background var(--duration-fast) var(--ease-out), color var(--duration-fast) var(--ease-out); }
#screen-msbgroup .msb-mode::after{ content:""; }
#screen-msbgroup .msb-mode:hover{ background:var(--sand-200); }
#screen-msbgroup .msb-mode.on{ background:var(--msb-c); color:#fff; box-shadow:var(--elev-1); }
#screen-msbgroup .msb-mode:focus-visible{ outline:3px solid var(--focus-ring); outline-offset:2px; }
/* ---- the keypad: a CALCULATOR ------------------------------------------
   User rule 2026-09-21: "it should look like a calculator with proper shades
   and style". So: 7 8 9 / 4 5 6 / 1 2 3 / 0 (the order on every calculator and
   phone a child has used — the digits used to run 1-5 / 6-0), sitting in a
   sunken tray, with keys that carry a real edge and press INTO it.
   ⚠ Four rows where there were two. The game screen must still fit without
   scrolling (the user's rule), so the keys are sized in a clamp that gives way
   on a short window rather than pushing the board off the screen. */
#screen-msbgroup .msb-keys{ align-self:stretch; display:grid; grid-template-columns:repeat(3,minmax(0,1fr));
  gap:var(--space-2); width:100%; max-width:340px; margin:0 auto; padding:var(--space-2);
  border-radius:var(--radius-lg); background:var(--bg-sunken);
  box-shadow:inset 0 1px 3px rgba(47,42,61,.10), 0 1px 0 var(--sand-50); }
#screen-msbgroup .msb-key{ min-height:clamp(40px, 7.2vh, 54px); border-radius:var(--radius-md); cursor:pointer;
  touch-action:manipulation; color:var(--text-primary); border:1px solid var(--border-subtle);
  background:linear-gradient(180deg, var(--sand-50) 0%, var(--bg-raised) 100%);
  box-shadow:0 2px 0 var(--sand-300), 0 1px 2px rgba(47,42,61,.10);
  font-family:var(--font-display); font-weight:var(--weight-display); font-size:clamp(22px, 3.4vh, 28px);
  transition:background var(--duration-fast) var(--ease-out), box-shadow var(--duration-fast) var(--ease-out); }
#screen-msbgroup .msb-key:hover{ background:linear-gradient(180deg, #fff 0%, var(--sand-100) 100%); }
#screen-msbgroup .msb-key:active{ transform:translateY(2px); box-shadow:inset 0 2px 4px rgba(47,42,61,.14); }
#screen-msbgroup .msb-key:focus-visible{ outline:3px solid var(--focus-ring); outline-offset:2px; }
/* the 0 runs along the bottom, as it does on a calculator */
#screen-msbgroup .msb-keys .msb-key:nth-child(10){ grid-column:1 / span 3; }
/* the answer written in its box, waiting for Check (js/19 msbColCheck) */
#screen-msbgroup .msb-pend{ color:var(--msb-ink); }
/* ⚠⚠ THE COLUMN GAMES: board BESIDE the calculator where there is room, stacked on a
   phone (2026-09-21). With the calculator's four rows stacked under the board,
   Level 8's board got 154px of the 258 it needs on a laptop and 71px on a short
   one, and spilled over the status bar and the hint — while the PAGE still fitted,
   which is all the check measured. Now: side by side from 720px, and on a phone
   the keys give a little height. test-msb measures each part against its box. */
@media (min-width:720px){
  #screen-msbgroup .msb-game:not(.msb-sgame) .msb-body{ max-width:760px; display:grid;
    grid-template-columns:minmax(0,1fr) minmax(250px,310px); grid-template-rows:auto minmax(0,1fr) auto;
    column-gap:var(--space-6); row-gap:var(--space-2); align-items:center; }
  #screen-msbgroup .msb-game:not(.msb-sgame) .msb-status{ grid-column:1 / -1; grid-row:1; }
  #screen-msbgroup .msb-game:not(.msb-sgame) .msb-board-wrap{ grid-column:1; grid-row:2; }
  #screen-msbgroup .msb-game:not(.msb-sgame) .msb-fb{ grid-column:1; grid-row:3; }
  #screen-msbgroup .msb-game:not(.msb-sgame) .msb-body > .msb-pad,
  #screen-msbgroup .msb-game:not(.msb-sgame) .msb-body > .msb-keys{ grid-column:2; grid-row:2 / span 2; align-self:center; }
  #screen-msbgroup .msb-game:not(.msb-sgame) .msb-keys{ max-width:none; }
}
/* the switch and the calculator travel together */
#screen-msbgroup .msb-pad{ align-self:stretch; display:flex; flex-direction:column; gap:var(--space-2); width:100%; }
#screen-msbgroup .msb-pad .msb-modes{ align-self:stretch; }
@media (max-width:719px){
  #screen-msbgroup .msb-game:not(.msb-sgame) .msb-key{ min-height:clamp(40px, 6vh, 48px); }
}
/* the answer box on a trading board is tappable (js/19 msbAnswerMode), so a child
   can move between the trade boxes and the answer in any order */
#screen-msbgroup .msb-ans{ position:relative; }
#screen-msbgroup .msb-ansbtn{ position:absolute; inset:0; width:100%; height:100%; padding:0; margin:0;
  background:none; border:0; cursor:pointer; }
#screen-msbgroup .msb-ansbtn:focus-visible{ outline:3px solid var(--focus-ring); outline-offset:2px; border-radius:inherit; }


/* ---- the result -------------------------------------------------------- */
#screen-msbgroup .msb-result .msb-body{ gap:var(--space-4); }
#screen-msbgroup .msb-stars{ display:flex; gap:6px; font-size:48px; line-height:1; color:var(--sand-300); }
#screen-msbgroup .msb-stars span.on{ color:var(--gold-500); animation:msbPop .5s cubic-bezier(.3,1.6,.5,1) both; }
#screen-msbgroup .msb-stars span.on:nth-child(2){ animation-delay:.15s; }
#screen-msbgroup .msb-stars span.on:nth-child(3){ animation-delay:.3s; }
#screen-msbgroup .msb-res-title{ margin:0; font-family:var(--font-display); font-weight:var(--weight-display);
  font-size:var(--text-2xl); line-height:var(--leading-tight); color:var(--text-primary); }
/* four now: right, wrong, time, best (the round is counted, not scored on first tries) */
#screen-msbgroup .msb-stats{ display:grid; grid-template-columns:repeat(4,minmax(0,1fr)); gap:var(--space-2); width:100%; max-width:430px; }
@media(max-width:420px){ #screen-msbgroup .msb-stats{ grid-template-columns:repeat(2,minmax(0,1fr)); max-width:280px; } }
#screen-msbgroup .msb-stat{ background:var(--bg-raised); border-radius:var(--radius-md); padding:var(--space-2) var(--space-3);
  min-width:0; text-align:center; }
#screen-msbgroup .msb-stat b{ display:block; font-family:var(--font-display); font-weight:var(--weight-display);
  font-size:var(--text-xl); color:var(--text-primary); }
#screen-msbgroup .msb-stat span{ font-size:var(--text-xs); color:var(--text-secondary); }
#screen-msbgroup .msb-empty .msb-sign{ margin-bottom:var(--space-1); }
#screen-msbgroup .msb-empty-text{ margin:0; max-width:36ch; color:var(--text-secondary); font-size:var(--text-base); }


/* ---- phones ------------------------------------------------------------ */
@media(max-width:420px){
  #screen-msbgroup .msb-stage{ height:calc(100vh - 184px); height:calc(100dvh - 184px); min-height:560px; }
  #screen-msbgroup .msb-body{ padding:var(--space-3) var(--space-3) var(--space-2); gap:var(--space-2); }
  #screen-msbgroup .msb-ctrl{ padding:var(--space-2) var(--space-3); gap:var(--space-2); }
  #screen-msbgroup .msb-intro-cap{ font-size:var(--text-base); }
  /* the coach already says "Step 5 of 10"; ten dots would wrap beside the buttons */
  #screen-msbgroup .msb-intro-dots{ visibility:hidden; }
  /* hidden, but it still takes room: keep the old 7px row so the control bar does not grow on a phone */
  #screen-msbgroup .msb-intro-dots .msb-dot{ height:7px; }
  #screen-msbgroup .msb-coach{ padding:var(--space-2) calc(28px + var(--space-2) * 2); }
  #screen-msbgroup .msb-coach-av{ left:var(--space-2); top:var(--space-2); width:28px; height:28px; font-size:15px; }
  /* still a heading on a phone: bigger than the 17px script line under it */
  #screen-msbgroup .msb-coach-strat{ font-size:var(--text-lg); }
  #screen-msbgroup .msb-coach-n{ font-size:var(--text-xs); }
  /* ⚠ the column intro's FIRST frame scales the sum by 1.55 to sit big in the
     middle, so at 29px a Year 5 sum (642 − 275 = ?) runs off both sides of a
     375px stage. 24px here still outranks the working, which drops to 20px. */
  #screen-msbgroup .msb-eq{ font-size:var(--text-xl); }
  #screen-msbgroup .msb-board{ grid-template-columns:28px repeat(var(--cols),54px); }
  #screen-msbgroup .msb-top, #screen-msbgroup .msb-bot{ font-size:40px; height:48px; }
  #screen-msbgroup .msb-minus{ font-size:34px; height:48px; }
  #screen-msbgroup .msb-trow{ height:24px; }
  #screen-msbgroup .msb-new{ font-size:22px; }
  #screen-msbgroup .msb-ans{ height:50px; font-size:38px; margin:0 3px 4px; }
  #screen-msbgroup .msb-board.tgame .msb-trow{ height:36px; }
  #screen-msbgroup .msb-twbox{ min-width:32px; height:30px; font-size:20px; }
  #screen-msbgroup .msb-tw{ font-size:20px; }
  /* the clamp above already gives way on a short window */
  #screen-msbgroup .msb-mode{ font-size:var(--text-sm); }
  #screen-msbgroup .msb-start, #screen-msbgroup .msb-btn2{ padding:0 var(--space-4); }
}
/* ---- strategy levels (js/21-speed-strategies.js) -----------------------
   The picture: the task line, a number line with jumps, a part-whole bar and
   the working lines. A part of the NEW step (.new) animates in; an answer in
   it (.msb-late) waits MSB_THINK_MS (2s) first — "45 − 10 = … 35". */
#screen-msbgroup .msb-s-scene{ flex:1; min-height:0; width:100%; display:flex; flex-direction:column;
  align-items:center; gap:var(--space-2); overflow:hidden; }
/* ▶ the task line is the QUESTION, so it outranks the working written below it
   (user rule 2026-09-20: every element of the animation carries its true weight;
   before this the task line, the bar and every working row were all --text-xl).
   Its size lives on .msb-eq, which levels 11 and 12 share. */
#screen-msbgroup .msb-s-task{ transition:none; }
/* the question and its PARTNER sum side by side (subtraction level 1, step 2):
   13 − 8 = ?  ⇄  8 + ? = 13. Same weight as the task line — it is the same
   question asked the other way. On a phone the pair stacks and the ⇄ turns
   to point between them. The ⇄ is inline-block so msbHi can zoom it
   (`scale` does nothing to an inline box). */
/* zoom targets (msbHi in js/19): `scale` does nothing to an inline box, and an
   SVG element scales about the SVG's corner unless told to use its own box */
#screen-msbgroup .msb-eqn{ display:inline-block; }
.msb-nl-jump text, .msb-nl-mark{ transform-box:fill-box; transform-origin:center; }
#screen-msbgroup .msb-partner{ display:flex; align-items:center; justify-content:center; gap:var(--space-3); flex-wrap:nowrap; }
#screen-msbgroup .msb-partner-sym{ display:inline-block; font-family:var(--font-display); font-weight:var(--weight-display);
  font-size:var(--text-2xl); line-height:1; color:var(--msb-c); }
@media(max-width:560px){
  #screen-msbgroup .msb-partner{ flex-direction:column; gap:2px; }
  #screen-msbgroup .msb-partner-sym{ rotate:90deg; font-size:var(--text-xl); }
}
.msb-nl{ display:block; width:100%; max-width:600px; height:auto; overflow:visible;
  font-family:var(--font-display); font-weight:var(--weight-display); }
.msb-nl-axis{ stroke:var(--ink-700); stroke-width:3; stroke-linecap:round; }
.msb-nl-tick{ stroke:var(--sand-500); stroke-width:1.5; }
.msb-nl-tick.big{ stroke:var(--ink-500); stroke-width:2; }
.msb-nl-mark circle{ fill:var(--bg-surface); stroke:var(--ink-700); stroke-width:3; }
.msb-nl-mark.land circle{ fill:var(--msb-c); stroke:var(--msb-c); }
.msb-nl-mark text{ font-size:19px; fill:var(--text-primary); text-anchor:middle; }
.msb-nl-jump path{ fill:none; stroke:var(--msb-c); stroke-width:3.5; stroke-linecap:round; }
.msb-nl-jump.up path{ stroke:var(--msb-ink); stroke-dasharray:none; }
.msb-nl-jump text{ font-size:18px; fill:var(--msb-ink); text-anchor:middle; }
.msb-nl-gap path{ fill:none; stroke:var(--ink-500); stroke-width:2.5; }
.msb-nl-gap text{ font-size:15px; fill:var(--text-secondary); text-anchor:middle; font-family:var(--font-body); }
/* the jump draws itself, then the landing point pops in */
.msb-nl-jump.new path{ stroke-dasharray:1; animation:msbDraw .8s var(--ease-out) both; }
.msb-nl-jump.new text{ animation:msbFade .4s ease .7s both; }
.msb-nl-mark.new{ animation:msbFade .4s ease .75s both; }
.msb-nl-gap.new{ animation:msbFade .5s ease .3s both; }
/* a jump can wait its turn (--jd, set by a level): skip counting draws 4, 8, 12 … one after another */
.msb-nl-jump.new path{ animation-delay:var(--jd, 0s); }
.msb-nl-jump.new text{ animation-delay:calc(var(--jd, 0s) + .7s); }
.msb-nl-mark.new{ animation-delay:calc(var(--jd, 0s) + .75s); }
@keyframes msbDraw{ from{ stroke-dashoffset:1; } to{ stroke-dashoffset:0; } }

.msb-bar{ width:100%; max-width:440px; display:flex; flex-direction:column; gap:4px;
  font-family:var(--font-display); font-weight:var(--weight-display); font-size:var(--text-xl); }
.msb-bar-whole{ text-align:center; padding:var(--space-2); border-radius:var(--radius-md);
  background:var(--msb-soft); color:var(--msb-ink); border:2px solid var(--msb-c); }
.msb-bar-parts{ display:flex; gap:4px; }
.msb-bar-part{ text-align:center; padding:var(--space-2); border-radius:var(--radius-md); min-width:0;
  background:var(--bg-surface); border:2px solid var(--border-control); color:var(--text-primary); }
.msb-bar-part.unk{ border-style:dashed; border-color:var(--msb-c); color:var(--msb-c); }
.msb-bar-part.found{ background:var(--state-correct-soft); border-color:var(--state-correct); color:var(--state-correct-ink); }
/* the WHOLE is what was found, on a question where the whole was missing */
.msb-bar-whole.found{ background:var(--state-correct-soft); border-color:var(--state-correct); color:var(--state-correct-ink); }
.msb-bar.new{ animation:msbFade .5s ease both; }

.msb-rows{ display:flex; flex-direction:column; align-items:center; gap:4px;
  font-family:var(--font-display); font-weight:var(--weight-display); font-size:var(--text-xl); color:var(--text-primary); }
.msb-row.new{ animation:msbFade .4s ease both; }
/* a short window (js/21 msbFitScene): the working lines give way, never the picture — tighter, then side by side */
#screen-msbgroup .fit1{ gap:6px; }
#screen-msbgroup .fit1 .msb-rows{ font-size:var(--text-lg); gap:0; line-height:1.15; }
#screen-msbgroup .fit2 .msb-rows{ flex-direction:row; flex-wrap:wrap; justify-content:center; column-gap:1.1em; font-size:var(--text-base); }
#screen-msbgroup .fit1 .msb-row.q, #screen-msbgroup .fit1 .msb-row.look{ margin-top:0; }
#screen-msbgroup .msb-scene.fit2{ gap:0; }
#screen-msbgroup .msb-scene.fit2 > .msb-eq{ padding-top:0; padding-bottom:0; }
#screen-msbgroup .msb-s-scene.fit2 .msb-wp{ padding-top:4px; padding-bottom:4px; }
/* Pick the strategy: a finished example kept as one quiet line */
.msb-row.done{ font-size:.8em; color:var(--text-secondary); }
.msb-row.done b{ font-family:var(--font-body); font-size:.8em; color:var(--msb-ink); }
.msb-row.q{ margin-top:var(--space-2); color:var(--msb-ink); }
/* Pick the strategy's opening: the example's sums side by side, "look at the numbers" */
.msb-row.look{ display:flex; flex-wrap:wrap; justify-content:center; gap:var(--space-3) var(--space-5); margin-top:var(--space-4); }
.msb-row.look span{ padding:var(--space-2) var(--space-4); border-radius:14px;
  background:color-mix(in srgb, var(--msb-c) 16%, transparent); }   /* ⚠ not --msb-soft: a shade off the card, invisible */
.msb-row.pick b{ display:inline-block; font-family:var(--font-body); font-size:var(--text-sm); font-weight:var(--weight-strong);
  padding:2px var(--space-3); border-radius:var(--radius-pill); background:var(--msb-soft); color:var(--msb-ink); }
.msb-late{ color:var(--state-correct-ink); }

/* the ? standing in for the box in the missing-number intro (subtraction 3) */
.msb-miss{ display:inline-grid; place-items:center; min-width:1.1em; padding:0 .12em; border-radius:10px;
  border:2.5px dashed var(--msb-c); color:var(--msb-c); }
.msb-miss.got{ border-style:solid; background:var(--state-correct-soft);
  border-color:var(--state-correct); color:var(--state-correct-ink); }
/* a narrated example sets --msb-late to when the answer is spoken */
.new .msb-late, .msb-bar-part .msb-late{ display:inline-block; animation:msbPop .45s cubic-bezier(.3,1.6,.5,1) var(--msb-late, 2s) both; }

/* the strategy game: one question, one typed answer */
#screen-msbgroup .msb-sq{ flex:1; min-height:0; width:100%; display:flex; flex-direction:column; align-items:center; justify-content:center; gap:var(--space-3); }
.msb-sq-line{ display:flex; align-items:center; justify-content:center; gap:var(--space-2);
  font-family:var(--font-display); font-weight:var(--weight-display); font-size:44px; color:var(--text-primary); }
.msb-sq-line .msb-eqop{ margin:0 .15em; }
/* a THREE-number question (Make tens first: 410 + 590 + 643 = ☐) is far wider than two, and
   ran off both edges of a phone at 36px. Its text follows the screen width instead. */
.msb-sq3{ display:contents; }
@media(max-width:560px){
  .msb-sq-line:has(.msb-sq3){ font-size:clamp(18px, 6.2vw, 36px); gap:var(--space-1); }
  .msb-sq-line:has(.msb-sq3) .msb-eqop{ margin:0 .08em; }
}
.msb-sq-text{ margin:0; max-width:32ch; text-align:center; font-family:var(--font-body); font-size:var(--text-lg);
  line-height:var(--leading-normal); color:var(--text-primary); }
.msb-sq-unit{ font-size:var(--text-xl); color:var(--text-secondary); }
.msb-sq-box{ min-width:2.4em; padding:0 .25em; text-align:center; border-radius:14px; background:#fff;
  border:2.5px solid var(--msb-c); color:var(--text-primary); line-height:1.25; }
.msb-sq-box.empty{ animation:msbBlink 1.4s ease-in-out infinite; }
.msb-sq-box.ok{ border-color:var(--state-correct); background:var(--state-correct-soft); color:var(--state-correct-ink); }
.msb-sq-box.shown{ border-color:var(--accent-border); background:var(--accent-soft); color:var(--accent-ink); }
.msb-sq-box.wrong{ border-color:var(--state-wrong); animation:msbShake .4s ease; }
/* Delete and Check stand in a fourth column, like a calculator's C and =.
   They are placed EXPLICITLY, so the ten digits flow around them into the 3x4
   block on the left without any of them being given a position of its own. */
#screen-msbgroup .msb-skeys{ grid-template-columns:repeat(4,minmax(0,1fr)); max-width:420px; }
#screen-msbgroup .msb-skeys .msb-key-back{ grid-column:4; grid-row:1; font-size:var(--text-xl);
  background:linear-gradient(180deg, var(--sand-100) 0%, var(--sand-200) 100%); }
#screen-msbgroup .msb-skeys .msb-key:nth-child(10){ grid-column:1 / span 3; }
#screen-msbgroup .msb-skeys.has-dot .msb-key:nth-child(10){ grid-column:1 / span 2; }
#screen-msbgroup .msb-skeys .msb-key-check{ grid-column:4; grid-row:2 / span 3; background:var(--action); color:var(--text-on-action);
  border-color:transparent; box-shadow:var(--elev-2); font-size:var(--text-lg); }
#screen-msbgroup .msb-skeys .msb-key-check:hover{ background:var(--action-hover); }
/* ⚠ measured 2026-10-02: on an iPad (1024x768) the keypad's 54px keys left the question 182px, and a
   four-line word problem needs 202 — the bubble rode up over "Question 1 of 10" (most Year 5 word
   problems in all four operations; 4px over on a laptop). The page still "fitted", so no suite saw it.
   Wide screens now take the key height from the screen a little sooner; phones are untouched. */
@media (min-width:720px){ #screen-msbgroup .msb-sgame .msb-skeys .msb-key{ min-height:clamp(40px, 5.8vh, 54px); } }   /* 6.2vh still left the longest ones 6px over on the iPad */
/* All text in the Speed Builder boxes is CENTRED (user, 2026-09-19).
   level 13: the problem card, lit numbers, the question underlined, compare bars */
.msb-wp{ width:100%; max-width:520px; padding:var(--space-3) var(--space-4); border-radius:var(--radius-lg);
  background:var(--bg-raised); border:1px solid var(--border-subtle); font-family:var(--font-body);
  font-size:var(--text-lg); line-height:var(--leading-normal); color:var(--text-primary); text-align:center; }
.msb-wp-n{ display:inline-block; font-weight:var(--weight-strong); }   /* inline-block: msbHi zooms it */
.msb-wp.lit .msb-wp-n{ background:var(--msb-soft); color:var(--msb-ink); border-radius:6px; padding:0 4px;
  box-shadow:inset 0 0 0 1.5px var(--msb-c); }
.msb-wp.lit .msb-wp-s.q{ text-decoration:underline; text-decoration-color:var(--msb-c); text-decoration-thickness:3px; text-underline-offset:4px; }
.msb-wp.new .msb-wp-n, .msb-wp.new .msb-wp-s.q{ animation:msbFade .5s ease both; }
.msb-wpbar{ max-width:480px; font-size:var(--text-lg); }
/* ⚠ measured 2026-10-02: on an iPad (1024x768) the example's scene is 308px and its fullest step
   (problem + bar + three working rows + the answer sentence) needs 326: the answer sentence was cut
   off (subtraction both years, addition and multiplication Year 5). No suite ran at iPad size. Same
   type sizes; only the spacing round the problem card and the bar closes up on a short, wide screen. */
@media (min-width:720px) and (max-height:799px){
  /* the same screen, the same cause, in the examples that draw a tall picture: multiplication's dot
     arrays lost their last working row (Times 5, Times 9, Split strategy: 29-34px over) and the white
     paper of division's Share equally lost its bottom edge (6px). The picture is drawn a little smaller. */
  #screen-msbgroup #msb-scene .msb-arr{ zoom:.8; }
  #screen-msbgroup #msb-scene .msb-paper{ max-width:min(100%,490px); }
  #screen-msbgroup #msb-scene:has(> .msb-wp){ gap:6px; }
  #screen-msbgroup #msb-scene > .msb-wp{ padding:var(--space-2) var(--space-4); }
  #screen-msbgroup #msb-scene > .msb-wpbar .msb-bar-whole, #screen-msbgroup #msb-scene > .msb-wpbar .msb-bar-part{ padding:var(--space-1) var(--space-2); }
}
.msb-bar-whole.unk{ border-style:dashed; background:var(--bg-surface); color:var(--msb-c); }
.msb-bar-part.given{ background:var(--msb-soft); }
/* what is LEFT OVER after the equal groups — narrower, and clearly not one */
.msb-bar-part.left{ background:repeating-linear-gradient(135deg,var(--sand-200) 0 6px,var(--bg-surface) 6px 12px);
  border-style:dashed; color:var(--text-secondary); }
.msb-cmp-row{ display:flex; }
.msb-cmp-row .msb-bar-whole, .msb-cmp-row .msb-bar-parts{ flex:1; }
.msb-row.say{ margin-top:var(--space-1); font-family:var(--font-body); font-size:var(--text-lg); color:var(--state-correct-ink); }

/* ---- MULTIPLICATION's explanation pages (2026-10-04: every intro first says what its idea means) ---------- */
/* a skip count written out: the numbers we land on bold, the ones skipped over faded (js/23 msbSkipRow) */
#screen-msbgroup .msb-skiprow{ display:inline-flex; flex-wrap:wrap; justify-content:center; gap:.1em .5em; }
#screen-msbgroup .msb-skiprow b{ color:var(--msb-ink); }
#screen-msbgroup .msb-skip{ opacity:.35; font-weight:400; }
/* a tens | ones chart (js/23 msbPV): the ×10 pattern's digit moving one place */
#screen-msbgroup .msb-row.pv{ display:flex; align-items:center; justify-content:center; gap:var(--space-3); }
#screen-msbgroup .msb-pv{ display:inline-flex; border:2px solid var(--msb-c); border-radius:12px; overflow:hidden; background:var(--bg-surface); }
#screen-msbgroup .msb-pv .pvc{ display:flex; flex-direction:column; align-items:center; min-width:3.1em; padding:2px 8px 4px; }
#screen-msbgroup .msb-pv .pvc + .pvc{ border-left:2px solid var(--msb-soft); }
#screen-msbgroup .msb-pv small{ font-size:.55em; font-weight:600; color:var(--text-secondary); }
#screen-msbgroup .msb-pv b{ min-height:1.2em; }
#screen-msbgroup .msb-pv .pvc.lit{ background:var(--msb-soft); }
#screen-msbgroup .msb-pv-arrow{ color:var(--msb-c); font-weight:700; }
/* the column intro's explain phase (js/19): the sum and the board step aside for the picture */
#screen-msbgroup .msb-explain{ display:none; }
#screen-msbgroup .msb-scene.explain .msb-explain{ display:flex; flex:1; align-items:center; justify-content:center; width:100%; }
#screen-msbgroup .msb-scene.explain > .msb-eq, #screen-msbgroup .msb-scene.explain > .msb-board-wrap{ display:none; }
/* short multiplication: hundreds · tens · ones, the order we work in, each column in turn (js/24 msbColChart) */
#screen-msbgroup .msb-cc{ display:flex; gap:clamp(8px, 2vw, 14px); }
#screen-msbgroup .msb-cc-col{ display:flex; flex-direction:column; align-items:center; gap:6px; width:clamp(76px, 22vw, 100px); }
#screen-msbgroup .msb-cc-h{ font-family:var(--font-body); font-weight:600; font-size:var(--text-sm); color:var(--text-secondary); }
#screen-msbgroup .msb-cc-box{ width:80%; height:clamp(80px, 15vh, 120px); border-radius:14px; background:var(--msb-soft); box-shadow:inset 0 0 0 2px rgba(0,0,0,.06); }
#screen-msbgroup .msb-cc-n{ width:34px; height:34px; border-radius:50%; background:var(--msb-c); color:#fff; display:grid; place-items:center;
  font-family:var(--font-display); font-weight:var(--weight-display); opacity:0; }
#screen-msbgroup .msb-cc.st1 .msb-cc-n, #screen-msbgroup .msb-cc.st2 .msb-cc-n{ opacity:1; }
#screen-msbgroup .msb-explain.live .msb-cc.st0 .msb-cc-col{ animation:msbFade .5s ease both; }
#screen-msbgroup .msb-explain.live .msb-cc.st0 .c2{ animation-delay:.35s; }
#screen-msbgroup .msb-explain.live .msb-cc.st0 .c1{ animation-delay:.7s; }
#screen-msbgroup .msb-explain.live .msb-cc.st1 .msb-cc-n{ animation:msbPop .45s ease both; }
#screen-msbgroup .msb-explain.live .msb-cc.st1 .c1 .msb-cc-n{ animation-delay:.6s; }
#screen-msbgroup .msb-explain.live .msb-cc.st1 .c2 .msb-cc-n{ animation-delay:1.6s; }
#screen-msbgroup .msb-explain.live .msb-cc.st1 .c3 .msb-cc-n{ animation-delay:2.6s; }
#screen-msbgroup .msb-explain.live .msb-cc.st2 .msb-cc-box{ animation:msbCcLit 1.1s ease both; }
#screen-msbgroup .msb-explain.live .msb-cc.st2 .c1 .msb-cc-box{ animation-delay:.4s; }
#screen-msbgroup .msb-explain.live .msb-cc.st2 .c2 .msb-cc-box{ animation-delay:1.5s; }
#screen-msbgroup .msb-explain.live .msb-cc.st2 .c3 .msb-cc-box{ animation-delay:2.6s; }
@keyframes msbCcLit{ 0%, 100%{ background:var(--msb-soft); } 30%, 70%{ background:var(--msb-c); } }
/* carrying: 6 × 4 = 24, the 4 written in the ones and the 2 carried above the tens, then travelling there (msbCarryChart) */
#screen-msbgroup .msb-cx{ display:flex; flex-direction:column; align-items:center; gap:var(--space-4); }
#screen-msbgroup .msb-cx-sum{ font-family:var(--font-display); font-weight:var(--weight-display); font-size:var(--text-2xl); color:var(--text-primary); }
#screen-msbgroup .msb-cx-sum b{ color:var(--state-correct-ink); }
#screen-msbgroup .msb-cx-chart{ position:relative; display:flex; gap:12px; --cxw:clamp(80px, 22vw, 96px); --cxdy:0px; }
#screen-msbgroup .msb-cx-col{ display:flex; flex-direction:column; align-items:center; gap:4px; width:var(--cxw); }
#screen-msbgroup .msb-cx-carry{ height:32px; min-width:32px; text-align:center; font-family:var(--font-display); font-weight:var(--weight-display);
  font-size:var(--text-xl); color:var(--msb-c); }
#screen-msbgroup .msb-cx-h{ font-family:var(--font-body); font-weight:600; font-size:var(--text-sm); color:var(--text-secondary); }
#screen-msbgroup .msb-cx-box{ width:76px; height:80px; border-radius:14px; background:var(--msb-soft); display:grid; place-items:center;
  font-family:var(--font-display); font-weight:var(--weight-display); font-size:2.2rem; color:var(--text-primary); }
#screen-msbgroup .msb-cx-arrow{ position:absolute; top:-4px; left:50%; transform:translateX(-50%); font-size:30px; line-height:1; color:var(--msb-c); }
#screen-msbgroup .msb-explain.live .msb-cx.st0 .msb-cx-sum b{ animation:msbPop .5s ease 1.6s both; }
#screen-msbgroup .msb-explain.live .msb-cx.st1 .msb-cx-col:last-child .msb-cx-box{ animation:msbPop .45s ease 3.2s both; }
#screen-msbgroup .msb-explain.live .msb-cx.st1 .msb-cx-carry{ animation:msbPop .45s ease 6.6s both; }
#screen-msbgroup .msb-explain.live .msb-cx.st2 .msb-cx-carry{ animation:msbCxMove 1.3s cubic-bezier(.4,0,.2,1) .5s both; }
#screen-msbgroup .msb-explain.live .msb-cx.st2 .msb-cx-arrow{ animation:msbFade .4s ease .3s both; }
/* MULTIPLICATION's pictures (js/49): bags of apples, an egg carton, apples in rows. Each movement plays on the page
   that says it (.live/.new, js/21); a still frame shows the end. Times follow the words at a narrator's pace. */
#screen-msbgroup .ml-bag, #screen-msbgroup .ml-badge, #screen-msbgroup .ml-tag, #screen-msbgroup .ml-total, #screen-msbgroup .ml-egg{ transform-box:fill-box; transform-origin:50% 100%; }
#screen-msbgroup .ml-gone{ opacity:0; }
#screen-msbgroup .msb-pic:is(.live, .new) .ml-fill .ml-bag{ animation:msbPop .45s ease calc(.5s + var(--i) * .3s) both; }
#screen-msbgroup .msb-pic:is(.live, .new) .ml-fill .ml-apple{ animation:mlDrop .45s cubic-bezier(.3,.7,.3,1.2) calc(1.9s + var(--i) * .25s + var(--j) * .1s) both; }
#screen-msbgroup .msb-pic:is(.live, .new) .ml-count .ml-badge{ animation:msbPop .4s ease calc(.7s + var(--i) * .3s) both; }
#screen-msbgroup .msb-pic:is(.live, .new) .ml-count .ml-tag{ animation:msbPop .4s ease calc(2.6s + var(--i) * .2s) both; }
#screen-msbgroup .msb-pic:is(.live, .new) .ml-count .ml-sum{ animation:msbFade .5s ease 4.8s both; }
#screen-msbgroup .msb-pic:is(.live, .new) .ml-totals .ml-total{ animation:msbPop .4s ease calc(1s + var(--i) * .8s) both; }
#screen-msbgroup .msb-pic:is(.live, .new) .ml-fill .ml-egg{ animation:msbPop .35s ease calc(2.4s + var(--j) * .09s) both; }
#screen-msbgroup .msb-pic:is(.live, .new) .ml-rows .ml-ring{ animation:msbFade .45s ease calc(.6s + var(--r) * 1s) both; }
#screen-msbgroup .msb-pic:is(.live, .new) .ml-morph .ml-mv{ animation:mlMove 1s cubic-bezier(.3,.7,.2,1) calc(.6s + var(--k) * .03s) both; }
#screen-msbgroup .msb-pic:is(.live, .new) .ml-morph .ml-gone{ animation:mlGone .7s ease .5s both; }
#screen-msbgroup .msb-pic:is(.live, .new) .ml-morph .ml-mat{ animation:msbFade .5s ease 1.3s both; }
#screen-msbgroup .msb-pic:is(.live, .new) .ml-lbl{ animation:msbFade .5s ease .4s both; }
@keyframes mlDrop{ from{ transform:translateY(-36px); opacity:0; } 60%{ opacity:1; } }
@keyframes mlMove{ from{ transform:translate(var(--fx), var(--fy)) scale(var(--fs)); } }
@keyframes mlGone{ from{ opacity:1; } to{ opacity:0; } }
/* a laptop or iPad has the room: the explanation charts drawn bigger (they sat small in an empty scene) */
@media (min-width:720px){
  #screen-msbgroup .msb-cc-col{ width:120px; }
  #screen-msbgroup .msb-cc-h{ font-size:var(--text-base); }
  #screen-msbgroup .msb-cc-box{ height:clamp(110px, 20vh, 150px); }
  #screen-msbgroup .msb-cc-n{ width:40px; height:40px; font-size:var(--text-lg); }
  #screen-msbgroup .msb-cx-sum{ font-size:var(--text-3xl); }
  #screen-msbgroup .msb-cx-chart{ --cxw:120px; --cxdy:0px; }
  #screen-msbgroup .msb-cx-carry{ height:40px; font-size:var(--text-2xl); }
  #screen-msbgroup .msb-cx-h{ font-size:var(--text-base); }
  #screen-msbgroup .msb-cx-box{ width:100px; height:104px; font-size:2.8rem; }
}
@keyframes msbCxMove{ from{ transform:translate(calc(var(--cxw) + 12px), var(--cxdy)); opacity:.5; } to{ transform:none; opacity:1; } }   /* from above the ones over to the tens: it started ON the 4 and covered it */
#screen-msbgroup .msb-sgame .msb-sq-text{ max-width:36ch; text-align:center; padding:var(--space-3) var(--space-4);
  border-radius:var(--radius-lg); background:var(--bg-raised); border:1px solid var(--border-subtle); }
#screen-msbgroup .msb-sgame .msb-sq-text .msb-wp-n{ font-weight:var(--weight-strong); }
/* with the "." key: . ⌫ Check share the last row */
#screen-msbgroup .msb-skeys.has-dot .msb-key-dot{ grid-column:3; grid-row:4; font-size:var(--text-xl); }

@media(max-width:420px){
  .msb-sq-line{ font-size:36px; }
  .msb-wp, #screen-msbgroup .msb-sgame .msb-sq-text{ font-size:var(--text-base); padding:var(--space-2) var(--space-3); }
  .msb-rows, .msb-bar{ font-size:var(--text-lg); }
  .msb-nl-mark text, .msb-nl-jump text{ font-size:22px; }
}

@media(prefers-reduced-motion:reduce){
  .msb-nl-jump.new path, .msb-nl-jump.new text, .msb-nl-mark.new, .msb-nl-gap.new, .msb-bar.new, .msb-row.new,
  .new .msb-late, .msb-sq-box.empty{ animation:none !important; }
}
@media(prefers-reduced-motion:reduce){
  #screen-msbgroup .msb-ans.active, #screen-msbgroup .msb-start.ready, #screen-msbgroup .msb-ans.pop,
  #screen-msbgroup .msb-new.pop, #screen-msbgroup .msb-intro-cap.pop{ animation:none; }
  #screen-msbgroup .msb-eq-ans, #msb-intro-board .msb-dig, #msb-intro-board .msb-new{ animation:none !important; }
  #screen-msbgroup .msb-eq{ transition:none; }
}

/* ---- the ARRAY: multiplication's picture -------------------------------
   Rows of dots. v9 names arrays and equal groups as THE representation for
   multiplication at Year 2 (AC9M2N05), and every later strategy in the section
   is shown by re-cutting the same array: the split strategy cuts it into two
   blocks of columns, short multiplication cuts it at the tens.
   Sizes come from JS (--d, --g) because they shrink with the row count. */
.msb-arr{ display:flex; flex-direction:column; gap:var(--g); align-items:center; }
.msb-arr.new{ animation:msbFade .5s ease both; }
.msb-arr-row{ display:flex; gap:var(--g); align-items:center; border-radius:var(--radius-pill);
  padding:2px; transition:background var(--duration-base) var(--ease-out); }
.msb-arr.grp .msb-arr-row{ padding:3px var(--space-2); background:var(--msb-soft);
  box-shadow:inset 0 0 0 2px var(--msb-c); }
.msb-arr-row.lit{ background:color-mix(in srgb,var(--msb-c) 22%,transparent); }
.msb-arr-d{ width:var(--d); height:var(--d); border-radius:50%; background:var(--msb-c); flex:0 0 auto; }
.msb-arr-d.b{ background:var(--msb-ink); opacity:.55; }
/* the SPLIT TREE, drawn downwards (division's Split strategy; js/21 msbTreeSvg).
   Lines draw on the step that says them; an answer waits MSB_THINK_MS like .msb-late */
.msb-tree{ display:block; width:100%; max-width:340px; height:auto; overflow:visible;
  font-family:var(--font-display); font-weight:var(--weight-display); }
.msb-tree path{ fill:none; stroke:var(--msb-c); stroke-width:3.5; stroke-linecap:round; stroke-linejoin:round; }
.msb-tree-n{ font-size:28px; fill:var(--text-primary); text-anchor:middle; }
.msb-tree-n.top{ font-size:30px; }
.msb-tree-n.got{ fill:var(--state-correct-ink); }
.msb-tree-by{ font-size:18px; fill:var(--msb-ink); dominant-baseline:middle; }
.msb-tree-by.plus{ font-size:22px; text-anchor:middle; }
.msb-tree text{ transform-box:fill-box; transform-origin:center; }
.msb-tree .new path{ stroke-dasharray:1; animation:msbDraw .6s var(--ease-out) .1s both; }
.msb-tree .new path.head{ stroke-dasharray:none; animation:msbFade .3s ease .6s both; }
.msb-tree-split.new text{ animation:msbFade .4s ease .65s both; }
.msb-tree .new .msb-tree-by{ animation:msbFade .3s ease .5s both; }
.msb-tree .new .msb-tree-late{ animation:msbPop .45s cubic-bezier(.3,1.6,.5,1) var(--msb-late, 2s) both; }
@media(prefers-reduced-motion:reduce){
  .msb-tree .new path, .msb-tree .new text{ animation:none !important; }
}
/* the narrated lesson's paper scene, played inside an example (js/21 msbSceneMount) */
.msb-paper{ margin:var(--space-2) auto 0; width:100%; max-width:min(100%,560px); align-self:stretch; }
.msb-paper svg{ display:block; width:100%; height:auto; }

/* a counter not dealt yet: it holds its place so the group keeps its size */
.msb-arr-d.held{ visibility:hidden; }
.msb-arr-d.pop{ animation:msbPop .42s var(--ease-out) both; }
/* the cut that shows a split: a gap wide enough to read as two blocks */
.msb-arr-cut{ width:calc(var(--g) * 2.5); flex:0 0 auto; }
.msb-arr-lbl{ display:flex; justify-content:center; gap:var(--space-5); font-family:var(--font-body);
  font-weight:var(--weight-strong); font-size:var(--text-sm); color:var(--text-secondary); }
@media(max-width:420px){
  .msb-arr-lbl{ font-size:var(--text-xs); gap:var(--space-3); }
}

