
  :root{
    --bg:#fff9ec; --card:#ffffff; --ink:#3a2d5c; --muted:#8a7fa8;
    /* Bolder kid palette (brighter, more saturated; hues kept so tints/shadows stay harmonised) */
    --blue:#2f7bff; --blue-dark:#1f5fe0; --blue-soft:#e6efff;
    --pink:#ff5da2; --pink-dark:#e63e88;
    --purple:#8b5cf6; --purple-dark:#6d28d9; --purple-soft:#f3ecff;
    --orange:#ff9838; --orange-dark:#f07d12;
    --green:#12c07a; --green-dark:#0aa565; --green-soft:#d9f7ea;
    --amber:#ffc233; --amber-soft:#fff2cc;
    --red:#ff5d5d; --red-soft:#ffe4e4;
    --line:#f0e6d6;
    /* Two greys for the Level 2 gap slots: the darker marks a gap still to fill, the
       lighter everything settled, so a finished word is not striped. */
    --gap-strong:#a49cb8; --gap-soft:#dcd8e4;
    /* Fonts */
    --font-display:"Fredoka","Baloo 2",cursive;
    --font-round:"Baloo 2",cursive;
    --font-body:"Nunito",system-ui,sans-serif;
    /* Bright accent set for chrome/hero (do not affect graphic tints) */
    --sky:#38bdf8; --sunny:#ffd23f; --coral:#ff6b6b; --mint:#3ddc97;
    --grad-hero:linear-gradient(135deg,#8b5cf6 0%,#2f7bff 55%,#38bdf8 100%);
  }
  *{box-sizing:border-box;}
  html{scrollbar-gutter:stable;}
  body{margin:0;font-family:"Nunito",system-ui,sans-serif;background:var(--bg);
       background-image:radial-gradient(circle at 12% 10%,#ffe9b0 0,transparent 32%),radial-gradient(circle at 88% 8%,#ffd6ec 0,transparent 30%),radial-gradient(circle at 50% 100%,#d9ecff 0,transparent 40%);
       color:var(--ink);padding:20px 14px 60px;-webkit-text-size-adjust:100%;}
  /* App shell. This used to be a hard max-width:740px, which silently CAPPED every
     screen — #screen-hub asked for 1100px, #screen-tphub for 900px and
     #screen-sections for 820px, and none of the three had ever taken effect.
     The shell now allows up to 1100px and each screen states its own width.
     ⚠ The rule below keeps every screen that does NOT name a width at the old
     740px, so lifting the cap changes only the screens named further down. An ID
     selector beats it, so those per-screen rules now finally apply. */
  .app{width:100%;max-width:1100px;margin:0 auto;}
  .app > [id^="screen-"]{max-width:740px;margin-left:auto;margin-right:auto;}
  h1{font-family:"Baloo 2",cursive;font-size:44px;margin:0;color:var(--purple-dark);letter-spacing:.5px;text-shadow:2px 2px 0 #fff,4px 4px 0 rgba(139,92,246,.18);}
  .sub{color:var(--muted);margin:2px 0 16px;font-size:16px;font-weight:700;}
  .card{background:var(--card);border:3px solid #fff;border-radius:26px;padding:24px 22px;box-shadow:0 10px 0 rgba(139,92,246,.12),0 12px 30px rgba(58,45,92,.12);}
  h2,h3{font-family:"Baloo 2",cursive;}
  button{font-family:"Baloo 2",cursive;cursor:pointer;border:none;border-radius:16px;font-weight:700;transition:transform .09s,filter .15s;}
  button:active{transform:scale(.96);}
  /* ===== consistent hover lift + shadow for ALL buttons ===== */
  button:where(:not(:disabled)):hover{transform:translateY(-2px);}
  .gnav-btn:hover,.gset-btn:hover,.gq-check:hover,.na-check:hover{transform:translateY(-3px);box-shadow:0 7px 0 var(--purple-dark);}
  .gnav-btn.alt:hover,.gset-btn.alt:hover{box-shadow:0 7px 0 #bcd4ff;}
  .gq-next:hover{transform:translateY(-3px);box-shadow:0 7px 0 var(--orange-dark);}
  .na-reset:hover{transform:translateY(-2px);box-shadow:0 6px 0 #bcd4ff;}
  .gq-opt:hover:not(:disabled),.qzopt:hover{transform:translateY(-2px);box-shadow:0 6px 14px rgba(58,45,92,.14);}
  .wb-learn:hover{box-shadow:0 6px 0 var(--orange-dark);}
  .wb-play:hover{box-shadow:0 6px 0 var(--blue-dark);}
  .wb-quiz:hover{box-shadow:0 6px 0 var(--green-dark);}
  .btn-primary{background:var(--blue);color:#fff;padding:15px 24px;width:100%;font-size:19px;box-shadow:0 5px 0 var(--blue-dark);}
  .btn-primary:hover{filter:brightness(1.05);transform:translateY(-3px);box-shadow:0 8px 0 var(--blue-dark);}
  .btn-primary:active{box-shadow:0 2px 0 var(--blue-dark);}
  .btn-ghost{background:var(--blue-soft);color:var(--blue-dark);padding:12px 18px;font-size:16px;}

  .grade-bar{background:#fff;border:3px solid #fff;border-radius:20px;padding:14px 16px;margin-bottom:18px;box-shadow:0 5px 0 rgba(139,92,246,.1);}
  .grade-label{display:block;font-family:"Baloo 2",cursive;font-size:15px;color:var(--muted);font-weight:700;margin-bottom:8px;}
  .grade-btns{display:flex;gap:8px;flex-wrap:wrap;}
  .grade-btn{flex:1;min-width:76px;background:var(--blue-soft);color:var(--blue-dark);padding:11px 8px;font-size:16px;border-radius:14px;}
  /* ---- HUB: DOMAIN SECTIONS & SUB-BUTTONS ---- */
  #screen-hub{max-width:1100px;margin:0 auto;padding:8px clamp(4px,2vw,20px) 20px;box-sizing:border-box;}
  .hub-header{text-align:center;}
  #screen-hub h1{margin:2px 0 0;font-size:clamp(24px,4vw,34px);}
  #screen-hub .sub{margin:2px 0 12px;}
  /* One tile per row, matching the stacked quest-part cards on #screen-sections. */
  .hub-2x2{display:grid;grid-template-columns:1fr;gap:11px;width:100%;align-items:start;}
  .domain-section{background:linear-gradient(160deg,#fff,var(--green-soft));border:3px solid var(--green);
    border-radius:22px;padding:14px 18px;box-shadow:0 6px 0 rgba(58,45,92,.07);display:flex;flex-direction:column;}
  .domain-section.highlight{border-color:var(--green);background:linear-gradient(160deg,#fff,var(--green-soft));}
  .ds-head{display:flex;align-items:center;gap:10px;flex:0 0 auto;}
  .ds-emoji{font-size:38px;line-height:1;flex-shrink:0;}
  .ds-title{font-family:"Baloo 2",cursive;font-size:21px;font-weight:800;color:var(--purple-dark);line-height:1.1;}
  .ds-desc{font-size:clamp(12px,1.4vw,14px);color:var(--muted);line-height:1.35;margin:5px 0 0;flex:0 0 auto;}
  .sub-btns{display:flex;flex-direction:column;gap:8px;flex:0 0 auto;margin-top:12px;}

  /* --- collapsible Core Knowledge tiles ---------------------------------
     Same pattern as the quest-part cards: the drawer opens ONLY on a press of
     the heading button (mouse, touch or keyboard) and the same press closes it
     again. Hover deliberately does not open it — see the note on .section-card.
     Only grid-template-rows animates, so nothing below jitters. */
  .ds-head{display:flex;align-items:center;gap:10px;width:100%;text-align:left;
    background:none;border:none;padding:0;margin:0;cursor:pointer;color:inherit;
    font-family:inherit;flex:0 0 auto;border-radius:12px;}
  .ds-head:focus-visible{outline:3px solid var(--purple);outline-offset:4px;}
  .ds-head .ds-title{flex:1;min-width:0;}
  .ds-chev{flex:0 0 auto;width:22px;height:22px;color:var(--purple);display:grid;place-items:center;
    transition:transform .38s cubic-bezier(.4,0,.2,1);}
  .ds-chev svg{width:19px;height:19px;display:block;}
  .ds-body{display:grid;grid-template-rows:0fr;opacity:0;
    transition:grid-template-rows .38s cubic-bezier(.4,0,.2,1), opacity .26s ease;}
  .ds-body-inner{overflow:hidden;min-height:0;visibility:hidden;transition:visibility 0s linear .38s;}
  .domain-section.open .ds-body{grid-template-rows:1fr;opacity:1;}
  .domain-section.open .ds-body-inner{visibility:visible;transition:visibility 0s linear 0s;}
  .domain-section.open .ds-chev{transform:rotate(180deg);}
  .domain-section{transition:box-shadow .25s ease,border-color .25s ease;overflow-anchor:none;}
  @media (hover:hover) and (pointer:fine){
    .domain-section:hover{box-shadow:0 7px 0 rgba(58,45,92,.10);}
  }

  /* --- the little icons: idle bob + pulsing glow, livelier on hover -------
     Each tile carries its own glow colour in --ds-glow. Only transform and
     filter animate, so none of this can move the layout. */
  .hub-2x2 .domain-section:nth-child(1){--ds-glow:139,92,246;}   /* purple  */
  .hub-2x2 .domain-section:nth-child(2){--ds-glow:255,152,56;}   /* orange  */
  .hub-2x2 .domain-section:nth-child(3){--ds-glow:47,123,255;}   /* blue    */
  .hub-2x2 .domain-section:nth-child(4){--ds-glow:18,192,122;}   /* green   */
  .ds-emoji{display:inline-block;transform-origin:50% 70%;
    animation:dsBob 3.4s ease-in-out infinite, dsGlow 2.6s ease-in-out infinite;}
  @keyframes dsBob{0%,100%{transform:translateY(0) rotate(0deg);}
                   50%{transform:translateY(-3px) rotate(-5deg);}}
  @keyframes dsGlow{0%,100%{filter:drop-shadow(0 0 3px rgba(var(--ds-glow),.45));}
                    50%{filter:drop-shadow(0 0 10px rgba(var(--ds-glow),.9));}}
  @media (hover:hover) and (pointer:fine){
    .domain-section:hover .ds-emoji{
      animation:dsWiggle .62s ease-in-out infinite, dsGlowHot 1.1s ease-in-out infinite;}
  }
  @keyframes dsWiggle{0%,100%{transform:translateY(-1px) rotate(-9deg) scale(1.1);}
                      50%{transform:translateY(-6px) rotate(9deg) scale(1.18);}}
  @keyframes dsGlowHot{0%,100%{filter:drop-shadow(0 0 7px rgba(var(--ds-glow),.75));}
                       50%{filter:drop-shadow(0 0 16px rgba(var(--ds-glow),1));}}
  @media (prefers-reduced-motion:reduce){
    .ds-emoji,.domain-section:hover .ds-emoji{animation:none;
      filter:drop-shadow(0 0 6px rgba(var(--ds-glow),.6));}
    .ds-body,.ds-chev,.domain-section{transition:none;}
  }
  .sub-btns.wide{margin-top:18px;}
  .sub-btn{display:flex;width:100%;align-items:center;justify-content:space-between;gap:7px;font-family:"Nunito";font-weight:800;font-size:clamp(13px,1.5vw,15px);padding:12px 16px;min-height:46px;border-radius:13px;cursor:pointer;border:2px solid transparent;transition:transform .08s,filter .12s,box-shadow .1s;}
  .sub-btn:active{transform:scale(.97);}
  .sub-btn.live{background:var(--green);color:#fff;box-shadow:0 4px 0 var(--green-dark);}
  .sub-btn.live:hover{filter:brightness(1.05);transform:translateY(-3px);box-shadow:0 7px 0 var(--green-dark);}
  .sub-btn.soon{background:var(--blue-soft);color:var(--muted);}
  .sub-btn.soon:hover{filter:brightness(.99);transform:translateY(-3px);box-shadow:0 6px 0 rgba(61,127,242,.16);}
  .go-tag{background:rgba(255,255,255,.28);color:#fff;font-size:12px;padding:2px 8px;border-radius:10px;}
  .soon-tag{background:var(--line);color:var(--muted);font-size:11px;padding:2px 7px;border-radius:10px;font-weight:800;}
  .topbar-spelling{margin-bottom:6px;}
  .hub-toast{position:fixed;left:50%;top:24px;transform:translateX(-50%) translateY(-20px);z-index:200;background:var(--purple);color:#fff;font-weight:800;font-size:15px;padding:12px 22px;border-radius:16px;box-shadow:0 8px 24px rgba(58,45,92,.3);opacity:0;pointer-events:none;transition:opacity .25s,transform .25s;max-width:88%;text-align:center;}
  .hub-toast.show{opacity:1;transform:translateX(-50%) translateY(0);}
  @media (max-width:560px){
    /* .hub-2x2 is single-column at every width now */
  }
  .grade-btn:hover{filter:brightness(.97);transform:translateY(-2px);}
  .grade-btn.active{background:var(--purple);color:#fff;box-shadow:0 4px 0 var(--purple-dark);}

  .vocab-tabs{display:flex;gap:8px;margin:2px 0 12px;flex-wrap:wrap;}
  .vocab-tab{background:linear-gradient(135deg,#8b5cf6,#ff5da2);color:#fff;border:none;border-radius:16px 16px 0 0;padding:12px 22px;font-weight:800;font-size:1rem;cursor:pointer;box-shadow:0 4px 0 rgba(112,56,224,.3);}
  .vocab-tab.active{filter:brightness(1.05);}
  .practice-banner{background:linear-gradient(135deg,#ff5da2,#8b5cf6);border-radius:24px;padding:22px 24px;color:#fff;margin-bottom:16px;display:flex;align-items:center;justify-content:space-between;gap:14px;flex-wrap:wrap;box-shadow:0 8px 0 rgba(112,56,224,.3);}
  .practice-banner h2{margin:0 0 4px;font-size:24px;}
  .practice-banner p{margin:0;font-size:15px;opacity:.95;font-weight:700;}
  .practice-banner button{background:#fff;color:var(--purple-dark);padding:14px 24px;font-size:18px;white-space:nowrap;box-shadow:0 5px 0 rgba(0,0,0,.15);}
  .practice-banner button:disabled{opacity:.55;cursor:not-allowed;}
  .overall{display:flex;gap:12px;margin-bottom:20px;flex-wrap:wrap;}
  .stat{flex:1;min-width:120px;border-radius:20px;padding:14px 16px;text-align:center;border:3px solid #fff;}
  .stat.s1{background:var(--amber-soft);} .stat.s2{background:var(--green-soft);} .stat.s3{background:var(--blue-soft);}
  .stat .n{font-family:"Baloo 2",cursive;font-size:28px;font-weight:800;color:var(--purple-dark);}
  .stat .l{font-size:13px;color:var(--muted);font-weight:700;}
  .weeks{display:grid;grid-template-columns:repeat(auto-fill,minmax(158px,1fr));gap:14px;}
  .week{background:var(--card);border:3px solid #fff;border-radius:22px;padding:14px;position:relative;box-shadow:0 5px 0 rgba(58,45,92,.1);transition:transform .12s;}
  .week:hover{transform:translateY(-3px);}
  .week.partial{background:var(--amber-soft);}
  .week.done{background:var(--green-soft);}
  .week .wk{font-size:12px;color:var(--muted);font-weight:800;letter-spacing:1px;}
  .week .wnum{font-family:"Baloo 2",cursive;font-size:26px;font-weight:800;color:var(--purple-dark);margin:0 0 6px;}
  .badge-status{display:inline-flex;align-items:center;gap:5px;font-size:12.5px;font-weight:800;padding:4px 10px;border-radius:20px;}
  .badge-status.ns{background:#f0ecf7;color:var(--muted);}
  .badge-status.pt{background:var(--amber);color:#7a5600;}
  .badge-status.dn{background:var(--green);color:#fff;}
  .week .score{font-size:12.5px;color:var(--green-dark);font-weight:800;margin-top:6px;}
  .week .peek{font-size:19px;margin-top:8px;line-height:1.35;}
  .week-btns{display:flex;gap:7px;margin-top:11px;}
  .week-btns button{flex:1;font-size:14px;padding:9px 6px;border-radius:12px;}
  .wb-learn{background:var(--orange);color:#fff;box-shadow:0 3px 0 var(--orange-dark);}
  .wb-play{background:var(--blue);color:#fff;box-shadow:0 3px 0 var(--blue-dark);}
  .wb-quiz{width:100%;margin-top:7px;background:var(--green);color:#fff;box-shadow:0 3px 0 var(--green-dark);font-size:14px;padding:9px 6px;border-radius:12px;}
  .check{position:absolute;top:-10px;right:-8px;font-size:30px;filter:drop-shadow(0 2px 2px rgba(0,0,0,.15));}
  .reset{margin-top:10px;text-align:center;}
  .save-row{display:flex;gap:10px;justify-content:center;flex-wrap:wrap;margin-top:24px;}
  .save-note-fixed{position:fixed;top:74px;right:16px;z-index:100;max-width:260px;text-align:right;color:var(--green-dark);background:var(--green-soft);border-radius:12px;padding:8px 12px;font-weight:800;font-size:13.5px;line-height:1.35;box-shadow:0 4px 14px rgba(58,45,92,.15);}
  .save-note-fixed:empty{display:none;}
  @media (max-width:560px){
    .save-note-fixed{top:60px;right:10px;max-width:200px;font-size:12.5px;}
  }
  .btn-save{background:var(--green);color:#fff;padding:13px 22px;font-size:16px;border-radius:14px;box-shadow:0 4px 0 var(--green-dark);}
  .btn-backup{background:var(--blue-soft);color:var(--blue-dark);padding:13px 18px;font-size:15px;border-radius:14px;}
  .save-note{text-align:center;color:var(--green-dark);font-weight:800;font-size:14px;min-height:20px;margin-top:10px;}
  .reset button{background:none;color:var(--muted);font-size:14px;font-weight:700;text-decoration:underline;padding:4px;box-shadow:none;font-family:"Nunito";}

  .topbar{display:flex;align-items:center;justify-content:space-between;margin-bottom:16px;gap:10px;}
  .back{background:var(--purple);color:#fff;padding:10px 16px;font-size:15px;box-shadow:0 4px 0 var(--purple-dark);transition:transform .09s,box-shadow .12s,filter .15s;}
  .back:hover{filter:brightness(1.04);transform:translateY(-2px);box-shadow:0 6px 0 var(--purple-dark);}
  .music-toggle{background:var(--amber);color:#7a5600;padding:8px 12px;font-size:18px;border-radius:14px;box-shadow:0 4px 0 #d99a00;}
  /* Topbar heading on every learn screen ("1.1 Phonemes and Graphemes: …").
     Baloo 2 at 400 was light and loosely tracked, so long part names ran into the
     grade badge and the longest wrapped to two lines. Bolder, tighter and allowed
     to shrink inside the flex row instead of pushing it wider. */
  .learn-title{font-family:"Baloo 2",cursive;font-size:clamp(17px,2.5vw,22px);font-weight:700;
    letter-spacing:-.4px;color:var(--purple-dark);flex:1;min-width:0;text-align:center;line-height:1.2;}
  .learn-card{display:flex;align-items:center;gap:16px;background:#fff;border:3px solid var(--line);border-radius:20px;padding:14px 16px;margin-bottom:12px;}
  .learn-card .em{font-size:52px;line-height:1;flex-shrink:0;}
  .learn-card .lw{font-family:"Baloo 2",cursive;font-size:24px;color:var(--blue-dark);font-weight:800;}
  .learn-card .ld{font-size:15px;color:var(--ink);font-weight:600;margin-top:4px;}
  .learn-card .lmeta{margin:3px 0 2px;}
  .learn-card .lex{font-size:16px;color:var(--ink);margin-top:6px;line-height:1.4;}
  .learn-card .lsyl{font-family:"Baloo 2",cursive;font-size:15px;color:var(--pink-dark);font-weight:700;letter-spacing:1px;margin-top:1px;}
  .chip{display:inline-block;font-size:12px;font-weight:800;padding:2px 9px;border-radius:20px;margin-right:6px;font-family:"Nunito";}
  .chip.pos{background:var(--purple-soft,#f0ebff);color:var(--purple-dark);}
  .chip.syl{background:var(--amber-soft);color:#7a5600;}
  .learn-card .say{background:var(--amber);color:#7a5600;border-radius:50%;width:48px;height:48px;font-size:22px;flex-shrink:0;box-shadow:0 4px 0 #d99a00;align-self:flex-start;}
  .learn-cta{margin-top:8px;}

  .progress-row{display:flex;justify-content:space-between;align-items:center;margin-bottom:10px;font-size:15px;color:var(--muted);font-weight:800;}
  .stars{font-size:20px;letter-spacing:2px;color:var(--amber);}
  .bar{height:14px;background:#f0e6d6;border-radius:10px;overflow:hidden;margin-bottom:20px;border:2px solid #fff;}
  .bar-fill{height:100%;background:linear-gradient(90deg,#ffc233,#ff9838);width:0;transition:width .3s;border-radius:8px;}
  .picture{display:flex;justify-content:center;align-items:center;height:140px;background:linear-gradient(160deg,#fff6dc,#ffe9f4);border-radius:22px;margin-bottom:16px;font-size:96px;line-height:1;border:3px solid #fff;}
  .gmeta{text-align:center;margin:0 0 8px;}
  .gexample{text-align:center;color:var(--ink);font-size:18px;font-style:italic;margin:2px 0 10px;line-height:1.45;}
  .exword{color:var(--red);font-weight:800;font-style:normal;}
  .gsyl{text-align:center;font-family:"Baloo 2",cursive;font-size:17px;color:var(--pink-dark);font-weight:700;letter-spacing:1px;margin:0 0 14px;min-height:14px;}
  .qzword{text-align:center;font-family:"Baloo 2",cursive;font-size:38px;font-weight:800;color:var(--purple-dark);line-height:1;margin:4px 0 2px;}
  .qzsyl{text-align:center;font-family:"Baloo 2",cursive;font-size:17px;color:var(--pink-dark);font-weight:700;letter-spacing:1px;margin:0 0 10px;}
  .qzprompt{text-align:center;font-family:"Baloo 2",cursive;font-size:18px;color:var(--ink);margin:0 0 12px;}
  .qzopt{display:block;width:100%;text-align:left;background:#fff;border:3px solid var(--line);border-radius:16px;padding:14px 16px;margin-bottom:10px;font-size:16px;font-weight:700;color:var(--ink);font-family:"Nunito";cursor:pointer;transition:transform .08s,border-color .15s,background .15s;line-height:1.35;}
  .qzopt:hover{border-color:var(--blue);}
  .qzopt:active{transform:scale(.98);}
  .qzopt.correct{background:var(--green-soft);border-color:var(--green);color:var(--green-dark);}
  .qzopt.wrong{background:var(--red-soft);border-color:var(--red);color:var(--red);}
  .qzopt.dim{opacity:.5;}
  .definition{font-size:21px;text-align:center;margin:0 0 6px;line-height:1.4;font-weight:700;}
  .hint{text-align:center;color:var(--muted);font-size:15px;margin:0 0 8px;font-weight:700;}
  input[type=text]{width:100%;padding:15px 16px;font-size:26px;font-family:"Baloo 2",cursive;text-align:center;border:3px solid var(--line);border-radius:16px;outline:none;letter-spacing:2px;margin-bottom:12px;color:var(--purple-dark);}
  input[type=text]:focus{border-color:var(--blue);}
  .helper-btns{display:flex;gap:10px;margin-bottom:14px;}
  .helper-btns button{flex:1;padding:11px 8px;font-size:15px;border-radius:14px;}
  .sound-btn{background:var(--amber);color:#7a5600;box-shadow:0 4px 0 #d99a00;}
  .peek-btn{background:var(--pink);color:#fff;box-shadow:0 4px 0 var(--pink-dark);}
  .reveal{text-align:center;font-family:"Baloo 2",cursive;font-size:24px;letter-spacing:4px;color:var(--pink-dark);min-height:20px;margin-bottom:8px;font-weight:800;}
  /* The child is told the cost of peeking on the spot, before they type. */
  .peek-note{font-family:var(--font-body);font-size:13.5px;font-weight:800;letter-spacing:0;
    color:var(--muted);line-height:1.35;margin-top:4px;}
  .feedback{text-align:center;font-size:18px;font-weight:800;min-height:24px;margin-bottom:10px;font-family:"Baloo 2",cursive;}
  .feedback.good{color:var(--green-dark);} .feedback.bad{color:var(--red);}

  .score-hero{text-align:center;padding:8px 0 2px;}
  .score-big{font-family:"Baloo 2",cursive;font-size:60px;font-weight:800;color:var(--purple-dark);line-height:1;}
  .score-sub{color:var(--muted);font-size:17px;margin-top:6px;font-weight:800;}
  .rbadge{display:inline-block;padding:10px 22px;border-radius:30px;font-family:"Baloo 2",cursive;font-weight:800;font-size:19px;margin:14px 0 16px;}
  .review-title{font-family:"Baloo 2",cursive;font-weight:800;font-size:17px;margin:16px 0 8px;}
  .review-item{display:flex;align-items:center;gap:10px;padding:11px 14px;border-radius:14px;margin-bottom:8px;font-size:16px;font-weight:700;}
  .review-item.correct{background:var(--green-soft);} .review-item.wrong{background:var(--red-soft);}
  .review-item .word{font-weight:800;} .review-item .typed{color:var(--muted);font-size:14px;}
  .row-btns{display:flex;gap:10px;margin-top:14px;}
  .row-btns button{flex:1;}

  /* ---- Results fit one screen ----
     Every reviewed word had a full 740px row to itself, so ten words ran ~270px past
     the fold and pushed Home / Play again off the bottom. "✓ action" does not need
     740px: the list is now a two-column grid (one column when the card is narrow), and
     the score hero is a little smaller. A list too long to fit — the Practice mix runs
     to 30 words — scrolls inside its own panel, so the PAGE still never scrolls and the
     buttons stay where the child can reach them. */
  #screen-results #reviewList{display:grid;grid-template-columns:repeat(auto-fit,minmax(230px,1fr));
    gap:7px;align-content:start;overflow-y:auto;max-height:calc(100vh - 340px);}
  #screen-results .review-title{grid-column:1/-1;font-size:16px;margin:10px 0 2px;}
  #screen-results #reviewList>.review-title:first-child{margin-top:0;}
  #screen-results .review-item{padding:8px 12px;margin-bottom:0;font-size:15px;gap:8px;min-width:0;}
  /* the word must survive; it is what the child wrote that gets clipped if anything does */
  #screen-results .review-item>span:last-child{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
  /* a row carrying a whole definition keeps the full width */
  #screen-results .review-item.wide{grid-column:1/-1;}
  #screen-results .score-hero{padding:4px 0 0;}
  #screen-results .score-big{font-size:52px;}
  #screen-results .score-sub{font-size:16px;margin-top:4px;}
  #screen-results .rbadge{margin:10px 0 8px;padding:8px 20px;font-size:18px;}
  #screen-results .row-btns{margin-top:12px;}
  /* On a phone 230px is too wide to fit two-up, but "✓ afternoon" still is — so the
     columns stay, and only the rows that also carry what the child wrote go full width. */
  @media (max-width:560px){
    #screen-results #reviewList{grid-template-columns:1fr 1fr;}
    #screen-results .review-item.wrong{grid-column:1/-1;}
  }
  .hidden{display:none !important;}

  /* ===== GRAMMAR ===== */
  .grade-btn.sel{background:var(--purple);color:#fff;box-shadow:0 4px 0 var(--purple-dark);}
  .gtopic-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(150px,1fr));gap:12px;margin-top:6px;}
  .ggroup-head{display:flex;align-items:center;gap:12px;margin:22px 0 4px;padding:12px 16px;background:linear-gradient(135deg,var(--purple-soft,#f4efff),#fff);border-radius:16px;border-left:6px solid var(--purple);}
  .ggroup-head:first-child{margin-top:8px;}
  .ggroup-icon{font-size:30px;flex-shrink:0;}
  .ggroup-titles{display:flex;flex-direction:column;gap:2px;}
  .ggroup-name{font-family:"Baloo 2",cursive;font-weight:800;font-size:20px;color:var(--purple-dark);line-height:1.1;}
  .ggroup-desc{font-size:13px;font-weight:700;color:var(--muted);line-height:1.25;}

  /* --- collapsible topic groups (Spelling / Grammar / Punctuation) -------
     The group heading keeps its place; the grid of topic cards under it opens
     when the heading is pressed and closes on the next press. Card treatment,
     type and icon behaviour all match the quest-part cards on #screen-sections. */
  .ggroup{background:linear-gradient(160deg,#fff,var(--green-soft));border:3px solid var(--green);
    border-radius:22px;padding:14px 18px;box-shadow:0 6px 0 rgba(58,45,92,.07);
    margin-bottom:11px;overflow-anchor:none;transition:box-shadow .25s ease;}
  /* the heading was a tinted bar; inside a card it becomes a plain button */
  .ggroup > .ggroup-head{display:flex;align-items:center;gap:12px;width:100%;text-align:left;
    background:none;border:none;border-left:none;border-radius:12px;padding:0;margin:0;
    cursor:pointer;color:inherit;font-family:inherit;}
  .ggroup > .ggroup-head:first-child{margin-top:0;}
  .ggroup > .ggroup-head:focus-visible{outline:3px solid var(--purple);outline-offset:4px;}
  .ggroup .ggroup-titles{flex:1;min-width:0;}
  .ggroup .ggroup-name{font-size:21px;color:var(--purple-dark);}
  .ggroup-chev{flex:0 0 auto;width:22px;height:22px;color:var(--purple);display:grid;place-items:center;
    transition:transform .38s cubic-bezier(.4,0,.2,1);}
  .ggroup-chev svg{width:19px;height:19px;display:block;}
  .ggroup-body{display:grid;grid-template-rows:0fr;opacity:0;
    transition:grid-template-rows .38s cubic-bezier(.4,0,.2,1), opacity .26s ease;}
  .ggroup-body-inner{overflow:hidden;min-height:0;visibility:hidden;transition:visibility 0s linear .38s;}
  .ggroup.open .ggroup-body{grid-template-rows:1fr;opacity:1;}
  .ggroup.open .ggroup-body-inner{visibility:visible;transition:visibility 0s linear 0s;}
  .ggroup.open .ggroup-chev{transform:rotate(180deg);}
  @media (hover:hover) and (pointer:fine){
    .ggroup:hover{box-shadow:0 7px 0 rgba(58,45,92,.10);}
  }
  /* the grid keeps its own top gap inside the clipped area */
  .ggroup .gtopic-grid{margin-top:12px;}

  /* group icons: the same bob + glow, cycling through the palette */
  .ggroup:nth-of-type(4n+1){--ds-glow:139,92,246;}
  .ggroup:nth-of-type(4n+2){--ds-glow:255,152,56;}
  .ggroup:nth-of-type(4n+3){--ds-glow:47,123,255;}
  .ggroup:nth-of-type(4n+4){--ds-glow:18,192,122;}
  .ggroup .ggroup-icon{font-size:38px;display:inline-block;transform-origin:50% 70%;
    animation:dsBob 3.4s ease-in-out infinite, dsGlow 2.6s ease-in-out infinite;}
  @media (hover:hover) and (pointer:fine){
    .ggroup:hover .ggroup-icon{
      animation:dsWiggle .62s ease-in-out infinite, dsGlowHot 1.1s ease-in-out infinite;}
  }
  @media (prefers-reduced-motion:reduce){
    .ggroup .ggroup-icon,.ggroup:hover .ggroup-icon{animation:none;
      filter:drop-shadow(0 0 6px rgba(var(--ds-glow),.6));}
    .ggroup-body,.ggroup-chev,.ggroup{transition:none;}
  }
  .gtopic-card{display:flex;flex-direction:column;align-items:center;gap:4px;text-align:center;
    background:#fff;border:3px solid #fff;border-radius:18px;padding:16px 10px;cursor:pointer;
    box-shadow:0 5px 0 rgba(139,92,246,.12);transition:transform .08s,box-shadow .1s;font-family:"Nunito";}
  .gtopic-card:active{transform:scale(.97);}
  .gtopic-card:hover{transform:translateY(-3px);box-shadow:0 8px 0 rgba(139,92,246,.28);}
  .gtopic-card .badge-status{margin-top:2px;}
  .gtopic-card.done{background:var(--green-soft);border-color:var(--green);}
  .gtopic-card.partial{background:var(--amber-soft);border-color:var(--amber);}
  .gt-icon{font-size:30px;}
  .gt-name{font-weight:800;font-size:15px;color:var(--ink);line-height:1.15;}
  .gt-num{color:var(--purple-dark);}
  .gt-meta{font-size:12px;color:var(--muted);font-weight:700;}
  .gsub-list{display:flex;flex-direction:column;gap:10px;margin-top:6px;}
  .gsub-btn{position:relative;display:flex;align-items:center;justify-content:space-between;gap:10px;
    background:#fff;border:3px solid #fff;border-radius:16px;padding:15px 18px;cursor:pointer;
    box-shadow:0 4px 0 rgba(139,92,246,.12);font-family:"Nunito";transition:transform .12s,box-shadow .12s;}
  .gsub-btn:not(.soon):hover{transform:translateY(-3px);box-shadow:0 7px 0 rgba(139,92,246,.18);}
  .gsub-btn:active{transform:scale(.98);}
  .gsub-btn.done{background:var(--green-soft);border-color:var(--green);}
  .gsub-btn.partial{background:var(--amber-soft);border-color:var(--amber);}
  .gsub-btn.soon{opacity:.7;cursor:default;}
  .gsub-name{font-weight:800;font-size:17px;color:var(--ink);}
  .gsub-num{color:var(--purple-dark);margin-right:2px;}
  .gsub-meta{display:flex;flex-direction:column;align-items:flex-end;gap:4px;flex:0 0 auto;}
  .gsub-score{font-size:12px;font-weight:800;color:var(--green-dark);}
  .gsub-btn.partial .gsub-score{color:#7a5600;}
  .gsub-check{position:absolute;top:-10px;right:-7px;font-size:22px;filter:drop-shadow(0 2px 2px rgba(0,0,0,.15));}
  .gsub-tag{font-weight:800;font-size:13px;color:var(--purple-dark);background:var(--purple-soft,#f4efff);padding:5px 10px;border-radius:10px;white-space:nowrap;}
  .gsub-tag.ok{color:var(--green-dark);background:var(--green-soft);}
  .gsub-tag.half{color:var(--orange-dark);background:var(--amber-soft);}
  /* Spelling parts list: ONE width for every part button in every area, and every
     button exactly one line tall.
       - the row spans the full app width, the same as every other section's list.
         (It was briefly capped at 640px to sit tight to the text; the user asked
         for the full width back on 2026-08-26, keeping the rules below.)
       - .gsub-name never wraps — the part names were shortened where they did not
         fit, so a two-line row cannot happen;
       - .gsub-meta is a ROW here, not a column, so "✋ Keep going" and "Best: 8/12"
         sit side by side instead of stacking and making that one row taller. */
  /* The two Spelling LIST screens get room to breathe, matching Test Practice.
     ⚠ #screen-ssquiz — the lesson pages and quiz — deliberately stays at the
     default 740px: at 19.2px body copy a 900px line runs about 90 characters,
     well past a comfortable measure for a Year 3 reader. */
  #screen-sstopics,#screen-sssubs{max-width:900px;padding:0 clamp(0px,1vw,10px);box-sizing:border-box;}
  #sssub-list{display:grid;grid-template-columns:100%;gap:10px;margin-top:6px;}
  #sssub-list .gsub-btn{width:100%;}
  #sssub-list .gsub-name{min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
  #sssub-list .gsub-meta{flex-direction:row;align-items:center;gap:8px;white-space:nowrap;}
  .gresult-best{font-weight:800;font-size:16px;color:var(--purple-dark);margin-top:2px;}
  /* large, clear illustration on each writing intro page */
  .wintro-graphic{margin:2px auto 14px;text-align:center;}
  .wintro-svg{display:block;width:min(78%,300px);height:auto;margin:0 auto;filter:drop-shadow(0 8px 16px rgba(58,45,92,.14));}
  /* All four intros -- Comprehension, Finding Information, Text Types and Writing -- are
     lesson pages inside .glesson now (renderCIntro, renderFIIntro, renderTTIntro,
     renderWIntro), so they share the lesson card, header row, dots and Back / Next. Only
     the list of ideas on a page is specific to an intro.
     The old cintro-* carousel rules (big heading below the bar, numbered-circle title,
     full-width Continue) were removed along with the last screen that used them. */
  .gintro-list{margin:0 0 14px;padding-left:24px;}
  .gintro-list li{font-size:17px;line-height:1.5;color:var(--ink);margin:0 0 6px;}
  .wintro-skip{text-align:center;margin-top:10px;}
  .cgroup-list{margin-top:6px;}
  .cgroup{margin-bottom:12px;}
  .cgroup-btn{width:100%;display:flex;align-items:center;gap:10px;background:#fff;border:2px solid #eadcff;border-radius:16px;padding:12px 14px;cursor:pointer;box-shadow:0 4px 0 rgba(139,92,246,.08);text-align:left;}
  .cgroup.open .cgroup-btn{border-color:var(--purple);background:#faf5ff;border-bottom-left-radius:0;border-bottom-right-radius:0;box-shadow:none;}
  .cgroup-btn .ggroup-icon{font-size:22px;}
  .cgroup-btn .ggroup-titles{display:flex;flex-direction:column;flex:1;}
  .cgroup-btn .ggroup-name{font-family:"Baloo 2",cursive;font-weight:800;color:var(--purple-dark);font-size:16px;line-height:1.15;}
  .cgroup-btn .ggroup-desc{font-size:12.5px;color:#7c6f95;font-weight:600;}
  .cgroup-meta{font-size:12px;font-weight:800;color:var(--purple);background:#f0e6ff;border-radius:10px;padding:2px 8px;}
  .cgroup-caret{font-size:20px;font-weight:800;color:var(--purple);width:20px;text-align:center;}
  .cgroup-subs{border:2px solid var(--purple);border-top:none;border-bottom-left-radius:16px;border-bottom-right-radius:16px;background:#faf5ff;padding:10px;display:flex;flex-direction:column;gap:8px;}
  .cpassage{background:linear-gradient(180deg,#fdfbff,#f4ecff);border:2px solid #e2d0ff;border-radius:16px;padding:14px 16px;margin-bottom:14px;box-shadow:0 3px 0 rgba(139,92,246,.08);}
  .cpassage-head{display:flex;align-items:center;gap:8px;margin-bottom:8px;flex-wrap:wrap;}
  .cpassage-icon{font-size:18px;}
  .cpassage-title{font-family:"Baloo 2",cursive;font-weight:800;color:var(--purple-dark);font-size:16px;}
  .cpassage-tag{font-size:11px;font-weight:800;text-transform:uppercase;letter-spacing:.4px;color:#fff;background:var(--purple);border-radius:10px;padding:2px 8px;}
  .cpassage-body{font-size:15.5px;line-height:1.6;color:var(--ink);font-weight:600;}
  .glesson{background:#fff;border:3px solid #fff;border-radius:20px;padding:18px 18px 20px;margin-bottom:16px;box-shadow:0 5px 0 rgba(139,92,246,.1);}
  /* ⚠ Emptying #nalesson when a quiz starts was not enough: the panel still drew its own
     white card — 3px border, 38px of padding and a 16px margin — so a blank box sat above
     every question taking 60px for nothing. An empty lesson panel has no business being
     visible at all. */
  .glesson:empty{display:none;}
  /* .glesson-badge is gone: it was a small "Year 3" pill inside every lesson page,
     saying again what the top bar already says on the same screen. */
  .glesson h2{font-family:"Baloo 2",cursive;margin:2px 0 8px;color:var(--purple-dark);font-size:24px;}
  /* Lesson body copy. Raised 16px -> 19.2px (+20%) on 2026-08-26 at the user's
     request. ⚠ This changes the 2-line paragraph budget: at 16px it was ~190
     characters, at 19.2px it is ~158. See the spelling-paragraph-length note. */
  .gdef{font-size:19.2px;line-height:1.5;color:var(--ink);margin:0 0 14px;}
  /* flex-end, not space-between: the page counter is the only thing left in this row
     now that the year badge has gone, and it should stay on the right where it was. */
  .glesson-head{display:flex;justify-content:flex-end;align-items:center;margin-bottom:6px;}
  .glesson-count{font-weight:800;font-size:13px;color:var(--muted);}
  .gtable{width:100%;border-collapse:collapse;margin:4px 0 14px;font-size:15px;border-radius:12px;overflow:hidden;box-shadow:0 2px 0 rgba(139,92,246,.08);}
  .gtable th{background:var(--purple);color:#fff;font-weight:800;text-align:left;padding:9px 12px;font-size:14px;}
  .gtable td{background:#fff;padding:9px 12px;border-bottom:2px solid var(--purple-soft,#f4efff);color:var(--ink);font-weight:600;}
  .gtable tr:last-child td{border-bottom:none;}
  .gtable td.gt-key{font-weight:800;color:var(--purple-dark);}
  .gtable tr:nth-child(even) td{background:#faf8ff;}
  /* Names a group of rows inside a long table. Wins over the zebra striping, which
     otherwise lands on it and makes the band look like just another row. */
  .gtable tr.gt-section td{background:var(--purple-soft,#f0ebff);color:var(--purple-dark);
    font-family:var(--font-round);font-weight:800;font-size:14px;letter-spacing:.3px;
    padding:7px 12px;border-bottom:2px solid #fff;}
  /* an audible table cell (table.sound in the JSON) — a chip the child taps to
     hear that sound or word. Sized to sit inside a row without changing its
     height, and it inherits the cell's colour so the gt-key column stays purple. */
  .gtable .gt-snd{display:inline-flex;align-items:center;gap:5px;font:inherit;color:inherit;
    background:var(--purple-soft,#f4efff);border:none;border-radius:9px;padding:3px 9px;margin:-2px 0;
    cursor:pointer;box-shadow:0 2px 0 rgba(139,92,246,.18);transition:transform .08s,box-shadow .1s,filter .12s;}
  .gtable .gt-snd .gt-snd-i{font-size:12px;line-height:1;opacity:.8;}
  .gtable .gt-snd:hover{filter:brightness(.97);transform:translateY(-1px);box-shadow:0 3px 0 rgba(139,92,246,.18);}
  .gtable .gt-snd:active{transform:translateY(1px);box-shadow:0 1px 0 rgba(139,92,246,.18);}
  .gtable .gt-snd:focus-visible{outline:3px solid var(--purple);outline-offset:2px;}
  /* several chips in one cell — a whole word sounded out. They drop the speaker
     glyph and tighten up so five sounds still fit on one line. */
  .gtable .gt-snd{white-space:nowrap;}
  .gtable .gt-snd.bare{padding:3px 8px;min-width:34px;justify-content:center;}
  .gtable .gt-snd + .gt-snd{margin-left:4px;}
  .gtable .gt-comma{padding:0 3px 0 1px;opacity:.5;font-weight:700;}
  /* Retrieval tables (js/09-numeracy.js, pg.table.reveal): the answer sits behind a
     tap so the page asks something instead of telling. Sized to a comfortable touch
     target and kept on one line so revealing never reflows the row. */
  .gt-hide{display:inline-flex;align-items:center;justify-content:center;
    min-width:44px;min-height:36px;padding:2px 10px;margin:-2px 0;
    font:inherit;font-weight:800;color:var(--purple-dark);
    background:var(--purple-soft,#f4efff);border:2px dashed var(--purple);
    border-radius:9px;cursor:pointer;line-height:1.2;white-space:nowrap;
    transition:background .15s ease,border-color .15s ease,color .15s ease;}
  .gt-hide:hover{background:#ece2ff;}
  .gt-hide:focus-visible{outline:3px solid var(--purple-dark);outline-offset:2px;}
  .gt-hide.on{background:transparent;border-color:transparent;border-style:solid;
    color:var(--ink);cursor:default;padding:2px 0;min-width:0;}
  /* Faded worked examples (js/09-numeracy.js, gd.worked) — the bridge between the
     lesson and the practice set. */
  .gwork-story{background:#fff8e6;border:2px solid #f0c14b;border-radius:12px;
    padding:12px 14px;margin:4px 0 12px;font-weight:700;color:var(--ink);line-height:1.45;}
  .gwork-table{margin-top:10px;}
  .gwork-table td{vertical-align:middle;}
  .gwork-given{font-weight:800;color:var(--purple-dark);}
  .gwork-slot{display:inline-flex;flex-wrap:wrap;gap:6px;}
  .gwork-chip{font:inherit;font-weight:700;font-size:14px;padding:7px 12px;min-height:36px;
    color:var(--purple-dark);background:#fff;border:2px solid var(--purple);border-radius:10px;
    cursor:pointer;line-height:1.2;transition:background .15s ease,color .15s ease,border-color .15s ease;}
  .gwork-chip:hover:not(:disabled){background:var(--purple-soft,#f4efff);}
  .gwork-chip:focus-visible{outline:3px solid var(--purple-dark);outline-offset:2px;}
  .gwork-chip.right{background:#e6f7ec;border-color:#25a35a;color:#146c39;cursor:default;}
  .gwork-chip.wrong{background:#fdeaea;border-color:#d9534f;color:#a33;text-decoration:line-through;cursor:default;}
  .gwork-chip.gone{display:none;}
  .gwork-msg{min-height:22px;margin:10px 0 2px;font-weight:700;color:var(--muted);}
  .glesson-nav .gnav-btn.is-locked{opacity:.45;cursor:not-allowed;}
  @media(prefers-reduced-motion:reduce){ .gwork-chip{transition:none;} }
  .gt-revealall{margin:-6px 0 14px;text-align:right;}
  .gt-revealall .gnav-btn{font-size:14px;padding:8px 14px;}
  @media(prefers-reduced-motion:reduce){ .gt-hide{transition:none;} }
  .gexbox{background:var(--green-soft);border-radius:14px;padding:12px 16px;margin:0 0 14px;}
  .gexlabel{display:inline-block;font-weight:800;font-size:12px;text-transform:uppercase;letter-spacing:.5px;color:var(--green-dark);margin-bottom:4px;}
  .gexbox ul{margin:2px 0 0;padding-left:20px;}
  .gexbox li{font-size:16px;font-weight:700;color:var(--ink);margin:3px 0;line-height:1.4;}
  .gtip{display:flex;gap:8px;align-items:flex-start;background:var(--amber-soft);border-radius:14px;padding:12px 14px;font-size:15px;font-weight:700;color:#8a6d1a;line-height:1.4;}
  .gtip-i{font-size:18px;flex-shrink:0;}
  .gdots{display:flex;gap:7px;justify-content:center;margin:16px 0 10px;}
  .gdot{width:9px;height:9px;border-radius:50%;background:#e3d9f7;transition:background .2s,transform .2s;}
  .gdot.on{background:var(--purple);transform:scale(1.25);}
  .glesson-nav{display:flex;justify-content:space-between;align-items:center;gap:10px;margin-top:4px;}
  .gnav-btn{background:var(--purple);color:#fff;font-family:"Nunito";font-weight:800;font-size:16px;padding:12px 22px;border-radius:14px;border:none;cursor:pointer;box-shadow:0 4px 0 var(--purple-dark);transition:transform .08s;}
  .gnav-btn:active{transform:scale(.97);}
  .gnav-btn.alt{background:var(--blue-soft);color:var(--blue-dark);box-shadow:0 4px 0 #bcd4ff;}
  .gnav-btn.small{font-size:14px;padding:9px 16px;margin-bottom:12px;}
  .gset-q{font-weight:800;margin:6px 0 8px;color:var(--muted);}
  .gset-btns,.gresult-btns{display:flex;flex-direction:column;gap:10px;}
  .gset-btn{background:var(--purple);color:#fff;font-family:"Nunito";font-weight:800;font-size:16px;
    padding:14px;border-radius:14px;border:none;cursor:pointer;box-shadow:0 4px 0 var(--purple-dark);transition:transform .08s;}
  .gset-btn:active{transform:scale(.98);}
  .gset-btn.alt{background:var(--blue-soft);color:var(--blue-dark);box-shadow:0 4px 0 #bcd4ff;}
  .gq-progress{display:flex;justify-content:space-between;align-items:center;font-weight:800;color:var(--muted);margin-bottom:10px;font-size:15px;}
  .gq-score{color:var(--purple-dark);}
  .gq-card{background:#fff;border:3px solid #fff;border-radius:20px;padding:20px 18px;box-shadow:0 5px 0 rgba(139,92,246,.1);}
  .gq-q{font-size:19px;font-weight:800;line-height:1.4;margin:0 0 16px;color:var(--ink);}
  .gq-opts{display:flex;flex-direction:column;gap:10px;}
  .gq-opt{text-align:left;background:var(--blue-soft);color:var(--ink);font-family:"Nunito";font-weight:700;
    font-size:17px;padding:14px 16px;border-radius:14px;border:2px solid transparent;cursor:pointer;transition:transform .08s,filter .1s;}
  .gq-opt:active{transform:scale(.98);}
  .gq-opt:hover:not(:disabled){filter:brightness(.97);}
  .gq-opt.correct{background:var(--green);color:#fff;border-color:var(--green-dark);}
  .gq-opt.wrong{background:var(--red);color:#fff;border-color:#d33;}
  .gq-opt:disabled{cursor:default;}
  /* Spelling: the child's choice BEFORE they press Check. It has to read as chosen
     without reading as marked, so it borrows the purple of the Check button it is
     about to hand over to — never the green or red of a graded answer. */
  .gq-opt.picked{background:var(--purple-soft,#f4efff);border-color:var(--purple);color:var(--purple-dark);font-weight:800;}
  .gq-mc-go{margin-top:14px;}
  .gq-mc-check{width:100%;}
  .gq-check:disabled{opacity:.45;cursor:default;box-shadow:0 4px 0 var(--purple-dark);}
  .gq-check:focus-visible,.gq-next:focus-visible,.gq-opt:focus-visible{outline:3px solid var(--ink);outline-offset:3px;}
  .gq-type{display:flex;gap:10px;}
  #gq-input{flex:1;font-family:"Nunito";font-weight:700;font-size:18px;padding:13px 15px;border-radius:14px;border:2.5px solid var(--line);outline:none;color:var(--ink);}
  #gq-input:focus{border-color:var(--purple);}
  #gq-input.correct{border-color:var(--green);background:var(--green-soft);}
  #gq-input.wrong{border-color:var(--red);background:var(--red-soft);}
  .gq-check{background:var(--purple);color:#fff;font-family:"Nunito";font-weight:800;font-size:16px;padding:13px 20px;border-radius:14px;border:none;cursor:pointer;box-shadow:0 4px 0 var(--purple-dark);}
  .gq-feedback{margin-top:14px;}
  .fb-ok{color:var(--green-dark);font-weight:800;font-size:17px;display:block;}
  .fb-no{color:var(--red);font-weight:800;font-size:16px;display:block;line-height:1.4;}
  .gq-next{display:block;width:100%;margin-top:12px;background:var(--orange);color:#fff;font-family:"Nunito";font-weight:800;font-size:17px;padding:13px;border-radius:14px;border:none;cursor:pointer;box-shadow:0 4px 0 var(--orange-dark);}
  /* Spelling quiz: NAPLAN-style dictation + proofreading items */
  .gq-card{position:relative;}
  .gq-card.has-art{padding-right:112px;}
  .gq-art{position:absolute;top:14px;right:14px;width:87px;height:87px;}
  .gq-art svg{width:100%;height:100%;display:block;}
  @media (max-width:480px){
    .gq-card.has-art{padding-right:18px;padding-top:96px;}
    .gq-art{top:10px;right:calc(50% - 43px);}
  }
  .gq-sent{background:var(--blue-soft);border-radius:14px;padding:14px 16px;font-size:18px;font-weight:700;line-height:1.6;color:var(--ink);margin:0 0 4px;}
  .gq-sent.ok{background:var(--green-soft);margin-top:10px;}
  .gq-blank{display:inline-block;min-width:86px;text-align:center;border-bottom:3px solid var(--purple);color:var(--purple);letter-spacing:2px;line-height:1.1;}
  .gq-bad{background:var(--red-soft);color:var(--red);border-bottom:3px dotted var(--red);border-radius:6px 6px 0 0;padding:0 4px;font-weight:800;}
  .gq-fixed{color:var(--green-dark);}
  .gq-retype{margin-top:12px;padding-top:12px;border-top:2px dashed var(--line);}
  .gq-retype-lbl{display:block;font-weight:800;font-size:15px;color:var(--ink);margin-bottom:8px;}
  .gq-round{color:var(--orange-dark);}
  #ssq-input.correct,#ssq-retype.correct{border-color:var(--green);background:var(--green-soft);}
  #ssq-input.wrong,#ssq-retype.wrong{border-color:var(--red);background:var(--red-soft);}
  .ss-areaquiz{border:2.5px solid var(--purple);}
  .gresult{background:#fff;border:3px solid #fff;border-radius:20px;padding:26px 20px;text-align:center;box-shadow:0 5px 0 rgba(139,92,246,.1);}
  .gresult-emoji{font-size:52px;}
  .gresult h2{font-family:"Baloo 2",cursive;color:var(--purple-dark);margin:6px 0;}
  .gresult-score{font-size:20px;font-weight:800;color:var(--ink);margin:6px 0;}
  .gresult-note{color:var(--muted);font-weight:700;margin:4px 0 16px;}

  /* ---- WRITING module ---- */
  .wpurpose{display:inline-block;background:var(--pink);color:#fff;font-weight:800;font-size:12px;padding:3px 12px;border-radius:20px;margin-bottom:8px;letter-spacing:.3px;}
  .wpurpose.narr{background:var(--blue);}
  .wlvl-badge{display:inline-block;font-weight:800;font-size:12px;padding:4px 12px;border-radius:20px;letter-spacing:.2px;}
  .wlvl-badge.easy{background:var(--green-soft);color:var(--green-dark);}
  .wlvl-badge.medium{background:#e3edff;color:var(--blue-dark);}
  .wlvl-badge.hard{background:var(--purple-soft);color:var(--purple-dark);}
  .wmodel{background:#eef6ff;border:2px solid #cfe3ff;border-radius:14px;padding:12px 14px;margin:0 0 14px;}
  .wmodel-label{display:inline-block;font-weight:800;color:var(--blue-dark);font-size:11px;text-transform:uppercase;letter-spacing:.5px;margin-bottom:5px;}
  /* pre-line so a model that demonstrates PARAGRAPHING actually shows its break.
     HTML collapses newlines by default, which rendered the two-paragraph models as
     one unbroken block — the exact thing the task is teaching against. Runs of
     spaces still collapse, and models without newlines are unaffected. */
  .wmodel p{margin:0;font-size:15.5px;line-height:1.55;color:var(--ink);font-weight:600;white-space:pre-line;}
  .wmodel .hl{background:#fff2b8;border-radius:5px;padding:0 3px;font-weight:800;}
  .wline{display:flex;gap:10px;align-items:flex-start;background:#faf8ff;border:2px solid #eee3ff;border-radius:12px;padding:10px 12px;margin:7px 0;}
  .wline-n{flex:0 0 auto;background:var(--purple);color:#fff;font-weight:800;width:22px;height:22px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:12px;margin-top:1px;}
  .wline-txt{font-size:14.5px;font-weight:600;color:var(--ink);line-height:1.45;}
  .wline-txt b{color:var(--purple-dark);}
  .wsent-tag{display:inline-block;font-size:10.5px;font-weight:800;text-transform:uppercase;letter-spacing:.3px;border-radius:8px;padding:1px 7px;margin-left:4px;vertical-align:middle;}
  .wsent-tag.simple{background:var(--green-soft);color:var(--green-dark);}
  .wsent-tag.compound{background:#e3edff;color:var(--blue-dark);}
  .wsent-tag.complex{background:var(--purple-soft);color:var(--purple-dark);}
  /* Lesson header row: the badges sit on the SAME line as the page count, the way
     a spelling lesson page reads. They used to stack above it, which left the count
     hanging out of line with the heading and everything under it. */
  .wlesson-head{justify-content:space-between;gap:10px;flex-wrap:wrap;}
  .whead-tags{display:flex;align-items:center;gap:8px;flex-wrap:wrap;min-width:0;}
  .whead-tags .wpurpose{margin-bottom:0;}
  /* The sentence card -- writing's sound card. Same lavender surface, same radius and
     padding as .ph-card (it reuses that class), so a child moving between Spelling and
     Writing sees one app. The text is the point, so it carries the weight; the tag
     drops to a quiet foot row underneath. */
  .wcard{display:flex;flex-direction:column;gap:7px;justify-content:center;}
  .wcard-text{margin:0;font-size:17px;font-weight:700;line-height:1.4;color:var(--ink);}
  .wcard-text .hl{background:var(--amber-soft,#ffeec2);border-radius:6px;padding:0 3px;}
  .wcard-text b{color:var(--purple-dark);}
  .wcard-foot{display:flex;align-items:center;gap:8px;flex-wrap:wrap;}
  /* the tag already has a left margin for sitting inline after a sentence; on the
     card it starts the row, so that margin has to go */
  .wcard-foot .wsent-tag{margin-left:0;}
  .wcard-note{font-size:13.5px;font-weight:700;color:var(--muted);line-height:1.35;}
  .wtask-head{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-bottom:4px;}
  .wtask-badge{font-weight:800;font-size:12px;padding:4px 12px;border-radius:20px;color:#fff;}
  .wtask-badge.clues{background:var(--green);}
  .wtask-badge.free{background:var(--orange);}
  .wtask-badge.combine{background:var(--blue);}
  /* pre-writing goals (product goals) + sentence-combining + revise nudge */
  .wgoals{background:var(--green-soft);border-radius:12px;padding:10px 12px;margin:0 0 10px;}
  .wgoals-label{display:block;font-weight:800;color:var(--green-dark);font-size:11px;text-transform:uppercase;letter-spacing:.4px;margin-bottom:5px;}
  .wgoals ul{margin:0;padding-left:20px;}
  .wgoals li{font-size:14px;font-weight:700;color:var(--ink);line-height:1.45;}
  /* the goals as a drop-down on the task screen (2026-09-30) */
  .wgoals-head{display:flex;align-items:center;justify-content:space-between;gap:8px;width:100%;background:none;border:0;padding:0;margin:0;font:inherit;text-align:left;cursor:pointer;}
  .wgoals-dd .wgoals-label{margin-bottom:0;}
  .wgoals-dd ul{margin-top:6px;}
  .wgoals-dd:not(.open) ul{display:none;}
  .wgoals-dd.open .ggroup-chev{transform:rotate(180deg);}
  .wcombine{display:flex;flex-direction:column;gap:8px;margin:0 0 10px;}
  .wcombine-s{background:var(--blue-soft);border:2px solid var(--blue);border-radius:12px;padding:10px 14px;font-size:16px;font-weight:800;color:var(--ink);}
  .wrevise-nudge{background:var(--purple-soft);border-radius:12px;padding:10px 12px;margin:10px 0 0;font-size:14px;font-weight:700;color:var(--purple-dark);line-height:1.4;}
  .wwords{background:var(--blue-soft);border-radius:12px;padding:10px 12px;margin:0 0 10px;}
  .wwords-label{display:block;font-weight:800;color:var(--blue-dark);font-size:11px;text-transform:uppercase;letter-spacing:.4px;margin-bottom:7px;}
  .wwords-row{display:flex;flex-wrap:wrap;gap:7px;}
  .wword-chip{background:#fff;border:2px solid var(--blue);color:var(--blue-dark);font-family:"Nunito";font-weight:800;font-size:14px;padding:6px 12px;border-radius:16px;cursor:pointer;}
  .wword-chip:active{transform:scale(.96);}
  #wbest-btn{margin-top:12px;}
  .wbest-card{background:#fff;border-radius:16px;padding:14px 16px;box-shadow:0 3px 0 rgba(139,92,246,.12);}
  .wbest-meta{font-size:12px;font-weight:800;color:var(--muted);margin-bottom:6px;}
  .wbest-meta b{color:var(--purple-dark);}
  .wbest-text{margin:0;font-size:15px;font-weight:600;color:var(--ink);line-height:1.5;white-space:pre-wrap;}
  .wbest-empty{background:var(--amber-soft);border-radius:14px;padding:14px 16px;font-weight:700;color:#8a6d1a;font-size:14px;line-height:1.5;}
  .wtask-q{font-size:16px;font-weight:800;color:var(--ink);margin:6px 0 8px;line-height:1.4;}
  .wclues{background:var(--amber-soft);border-radius:12px;padding:10px 12px;margin:0 0 10px;}
  .wclues-label{display:block;font-weight:800;color:#8a6d1a;font-size:11px;text-transform:uppercase;letter-spacing:.4px;margin-bottom:5px;}
  .wclues ul{margin:0;padding-left:18px;}
  .wclues li{font-size:14px;font-weight:700;color:#7a5a12;margin:3px 0;line-height:1.4;}
  .wstarter{display:flex;flex-wrap:wrap;gap:6px;margin:0 0 10px;}
  .wstarter-chip{background:var(--blue-soft);color:var(--blue-dark);font-weight:800;font-size:13px;border:none;border-radius:10px;padding:7px 11px;cursor:pointer;font-family:"Nunito";}
  .wstarter-chip:active{transform:scale(.96);}
  .wstarter-chip:hover{filter:brightness(.97);}
  .wtextarea{width:100%;min-height:96px;border:2px solid #e2d0ff;border-radius:14px;padding:12px 14px;font-family:"Nunito";font-size:15.5px;font-weight:600;color:var(--ink);line-height:1.5;resize:vertical;background:#fff;}
  .wtextarea:focus{outline:none;border-color:var(--purple);box-shadow:0 0 0 3px var(--purple-soft);}
  .wcount{font-size:12px;font-weight:700;color:var(--muted);margin:5px 2px 10px;text-align:right;}
  .wcheck-list{margin:12px 0 0;}
  .wcheck-item{display:flex;gap:9px;align-items:flex-start;font-size:14px;font-weight:700;color:var(--ink);background:#fff;border:2px solid #eee3ff;border-radius:11px;padding:9px 11px;margin:6px 0;line-height:1.4;transition:background .15s,border-color .15s;}
  .wcheck-item.on{background:var(--green-soft);border-color:var(--green);}
  .wcheck-box{flex:0 0 auto;width:20px;height:20px;border:2px solid #cbb8ee;border-radius:6px;display:flex;align-items:center;justify-content:center;font-size:13px;color:#fff;background:#fff;cursor:pointer;}
  .wcheck-item.on .wcheck-box{background:var(--green);border-color:var(--green-dark);}
  .wselfcheck-title{font-family:"Baloo 2",cursive;font-weight:800;color:var(--purple-dark);font-size:15px;margin:14px 0 2px;}
  .wselfcheck-hint{font-size:13px;color:var(--muted);font-weight:700;margin:0 0 4px;}
  .wtask-nav{display:flex;justify-content:space-between;gap:10px;margin-top:14px;align-items:center;flex-wrap:wrap;}
  .wpill{display:inline-flex;gap:6px;align-items:center;background:var(--purple-soft);color:var(--purple-dark);font-weight:800;font-size:12px;padding:4px 11px;border-radius:20px;}
  .wreveal{background:#f0fff6;border:2px solid #b6ecca;border-radius:14px;padding:12px 14px;margin:12px 0 0;}
  .wreveal-label{display:inline-block;font-weight:800;color:var(--green-dark);font-size:11px;text-transform:uppercase;letter-spacing:.4px;margin-bottom:5px;}
  .wreveal p{white-space:pre-line;}   /* see .wmodel p — keeps a model's paragraph break visible */
  .wreveal p{margin:0;font-size:15px;line-height:1.55;color:var(--ink);font-weight:600;}
  .wtip-inline{display:flex;gap:8px;align-items:flex-start;background:var(--amber-soft);border-radius:12px;padding:10px 12px;font-size:14px;font-weight:700;color:#8a6d1a;line-height:1.4;margin:10px 0 0;}
  .wstage-map{display:flex;flex-direction:column;gap:6px;margin:6px 0 14px;}
  .wstage-row{display:flex;gap:10px;align-items:center;background:#faf8ff;border:2px solid #eee3ff;border-radius:12px;padding:9px 12px;}
  .wstage-row.cur{background:var(--purple-soft);border-color:var(--purple);}
  .wstage-ic{font-size:18px;flex:0 0 auto;}
  .wstage-name{font-weight:800;color:var(--purple-dark);font-size:14.5px;}
  .wstage-desc{font-size:13px;color:var(--muted);font-weight:700;}

  /* ---- WELCOME (grade selection) screen ---- */
  #screen-welcome{max-width:640px;margin:0 auto;padding:8px clamp(4px,2vw,20px) 20px;}

  /* --- welcome blurb: a plain text box ------------------------------------
     Reverted 2026-08-26 at the user's request. It was briefly a collapsible
     drawer (hover, then click-only); it is now simply a card whose heading and
     three paragraphs are all on screen at once. No button, no chevron, no
     hover state, nothing to press. The waving hand keeps its idle bob because
     that animation is decorative and cannot be mistaken for a control. */
  .wb-head{display:flex;align-items:center;gap:10px;}
  .wb-head .big{flex:1;min-width:0;line-height:1.25;}
  .wb-icon{flex:0 0 auto;font-size:30px;line-height:1;display:inline-block;transform-origin:50% 70%;
    --ds-glow:255,152,56;
    animation:dsBob 3.4s ease-in-out infinite, dsGlow 2.6s ease-in-out infinite;}
  @media (prefers-reduced-motion:reduce){
    .wb-icon{animation:none;filter:drop-shadow(0 0 6px rgba(var(--ds-glow),.6));}
  }

  /* ---- SECTIONS (3-part) screen ---- */
  #screen-sections{max-width:820px;margin:0 auto;padding:8px clamp(4px,2vw,20px) 20px;overflow-anchor:none;}
  .grade-flag{display:inline-flex;align-items:center;gap:6px;background:var(--purple);color:#fff;font-family:"Baloo 2",cursive;font-weight:800;font-size:15px;padding:6px 14px;border-radius:14px;box-shadow:0 4px 0 var(--purple-dark);}
  .grade-flag button{background:rgba(255,255,255,.25);color:#fff;font-family:"Nunito";font-weight:800;font-size:12px;padding:3px 9px;border-radius:9px;margin-left:4px;}
  /* Sized to match the .back button it shares the top bar with — same padding, font
     size, corner radius and shadow depth, so the two ends of the bar are a pair. */
  .grade-badge{display:inline-flex;align-items:center;gap:6px;background:var(--purple);color:#fff;font-family:"Baloo 2",cursive;font-weight:800;font-size:15px;padding:10px 16px;border-radius:16px;white-space:nowrap;box-shadow:0 4px 0 var(--purple-dark);}
  .bonus-banner{position:relative;overflow:hidden;display:flex;align-items:center;gap:clamp(12px,2vw,20px);width:100%;text-align:left;margin-bottom:clamp(12px,1.8vw,20px);background:linear-gradient(135deg,#ff8a00,#ff5da2 52%,#8b5cf6);color:#fff;border:3px solid rgba(255,255,255,.55);border-radius:22px;padding:clamp(16px,2.2vw,20px) clamp(18px,2.4vw,24px);cursor:pointer;box-shadow:0 8px 22px rgba(255,93,162,.4),0 5px 0 rgba(150,45,130,.28);font-family:"Nunito";transition:transform .12s,box-shadow .2s,filter .12s;animation:bonusPulse 2.8s ease-in-out infinite;}
  .bonus-banner:hover{filter:brightness(1.05);box-shadow:0 13px 32px rgba(255,93,162,.52),0 7px 0 rgba(150,45,130,.28);}
  .bonus-banner:active{transform:scale(.99);}
  .bonus-banner::after{content:"";position:absolute;top:0;left:-60%;width:40%;height:100%;background:linear-gradient(100deg,transparent,rgba(255,255,255,.5),transparent);transform:skewX(-18deg);animation:bonusShine 3.8s ease-in-out infinite;pointer-events:none;}
  @keyframes bonusShine{0%{left:-60%;}55%,100%{left:135%;}}
  @keyframes bonusPulse{0%,100%{box-shadow:0 8px 22px rgba(255,93,162,.4),0 5px 0 rgba(150,45,130,.28);}50%{box-shadow:0 8px 30px rgba(255,93,162,.66),0 5px 0 rgba(150,45,130,.28);}}
  .bonus-art{position:relative;z-index:1;flex:0 0 auto;width:clamp(58px,11vw,80px);height:clamp(58px,11vw,80px);display:block;filter:drop-shadow(0 3px 5px rgba(0,0,0,.18));animation:bonusFloat 3.2s ease-in-out infinite;}
  .bonus-art svg{width:100%;height:100%;display:block;}
  @keyframes bonusFloat{0%,100%{transform:translateY(0) rotate(0);}50%{transform:translateY(-4px) rotate(-2deg);}}
  .bonus-text{position:relative;z-index:1;display:flex;flex-direction:column;gap:3px;flex:1;min-width:0;}
  .bonus-title{font-family:"Baloo 2",cursive;font-size:clamp(19px,2.6vw,24px);font-weight:800;text-shadow:0 1px 2px rgba(140,40,110,.25);}
  .bonus-desc{font-size:13.5px;font-weight:700;opacity:.96;}
  .bonus-go{position:relative;z-index:1;font-weight:800;background:rgba(255,255,255,.28);border:1.5px solid rgba(255,255,255,.5);padding:9px 15px;border-radius:12px;white-space:nowrap;flex:0 0 auto;}
  @media(max-width:520px){ .bonus-desc{display:none;} }
  @media(prefers-reduced-motion:reduce){ .bonus-banner,.bonus-art,.bonus-banner::after{animation:none;} }

  /* --- collapsible bonus banner (same behaviour as the quest-part cards) --- */
  /* the banner used to BE the button and was display:flex; it is now a wrapper,
     so the flex row has to go or the head only gets a share of the width and
     the title wraps onto four lines. */
  .bonus-banner{display:block;cursor:default;}
  .bonus-head{display:flex;align-items:center;gap:clamp(12px,2vw,20px);width:100%;
    background:none;border:none;padding:0;margin:0;cursor:pointer;text-align:left;
    color:inherit;font-family:inherit;position:relative;z-index:1;}
  .bonus-head:focus-visible{outline:3px solid #fff;outline-offset:4px;border-radius:14px;}
  .bonus-head .bonus-title{flex:1;min-width:0;}
  .bonus-chev{flex:0 0 auto;width:26px;height:26px;color:#fff;display:grid;place-items:center;
    transition:transform .38s cubic-bezier(.4,0,.2,1);}
  .bonus-chev svg{width:22px;height:22px;display:block;}
  .bonus-body{position:relative;z-index:1;display:grid;grid-template-rows:0fr;opacity:0;
    transition:grid-template-rows .38s cubic-bezier(.4,0,.2,1),opacity .26s ease;}
  .bonus-body-inner{overflow:hidden;min-height:0;visibility:hidden;display:flex;align-items:center;
    gap:14px;flex-wrap:wrap;transition:visibility 0s linear .38s;}
  .bonus-body-inner > *{margin-top:12px;}
  .bonus-body-inner .bonus-desc{display:block;flex:1;min-width:180px;}
  .bonus-banner.open .bonus-body{grid-template-rows:1fr;opacity:1;}
  .bonus-banner.open .bonus-body-inner{visibility:visible;transition:visibility 0s linear 0s;}
  .bonus-banner.open .bonus-chev{transform:rotate(180deg);}
  /* the collapsed banner is short, so shrink the mascot to match the row */
  .bonus-art{width:clamp(44px,7vw,58px);height:clamp(44px,7vw,58px);}
  /* the old rule hid the blurb on small screens; it now lives in the drawer */
  @media(max-width:520px){ .bonus-body-inner .bonus-desc{display:block;} }
  @media(prefers-reduced-motion:reduce){ .bonus-body,.bonus-chev{transition:none;} }

  /* --- fit the quest page in one screen ---------------------------------- */
  .sections-top{display:flex;align-items:center;justify-content:space-between;gap:10px;margin-bottom:10px;flex-wrap:wrap;}
  .section-titles{flex:1;}

  /* --- collapsible quest-part cards -------------------------------------
     The write-up and Start button sit in .section-body, which is closed by
     default. It opens ONLY on a press of the heading button — the chevron on
     its right is the affordance — and the next press closes it again.
     Hover-to-open was removed 2026-08-25: drawers fired as the pointer swept
     across the page, and hover does not exist on the Capacitor build anyway.
     :focus-within was removed with it, because a click leaves the heading
     focused and the drawer could then never close. The 0fr -> 1fr grid trick
     animates to the real content height, which max-height cannot do without a
     magic number. */
  .section-head{display:flex;align-items:center;gap:12px;width:100%;text-align:left;
    background:none;border:none;padding:0;margin:0;border-radius:14px;cursor:pointer;
    font-family:inherit;color:inherit;transition:transform .18s ease;}
  .section-head:focus-visible{outline:3px solid var(--purple);outline-offset:4px;}
  .section-chev{margin-left:auto;flex-shrink:0;width:26px;height:26px;color:var(--purple);
    display:grid;place-items:center;transition:transform .38s cubic-bezier(.4,0,.2,1);}
  .section-chev svg{width:22px;height:22px;display:block;}
  .section-body{display:grid;grid-template-rows:0fr;opacity:0;
    transition:grid-template-rows .38s cubic-bezier(.4,0,.2,1), opacity .26s ease;}
  /* min-height:0 lets the inner track actually collapse inside the grid row */
  .section-body-inner{overflow:hidden;min-height:0;visibility:hidden;transition:visibility 0s linear .38s;}
  .section-card.open .section-body{grid-template-rows:1fr;opacity:1;}
  .section-card.open .section-body-inner{visibility:visible;transition:visibility 0s linear 0s;}
  .section-card.open .section-chev{transform:rotate(180deg);}
  /* a closed card should not look like a dead tile */
  .section-card{transition:box-shadow .25s ease,transform .25s ease;}
  @media (hover:hover) and (pointer:fine){
    .section-card:hover{box-shadow:0 9px 0 rgba(58,45,92,.10);}
  }
  @media (prefers-reduced-motion:reduce){
    .section-body,.section-chev,.section-head,.section-card{transition:none;}
  }

  /* ============ NAPLAN TEST PRACTICE ============ */
  #screen-tphub,#screen-tpcover,#screen-tptest,#screen-tpresults{max-width:900px;margin:0 auto;padding:8px clamp(4px,2vw,20px) 24px;box-sizing:border-box;}
  /* hub: choose a domain */
  .tp-intro{background:#eef4ff;border:2px solid #cfe0ff;border-radius:16px;padding:14px 16px;font-size:15px;font-weight:700;color:var(--ink);margin:0 0 16px;line-height:1.5;}
  .tp-grid{display:grid;grid-template-columns:1fr;gap:11px;align-items:start;}
  .tp-domain{background:linear-gradient(160deg,#fff,var(--green-soft));border:3px solid var(--green);
    border-radius:22px;padding:14px 18px;box-shadow:0 6px 0 rgba(58,45,92,.07);
    display:flex;flex-direction:column;overflow-anchor:none;
    transition:box-shadow .25s ease,border-color .25s ease;}
  .tp-domain .tpd-emoji{font-size:38px;line-height:1;flex-shrink:0;}
  .tp-domain .tpd-title{font-family:"Baloo 2",cursive;font-size:21px;font-weight:800;color:var(--purple-dark);
    margin:0;flex:1;min-width:0;line-height:1.1;}
  .tp-domain .tpd-desc{font-size:14px;font-weight:600;color:var(--muted);line-height:1.4;margin:12px 0 12px;}
  .tp-setbtns{display:flex;flex-direction:column;gap:9px;}

  /* --- collapsible Test Practice domains --------------------------------
     Identical mechanism to .ds-body: only grid-template-rows animates, and the
     drawer opens and closes solely on presses of the heading button. */
  .tpd-head{display:flex;align-items:center;gap:10px;width:100%;text-align:left;
    background:none;border:none;padding:0;margin:0;cursor:pointer;color:inherit;
    font-family:inherit;flex:0 0 auto;border-radius:12px;}
  .tpd-head:focus-visible{outline:3px solid var(--purple);outline-offset:4px;}
  .tpd-chev{flex:0 0 auto;width:22px;height:22px;color:var(--purple);display:grid;place-items:center;
    transition:transform .38s cubic-bezier(.4,0,.2,1);}
  .tpd-chev svg{width:19px;height:19px;display:block;}
  .tpd-body{display:grid;grid-template-rows:0fr;opacity:0;
    transition:grid-template-rows .38s cubic-bezier(.4,0,.2,1), opacity .26s ease;}
  .tpd-body-inner{overflow:hidden;min-height:0;visibility:hidden;transition:visibility 0s linear .38s;}
  .tp-domain.open .tpd-body{grid-template-rows:1fr;opacity:1;}
  .tp-domain.open .tpd-body-inner{visibility:visible;transition:visibility 0s linear 0s;}
  .tp-domain.open .tpd-chev{transform:rotate(180deg);}
  @media (hover:hover) and (pointer:fine){
    .tp-domain:hover{box-shadow:0 7px 0 rgba(58,45,92,.10);}
  }

  /* icons: same bob + glow as Core Knowledge, colour-matched per domain
     (reading blue, language purple, writing orange, numeracy green) */
  .tp-grid .tp-domain:nth-child(1){--ds-glow:47,123,255;}
  .tp-grid .tp-domain:nth-child(2){--ds-glow:139,92,246;}
  .tp-grid .tp-domain:nth-child(3){--ds-glow:255,152,56;}
  .tp-grid .tp-domain:nth-child(4){--ds-glow:18,192,122;}
  .tpd-emoji{display:inline-block;transform-origin:50% 70%;
    animation:dsBob 3.4s ease-in-out infinite, dsGlow 2.6s ease-in-out infinite;}
  @media (hover:hover) and (pointer:fine){
    .tp-domain:hover .tpd-emoji{
      animation:dsWiggle .62s ease-in-out infinite, dsGlowHot 1.1s ease-in-out infinite;}
  }
  @media (prefers-reduced-motion:reduce){
    .tpd-emoji,.tp-domain:hover .tpd-emoji{animation:none;
      filter:drop-shadow(0 0 6px rgba(var(--ds-glow),.6));}
    .tpd-body,.tpd-chev,.tp-domain{transition:none;}
  }
  .tp-setbtn{display:flex;align-items:center;justify-content:space-between;background:var(--blue-soft);color:var(--blue-dark);border:2px solid transparent;border-radius:13px;padding:11px 14px;font-family:"Nunito";font-weight:800;font-size:14.5px;text-align:left;box-shadow:0 3px 0 rgba(58,45,92,.08);}
  .tp-setbtn:hover{filter:brightness(1.03);transform:translateY(-1px);}
  .tp-setbtn .tp-go{background:var(--blue);color:#fff;font-size:12px;padding:3px 10px;border-radius:9px;}
  .tp-setbtn.done{background:var(--green-soft);color:var(--green-dark);}
  .tp-setbtn.done .tp-go{background:var(--green);}
  .tp-setbtn .tp-meta{font-size:11.5px;color:var(--muted);font-weight:700;display:block;margin-top:2px;}
  .tp-domain.locked{opacity:.75;}
  .tp-lock{background:var(--amber-soft);color:#8a6d1a;font-size:12px;font-weight:800;padding:8px 12px;border-radius:11px;text-align:center;}

  /* cover page (official-looking test instructions) */
  .tp-cover{background:#fff;border:3px solid var(--purple-soft);border-radius:22px;padding:0;overflow:hidden;box-shadow:0 10px 0 rgba(139,92,246,.1),0 14px 34px rgba(58,45,92,.12);}
  .tp-cover-band{background:linear-gradient(135deg,var(--purple),var(--blue));color:#fff;padding:22px 24px;}
  .tp-cover-band .tpc-kicker{font-family:"Nunito";font-weight:800;font-size:12.5px;letter-spacing:2px;text-transform:uppercase;opacity:.9;}
  .tp-cover-band h1{color:#fff;font-size:clamp(28px,5vw,40px);text-shadow:2px 2px 0 rgba(0,0,0,.12);margin:4px 0 2px;}
  .tp-cover-band .tpc-sub{font-family:"Nunito";font-weight:700;font-size:15px;opacity:.95;}
  .tp-cover-inner{padding:20px 24px 24px;}
  .tp-facts{display:flex;flex-wrap:wrap;gap:10px;margin:0 0 18px;}
  .tp-fact{flex:1 1 130px;background:var(--purple-soft);border-radius:14px;padding:12px 14px;text-align:center;}
  .tp-fact .tpf-n{font-family:"Baloo 2",cursive;font-size:26px;font-weight:800;color:var(--purple-dark);line-height:1;}
  .tp-fact .tpf-l{font-size:12px;font-weight:800;color:var(--muted);text-transform:uppercase;letter-spacing:.4px;margin-top:4px;}
  .tp-instructions{background:#fbf8ff;border:2px solid var(--purple-soft);border-radius:16px;padding:16px 18px;margin:0 0 18px;}
  .tp-instructions h3{font-family:"Baloo 2",cursive;color:var(--purple-dark);font-size:18px;margin:0 0 8px;}
  .tp-instructions ol{margin:0;padding-left:20px;}
  .tp-instructions li{font-size:14.5px;font-weight:600;color:var(--ink);line-height:1.55;margin-bottom:6px;}
  .tp-startbtn{display:block;width:100%;background:var(--green);color:#fff;font-size:20px;padding:16px;border-radius:16px;box-shadow:0 5px 0 var(--green-dark);}
  .tp-startbtn:hover{filter:brightness(1.05);}
  .tp-cover-note{font-size:12.5px;color:var(--muted);font-weight:700;text-align:center;margin:12px 0 0;line-height:1.4;}

  /* running test */
  .tp-bar{position:sticky;top:0;z-index:40;background:#fff;border:2px solid var(--line);border-radius:16px;padding:10px 14px;display:flex;align-items:center;flex-wrap:wrap;gap:10px 12px;box-shadow:0 4px 14px rgba(58,45,92,.1);margin-bottom:14px;}
  .tp-timer{display:flex;align-items:center;gap:7px;font-family:"Baloo 2",cursive;font-weight:800;font-size:22px;color:var(--purple-dark);white-space:nowrap;}
  .tp-timer.warn{color:var(--orange-dark);}
  .tp-timer.danger{color:var(--red);animation:tpPulse 1s infinite;}
  @keyframes tpPulse{0%,100%{opacity:1;}50%{opacity:.55;}}
  .tp-progresswrap{flex:1 1 130px;min-width:0;}
  .tp-progresswrap .tp-plabel{font-size:12px;font-weight:800;color:var(--muted);margin-bottom:3px;}
  .tp-pbar{height:9px;background:var(--line);border-radius:6px;overflow:hidden;}
  .tp-pbar-fill{height:100%;background:linear-gradient(90deg,var(--green),var(--blue));width:0;transition:width .25s;}
  /* the writing test shows a phase as well as a time, so the chip has to be
     narrower than the plain countdown or it pushes the bar off a phone screen */
  .tp-timer.phased{font-size:17px;gap:5px;flex-wrap:wrap;}
  .tp-timer .tp-tot{font-style:normal;font-size:12px;font-weight:800;color:var(--muted);white-space:nowrap;}
  .tp-submit-top{background:var(--purple);color:#fff;font-size:13px;padding:8px 14px;border-radius:11px;box-shadow:0 3px 0 var(--purple-dark);white-space:nowrap;}
  .tp-quit-top{background:var(--red-soft,#ffe0e0);color:var(--red,#d33);font-weight:800;font-size:13px;padding:8px 12px;border-radius:11px;box-shadow:0 3px 0 rgba(211,51,51,.28);white-space:nowrap;border:none;cursor:pointer;}
  .tp-quit-top:active{transform:translateY(2px);box-shadow:0 1px 0 rgba(211,51,51,.28);}

  .tp-qcard{background:#fff;border:3px solid var(--line);border-radius:20px;padding:20px 22px;box-shadow:0 6px 0 rgba(58,45,92,.06);}
  .tp-secttag{display:inline-block;background:var(--blue-soft);color:var(--blue-dark);font-family:"Nunito";font-weight:800;font-size:11.5px;letter-spacing:1px;text-transform:uppercase;padding:4px 11px;border-radius:9px;margin-bottom:10px;}
  .tp-stimulus{background:#fbfaf6;border:2px solid var(--line);border-radius:14px;padding:14px 16px;margin:0 0 16px;}
  /* Test Practice is 900px wide now that the .app cap no longer silences its own
     max-width. Passage PROSE keeps the ~700px measure it had at 740px, so lines do
     not stretch to ~90 characters; the extra width goes to the artwork and the
     answer options instead. Images sit outside .tp-stim-body and still use it all. */
  .tp-stim-body{max-width:700px;}
  .tp-stim-title{font-family:"Baloo 2",cursive;font-weight:800;color:var(--purple-dark);font-size:19px;margin:0 0 4px;text-align:center;}
  .tp-stim-byline{font-size:12.5px;color:var(--muted);font-weight:700;text-align:center;margin:0 0 10px;font-style:italic;}
  .tp-stim-body{font-size:15.5px;line-height:1.65;color:var(--ink);font-weight:600;}
  .tp-stim-body p{margin:0 0 10px;}
  .tp-stim-body .para-num{color:var(--muted);font-weight:800;font-size:12px;margin-right:6px;vertical-align:top;}
  /* A poem is set the way the real reading magazines set one: the lines are
     LEFT-aligned as a block, and the block is centred on the page. Centring
     every line individually (and italicising the lot) is a greetings-card
     look — no NAPLAN poem is printed that way, and it destroys the shape the
     poet built, which is exactly what some poem items ask about. */
  .tp-poem{white-space:pre-line;line-height:1.75;text-align:left;
           width:fit-content;max-width:100%;margin:0 auto;}
  .tp-poem-by{text-align:right;font-size:13px;font-weight:700;color:var(--muted);
              font-style:italic;margin:10px auto 0;width:fit-content;max-width:100%;}
  .tp-stim-img{display:block;margin:10px auto;max-width:100%;width:auto;height:auto;border-radius:10px;}
  .tp-caption{font-size:12.5px;color:var(--muted);font-weight:700;text-align:center;margin:4px 0 0;font-style:italic;}
  /* numbered footnote glossary under a passage — the device the real Year 5
     magazines use to gloss one hard word instead of rewriting the sentence */
  .tp-stim-note{margin:12px 0 0;padding:9px 12px 7px;border-top:2px solid var(--line);}
  .tp-stim-note p{margin:0 0 4px;font-size:13px;line-height:1.5;color:var(--muted);font-weight:700;}
  .tp-stim-note p:last-child{margin-bottom:0;}

  .tp-qnum{font-family:"Baloo 2",cursive;font-weight:800;color:var(--muted);font-size:14px;margin:0 0 4px;}
  .tp-qstem{font-size:17px;font-weight:700;color:var(--ink);line-height:1.5;margin:0 0 14px;}
  .tp-opt{display:flex;align-items:flex-start;gap:11px;width:100%;text-align:left;background:#fff;border:3px solid var(--line);border-radius:14px;padding:13px 15px;margin-bottom:10px;font-size:15.5px;font-weight:700;color:var(--ink);font-family:"Nunito";line-height:1.4;cursor:pointer;transition:transform .07s,border-color .12s,background .12s;}
  .tp-opt:hover{border-color:var(--blue);transform:translateX(2px);}
  .tp-opt.sel{border-color:var(--purple);background:var(--purple-soft);}
  .tp-opt .tp-letter{flex:none;width:26px;height:26px;border-radius:50%;background:var(--line);color:var(--ink);font-family:"Baloo 2",cursive;font-weight:800;font-size:14px;display:flex;align-items:center;justify-content:center;margin-top:1px;}
  .tp-opt.sel .tp-letter{background:var(--purple);color:#fff;}
  /* picture answer options — four diagrams in a 2x2 grid, like "which spinner…" on the real paper */
  .tp-opts.pic{display:grid;grid-template-columns:1fr 1fr;gap:10px;}
  .tp-opts.pic .tp-opt{flex-direction:column;align-items:center;gap:6px;margin-bottom:0;padding:10px;}
  .tp-opts.pic .tp-letter{margin-top:0;}
  .tp-optpic{display:block;width:100%;}
  .tp-optpic svg,.tp-optpic img{display:block;margin:0 auto;width:auto;max-width:100%;height:auto;max-height:150px;border-radius:8px;}
  @media (max-width:420px){ .tp-opts.pic{grid-template-columns:1fr;} .tp-optpic svg,.tp-optpic img{max-height:170px;} }
  /* a tall, narrow diagram scaled to the card width towers off the screen — cap its height
     and let it shrink to its natural width instead */
  .tp-qcard .na-graph svg, .tp-rev-item .na-graph svg{width:auto;max-width:100%;max-height:300px;margin:0 auto;}

  /* number-entry: a short boxed answer field, not a full-width text input */
  .tp-answerbox{display:flex;justify-content:center;margin:6px 0 2px;}
  .tp-typewrap input[type=text]{width:170px;font-size:28px;font-weight:800;text-align:center;letter-spacing:1px;padding:12px 14px;border:3px solid var(--purple);border-radius:14px;background:#fff;font-family:"Baloo 2",cursive;color:var(--ink);}
  .tp-typewrap input[type=text]:focus{outline:none;border-color:var(--purple-dark);box-shadow:0 0 0 4px var(--purple-soft);}
  .tp-typewrap.has-pre{display:flex;align-items:center;gap:8px;}
  .tp-typepre{font-family:"Baloo 2",cursive;font-weight:800;font-size:30px;color:var(--purple-dark);flex:none;}
  .tp-typehint{text-align:center;}
  .tp-typehint{font-size:13px;color:var(--muted);font-weight:700;margin:2px 0 0;}

  /* practice questions (untimed, before the test) */
  .tp-pfeedback{border-radius:14px;padding:12px 14px;margin-top:12px;border:3px solid;}
  .tp-pfeedback.ok{background:var(--green-soft,#e8f9ee);border-color:var(--green);}
  .tp-pfeedback.no{background:var(--amber-soft,#fff4d6);border-color:var(--amber);}
  .tp-pfb-head{font-family:"Baloo 2",cursive;font-weight:800;font-size:16px;margin:0 0 4px;color:var(--ink);}
  .tp-revpic{display:block;max-width:150px;margin:6px 0;}
  .tp-revpic svg,.tp-revpic img{display:block;width:100%;height:auto;max-height:110px;border-radius:6px;}

  .tp-nav{display:flex;gap:10px;margin-top:16px;align-items:center;}
  .tp-nav .tp-prev{background:var(--blue-soft);color:var(--blue-dark);box-shadow:0 4px 0 #c3d8ff;}
  .tp-nav .tp-next{background:var(--purple);color:#fff;box-shadow:0 4px 0 var(--purple-dark);margin-left:auto;}
  .tp-nav button{font-family:"Nunito";font-weight:800;font-size:15px;padding:12px 20px;border-radius:13px;}
  .tp-flagbtn{background:none;border:2px solid var(--amber);color:#8a6d1a;font-family:"Nunito";font-weight:800;font-size:13px;padding:9px 13px;border-radius:12px;}
  .tp-flagbtn.on{background:var(--amber);color:#5c4708;}

  /* question navigator grid */
  .tp-navigator{background:#fff;border:2px solid var(--line);border-radius:16px;padding:14px 16px;margin-top:14px;}
  .tp-navigator h4{font-family:"Baloo 2",cursive;color:var(--purple-dark);font-size:15px;margin:0 0 10px;}
  .tp-navgrid{display:grid;grid-template-columns:repeat(auto-fill,minmax(38px,1fr));gap:7px;}
  .tp-navcell{aspect-ratio:1;border:2px solid var(--line);border-radius:10px;background:#fff;font-family:"Baloo 2",cursive;font-weight:800;font-size:14px;color:var(--muted);cursor:pointer;display:flex;align-items:center;justify-content:center;position:relative;}
  .tp-navcell.answered{background:var(--green-soft);border-color:var(--green);color:var(--green-dark);}
  .tp-navcell.current{border-color:var(--purple);border-width:3px;color:var(--purple-dark);}
  .tp-navcell.flagged::after{content:"";position:absolute;top:-4px;right:-4px;width:11px;height:11px;background:var(--amber);border-radius:50%;border:2px solid #fff;}
  .tp-navlegend{display:flex;gap:14px;flex-wrap:wrap;margin-top:10px;font-size:11.5px;font-weight:700;color:var(--muted);}
  .tp-navlegend span{display:inline-flex;align-items:center;gap:5px;}
  .tp-dot{width:11px;height:11px;border-radius:3px;display:inline-block;}

  /* writing test */
  .tp-wprompt{background:#fff8ec;border:2px solid var(--amber);border-radius:16px;padding:16px 18px;margin:0 0 14px;}
  .tp-wprompt .tpw-type{display:inline-block;background:var(--amber);color:#5c4708;font-weight:800;font-size:12px;letter-spacing:1px;text-transform:uppercase;padding:3px 10px;border-radius:9px;margin-bottom:8px;}
  .tp-wprompt h2{font-family:"Baloo 2",cursive;color:var(--purple-dark);font-size:22px;margin:0 0 8px;}
  .tp-wprompt .tpw-body{font-size:15.5px;font-weight:600;color:var(--ink);line-height:1.6;}
  .tp-wprompt .tpw-body ul{margin:8px 0 0;padding-left:20px;}
  .tp-wprompt .tpw-body li{margin-bottom:4px;}
  .tp-wta{width:100%;min-height:340px;border:2px solid #e2d0ff;border-radius:14px;padding:14px 16px;font-family:"Nunito";font-size:16px;font-weight:600;color:var(--ink);line-height:1.7;resize:vertical;background:#fff;}
  .tp-wta:focus{outline:none;border-color:var(--purple);box-shadow:0 0 0 3px var(--purple-soft);}
  .tp-wfoot{display:flex;align-items:center;justify-content:space-between;margin-top:10px;flex-wrap:wrap;gap:10px;}
  .tp-wcount{font-family:"Baloo 2",cursive;font-weight:800;color:var(--muted);font-size:15px;}

  /* ---- writing test: the official prompt page ---- */
  .tp-wprompt.tpw-page{padding:20px 22px 18px;}
  .tp-wprompt.tpw-page h2{font-size:30px;margin:2px 0 10px;letter-spacing:.2px;}
  .tpw-instr{font-size:16.5px;font-weight:800;color:var(--ink);line-height:1.55;margin:0 0 10px;}
  .tpw-sparks{margin:0 0 14px;padding-left:22px;font-size:15.5px;font-weight:600;color:var(--ink);line-height:1.6;}
  .tpw-sparks li{margin-bottom:5px;}
  /* the stimulus is a full-page artwork, not a question diagram — it gets its
     own height allowance, well above the 300px numeracy cap */
  .tp-qcard .tpw-stim svg, .tpw-stim svg{max-height:440px !important;}
  .tpw-stim{border-color:var(--amber) !important;background:#fff !important;padding:8px !important;}
  .tpw-boxed{border-radius:14px;padding:12px 16px;margin:12px 0 0;}
  .tpw-boxed h4{font-family:"Baloo 2",cursive;font-size:17px;margin:0 0 6px;}
  .tpw-boxed ul{margin:0;padding-left:20px;font-size:15px;font-weight:600;line-height:1.55;}
  .tpw-boxed li{margin-bottom:3px;}

  /* ============================================================
     READING — split-screen panes and the item types the real
     Reading test uses beyond multiple choice.
     ============================================================ */

  /* The online test shows the text in one pane and the question beside it.
     Wide screens get exactly that, with the text scrolling on its own so a
     long text never pushes the question out of reach. */
  /* The reading test is the only part of Test Practice that needs two columns,
     so it — and only it — breaks out of the width the other screens use.
     Two caps have to give way, not one: the test screen's own 900px, and the
     .app wrapper's 740px, which is an ancestor and was the real constraint —
     it left a half-width passage barely 307px wide, which is what made a
     180-word text run past 20 lines and squeezed the artwork to a thumbnail.
     The class goes on <body> so a single flag can reach both.
     The engine puts it on while a reading unit is showing and takes it off
     again everywhere else, so no other screen changes width. */
  /* The reading test keeps the SAME width as every other test screen. Two
     columns need roughly 1100px to give the options a usable measure, and at
     740px they would be about 190px wide — so reading is a single column, with
     the passage in a panel that scrolls inside itself and stays pinned under
     the timer bar. The child always has the text one glance away, and the
     question underneath it never gets pushed off the screen.
     `tpFitReadPane()` then sizes the picture to whatever height is left over,
     so the text is never buried by the artwork. */
  /* Three zones in one screenful: picture on top (stays for the whole unit),
     passage in the middle (the only thing that scrolls, and the biggest zone),
     question at the bottom (sized to its content, never scrolled).
     The card's height is set by tpLayoutReading() from the real space left
     under the timer bar, so the page itself never scrolls. */
  body.tp-readmode{padding-bottom:10px;}
  body.tp-readmode #screen-tptest{padding-bottom:0;}
  .tp-reading{display:flex;flex-direction:column;gap:12px;overflow:hidden;}
  /* The zone sizes to its content; the picture is bounded by --tp-artzone, which
     tpLayoutReading() sets from the space actually spare. Bounding the picture
     rather than the zone avoids the circular sizing you get from max-height:100%
     inside a content-sized flex column — that collapses the picture to nothing. */
  /* tpLayoutReading() sets the picture's width and height explicitly, from its
     own aspect ratio and the space actually spare. It has to: an SVG carries no
     intrinsic width, so inside a shrink-to-fit column `width:auto` resolves to
     zero and the picture disappears. */
  .tp-artzone{display:block;width:100%;text-align:center;margin:0 0 10px;}
  .tp-artzone .tp-zoomwrap{display:block;width:-moz-fit-content;width:fit-content;margin:0 auto;max-width:100%;}
  /* the shared .na-graph frame (border + 10px padding) costs 24px of picture height here */
  .tp-artzone .na-graph{display:block;margin:0;padding:0;border:0;background:none;border-radius:0;overflow:visible;}
  .tp-artzone .na-graph svg,
  .tp-artzone .tp-stim-img{display:block;margin:0 auto;max-width:100%;max-height:34vh;}
  .tp-artzone .tp-caption{margin:3px 0 0;}
  .tp-readinstr{font-size:13.5px;font-weight:800;color:var(--muted);margin:0 0 8px;}
  /* Small screens: normal flow, page scrolls. Three fixed zones do not fit a
     phone, so the picture keeps a modest cap, the passage keeps its own scroll
     panel, and the question simply follows underneath. */
  .tp-reading.tp-flow{display:block;overflow:visible;height:auto !important;}
  .tp-reading.tp-flow .tp-artzone{margin-bottom:10px;}
  .tp-reading.tp-flow .tp-artzone .na-graph svg,
  .tp-reading.tp-flow .tp-artzone .tp-stim-img{max-height:22vh;width:auto;height:auto;}
  .tp-reading.tp-flow .tp-readpane{max-height:44vh;margin-bottom:12px;}
  /* --tp-barh is measured from the real timer bar at render time. The bar is
     sticky at top:0 with a high z-index, so a panel pinned any higher than the
     bar's height slides its first lines underneath it. The calc reserves room
     for the stem and options below; the clamp keeps it sane on a tiny phone
     and on a tall desktop. */
  /* flex:1 makes the passage absorb every pixel the picture and question do not
     need; min-height:0 is what actually lets it scroll inside a flex column. */
  .tp-readpane{flex:1 1 auto;min-height:0;min-width:0;overflow-y:auto;
               background:#fbfaf6;border:2px solid var(--line);border-radius:14px;padding:12px 14px;}
  .tp-readpane .tp-stimulus{background:none;border:0;padding:0;margin:0;}
  .tp-qpane{flex:0 0 auto;min-width:0;}
  .tp-readpane .tp-stimulus{margin-bottom:0;}
  .tp-readpane::-webkit-scrollbar{width:10px;}
  .tp-readpane::-webkit-scrollbar-thumb{background:var(--line);border-radius:6px;}

  /* order: a numbered box beside each statement, the way the paper prints it */
  .tp-order{margin:4px 0 8px;}
  .tp-orow{display:flex;align-items:center;gap:11px;background:#fff;border:3px solid var(--line);
           border-radius:14px;padding:10px 13px;margin-bottom:9px;}
  .tp-orow.locked{background:var(--blue-soft);border-color:var(--blue);}
  .tp-obox{flex:none;width:42px;height:42px;border-radius:11px;border:3px dashed var(--purple);
           background:#fff;color:var(--purple-dark);font-family:"Baloo 2",cursive;font-weight:800;
           font-size:20px;cursor:pointer;display:flex;align-items:center;justify-content:center;
           transition:background .12s,border-color .12s;padding:0;}
  .tp-obox:hover{background:var(--purple-soft);}
  .tp-obox.on{border-style:solid;background:var(--purple);color:#fff;}
  .tp-obox.locked{border-style:solid;border-color:var(--blue);background:var(--blue);color:#fff;cursor:default;}
  .tp-otext{font-size:15.5px;font-weight:700;color:var(--ink);line-height:1.4;}

  /* multi-select: same option rows, but the letter chip becomes a tick */
  .tp-opts.tp-multi .tp-opt.sel .tp-letter{background:var(--green);color:#fff;}
  .tp-mcount{font-weight:800;color:var(--purple-dark);}

  /* short written answer — a sentence, so a full-width field and a text keyboard */
  .tp-shortin{width:100%;font-size:17px;font-weight:700;padding:13px 15px;border:3px solid var(--purple);
              border-radius:14px;background:#fff;font-family:"Nunito";color:var(--ink);}
  .tp-shortin:focus{outline:none;border-color:var(--purple-dark);box-shadow:0 0 0 4px var(--purple-soft);}
  .tp-answerbox:has(.tp-shortin){display:block;}

  /* reading artwork is illustration, not a question diagram — it gets the same
     height allowance the writing stimulus has, well above the 300px cap */
  /* Reading artwork is illustration, not a question diagram, so it is not held
     to the 300px numeracy cap — but it IS capped by height rather than left to
     fill the column. In a wide pane the picture shares the height with the text,
     so height is the scarce resource: capping it means a wider column buys a
     bigger picture instead of a taller one. */
  /* The cap is tied to viewport HEIGHT, not just a fixed number, because the
     picture and the text share one pane: a 180-word text is ~420px on its own,
     so on a short window something has to give. Tall screens get the full-size
     picture and no scrolling; short ones shrink the picture rather than bury
     the text. Tap-to-enlarge covers the difference either way. */
  .tp-qcard .tp-rstim svg, .tp-rstim svg{max-height:var(--tp-artmax,clamp(150px,26vh,300px)) !important;}
  .tp-readpane .tp-stim-img{max-height:var(--tp-artmax,clamp(150px,26vh,300px));}
  /* Inside the art zone the picture is sized entirely by tpLayoutReading(), which
     sets BOTH width and height from the real aspect ratio. The caps above are for
     question diagrams and the results review; left applying here they clamp the
     height while the width stays put, which squashes a photo out of proportion. */
  .tp-artzone .na-graph svg,
  .tp-artzone .tp-stim-img{max-height:none !important;max-width:100%;}
  @media (max-width:560px){
    .tp-qcard .tp-rstim svg, .tp-rstim svg{max-height:var(--tp-artmax,clamp(120px,18vh,200px)) !important;}
    .tp-readpane .tp-stim-img{max-height:var(--tp-artmax,clamp(120px,18vh,200px));}
    /* every reclaimed pixel is another word per line, and fewer lines to scroll */
    .tp-reading.tp-qcard{padding:14px 12px;}
    .tp-reading .tp-stimulus{padding:12px 12px;}
    .tp-artzone .na-graph svg,
    .tp-artzone .tp-stim-img{max-height:none !important;}
  }
  /* The stimulus already carries the text's title, so the section chip beside it
     was saying the same word twice and costing a line of pane height. */
  .tp-readpane .tp-secttag{display:none;}

  /* Options two-up: A B on one row, C D on the next. Four stacked rows is the
     single biggest consumer of the question zone, and halving it is what lets
     the whole screen fit. */
  .tp-reading .tp-qpane .tp-opts{display:grid;grid-template-columns:1fr 1fr;gap:9px;}
  .tp-reading .tp-qpane .tp-opt{margin-bottom:0;padding:8px 11px;font-size:14.5px;align-items:center;}
  .tp-reading .tp-qpane .tp-nav button{padding:10px 16px;font-size:15px;}
  .tp-reading .tp-qpane .tp-opt .tp-letter{margin-top:0;}
  .tp-reading .tp-qpane .tp-qnum{margin-bottom:2px;}
  .tp-reading .tp-qpane .tp-qstem{font-size:16px;margin-bottom:9px;}
  .tp-reading .tp-qpane .tp-nav{margin-top:10px;}
  .tp-reading .tp-qpane .tp-typehint{margin:4px 0 0;font-size:12.5px;}
  /* Sequencing rows go two-up as well. The child is assigning a number to each
     statement rather than reading them in sequence, so a two-column list costs
     nothing in clarity and halves the height. */
  .tp-reading .tp-qpane .tp-order{display:grid;grid-template-columns:1fr 1fr;gap:7px;margin:2px 0 4px;}
  .tp-reading .tp-qpane .tp-orow{padding:5px 9px;margin-bottom:0;}
  .tp-reading .tp-qpane .tp-obox{width:30px;height:30px;font-size:15px;border-width:2px;}
  .tp-reading .tp-qpane .tp-otext{font-size:14.5px;}
  /* Four picture options at full size push the passage off the screen, so in
     this layout they are held to a size that still leaves the text room —
     tapping the picture at the top enlarges anything that needs a closer look. */
  .tp-reading .tp-qpane .tp-optpic svg,
  .tp-reading .tp-qpane .tp-optpic img{max-height:64px;}
  .tp-reading .tp-qpane .tp-opts.pic .tp-opt{padding:6px;gap:3px;}
  .tp-reading .tp-qpane .tp-opts.pic .tp-letter{width:21px;height:21px;font-size:12px;}

  @media (max-width:560px){
    .tp-reading .tp-qpane .tp-opts{grid-template-columns:1fr;}
  }
  /* Under the reading card the navigator has to earn its space: no heading, and
     smaller cells, so it fits on screen with the three zones above it. */
  body.tp-readmode .tp-navigator{margin-top:8px;padding:7px 10px;border-radius:13px;}
  body.tp-readmode .tp-navigator h4{display:none;}
  body.tp-readmode .tp-navgrid{grid-template-columns:repeat(auto-fill,minmax(25px,1fr));gap:4px;}
  body.tp-readmode .tp-navcell{font-size:11.5px;border-radius:7px;border-width:2px;}
  body.tp-readmode .tp-navcell.current{border-width:2px;}
  body.tp-readmode .tp-navcell.flagged::after{width:8px;height:8px;top:-3px;right:-3px;border-width:1.5px;}
  body.tp-readmode .tp-navlegend{margin-top:5px;font-size:10.5px;gap:10px;}
  body.tp-readmode .tp-dot{width:9px;height:9px;}

  /* Tap-to-enlarge: on a phone the capped picture is too small to study, so it
     opens full-width over the page. Reuses the existing #tp-modal-bg element. */
  .tp-zoomable{cursor:zoom-in;}
  .tp-zoomwrap{position:relative;max-width:100%;}
  .tp-lightbox{background:#fff;border-radius:18px;padding:12px;width:min(1100px,94vw);max-width:min(1100px,94vw);
               max-height:96vh;overflow:hidden;box-shadow:0 20px 50px rgba(0,0,0,.35);}
  /* tpFitLightbox() sets both dimensions; CSS only keeps it centred. */
  .tp-lightbox img,.tp-lightbox svg{display:block;margin:0 auto;border-radius:10px;}
  .tp-lightbox .tp-lbclose{display:block;margin:12px auto 2px;background:var(--purple);color:#fff;
                           font-size:16px;padding:11px 24px;border-radius:13px;box-shadow:0 4px 0 var(--purple-dark);}
  .tp-lightbox .tp-lbcap{font-size:13px;font-weight:700;color:var(--muted);text-align:center;margin:8px 0 0;}
  @media (max-width:560px){ .tp-lightbox{padding:10px;width:96vw;max-width:96vw;} }

  /* results: which kind of reading went well */
  .tp-skills{background:#fff;border:3px solid var(--line);border-radius:18px;padding:16px 18px;margin:0 0 18px;}
  .tp-skills h4{font-family:"Baloo 2",cursive;font-size:17px;margin:0 0 12px;color:var(--purple-dark);}
  .tp-skillrow{margin-bottom:13px;}
  .tp-skillrow:last-child{margin-bottom:0;}
  .tp-skilltop{display:flex;justify-content:space-between;align-items:baseline;gap:10px;}
  .tp-skillname{font-weight:800;font-size:15px;color:var(--ink);}
  .tp-skillscore{font-family:"Baloo 2",cursive;font-weight:800;font-size:15px;color:var(--muted);}
  .tp-skillbar{height:12px;border-radius:7px;background:var(--line);overflow:hidden;margin:5px 0 3px;}
  .tp-skillbar span{display:block;height:100%;border-radius:7px;transition:width .5s ease;}
  .tp-skilldesc{font-size:12.5px;font-weight:600;color:var(--muted);}
  .tpw-boxed.think{background:#eef4ff;border:2px solid #bfd4ff;}
  .tpw-boxed.think h4{color:var(--blue-dark);}
  .tpw-boxed.remem{background:#eefaf1;border:2px solid #bfe6cd;}
  .tpw-boxed.remem h4{color:var(--green-dark);}
  .tpw-note{font-size:13.5px;font-weight:700;color:var(--muted);margin:12px 0 0;line-height:1.5;}

  /* ---- the phase banner: what the supervisor would be saying ---- */
  .tpw-phase{display:flex;align-items:center;gap:12px;flex-wrap:wrap;border-radius:16px;
    padding:12px 16px;margin:0 0 14px;border:2px solid var(--line);background:#fff;}
  .tpw-phase.plan{background:#f3eeff;border-color:var(--purple);}
  .tpw-phase.write{background:#eefaf1;border-color:var(--green);}
  .tpw-phase.edit{background:#fff5e0;border-color:var(--amber);}
  .tpw-pico{font-size:26px;line-height:1;}
  .tpw-ptxt{display:flex;flex-direction:column;flex:1 1 220px;}
  .tpw-ptxt b{font-family:"Baloo 2",cursive;font-size:18px;color:var(--purple-dark);}
  .tpw-ptxt span{font-size:13.5px;font-weight:700;color:var(--muted);line-height:1.45;}
  .tpw-psteps{display:flex;gap:6px;}
  .tpw-psteps i{font-style:normal;font-size:11.5px;font-weight:800;letter-spacing:.4px;text-transform:uppercase;
    padding:4px 9px;border-radius:20px;background:#fff;border:2px solid var(--line);color:var(--muted);}
  .tpw-psteps i.done{background:var(--green);border-color:var(--green);color:#fff;}
  /* a child who has finished should never have to sit and watch the clock */
  .tpw-pnext{flex:0 0 auto;background:var(--purple);color:#fff;border:none;cursor:pointer;
    font-family:"Baloo 2",cursive;font-size:15px;font-weight:800;padding:9px 16px;
    border-radius:12px;box-shadow:0 3px 0 var(--purple-dark);}
  .tpw-pnext:active{transform:translateY(2px);box-shadow:0 1px 0 var(--purple-dark);}
  .tpw-pnexthint{flex:1 1 100%;font-size:12.5px;font-weight:700;color:var(--muted);line-height:1.45;}
  .tpw-locknext{margin-top:12px;background:var(--purple);color:#fff;border:none;cursor:pointer;
    font-family:"Baloo 2",cursive;font-size:15px;font-weight:800;padding:9px 18px;
    border-radius:12px;box-shadow:0 3px 0 var(--purple-dark);}
  .tpw-locknext:active{transform:translateY(2px);box-shadow:0 1px 0 var(--purple-dark);}
  .tpw-psteps i.on{background:var(--purple);border-color:var(--purple);color:#fff;}

  /* ---- planning page: the blank sheet the real test collects but never marks ---- */
  .tpw-plan{border:2px dashed var(--purple);border-radius:14px;background:#faf7ff;margin:0 0 12px;}
  .tpw-plan summary{cursor:pointer;padding:11px 15px;font-family:"Baloo 2",cursive;font-size:16px;color:var(--purple-dark);}
  .tpw-plan[open] summary{border-bottom:2px dashed var(--purple);}
  .tpw-planta{min-height:150px;border:none;background:transparent;border-radius:0 0 12px 12px;}
  .tpw-planta:focus{box-shadow:none;}

  /* ---- the answer box, closed until the writing call ---- */
  .tpw-answer{position:relative;}
  .tpw-answer .tp-wta:disabled{background:#f4f2f7;color:var(--muted);}
  .tpw-lock{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;
    border-radius:14px;background:rgba(244,242,247,.88);text-align:center;padding:20px;}
  .tpw-lock div{font-size:16px;font-weight:800;color:var(--purple-dark);line-height:1.7;}
  .tpw-lock b{display:block;font-family:"Baloo 2",cursive;font-size:19px;margin:6px 0 4px;}
  .tpw-lock span{display:block;font-size:14px;color:var(--muted);}

  /* ---- results: the marked report, ten criteria ---- */
  .tpw-outof{font-size:26px;color:var(--muted);}
  .tpw-focus{margin:12px auto 0;max-width:560px;background:#fff4e2;border:2px solid var(--amber);
    color:#5c4708;border-radius:12px;padding:9px 14px;font-size:13.5px;font-weight:700;line-height:1.5;}
  .tpw-focus i{font-style:normal;color:#8a6a2c;}
  .tpw-mark-intro{font-size:14.5px;font-weight:700;color:var(--muted);line-height:1.6;margin:0 0 14px;}
  .tpw-crit{background:#fff;border:2px solid var(--line);border-radius:16px;padding:14px 16px;margin-bottom:12px;}
  .tpw-chead{display:flex;align-items:center;gap:10px;flex-wrap:wrap;}
  .tpw-cnum{flex:none;width:28px;height:28px;border-radius:9px;background:var(--purple-soft);color:var(--purple-dark);
    display:flex;align-items:center;justify-content:center;font-weight:800;font-size:14px;}
  .tpw-cname{flex:1 1 150px;display:flex;flex-direction:column;font-family:"Baloo 2",cursive;
    font-size:17px;color:var(--purple-dark);line-height:1.2;}
  .tpw-ckid{font-family:"Nunito";font-size:12.5px;font-weight:700;color:var(--muted);}
  .tpw-cscore{font-family:"Baloo 2",cursive;font-size:19px;font-weight:800;color:#fff;
    padding:3px 12px;border-radius:20px;}
  .tpw-cscore span{font-size:13px;opacity:.8;}
  .tpw-cscore.hi{background:var(--green);}
  .tpw-cscore.mid{background:var(--amber);color:#5c4708;}
  .tpw-cscore.lo{background:#e0554f;}
  /* one pip per mark available, filled to the mark scored */
  .tpw-pips{display:flex;gap:5px;margin:10px 0 10px;}
  .tpw-pips i{flex:1 1 0;height:8px;border-radius:4px;background:var(--line);}
  .tpw-pips i.on{background:var(--purple);}
  .tpw-focusline{font-size:13.5px;font-weight:600;color:var(--muted);line-height:1.5;margin:0 0 6px;}
  .tpw-focusline b,.tpw-desc b{color:var(--purple-dark);font-weight:800;}
  .tpw-desc{font-size:14.5px;font-weight:700;color:var(--ink);line-height:1.5;margin:0 0 12px;}
  .tpw-fbcols{display:flex;gap:10px;flex-wrap:wrap;}
  .tpw-fb{flex:1 1 240px;border-radius:12px;padding:10px 13px;}
  .tpw-fb h5{margin:0 0 6px;font-family:"Baloo 2",cursive;font-size:14.5px;}
  .tpw-fb ul{margin:0;padding-left:17px;}
  .tpw-fb li{font-size:13.5px;font-weight:600;line-height:1.55;margin-bottom:5px;}
  .tpw-fb.well{background:#eefaf1;border:2px solid #bfe6cd;}
  .tpw-fb.well h5{color:var(--green-dark);}
  .tpw-fb.well li{color:#2c5c40;}
  .tpw-fb.fix{background:#fff4e2;border:2px solid #f2d9a8;}
  .tpw-fb.fix h5{color:#8a6a2c;}
  .tpw-fb.fix li{color:#6b5324;}
  .tpw-all{margin-top:10px;}
  .tpw-all summary{cursor:pointer;font-size:13px;font-weight:800;color:var(--purple);}
  .tpw-all ol{margin:8px 0 0;padding-left:26px;font-size:13.5px;font-weight:600;color:var(--muted);line-height:1.5;}
  .tpw-all li{margin-bottom:4px;}
  .tpw-all li.on{color:var(--ink);font-weight:800;}
  .tpw-model{border:2px solid var(--line);border-radius:12px;overflow:hidden;}
  /* four labelled columns: criterion, your mark, the model's mark, the gap */
  .tpw-mrow{display:grid;grid-template-columns:1fr 56px 56px 54px;align-items:center;gap:6px;
    padding:7px 12px;font-size:14px;font-weight:700;color:var(--ink);border-bottom:1px solid var(--line);}
  .tpw-mrow:last-child{border-bottom:none;}
  .tpw-mrow em{font-style:normal;font-family:"Baloo 2",cursive;font-weight:800;font-size:16px;
    text-align:center;color:var(--purple-dark);}
  .tpw-mrow em u{text-decoration:none;font-family:"Nunito";font-size:11px;font-weight:700;color:var(--muted);}
  .tpw-mrow i{font-style:normal;font-size:11.5px;font-weight:800;padding:2px 0;border-radius:20px;text-align:center;}
  .tpw-mrow i.up{background:#eefaf1;color:var(--green-dark);}
  .tpw-mrow i.down{background:#ffe9e7;color:#a8362f;}
  .tpw-mrow i.same{background:var(--line);color:var(--muted);}
  .tpw-mrow.head{background:#f6f4fa;font-size:11px;font-weight:800;letter-spacing:.5px;
    text-transform:uppercase;color:var(--muted);}
  .tpw-mrow.head em,.tpw-mrow.head i{font-family:"Nunito";font-size:11px;font-weight:800;
    color:var(--muted);background:none;letter-spacing:.5px;}
  .tpw-mrow.total{background:var(--purple-soft);color:var(--purple-dark);font-weight:800;}
  .tpw-mrow.total em{font-size:19px;}


  /* results */
  .tp-results-hero{text-align:center;background:#fff;border:3px solid var(--line);border-radius:22px;padding:26px 22px;box-shadow:0 8px 0 rgba(58,45,92,.07);}
  .tp-score-ring{font-family:"Baloo 2",cursive;font-size:58px;font-weight:800;color:var(--purple-dark);line-height:1;}
  .tp-score-sub{font-size:16px;font-weight:700;color:var(--muted);margin-top:4px;}
  .tp-rbadge{display:inline-block;padding:9px 20px;border-radius:26px;font-family:"Baloo 2",cursive;font-weight:800;font-size:18px;margin:14px 0 4px;}
  .tp-stat-row{display:flex;gap:10px;justify-content:center;flex-wrap:wrap;margin-top:16px;}
  .tp-stat{background:var(--purple-soft);border-radius:14px;padding:11px 16px;min-width:90px;}
  .tp-stat .n{font-family:"Baloo 2",cursive;font-size:24px;font-weight:800;color:var(--purple-dark);}
  .tp-stat .l{font-size:11.5px;font-weight:800;color:var(--muted);text-transform:uppercase;}
  .tp-review-title{font-family:"Baloo 2",cursive;font-weight:800;font-size:20px;color:var(--purple-dark);margin:22px 0 10px;}
  .tp-rev-item{background:#fff;border:2px solid var(--line);border-radius:15px;padding:14px 16px;margin-bottom:11px;}
  .tp-rev-item.correct{border-color:var(--green);background:var(--green-soft);}
  .tp-rev-item.wrong{border-color:var(--red);background:var(--red-soft);}
  .tp-rev-item.skipped{border-color:var(--amber);background:var(--amber-soft);}
  .tp-rev-q{font-size:15px;font-weight:800;color:var(--ink);margin:0 0 6px;line-height:1.4;}
  .tp-rev-line{font-size:14px;font-weight:700;margin:3px 0;line-height:1.4;}
  .tp-rev-line .lbl{font-weight:800;}
  .tp-rev-yours{color:var(--red);} .tp-rev-yours.ok{color:var(--green-dark);}
  .tp-rev-correct{color:var(--green-dark);}
  .tp-rev-why{font-size:13.5px;font-weight:600;color:var(--muted);margin-top:5px;line-height:1.45;font-style:italic;}
  .tp-writing-review{background:#fff;border:2px solid var(--purple-soft);border-radius:15px;padding:16px 18px;}
  .tp-writing-review h4{font-family:"Baloo 2",cursive;color:var(--purple-dark);margin:0 0 8px;font-size:17px;}
  .tp-wr-text{background:#fbfaf6;border:2px solid var(--line);border-radius:12px;padding:12px 14px;font-size:14.5px;line-height:1.6;color:var(--ink);font-weight:600;white-space:pre-wrap;max-height:260px;overflow:auto;}
  .tp-checklist{margin:12px 0 0;}
  .tp-check{display:flex;align-items:flex-start;gap:9px;font-size:14px;font-weight:700;color:var(--ink);margin-bottom:6px;line-height:1.4;}
  .tp-check .cb{flex:none;width:22px;height:22px;border-radius:7px;background:var(--line);color:#fff;display:flex;align-items:center;justify-content:center;font-size:14px;font-weight:800;}
  .tp-check.on .cb{background:var(--green);}
  .tp-again{display:flex;gap:10px;margin-top:20px;flex-wrap:wrap;}
  .tp-again button{flex:1;min-width:150px;font-family:"Nunito";font-weight:800;font-size:15px;padding:13px;border-radius:14px;}
  .tp-again .retry{background:var(--blue);color:#fff;box-shadow:0 4px 0 var(--blue-dark);}
  .tp-again .home{background:var(--purple);color:#fff;box-shadow:0 4px 0 var(--purple-dark);}

  /* timeout modal */
  .tp-modal-bg{position:fixed;inset:0;background:rgba(58,45,92,.55);display:flex;align-items:center;justify-content:center;z-index:1000;padding:20px;overflow-y:auto;backdrop-filter:blur(2px);}
  .tp-modal{background:#fff;border-radius:22px;padding:26px 24px;max-width:400px;text-align:center;box-shadow:0 20px 50px rgba(0,0,0,.3);}
  .tp-modal h2{font-family:"Baloo 2",cursive;color:var(--purple-dark);font-size:26px;margin:0 0 8px;}
  .tp-modal p{font-size:15px;font-weight:700;color:var(--ink);line-height:1.5;margin:0 0 16px;}
  .tp-modal button{background:var(--purple);color:#fff;font-size:17px;padding:13px 26px;border-radius:14px;box-shadow:0 4px 0 var(--purple-dark);}
  .tp-confirm-list{text-align:left;font-size:14px;font-weight:700;color:var(--ink);background:var(--amber-soft);border-radius:12px;padding:12px 14px;margin:0 0 16px;line-height:1.6;}

  /* ===== TEST GUIDE styles ===== */
  .tg-grid{display:flex;flex-direction:column;gap:12px;}
  .tg-domain-card{display:flex;align-items:center;gap:14px;width:100%;text-align:left;background:#fff;border:3px solid var(--line);border-radius:20px;padding:16px 18px;box-shadow:0 5px 0 rgba(58,45,92,.07);cursor:pointer;transition:transform .08s,border-color .12s,box-shadow .1s;font-family:"Nunito";}
  .tg-domain-card:hover{border-color:var(--purple);transform:translateX(2px);}
  .tg-domain-card:active{transform:scale(.99);}
  .tg-dom-emoji{font-size:34px;flex:none;line-height:1;}
  .tg-dom-txt{display:flex;flex-direction:column;gap:3px;flex:1;}
  .tg-dom-name{font-family:"Baloo 2",cursive;font-weight:800;font-size:20px;color:var(--ink);}
  .tg-dom-desc{font-size:13.5px;color:var(--muted);font-weight:700;line-height:1.35;}
  .tg-dom-arrow{font-family:"Baloo 2",cursive;font-weight:800;font-size:22px;color:var(--purple);flex:none;}

  .tg-sec-list{display:flex;flex-direction:column;gap:10px;margin-top:6px;}
  .tg-sec-btn{display:flex;align-items:center;gap:10px;width:100%;text-align:left;background:#fff;border:3px solid var(--line);border-radius:16px;padding:14px 16px;box-shadow:0 4px 0 rgba(58,45,92,.06);cursor:pointer;transition:transform .08s,border-color .12s;font-family:"Nunito";}
  .tg-sec-btn:hover{border-color:var(--blue);transform:translateX(2px);}
  .tg-sec-btn:active{transform:scale(.99);}
  .tg-sec-main{display:flex;flex-direction:column;gap:2px;flex:1;}
  .tg-sec-name{font-family:"Baloo 2",cursive;font-weight:800;font-size:17px;color:var(--ink);}
  .tg-sec-blurb{font-size:12.5px;color:var(--muted);font-weight:700;line-height:1.3;}
  .tg-sec-tag{flex:none;font-family:"Nunito";font-weight:800;font-size:11px;padding:4px 9px;border-radius:20px;background:var(--blue-soft);color:var(--blue-dark);white-space:nowrap;}
  .tg-sec-tag.prac{background:var(--green-soft);color:var(--green-dark);}

  .tg-passage{background:var(--amber-soft);border:3px solid var(--amber);border-radius:18px;padding:16px 18px;margin-bottom:14px;}
  .tg-pass-badge{display:inline-block;background:var(--amber);color:#6b4e00;font-weight:800;font-size:12px;padding:3px 11px;border-radius:20px;margin-bottom:8px;}
  .tg-pass-title{font-family:"Baloo 2",cursive;color:var(--ink);margin:2px 0 8px;font-size:20px;}
  .tg-pass-body{font-size:15.5px;line-height:1.55;color:var(--ink);font-weight:600;}
  .tg-pass-body p{margin:0 0 10px;}
  .tg-pass-body p:last-child{margin-bottom:0;}

  .tg-prompt{background:var(--purple-soft);border:3px solid var(--purple);border-radius:18px;padding:16px 18px;margin:12px 0 14px;}
  .tg-prompt-badge{display:inline-block;background:var(--purple);color:#fff;font-weight:800;font-size:12px;padding:3px 11px;border-radius:20px;margin-bottom:8px;}
  .tg-check{background:#fff;border:3px solid var(--green);border-radius:18px;padding:14px 18px;margin-bottom:14px;box-shadow:0 4px 0 var(--green-soft);}
  .tg-check-head{font-family:"Baloo 2",cursive;font-weight:800;color:var(--green-dark);font-size:17px;margin-bottom:8px;}
  .tg-check-list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:8px;}
  .tg-check-list li{font-size:14.5px;font-weight:700;color:var(--ink);line-height:1.4;}
  .tg-check-list label{display:flex;align-items:flex-start;gap:9px;cursor:pointer;}
  .tg-cbx{margin-top:3px;width:18px;height:18px;flex:none;accent-color:var(--green);}
  .tg-check-list li.ticked span{text-decoration:line-through;color:var(--muted);}
  .tg-write-note{font-size:13px;color:var(--muted);font-weight:700;line-height:1.45;background:var(--blue-soft);border-radius:14px;padding:12px 14px;margin:0;}

  /* ===== NUMBER & ALGEBRA — extra question-type styles ===== */
  .na-instr{font-weight:800;color:var(--purple-dark);margin:0 0 10px;font-size:15px;}
  /* drag: ordering */
  .na-dragrow{display:flex;flex-wrap:wrap;gap:10px;margin:6px 0 4px;justify-content:center;}
  .na-chip{background:var(--blue-soft);color:var(--blue-dark);font-weight:800;font-size:17px;
    border:3px solid #cfe0ff;border-radius:14px;padding:12px 16px;cursor:grab;user-select:none;
    box-shadow:0 3px 0 #bcd4ff;touch-action:none;min-width:44px;text-align:center;transition:transform .08s;}
  .na-chip.dragging{opacity:.5;transform:scale(1.05);}
  .na-chip.placed{cursor:default;}
  .na-slots{display:flex;flex-wrap:wrap;gap:10px;justify-content:center;margin:10px 0;}
  .na-slot{min-width:56px;min-height:52px;border:3px dashed #c9b8f0;border-radius:14px;
    display:flex;align-items:center;justify-content:center;background:#faf8ff;padding:4px;transition:background .12s,border-color .12s;}
  .na-slot.over{background:var(--purple-soft);border-color:var(--purple);}
  .na-slot.filled{border-style:solid;border-color:var(--purple);background:#fff;}
  .na-slotlabel{font-size:12px;font-weight:800;color:var(--muted);text-align:center;margin-bottom:2px;}
  .na-slotwrap{display:flex;flex-direction:column;align-items:center;gap:2px;}
  /* drag: matching into bins */
  .na-bins{display:flex;gap:10px;flex-wrap:wrap;justify-content:center;margin:10px 0;}
  .na-bin{flex:1;min-width:120px;border:3px solid #d9ccf5;border-radius:16px;background:#faf8ff;padding:8px;min-height:70px;transition:background .12s,border-color .12s;}
  .na-bin.over{background:var(--purple-soft);border-color:var(--purple);}
  .na-bin-title{font-weight:800;color:var(--purple-dark);font-size:14px;text-align:center;margin-bottom:6px;}
  .na-bin-items{display:flex;flex-wrap:wrap;gap:6px;justify-content:center;min-height:30px;}
  .na-bin .na-chip{font-size:15px;padding:8px 12px;}
  .na-pool{display:flex;flex-wrap:wrap;gap:8px;justify-content:center;margin:6px 0 12px;padding:8px;background:#f4f4fb;border-radius:14px;min-height:44px;}
  /* graph question */
  .na-graph{background:#fff;border:2px solid var(--purple-soft);border-radius:16px;padding:10px;margin:4px 0 12px;overflow-x:auto;}
  /* Power practice: Daily Mix / Facts Sprint cards + Topic Challenge button */
  .na-power-row{margin-bottom:6px;}
  .na-power-card{border:2.5px dashed var(--purple);}
  .na-power-card.soon{opacity:.65;border-style:dashed;}
  .na-challenge{border:2.5px solid var(--purple);}
  /* Facts Sprint */
  .na-sprint{text-align:center;}
  .sprint-top{display:flex;justify-content:space-between;align-items:center;font-weight:800;color:var(--muted);font-size:16px;}
  .sprint-clock{font-family:"Baloo 2",cursive;font-size:34px;color:var(--purple-dark);line-height:1;}
  .sprint-clock.low{color:var(--red);}
  .sprint-score b{color:var(--purple-dark);}
  .sprint-bar{height:8px;background:var(--purple-soft);border-radius:6px;margin:10px 0 18px;overflow:hidden;}
  .sprint-fill{height:100%;width:100%;background:var(--purple);border-radius:6px;transition:width 1s linear;}
  .sprint-q{font-family:"Baloo 2",cursive;font-size:44px;font-weight:700;color:var(--ink);margin:10px 0 18px;line-height:1.2;}
  .sprint-q.ok{color:var(--green-dark);}
  .sprint-q.no{color:var(--red);}
  .sprint-type{max-width:320px;margin:0 auto;}
  /* Cap question-stimulus height: a tall, narrow figure (e.g. base-ten with one
     column) would otherwise scale to many hundreds of pixels and push the answer
     controls off screen. Lesson figures (.na-fig) already had this cap. */
  .na-graph svg{display:block;margin:0 auto;max-width:100%;height:auto;max-height:300px;}
  /* lesson-page figures (images shown inside the lesson, not just questions) */
  .na-figrow{display:flex;flex-wrap:wrap;gap:16px;justify-content:center;align-items:stretch;margin:16px 0 20px;}
  .na-fig{margin:0;flex:1 1 300px;max-width:400px;min-width:0;background:var(--card);
    border:2px solid var(--purple-soft);border-radius:20px;
    box-shadow:0 6px 18px rgba(112,56,224,.13);overflow:hidden;display:flex;flex-direction:column;}
  .na-fig .na-graph{border:none;box-shadow:none;background:transparent;border-radius:0;margin:0;
    padding:22px 18px;display:flex;align-items:center;justify-content:center;flex:1;overflow-x:auto;}
  .na-fig .na-graph svg{width:100%;height:auto;max-height:300px;}
  .na-figcap{font-size:14px;color:var(--purple-dark);background:var(--purple-soft);
    font-weight:800;padding:11px 14px;line-height:1.35;text-align:center;}
  .na-check{background:var(--purple);color:#fff;font-family:"Nunito";font-weight:800;font-size:16px;
    border:none;border-radius:14px;padding:12px 18px;box-shadow:0 4px 0 var(--purple-dark);cursor:pointer;margin-top:4px;}
  .na-check:active{transform:scale(.98);}
  .na-check:disabled{opacity:.5;cursor:default;}
  .na-reset{background:var(--blue-soft);color:var(--blue-dark);font-weight:800;font-size:14px;border:none;
    border-radius:12px;padding:9px 14px;box-shadow:0 3px 0 #bcd4ff;cursor:pointer;margin:2px 0 0 8px;}
  .na-reset:active{transform:scale(.98);}
  .na-btnrow{display:flex;align-items:center;justify-content:center;gap:4px;margin-top:8px;flex-wrap:wrap;}


/* ---- next block ---- */


    .spell-menu{display:flex;flex-direction:column;gap:14px;max-width:560px;margin:20px auto 8px;}
    .spell-menu-btn{display:flex;flex-direction:column;align-items:flex-start;gap:5px;text-align:left;font-family:"Nunito";background:var(--card);border:2px solid var(--purple-soft);border-radius:20px;padding:18px 22px;cursor:pointer;box-shadow:0 5px 0 rgba(112,56,224,.12);transition:transform .08s,filter .12s;}
    .spell-menu-btn:hover{filter:brightness(.99);transform:translateY(-2px);}
    .spell-menu-btn:active{transform:scale(.99);}
    .smb-icon{font-size:32px;line-height:1;}
    .smb-title{font-size:21px;font-weight:800;color:var(--purple-dark);}
    .smb-desc{font-size:14px;font-weight:700;color:var(--muted);}
    .spell-menu-btn.skills{border-color:var(--green-soft);box-shadow:0 5px 0 rgba(18,165,88,.12);}
    .spell-menu-btn.skills .smb-title{color:var(--green-dark);}
    /* phoneme sound cards */
    /* Two-up on a wide screen, one-up on a phone — auto-fill decides from the column
       width, so there is no breakpoint to keep in sync. align-items:start stops a
       short card stretching to match a tall neighbour. */
    .ph-cards{display:grid;grid-template-columns:repeat(auto-fill,minmax(300px,1fr));gap:12px;align-items:stretch;margin:14px 0;}
    .ph-card{background:var(--purple-soft);border-radius:16px;padding:11px 13px;margin:0;}
    .ph-card.wide{grid-column:1 / -1;}
    /* A word too long for one chip row keeps its column and wraps instead of spanning both,
       so two cards always sit side by side. row-gap is what stops the two chip lines
       touching; .ph-chips already wraps, it was only ever .wide that prevented it. */
    .ph-card.multiline .ph-chips{row-gap:6px;}
    /* the + and the chip it introduces travel together, so a wrapped row never ends on a + */
    .ph-join{display:flex;align-items:baseline;gap:5px;min-width:0;}
    /* A crowded chip row (4+ sounds) gets a smaller picture and a tighter gap so it
       still fits on ONE line in a normal column. Only if that is not enough does
       ssFitCards fall back to .wide, which spans the card across both columns. */
    .ph-card.has-art.tight{padding-right:86px;}
    .ph-card.tight .ph-art{width:70px;height:70px;}
    .ph-card.tight .ph-chips{gap:4px;}
    /* A four-sound word with a wide chip (er, ck) needs more room than .tight frees,
       so there is one more step before giving up and spanning the whole grid. */
    .ph-card.has-art.tighter{padding-right:74px;}
    .ph-card.tighter .ph-art{width:58px;height:58px;}
    .ph-card.tighter .ph-chips{gap:3px;}
    /* Card picture sits in the space to the right of the word button, so it costs
       no extra height. The reserved padding keeps the chip row clear of it, and
       ssFitCards() measures what is left, so a card with art still pairs up. */
    .ph-card.has-art{position:relative;padding-right:104px;}
    .ph-art{position:absolute;top:9px;right:10px;width:87px;height:87px;pointer-events:none;}
    .ph-art svg{display:block;width:100%;height:100%;}
    .ph-word-row{display:flex;gap:10px;flex-wrap:wrap;align-items:center;margin-bottom:9px;}
    /* CHECK PAGES — a single no-stakes question sitting inside the lesson. Quiet by
       design: this is not the marked quiz, so it must not look like one. */
    .gcheck{margin:18px 0 4px;padding:16px 18px;background:var(--lav-soft,#f3efff);border:2px solid var(--lav,#c9b8f5);border-radius:16px;}
    .gcheck-q{margin:0 0 12px;font-weight:800;font-size:17px;line-height:1.4;color:var(--ink);}
    .gcheck-opts{display:flex;flex-direction:column;gap:8px;}
    .gcheck-opts.is-phon{flex-direction:row;flex-wrap:wrap;}
    .gcheck-opt{display:flex;align-items:center;gap:8px;text-align:left;font-family:"Nunito";font-size:15.5px;font-weight:700;color:var(--ink);background:#fff;border:2px solid var(--lav,#c9b8f5);border-radius:12px;padding:10px 14px;cursor:pointer;}
    .gcheck-opts.is-phon .gcheck-opt{font-size:19px;padding:10px 16px;}
    .gcheck-opt:hover:not(:disabled){border-color:var(--purple,#7c5cd6);}
    .gcheck-opt:disabled{cursor:default;}
    .gcheck-opt.is-right{border-color:var(--green,#3aa66b);background:var(--green-soft,#e7f7ee);color:var(--green-ink,#1c6b41);}
    .gcheck-opt.is-wrong{border-color:var(--red,#d4483b);background:var(--red-soft,#fdeceb);color:var(--red,#d4483b);}
    .gcheck-opt.is-dim{opacity:.5;}
    .gcheck-opt.picked{border-color:var(--purple,#7c5cd6);background:var(--lav-soft,#f3efff);box-shadow:0 0 0 3px rgba(124,92,214,.18);}
    .gcheck-play{font-size:14px;opacity:.8;}
    /* the symbol appears only AFTER the answer is committed — before that the boxes are
       Sound 1/2/3 so the child has to listen rather than read */
    .gcheck-reveal{font-size:14px;font-weight:800;opacity:.75;margin-left:2px;}
    .gcheck-go{margin-top:12px;}
    .gcheck-check{font-family:"Nunito";}
    .gcheck-fb{margin-top:12px;font-size:15px;line-height:1.5;color:var(--ink);background:#fff;border-radius:10px;padding:10px 13px;}
    .gcheck-fb.is-right{background:var(--green-soft,#e7f7ee);}

    /* ⚠ A CAPITAL FIRST LETTER, asked for in the 2026-09-02 read-through: the WORD on a
       sound card, in a table cell and on a word chip reads Cat, not cat and not CAT.
       (The first attempt shouted the whole word; the ask was the first letter only.)
       Done here and not in the data,
       because the stored word is also the audio clip id, the art key and the string a
       dictation answer is graded against — this changes the look and touches none of that.
       Never add .ph-graph to this list: those chips carry letter patterns (a-e, sh, igh),
       which are graphemes, not words.
       ⚠ CAPITALIZE, not uppercase: the ask is a capital FIRST LETTER — Cat, not CAT. */
    .ph-word-btn,.gt-snd,.ph-chip.is-word .ph-graph{text-transform:capitalize;}
    .ph-word-btn{background:var(--amber);color:#7a5600;font-weight:800;border:none;border-radius:12px;padding:9px 15px;font-size:16px;cursor:pointer;box-shadow:0 3px 0 #d99a00;font-family:"Nunito";}
    .ph-blend-btn{background:var(--blue);color:#fff;font-weight:800;border:none;border-radius:12px;padding:9px 15px;font-size:15px;cursor:pointer;box-shadow:0 3px 0 var(--blue-dark);font-family:"Nunito";}
    .ph-word-btn:active,.ph-blend-btn:active,.ph-chip:active{transform:translateY(1px);}
    /* The written syllable split (areas 4 and 5). Plain text, deliberately not chip-shaped:
       a syllable has no recording of its own. In those two areas it is the only row under
       the word button — the sound chips are gone from every card there — so the card reads
       word -> split -> note. In area 9 (`is-morph`) the chips are still below it. */
    /* gap:0 on purpose — "rab-bit" has to read as one split word, and any gap around the
       dash makes it read as two separate words with a stray dash between them. */
    .ph-syls{display:flex;align-items:baseline;gap:0;flex-wrap:wrap;margin:-3px 0 8px;}
    .ph-syl{font-size:17px;font-weight:800;color:var(--purple-dark);letter-spacing:.2px;}
    .ph-syl-dash{font-size:15px;font-weight:800;color:var(--muted);}
    /* a word-family split (c + at) needs air around its +, unlike a syllable dash */
    .ph-syls.is-morph .ph-syl-dash{padding:0 5px;}
    /* A chip that plays a whole WORD rather than a sound — the base word inside a longer
       one. Green so it reads as a different kind of thing from the purple sound chips. */
    .ph-chip.is-word{border-color:var(--green,#12a558);box-shadow:0 3px 0 rgba(18,165,88,.20);}
    .ph-chip.is-word .ph-graph{color:var(--green-dark,#0b7a40);}
    .ph-beats{margin-left:8px;background:#fff;border:2px solid var(--purple);border-radius:999px;
              padding:1px 9px;font-size:11.5px;font-weight:800;color:var(--purple-dark);}
    .ph-chips{display:flex;align-items:center;gap:5px;flex-wrap:wrap;}
    /* letter and its sound sit SIDE BY SIDE on one line inside the box (was stacked
       over two lines, which made every card taller than it needed to be). */
    .ph-chip{display:flex;flex-direction:row;align-items:baseline;justify-content:center;gap:4px;background:#fff;border:2px solid var(--purple);border-radius:12px;padding:6px 8px;cursor:pointer;font-family:"Nunito";min-width:0;box-shadow:0 3px 0 rgba(112,56,224,.18);}
    /* A muted part — letters with no sound behind them. It must not look pressable:
       no shadow, no pointer, a dashed edge and a flat ground, so a child reads it as a
       label rather than a button that has stopped working. */
    .ph-chip.is-quiet{background:var(--paper,#f7f4fd);border-style:dashed;border-color:rgba(112,56,224,.38);box-shadow:none;cursor:default;padding:6px 10px;}
    .ph-chip.is-quiet .ph-graph{color:var(--muted);}
    .ph-graph{font-size:20px;font-weight:800;color:var(--purple-dark);line-height:1;}
    .ph-sym{font-size:11.5px;font-weight:700;color:var(--muted);}
    .ph-plus{font-size:15px;font-weight:800;color:var(--muted);}
    .ph-note{margin-top:8px;font-size:14px;font-weight:700;color:var(--ink);}
    .gq-listen{display:flex;flex-direction:column;gap:12px;align-items:flex-start;}
    .gq-listen .ph-word-btn{font-size:17px;}
    /* group headings in the skill-parts list */
    .ss-group-head{font-family:"Nunito";font-weight:800;font-size:15px;color:var(--purple-dark);margin:18px 4px 8px;letter-spacing:.3px;text-transform:uppercase;opacity:.85;}
    .ss-group-head:first-child{margin-top:2px;}

  /* =========================================================
     WELCOME SCREEN REDESIGN (additive; GSAP/Lottie enhanced)
     Overrides earlier #screen-welcome rules by source order.
     ========================================================= */




  /* GSAP prep: only pre-hide entrance targets when motion is allowed AND GSAP present.
     The .gsap-ready flag is set on <html> by js/13-ui.js so no-JS/reduced-motion users see content immediately. */
  @media(prefers-reduced-motion:no-preference){
    html.gsap-ready #screen-welcome .welcome-title,
    html.gsap-ready #screen-welcome .welcome-emojis,
    html.gsap-ready #screen-welcome .welcome-blurb,
    html.gsap-ready #screen-welcome .grade-pick-label,
    html.gsap-ready #screen-welcome .grade-choice-btn{opacity:0;will-change:transform,opacity;}
  }
  /* ===== END-OF-QUIZ REWARD OVERLAY (js/14-reward.js) ===== */
  .reward-overlay{position:fixed;inset:0;z-index:100000;display:flex;align-items:center;justify-content:center;
    padding:20px;background:rgba(58,45,92,.58);backdrop-filter:blur(3px);-webkit-backdrop-filter:blur(3px);}
  .reward-confetti{position:absolute;inset:0;width:100%;height:100%;pointer-events:none;z-index:2;}
  .reward-card{position:relative;z-index:1;text-align:center;max-width:440px;width:100%;}
  .reward-kid{width:min(74vw,340px);margin:0 auto;position:relative;}
  .reward-kid svg,.reward-kid-img{width:100%;height:auto;display:block;filter:drop-shadow(0 14px 24px rgba(0,0,0,.28));}
  .reward-kid-svg-wrap{display:none;}
  .reward-kid svg .rk-wink,.reward-kid svg .rk-tear{transform-box:fill-box;transform-origin:50% 50%;}
  /* gloomy rain cloud — low-score tier only (added via JS) */
  .reward-rain{position:absolute;inset:0;overflow:visible;pointer-events:none;z-index:2;}
  .reward-rain .rk-cloud{position:absolute;top:1%;left:50%;transform:translateX(-50%);width:50%;height:auto;
    filter:drop-shadow(0 5px 7px rgba(0,0,0,.25));animation:rk-cloud-bob 3s ease-in-out infinite;}
  .reward-rain .rk-drop{position:absolute;top:14%;width:4px;height:17px;border-radius:3px;
    background:linear-gradient(180deg,#7fb2ff,rgba(127,178,255,0));opacity:0;box-shadow:0 0 3px rgba(127,178,255,.6);
    animation:rk-rain 1.1s linear infinite;}
  @keyframes rk-rain{0%{transform:translateY(-4px);opacity:0;}14%{opacity:.95;}100%{transform:translateY(260px);opacity:0;}}
  @keyframes rk-cloud-bob{0%,100%{transform:translateX(-50%) translateY(0);}50%{transform:translateX(-50%) translateY(-4px);}}
  @media (prefers-reduced-motion:reduce){.reward-rain .rk-drop{animation:none;opacity:.55;}.reward-rain .rk-cloud{animation:none;}}
  .reward-title{font-family:var(--font-display);font-weight:700;color:#fff;font-size:clamp(24px,6vw,38px);
    line-height:1.1;margin:16px 0 4px;text-shadow:0 2px 0 rgba(0,0,0,.18);}
  .reward-sub{font-family:var(--font-round);font-weight:700;color:#fff;opacity:.96;
    font-size:clamp(15px,3.4vw,19px);margin:0 0 20px;text-shadow:0 1px 0 rgba(0,0,0,.15);}
  .reward-btn{font-family:var(--font-round);font-weight:800;color:#fff;font-size:19px;border:none;border-radius:16px;
    padding:14px 28px;cursor:pointer;transition:transform .09s,filter .15s;}
  .reward-btn:hover{filter:brightness(1.06);transform:translateY(-2px);}
  .reward-btn:active{transform:scale(.97);}

  /* ---- Play level select ---- */
  .levels-sub{margin-bottom:18px;}
  .levels-list{display:flex;flex-direction:column;gap:14px;}
  .level-card{position:relative;display:flex;align-items:flex-start;gap:14px;width:100%;text-align:left;
    background:#fff;border:3px solid var(--line);border-radius:20px;padding:16px 18px;cursor:pointer;
    font-family:var(--font-body);transition:transform .08s,border-color .15s,box-shadow .15s,background .15s;}
  .level-card:hover{transform:translateY(-2px);box-shadow:0 8px 18px rgba(58,45,92,.12);border-color:var(--blue);}
  .level-card:active{transform:scale(.99);}
  .level-card.partial{border-color:var(--amber);background:#fffdf5;}
  .level-card.done{border-color:var(--green);background:var(--green-soft);}
  .level-card.locked{cursor:default;opacity:.72;background:#faf8fc;border-style:dashed;border-color:#e2dcef;}
  .level-card.locked:hover{transform:none;box-shadow:none;border-color:#e2dcef;}
  .level-emoji{font-size:34px;line-height:1;flex:0 0 auto;margin-top:2px;}
  .level-body{display:flex;flex-direction:column;gap:5px;flex:1;min-width:0;}
  .level-name{font-family:var(--font-round);font-weight:800;font-size:18px;color:var(--ink);}
  .level-desc{font-size:14px;color:var(--muted);font-weight:700;line-height:1.35;}
  .level-meta{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-top:2px;}
  .level-lock-note{font-size:12.5px;font-weight:800;color:var(--muted);margin-top:2px;}
  .level-card .gsub-check{top:-8px;right:-6px;}

  /* ---- Level 1 options are wider on the level screen ---- */
  #l1options .qzopt{text-align:center;font-size:20px;font-weight:800;letter-spacing:.5px;font-family:var(--font-round);}

  /* ---- Level 1: the whole word fits on one screen, no scrolling ----
     Four spellings stacked one per row, a 140px picture and a full-width "Hear it" row
     put this level ~200px past the fold. The options now sit two-up (falling back to one
     column when the screen is too narrow for a long word), the picture is smaller, and
     "Hear it" rides on the chip line. */
  #l1options{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:10px;}
  /* the star row grows as the run goes on, which is what put the late questions at 625
     of the 640 budget — the card padding gives that back */
  #screen-lvl1 .card{padding-top:18px;padding-bottom:18px;}
  #l1options .qzopt{margin-bottom:0;padding:12px 34px;position:relative;}
  #screen-lvl1 .picture{height:96px;font-size:62px;margin-bottom:10px;}
  #screen-lvl1 .bar{margin-bottom:12px;}
  #screen-lvl1 .definition{font-size:20px;}
  #screen-lvl1 .qzprompt{font-size:16px;margin-bottom:10px;}
  #screen-lvl1 .gmeta{display:flex;align-items:center;justify-content:center;gap:8px;}
  #screen-lvl1 .gmeta .chip{margin-right:0;}
  /* the compact "Hear it": a chip, not the full-width helper row it used to have */
  .sound-chip{padding:5px 12px;font-size:13px;font-weight:800;border:none;border-radius:20px;
    font-family:var(--font-body);cursor:pointer;box-shadow:0 2px 0 #d99a00;line-height:1.3;}
  .sound-chip:active{transform:translateY(1px);box-shadow:none;}
  /* Chosen, but not yet checked — the tap lands immediately, the marking waits.
     Shared by Level 1 and the Meaning quiz, which commit an answer the same way. */
  #l1options .qzopt.sel,#qzoptions .qzopt.sel{border-color:var(--purple,#8b7fd4);background:var(--purple-soft,#f0ebff);}
  /* The mark, not colour alone, says which one it was. */
  #l1options .qzopt.correct::after,#l1options .qzopt.wrong::after,
  #qzoptions .qzopt.correct::after,#qzoptions .qzopt.wrong::after{
    position:absolute;right:12px;top:50%;transform:translateY(-50%);font-size:20px;font-weight:900;}
  #l1options .qzopt.correct::after,#qzoptions .qzopt.correct::after{content:"✓";}
  #l1options .qzopt.wrong::after,#qzoptions .qzopt.wrong::after{content:"✗";}
  /* One column on a phone — a 13-letter word will not sit two-up at 375px — so the
     picture and the options give back the height the second column was saving. */
  /* ---- Meaning quiz: the same treatment as Level 1 ----
     Four meanings stacked one per row plus a 140px picture ran ~190px past the fold.
     The meanings are sentences, not single words, so the columns are wider than Level 1's
     and an option that needs two lines simply takes them. */
  #qzoptions{display:grid;grid-template-columns:repeat(auto-fit,minmax(270px,1fr));gap:9px;align-items:stretch;}
  #qzoptions .qzopt{margin-bottom:0;padding:8px 32px 8px 14px;position:relative;font-size:15.5px;}
  /* The ceiling is four two-line meanings at once, which sat at 639 of the 640 budget —
     one pixel is not headroom, so the picture and the card padding gave some back. */
  #screen-quiz .card{padding-top:18px;padding-bottom:18px;}
  #screen-quiz .picture{height:76px;font-size:52px;margin-bottom:6px;}
  #screen-quiz .bar{margin-bottom:12px;}
  #screen-quiz .qzword{font-size:32px;}
  #screen-quiz .qzsyl{font-size:16px;margin-bottom:8px;}
  #screen-quiz .qzprompt{font-size:16px;margin-bottom:10px;}
  #screen-quiz .sound-btn{margin-bottom:10px !important;}

  @media (max-width:480px){
    /* At 375px the top bar carries four things, so the title wraps to two lines and the
       bar is 82px, not 44 — that plus the grown star row is what pushed the late
       questions ~35px past the fold. The picture and the options give it back. */
    /* Four items in a 335px bar left the title about 90px, so "Level 1 · Week 1" broke
       across four lines wedged between two purple buttons. Give it its own row above
       them: slightly shorter than the four-line wrap, and far easier to read.
       Only these two — "Week 1" and "Week 1 quiz" still fit the bar on one line, and
       moving them would ADD a row rather than replace one. */
    #screen-lvl1 .topbar,#screen-lvl2 .topbar{flex-wrap:wrap;}
    #screen-lvl1 .learn-title,#screen-lvl2 .learn-title{order:-1;flex-basis:100%;text-align:center;}
    #screen-lvl1 .card,#screen-quiz .card{padding-top:14px;padding-bottom:14px;}
    #screen-lvl1 .picture{height:64px;font-size:44px;margin-bottom:8px;}
    #screen-lvl1 .qzprompt{font-size:15px;margin-bottom:8px;}
    #screen-lvl1 .hint{margin-bottom:6px;}
    #l1options{gap:8px;}
    #l1options .qzopt{padding:8px 30px;font-size:18px;}
    #screen-quiz .picture{height:72px;font-size:48px;}
    #qzoptions{gap:8px;}
    #qzoptions .qzopt{padding:9px 30px 9px 12px;font-size:15px;}
  }

  /* ---- Level 2: fill the gaps ---- */
  /* Letters sit almost as close as they would in ordinary type — a wide gap here was
     what still made a finished word look like separate tiles. 2px is the smallest that
     keeps the underline segments distinguishable, so an unfilled gap is still findable. */
  .l2-slots{display:flex;flex-wrap:wrap;justify-content:center;gap:2px;margin:6px 0 16px;min-height:66px;}
  /* The point of this level is to end up looking at ONE WORD, so every letter — given
     or placed — is the same ink colour with no box behind it. The only thing that
     changes is the weight of the underline: a gap still to fill gets the darker grey so
     it reads as a target, and anything settled gets the lighter grey, so once the last
     gap is filled the word sits on one even line instead of a stripe of coloured tiles. */
  /* min-width is a FLOOR, not a column width: at 36px most letters are wider than 18px,
     so each box is sized by its own glyph and the word gets natural proportional
     spacing. A larger floor would reopen the gaps under narrow letters like l and i.
     ⚠ GIVEN letters only. A gap is sized by the invisible .l2-ghost inside it and then
     pinned to a fixed px width by l2SizeGaps, so it cannot change size when it is
     filled — that resizing is what used to make the word slide about under the child's
     finger, up to 20px per word. */
  .l2-slot{position:relative;display:inline-flex;align-items:center;justify-content:center;
    min-width:18px;height:62px;padding:0 1px;
    font-family:var(--font-round);font-weight:800;font-size:36px;color:var(--ink);
    border-bottom:4px solid var(--gap-strong);background:transparent;text-transform:lowercase;
    transition:border-bottom-color .15s;}
  /* holds the slot open at the width of the letter that belongs there; never seen */
  .l2-ghost{visibility:hidden;}
  /* the letter the child placed, drawn over the ghost so it adds no width of its own */
  .l2-ch{position:absolute;left:0;right:0;top:0;bottom:0;display:flex;align-items:center;justify-content:center;}
  .l2-slot.fixed{border-bottom-color:var(--gap-soft);}
  .l2-slot.filled{border-bottom-color:var(--gap-soft);cursor:pointer;}
  /* Tapping a placed letter takes it back, and the slot is now only ~20px wide. This
     grows the hit area VERTICALLY only — widening it would overlap the neighbouring
     letter and take the wrong one back. */
  .l2-slot.filled::after{content:"";position:absolute;left:0;right:0;top:-6px;bottom:-10px;}
  /* the only affordance left for "tap to take that letter back", now the box has gone */
  .l2-slot.filled:hover{border-bottom-color:var(--gap-strong);}
  .l2-slot.bad{color:var(--red);border-bottom-color:var(--red);}
  .l2-tray{display:flex;flex-wrap:wrap;justify-content:center;gap:10px;margin-bottom:14px;min-height:52px;}
  .l2-tile{min-width:46px;height:52px;padding:0 8px;font-family:var(--font-round);font-weight:800;font-size:24px;
    color:#fff;background:var(--purple);border:none;border-radius:14px;box-shadow:0 4px 0 var(--purple-dark);
    cursor:pointer;text-transform:lowercase;transition:transform .08s,filter .15s;}
  .l2-tile:hover{filter:brightness(1.06);transform:translateY(-2px);}
  .l2-tile:active{transform:translateY(2px);box-shadow:0 2px 0 var(--purple-dark);}

  /* ---- Intro quiz (mixed question types) ---- */
  .wq-type{display:inline-block;font-family:var(--font-round);font-weight:800;font-size:12.5px;letter-spacing:.4px;
    text-transform:uppercase;color:var(--purple-dark);background:var(--purple-soft);border-radius:20px;padding:4px 12px;margin-bottom:8px;}
  .wq-q{font-size:19px;line-height:1.4;font-weight:800;color:var(--ink);font-family:var(--font-round);margin:0 0 14px;}
  /* true / false */
  .wq-tf{display:flex;gap:12px;}
  .wq-tf-btn{flex:1;font-family:var(--font-round);font-weight:800;font-size:19px;color:#fff;border:none;border-radius:16px;
    padding:18px 10px;cursor:pointer;transition:transform .08s,filter .15s;}
  .wq-tf-btn.tv{background:var(--green);box-shadow:0 5px 0 var(--green-dark);}
  .wq-tf-btn.fv{background:var(--red);box-shadow:0 5px 0 #d23c3c;}
  .wq-tf-btn:hover{filter:brightness(1.05);transform:translateY(-2px);}
  .wq-tf-btn:active{transform:translateY(2px);}
  .wq-tf-btn.correct{outline:4px solid var(--green-dark);outline-offset:2px;}
  .wq-tf-btn.wrong{outline:4px solid #d23c3c;outline-offset:2px;}
  .wq-tf-btn.dim{opacity:.45;}
  /* order the parts (tap-to-place) */
  .wq-slots{display:flex;flex-direction:column;gap:8px;margin-bottom:12px;}
  .wq-slot{display:flex;align-items:center;gap:12px;min-height:48px;padding:8px 12px;border-radius:14px;
    border:2.5px dashed var(--line);background:#fbfaff;color:var(--muted);font-weight:700;font-size:15px;line-height:1.3;}
  .wq-slot.filled{border-style:solid;border-color:var(--purple);background:var(--purple-soft);color:var(--ink);cursor:pointer;}
  .wq-slot.ok{border-style:solid;border-color:var(--green);background:var(--green-soft);color:var(--ink);}
  .wq-slot.no{border-style:solid;border-color:var(--red);background:var(--red-soft);color:var(--ink);}
  .wq-slot-n{flex:0 0 auto;width:26px;height:26px;border-radius:50%;background:var(--purple);color:#fff;
    font-family:var(--font-round);font-weight:800;font-size:14px;display:flex;align-items:center;justify-content:center;}
  .wq-slot.ok .wq-slot-n{background:var(--green-dark);}.wq-slot.no .wq-slot-n{background:#d23c3c;}
  .wq-slot-txt{flex:1;}
  .wq-tray{display:flex;flex-direction:column;gap:8px;}
  .wq-oitem{width:100%;text-align:left;font-family:var(--font-body);font-weight:700;font-size:15px;line-height:1.3;color:var(--ink);
    background:#fff;border:2.5px solid var(--purple);border-radius:14px;padding:12px 14px;cursor:pointer;
    box-shadow:0 3px 0 rgba(139,92,246,.28);transition:transform .08s,filter .15s;}
  .wq-oitem:hover{filter:brightness(1.02);transform:translateY(-1px);}
  .wq-oitem:active{transform:translateY(2px);box-shadow:0 1px 0 rgba(139,92,246,.28);}

  /* --- welcome screen: fit a phone without scrolling ----------------------
     Collapsing the blurb took the page from 1232px to 920px on a 375x812
     screen, but Year 5 still sat ~108px below the fold. These are phone-only
     trims to the hero: a smaller mascot, tighter Year buttons and less dead
     space. Desktop is untouched. */
  @media (max-width:560px){
    #screen-welcome{padding-bottom:6px;}
    #screen-welcome .welcome-hero{margin-top:8px;}
    #screen-welcome .welcome-emojis{font-size:26px;margin:4px 0 2px;}
    #screen-welcome .welcome-blurb{margin:10px 0 12px;padding:14px 16px;}
    #screen-welcome .grade-choice{gap:10px;}
    #screen-welcome .grade-choice-btn{padding:13px 16px;}
    #screen-welcome .grade-choice-btn .gc-emoji{font-size:38px;}
  }

  /* =========================================================
     COLLAPSIBLE CHEVRONS — the visible "open me" control
     Added 2026-08-25 with the hover-to-open removal. With hover gone the
     drawers need an affordance that reads as pressable, so every chevron
     becomes a round chip on the right-hand end of its heading button. The
     whole heading is still the click target; the chip just says where.
     ========================================================= */
  .ds-chev,.ggroup-chev,.section-chev,.tpd-chev,.bonus-chev{
    width:32px;height:32px;border-radius:50%;
    background:rgba(139,92,246,.12);
    transition:transform .38s cubic-bezier(.4,0,.2,1),background .18s ease;
  }
  .section-chev,.bonus-chev{width:34px;height:34px;}
  .ds-chev svg,.ggroup-chev svg,.tpd-chev svg{width:17px;height:17px;}
  .section-chev svg,.bonus-chev svg{width:19px;height:19px;}
  /* the banner is a bright gradient, so its chip is white-on-colour */
  .bonus-chev{background:rgba(255,255,255,.24);}
  /* the chip lifts when the pointer is over the heading it belongs to — a hint,
     not an action: nothing opens until the press. */
  @media (hover:hover) and (pointer:fine){
    .ds-head:hover .ds-chev,
    .ggroup > .ggroup-head:hover .ggroup-chev,
    .section-head:hover .section-chev,
    .tpd-head:hover .tpd-chev{background:rgba(139,92,246,.22);}
    .bonus-head:hover .bonus-chev{background:rgba(255,255,255,.38);}
  }
  .ds-head:active .ds-chev,
  .ggroup > .ggroup-head:active .ggroup-chev,
  .section-head:active .section-chev,
  .tpd-head:active .tpd-chev,
  .bonus-head:active .bonus-chev{transform:scale(.9);}
  .domain-section.open .ds-head:active .ds-chev,
  .ggroup.open > .ggroup-head:active .ggroup-chev,
  .section-card.open .section-head:active .section-chev,
  .tp-domain.open .tpd-head:active .tpd-chev,
  .bonus-banner.open .bonus-head:active .bonus-chev{transform:rotate(180deg) scale(.9);}
  @media (prefers-reduced-motion:reduce){
    .ds-chev,.ggroup-chev,.section-chev,.tpd-chev,.bonus-chev{transition:none;}
  }

/* =====================================================================
   WELCOME SCREEN — Ochre & Ink + Fredoka/Lexend
   Approved and merged 2026-08-26. Screen 1 of 46.

   Scope is deliberately narrow: #screen-welcome and the page ground. Nothing
   here touches another screen, engine logic or a progress key. When approved,
   these rules move into css/styles.css as-is. */

/* ---- page ground -------------------------------------------------------
   The old body background threw a pink blob and a blue blob over a cream
   ground — the two hues that appear nowhere in the 46 fixed illustrations.
   Same technique, warm palette: gold above, clay to the side, sand below. */
/* ⚠ SCOPED to the welcome screen with :has(). The proposal restyled <body>
     globally, which would repaint all 46 screens — including the 45 that have
     not been reviewed yet. This paints the warm ground only while the welcome
     screen is the visible one; every other screen keeps the old ground until it
     is migrated in turn. A browser without :has() simply keeps the old
     background, which is the correct fallback.
     REMOVE THE :has() WRAPPER once the last screen has migrated. */
  body:has(#screen-welcome:not(.hidden)){
    background:var(--bg-page);
    background-image:
      radial-gradient(circle at 12% 8%,  rgba(224,160,32,.28) 0, transparent 34%),
      radial-gradient(circle at 88% 6%,  rgba(168,72,31,.14)  0, transparent 30%),
      radial-gradient(circle at 50% 100%, rgba(91,63,168,.10) 0, transparent 42%);
    color:var(--text-primary);
  }
  #screen-welcome{ font-family:var(--font-body); font-weight:var(--weight-body); }

/* ---- hero --------------------------------------------------------------
   The title is SOLID, in the action colour. The old screen ran a
   violet-to-blue-to-sky gradient through it (--grad-hero), which was
   decoration the design system never asked for, built from the two hues that
   appear nowhere in the 46 illustrations. Recolouring that gradient would have
   kept the habit and changed only the paint.

   Using --action rather than a raw violet also means the title lightens by
   itself in dark mode; the gradient version stayed dark-on-dark. */
/* The hero opens straight on the title — the logo that used to sit above it was
   removed 2026-08-25 at the user's request, and nothing replaces it. */
#screen-welcome .welcome-hero{ text-align:center; margin:var(--space-5) 0 var(--space-1); }

#screen-welcome .welcome-title{
  font-family:var(--font-display);
  font-weight:var(--weight-shout);           /* the one 700 on this screen */
  font-size:clamp(34px,6.4vw,52px);
  line-height:var(--leading-tight);
  letter-spacing:-.5px;
  margin:var(--space-1) 0 0;
  color:var(--action);
  /* explicitly clear the old treatment, which set all three */
  background:none;
  -webkit-text-fill-color:currentColor;
  text-shadow:none;
  filter:none;
}

#screen-welcome .welcome-emojis{
  font-size:30px; letter-spacing:6px; text-align:center;
  margin:var(--space-2) 0 var(--space-1);
}

/* ---- blurb -------------------------------------------------------------
   Was a 3px WHITE border on a white card — an invisible border doing nothing —
   with a 16.5px half-pixel body size at weight 700 for every paragraph. Now a
   real boundary, body copy at 400, and only the lead line carries display weight. */
#screen-welcome .welcome-blurb{
  background:var(--bg-surface);
  border:1px solid var(--border-subtle);
  border-radius:var(--radius-xl);
  padding:var(--space-5) var(--space-5);
  margin:var(--space-4) 0 var(--space-6);
  box-shadow:var(--elev-2);
}
#screen-welcome .welcome-blurb p{
  margin:0 0 var(--space-3);
  font-family:var(--font-body);
  font-size:var(--text-base);
  font-weight:var(--weight-body);
  line-height:var(--leading-normal);
  color:var(--text-primary);
}
#screen-welcome .welcome-blurb p:last-child{ margin-bottom:0; }
#screen-welcome .welcome-blurb .big{
  font-family:var(--font-display);
  font-weight:var(--weight-display);
  font-size:var(--text-xl);
  line-height:var(--leading-snug);
  color:var(--action);
}
#screen-welcome .wb-head{ display:flex; align-items:center; gap:var(--space-3); }
#screen-welcome .wb-icon{ font-size:30px; line-height:1; flex:0 0 auto; }

/* ---- "Pick your year" label ---- */
#screen-welcome .grade-pick-label{
  display:flex; align-items:center; justify-content:center; gap:var(--space-2);
  font-family:var(--font-display);
  font-weight:var(--weight-display);
  font-size:var(--text-lg);
  color:var(--text-primary);
  margin:0 0 var(--space-4);
}
#screen-welcome .grade-pick-label .gpl-icon{
  width:22px; height:22px; color:var(--accent-border);   /* was --amber at 1.61:1 */
}

/* ---- grade buttons -----------------------------------------------------
   Was a 4px --blue-soft frame (#e6efff) on white: 1.2:1, effectively no border,
   plus a 8px offset shadow in a blue that does not exist in the artwork. */
#screen-welcome .grade-choice{
  display:flex; gap:var(--space-4); flex-wrap:wrap; justify-content:center;
}
#screen-welcome .grade-choice-btn{
  position:relative; overflow:hidden;
  flex:1; min-width:200px;
  min-height:var(--tap-min);
  background:var(--bg-surface);
  border:2px solid var(--border-control);
  border-radius:var(--radius-xl);
  padding:var(--space-6) var(--space-5);
  text-align:center;                    /* was inherited from the deleted .grade-choice-btn rule */
  /* A solid offset under the diffuse shadow. The old screen got its playfulness
     from a chunky 8px offset; dropping it entirely made these read as form
     controls. This keeps the chunk but in the theme's own violet. */
  box-shadow:0 4px 0 rgba(91,63,168,.16), var(--elev-2);
  cursor:pointer;
  transition:transform var(--duration-fast) var(--ease-out),
             box-shadow var(--duration-fast) var(--ease-out),
             border-color var(--duration-fast) var(--ease-out);
}
#screen-welcome .grade-choice-btn::before{
  content:""; position:absolute; inset:0; border-radius:inherit;
  background:var(--action-soft); opacity:0;
  transition:opacity var(--duration-base) var(--ease-out); pointer-events:none;
}
#screen-welcome .grade-choice-btn:hover{
  border-color:var(--action); transform:translateY(-3px);
  box-shadow:0 7px 0 rgba(91,63,168,.20), var(--elev-3);
}
#screen-welcome .grade-choice-btn:hover::before{ opacity:.5; }
#screen-welcome .grade-choice-btn:active{
  transform:translateY(0); box-shadow:0 1px 0 rgba(91,63,168,.16), var(--elev-1);
}

/* This screen had NO focus ring at all — the very first choice a keyboard user
   makes was invisible to them. */
#screen-welcome .grade-choice-btn:focus-visible{
  outline:3px solid var(--focus-ring); outline-offset:3px;
}

#screen-welcome .grade-choice-btn .gc-emoji{
  font-size:50px; line-height:1;
  filter:drop-shadow(0 3px 5px rgba(47,42,61,.16));
}
#screen-welcome .grade-choice-btn .gc-year{
  font-family:var(--font-display);
  font-weight:var(--weight-display);
  font-size:var(--text-2xl);
  line-height:var(--leading-tight);
  color:var(--action);
  margin-top:var(--space-2);
}
#screen-welcome .grade-choice-btn .gc-age{
  font-family:var(--font-body);
  font-weight:var(--weight-body);
  font-size:var(--text-sm);
  color:var(--text-secondary);          /* was --muted at 3.70:1, now 6.24:1 */
  margin-top:var(--space-1);
}
#screen-welcome .gc-go{
  position:absolute; top:var(--space-3); right:var(--space-3);
  width:34px; height:34px; border-radius:var(--radius-pill);
  background:var(--action); color:var(--text-on-action);
  display:flex; align-items:center; justify-content:center;
  box-shadow:var(--elev-1);
  transform:translateX(6px); opacity:0;
  transition:transform var(--duration-base) var(--ease-out),
             opacity var(--duration-base) var(--ease-out);
}
#screen-welcome .gc-go svg{ width:18px; height:18px; }
#screen-welcome .grade-choice-btn:hover .gc-go,
#screen-welcome .grade-choice-btn:focus-visible .gc-go{ transform:translateX(0); opacity:1; }

/* =====================================================================
   YOUR QUEST (#screen-sections) — Ochre & Ink + Fredoka/Lexend
   Approved and merged 2026-08-26. Screen 2 of 46.

   Decisions taken 2026-08-26, after review:

   1. The Bonus banner KEEPS its existing gradient, pulse and artwork. It is a
      separate engine outside the Core Knowledge areas, so it is allowed to sit
      outside the theme. See the note above those rules for the contrast cost.

   2. GREEN STAYS, and is the theme's --green-600 rather than the old #12c07a.
      Green marks a quest part as open: the card boundary, the soft wash behind
      it and the "Ready to play" pill. The trade-off was put to the user and
      accepted — green also means "correct" in the quiz engine, so it no longer
      means that uniquely.

   3. Only the values change where they had to. .section-tag.ok was white on
      --green at 2.37:1; the same look in --green-600/--green-100 is 6.70:1.
   ===================================================================== */

/* ---- page ground, matching Welcome ---- */
body:has(#screen-sections:not(.hidden)){
  background:var(--bg-page);
  background-image:
    radial-gradient(circle at 12% 8%,  rgba(224,160,32,.28) 0, transparent 34%),
    radial-gradient(circle at 88% 6%,  rgba(168,72,31,.14)  0, transparent 30%),
    radial-gradient(circle at 50% 100%, rgba(91,63,168,.10) 0, transparent 42%);
  color:var(--text-primary);
}
#screen-sections{ font-family:var(--font-body); font-weight:var(--weight-body); }

/* ---- heading ---- */
#screen-sections .hub-header h1{
  font-family:var(--font-display);
  font-weight:var(--weight-shout);
  font-size:var(--text-3xl);
  line-height:var(--leading-tight);
  letter-spacing:-.5px;
  color:var(--action);
  margin:var(--space-3) 0 var(--space-2);
}

/* ---- top bar: back + year flag ---- */
#screen-sections .sections-top{
  display:flex; align-items:center; justify-content:space-between;
  gap:var(--space-3); margin-bottom:var(--space-3); flex-wrap:wrap;
}
#screen-sections .back{
  font-family:var(--font-display); font-weight:var(--weight-display);
  font-size:var(--text-base); line-height:var(--leading-snug);
  min-height:var(--tap-min); padding:var(--space-2) var(--space-4);
  background:var(--action-soft); color:var(--action-soft-ink);
  border:1px solid var(--border-control); border-radius:var(--radius-md);
  box-shadow:none;
}
#screen-sections .back:hover{ background:var(--bg-raised); transform:translateY(-2px); }
#screen-sections .back:focus-visible{ outline:3px solid var(--focus-ring); outline-offset:3px; }

#screen-sections .grade-flag{
  display:inline-flex; align-items:center; gap:var(--space-2);
  font-family:var(--font-body); font-weight:var(--weight-strong);
  font-size:var(--text-sm);
  background:var(--accent-soft); color:var(--accent-ink);
  border:1px solid var(--accent-border);
  padding:var(--space-2) var(--space-4); border-radius:var(--radius-pill);
  box-shadow:none;
}

/* ---- intro card ---- */
#screen-sections .sections-intro{
  background:var(--bg-surface);
  border:1px solid var(--border-subtle);
  border-radius:var(--radius-lg);
  padding:var(--space-4) var(--space-5);
  margin:var(--space-2) 0 var(--space-5);
  box-shadow:var(--elev-1);
}
#screen-sections .sections-intro p{
  margin:0; font-family:var(--font-body);
  font-size:var(--text-base); font-weight:var(--weight-body);
  line-height:var(--leading-normal); color:var(--text-primary);
}
#screen-sections .sections-intro b{ font-weight:var(--weight-strong); color:var(--action-soft-ink); }

/* ---- BONUS banner ---------------------------------------------------
   RETAINED AS-IS at the user's decision 2026-08-26: the Vocabulary Builder is a
   separate engine sitting outside the Core Knowledge areas, so its orange ->
   hot-pink -> violet gradient, its pulse and its artwork all stay untouched.

   ⚠ Recorded so it is not lost: white text on that gradient measures 2.36:1 at
   the orange end, 2.86:1 through the pink and 4.23:1 at the violet — below the
   4.5:1 AA minimum along its whole length. Accepted deliberately.

   The only two changes below are non-visual accessibility fixes: the Open
   button was 41px tall (under the 44px minimum) and neither control had a
   focus ring. Neither alters a colour. */
#screen-sections .bonus-go{
  min-height:var(--tap-min);
  padding:var(--space-3) var(--space-4);
}
#screen-sections .bonus-go:focus-visible,
#screen-sections .bonus-head:focus-visible{
  outline:3px solid #fff; outline-offset:3px; border-radius:var(--radius-md);
}

/* ---- quest-part cards -------------------------------------------- */
#screen-sections .section-card{
  background:var(--bg-surface);
  border:1px solid var(--border-subtle);
  border-radius:var(--radius-lg);
  padding:var(--space-4) var(--space-5);
  margin-bottom:var(--space-3);
  box-shadow:var(--elev-2);
}
/* The soft green wash is BACK. The original was
   linear-gradient(160deg,#fff,var(--green-soft)) with a --green border; it read
   as "this part is open" and it is what the card looks like as it expands and
   collapses. Same idea, theme greens: --green-100 is the palette's soft green
   and --green-600 clears 5.06:1 as a boundary (the old --green was 2.37:1). */
#screen-sections .section-card.live{
  border-color:var(--green-600);
  border-width:2px;
  background:linear-gradient(160deg,var(--bg-surface) 0%,var(--green-100) 100%);
}
#screen-sections .section-card.soon{ opacity:1; }      /* say it, don't fade it */
#screen-sections .section-card.soon .section-name{ color:var(--text-secondary); }

#screen-sections .section-head{
  display:flex; align-items:center; gap:var(--space-3);
  min-height:var(--tap-min); width:100%; text-align:left;
}
#screen-sections .section-head:focus-visible{
  outline:3px solid var(--focus-ring); outline-offset:3px; border-radius:var(--radius-md);
}
#screen-sections .section-emoji{ font-size:36px; line-height:1; flex-shrink:0; }
#screen-sections .section-name{
  font-family:var(--font-display); font-weight:var(--weight-display);
  font-size:var(--text-xl); line-height:var(--leading-snug);
  color:var(--text-primary);
}

/* Status: one mechanism, sentence case, never colour alone. */
#screen-sections .section-tag{
  display:inline-flex; align-items:center; gap:var(--space-1);
  font-family:var(--font-body); font-weight:var(--weight-strong);
  font-size:var(--text-sm); letter-spacing:0; text-transform:none;
  padding:var(--space-1) var(--space-3); border-radius:var(--radius-pill);
  margin-top:var(--space-1); border:1px solid transparent;
}
#screen-sections .section-tag.ok{           /* was white on --green, 2.37:1 */
  background:var(--green-100); color:var(--green-700); border-color:var(--green-600);
}
#screen-sections .section-tag.wait{
  background:var(--bg-sunken); color:var(--text-secondary); border-color:var(--border-subtle);
}

#screen-sections .section-desc{
  font-family:var(--font-body); font-weight:var(--weight-body);
  font-size:var(--text-base); line-height:var(--leading-normal);
  color:var(--text-primary); margin:var(--space-3) 0 0;
}

/* The one primary action per card, in the theme's green. */
#screen-sections .section-enter{
  display:block; width:100%; margin-top:var(--space-4);
  font-family:var(--font-display); font-weight:var(--weight-display);
  font-size:var(--text-base); min-height:var(--tap-min);
  padding:var(--space-3) var(--space-5);
  background:var(--green-600); color:#fff;   /* 5.14:1 — the old --green was 2.37:1 */
  border:none; border-radius:var(--radius-md);
  box-shadow:0 3px 0 rgba(13,125,85,.30), var(--elev-2);
}
#screen-sections .section-enter:hover{
  filter:none; background:var(--green-700); transform:translateY(-2px);
  box-shadow:0 5px 0 rgba(13,125,85,.30), var(--elev-3);
}
#screen-sections .section-enter:active{
  transform:translateY(0); box-shadow:0 1px 0 rgba(13,125,85,.30), var(--elev-1);
}
#screen-sections .section-enter:focus-visible{ outline:3px solid var(--focus-ring); outline-offset:3px; }

#screen-sections .section-chev{ color:var(--text-secondary); }

/* The closed-card hover kept a hardcoded purple-tinted offset shadow
   (0 9px 0 rgba(58,45,92,.10)) that no longer matches the elevation scale. */
@media (hover:hover) and (pointer:fine){
  #screen-sections .section-card:hover{ box-shadow:var(--elev-3); }
}

  /* ===== Narrated lesson animation (js/16-narration.js) ===== */
  .nr-stage{margin:18px 0 6px;background:var(--card);border:2px solid var(--purple-soft);
    border-radius:20px;box-shadow:0 6px 18px rgba(112,56,224,.13);overflow:hidden;}
  .nr-scene{padding:16px 14px 4px;}
  .nr-scene svg{width:100%;height:auto;max-height:360px;display:block;}
  .nr-controls{display:flex;align-items:center;gap:14px;flex-wrap:wrap;
    padding:12px 16px;background:var(--purple-soft);}
  .nr-play{display:inline-flex;align-items:center;gap:9px;background:var(--purple);color:#fff;
    font-family:"Nunito";font-weight:800;font-size:16px;border:none;border-radius:14px;
    padding:11px 20px;box-shadow:0 4px 0 var(--purple-dark);cursor:pointer;}
  .nr-play:active{transform:translateY(2px);box-shadow:0 2px 0 var(--purple-dark);}
  .nr-icon{font-size:15px;line-height:1;}
  .nr-caption{font-size:14px;font-weight:700;color:var(--purple-dark);flex:1 1 220px;min-width:0;}
  @media (prefers-reduced-motion: reduce){
    /* The animation is the explanation, so it still runs — but nothing decorative moves. */
    .nr-play{transition:none;}
  }

  /* ===== "Share them out" activity (js/17-share-activity.js) ===== */
  .ns-stage{margin:18px 0 6px;background:var(--card);border:2px solid var(--purple-soft);
    border-radius:20px;box-shadow:0 6px 18px rgba(112,56,224,.13);overflow:hidden;}
  .ns-scene{padding:14px 12px 4px;}
  .ns-scene svg{width:100%;height:auto;max-height:380px;display:block;}
  /* ⚠ In a QUIZ the activity is a working-out aid, not the lesson, and it has to leave room for
     the question, the answer box and the feedback on one screen. Full size it pushed every
     clickable question 85-111px past the viewport. Keyed off data-helper so the lesson pages,
     where the activity IS the lesson, keep their full size. */
  .ns-stage[data-helper="1"] .ns-scene svg{max-height:284px;}
  .ns-stage[data-helper="1"] .ns-controls{padding:8px 14px;}
  .ns-stage[data-helper="1"] .ns-reset{font-size:14px;padding:7px 14px;}
  /* ⚠⚠ DO NOT SHRINK THE AID WHEN THE ANSWER IS CHECKED. It used to drop to 140px and dim so
     the feedback and Next would fit the same screen; the baskets visibly collapsed under the
     child's hand the instant they pressed Check, and the user rejected it outright. The page is
     allowed to scroll after an answer instead, and naRenderQuestion scrolls the Next button into
     view so the thing to press next is never below the fold. Nothing may key off .gq-answered
     to resize this picture. */
  .ns-basket{cursor:pointer;}
  .ns-basket:focus{outline:3px solid var(--purple);outline-offset:3px;border-radius:14px;}
  .ns-controls{display:flex;align-items:center;gap:10px;flex-wrap:wrap;
    padding:12px 16px;background:var(--purple-soft);}
  .ns-check,.ns-reset{font-family:"Nunito";font-weight:800;font-size:16px;border:none;
    border-radius:14px;padding:11px 18px;cursor:pointer;}
  .ns-check{background:var(--purple);color:#fff;box-shadow:0 4px 0 var(--purple-dark);}
  .ns-reset{background:var(--card);color:var(--purple-dark);box-shadow:0 4px 0 var(--purple-soft);}
  .ns-check:active,.ns-reset:active{transform:translateY(2px);box-shadow:none;}
  .ns-msg{font-size:14.5px;font-weight:800;flex:1 1 240px;min-width:0;color:var(--purple-dark);}
  .ns-msg.ns-right{color:var(--green-dark);}
  .ns-msg.ns-wrong,.ns-msg.ns-warn{color:#c0392b;}

  /* ===== typed answer on the paper pages, and the reveal over the picture ===== */
  /* ⚠⚠ MUST out-rank the global input[type=text] near the top of this file (0-1-1), which sets
     26px text, 15px padding and a bottom margin. A bare .ns-answer-box loses and renders as the
     app's big single-answer field. Same trap as .nb-type on the lesson pages. */
  .ns-controls input.ns-answer-box{font-family:"Nunito";font-weight:800;font-size:20px;
    color:var(--purple-dark);background:var(--card);border:2px solid var(--purple);
    border-radius:12px;padding:8px 10px;width:86px;margin:0;letter-spacing:0;text-align:center;}
  .ns-controls input.ns-answer-box:focus{border-color:var(--purple-dark);}
  .ns-controls input.ns-answer-box:disabled{opacity:1;color:var(--green-dark);
    border-color:var(--green-dark);background:var(--green-soft);}
  .ns-check:disabled{background:var(--green-soft);color:var(--green-dark);box-shadow:none;
    cursor:default;}

  .ns-scene{position:relative;}
  /* the picture steps back behind the answer rather than disappearing — the child can still see
     the share they made, which is what the number is describing */
  .ns-stage.ns-done .ns-scene svg{filter:blur(4px);opacity:.55;transition:filter .25s,opacity .25s;}
  .ns-solved{position:absolute;inset:0;display:none;flex-direction:column;align-items:center;
    justify-content:center;gap:2px;pointer-events:none;}
  .ns-stage.ns-done .ns-solved{display:flex;}
  .ns-solved-tick{font-size:54px;line-height:1;color:var(--green-dark);font-weight:900;}
  .ns-solved-num{font-family:"Nunito";font-size:92px;line-height:1;font-weight:800;
    color:var(--green-dark);}
  .ns-solved-each{font-family:"Nunito";font-size:20px;font-weight:800;color:var(--purple-dark);}
  @media (prefers-reduced-motion: reduce){
    .ns-stage.ns-done .ns-scene svg{transition:none;}
  }


  /* ===== "write the division" table (js/18-build-sentence.js) ===== */
  .nb-wrap{margin:4px 0 14px;}
  /* three questions to a row — six stacked rows did not fit the screen */
  .nb-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:10px;}
  @media (max-width:700px){ .nb-grid{grid-template-columns:repeat(2,minmax(0,1fr));} }
  @media (max-width:470px){ .nb-grid{grid-template-columns:1fr;} }
  .nb-q{background:#fff;border:2px solid var(--purple-soft);border-radius:14px;padding:10px 11px;}
  .nb-ask{margin:0 0 8px;font-size:15px;line-height:1.35;font-weight:800;color:var(--purple-dark);}
  .nb-cell{white-space:normal;display:flex;align-items:center;flex-wrap:wrap;gap:2px;}
  .nb-q.nb-right{background:var(--green-soft);border-color:var(--green-dark);}
  .nb-q.nb-wrong{background:#fdeeec;border-color:#c0392b;}
  .nb-q.nb-todo{background:#fffaf0;}
  .nb-q .nb-mark{margin-left:2px;}
  /* the question's own Check, and the tick or cross beside it */
  .nb-foot{display:flex;align-items:center;gap:8px;margin-top:7px;}
  .nb-qcheck{font-family:"Nunito";font-weight:800;font-size:14px;border:none;border-radius:11px;
    padding:6px 14px;cursor:pointer;background:var(--purple);color:#fff;
    box-shadow:0 3px 0 var(--purple-dark);}
  .nb-qcheck:active{transform:translateY(2px);box-shadow:none;}
  .nb-qcheck:focus-visible{outline:3px solid var(--purple-dark);outline-offset:2px;}
  .nb-qcheck:disabled{background:var(--green-soft);color:var(--green-dark);box-shadow:none;
    cursor:default;}
  .nb-q.nb-right .nb-mark{color:var(--green-dark);}
  .nb-q.nb-wrong .nb-mark{color:#c0392b;}
  /* the three dropdowns read as one sentence, so they sit on one line and wrap together */
  .nb-pick{font-family:"Nunito";font-weight:800;font-size:16px;color:var(--purple-dark);
    background:var(--card);border:2px solid var(--purple-soft);border-radius:10px;
    padding:5px 6px;margin-right:5px;min-width:62px;cursor:pointer;}
  .nb-pick:focus-visible{outline:3px solid var(--purple);outline-offset:2px;}
  .nb-pick:disabled{opacity:1;color:var(--green-dark);border-color:var(--green-soft);
    background:var(--green-soft);cursor:default;}
  .nb-tail{font-weight:800;color:var(--purple-dark);font-size:16px;margin-left:2px;}
  /* The typed answer box on the last page.
     ⚠⚠ SELECTOR MUST OUT-RANK THE GLOBAL input[type=text] AT THE TOP OF THIS FILE, which sets
     font-size:26px, padding:15px and margin-bottom:12px for the app's big single-answer fields.
     A bare .nb-type loses that fight (0-1-0 against 0-1-1) and the box rendered 78px tall instead
     of 40 — which showed up only as "the cards are mysteriously too tall for the screen". */
  .nb-q input.nb-type{font-family:"Nunito";font-weight:800;font-size:20px;color:var(--purple-dark);
    background:var(--card);border:2px solid var(--purple-soft);border-radius:10px;
    padding:5px 8px;width:74px;margin:0;letter-spacing:0;text-align:center;}
  .nb-q input.nb-type:focus{border-color:var(--purple);}
  .nb-q input.nb-type:focus-visible{outline:3px solid var(--purple);outline-offset:2px;}
  .nb-q input.nb-type:disabled{opacity:1;color:var(--green-dark);border-color:var(--green-dark);
    background:var(--green-soft);}
  .nb-mark{font-weight:900;font-size:18px;margin-left:8px;}
  /* ⚠ Once every card carries its own Check, this bar has no primary action left — only a
     reset and the running score. A full action bar for that was 74px of the page height
     doing nothing, and it pushed the page over the one-screen budget. */
  .nb-controls{display:flex;align-items:center;gap:12px;flex-wrap:wrap;padding:9px 2px 0;
    background:none;}
  .nb-reset{font-family:"Nunito";font-weight:800;font-size:14px;border:none;
    border-radius:12px;padding:7px 15px;cursor:pointer;}
  .nb-reset{background:var(--card);color:var(--purple-dark);box-shadow:0 3px 0 var(--purple-soft);}
  .nb-reset:active{transform:translateY(2px);box-shadow:none;}
  .nb-msg{font-size:14.5px;font-weight:800;flex:1 1 240px;min-width:0;color:var(--purple-dark);}
  .nb-msg.nb-is-right{color:var(--green-dark);}
  .nb-msg.nb-is-wrong{color:#c0392b;}

  /* ---- the guided walkthrough: one step at a time ---- */
  .nw-wrap{margin:4px 0 14px;}
  /* the question, printed once at the top — every step refers back to it, so it is set like the
     printed question on the paper pages rather than like a heading */
  /* ⚠ Bigger than the step text, not the same size as it. Every step refers back to this line,
     and a child re-reads it half a dozen times on the way down the page — at 19px it read as one
     more row rather than as the thing being answered. */
  .nw-ask{margin:0 0 12px;padding:13px 16px;border-radius:12px;background:var(--purple-soft);
    font-size:24px;font-weight:800;color:var(--purple-dark);text-align:center;line-height:1.3;}
  @media (max-width:560px){ .nw-ask{font-size:21px;} }
  .nw-steps{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:9px;}
  /* ⚠ ONE ROW: number, words, box, Check. The box belongs on the RIGHT OF THE LINE so a step
     reads as a sentence with a gap in it, not as a question with a form underneath it. */
  .nw-step{display:flex;align-items:center;flex-wrap:wrap;gap:10px;
    background:#fff;border:2px solid var(--purple-soft);border-radius:14px;padding:10px 12px;}
  /* ⚠⚠ SETTING `display` DEFEATS THE `hidden` ATTRIBUTE. The browser hides [hidden] with a
     user-agent `display:none`, which any author rule with a display wins against — so every step
     rendered at once and the whole point of the page (one step at a time) silently did not
     happen. It looked like the JS had failed. Anything with a display needs this line. */
  .nw-step[hidden]{display:none;}
  .nw-step.nw-right{background:var(--green-soft);border-color:var(--green-dark);}
  .nw-step.nw-wrong{background:#fdeeec;border-color:#c0392b;}
  .nw-step.nw-right .nb-mark{color:var(--green-dark);}
  .nw-step.nw-wrong .nb-mark{color:#c0392b;}
  .nw-num{flex:0 0 auto;width:28px;height:28px;border-radius:50%;background:var(--purple);
    color:#fff;font-weight:800;font-size:15px;display:flex;align-items:center;justify-content:center;}
  /* the words are just words — same size and weight as the page's own paragraphs */
  .nw-text{flex:1 1 220px;margin:0;font-size:19.2px;line-height:1.5;color:var(--ink);}
  /* ⚠ `.nw-step input` and not a bare class: the app's global input[type=text] is 0-1-1 and
     beats a lone .nb-type, which rendered the box 78px tall. Third time this trap has bitten. */
  .nw-step input.nb-type{flex:0 0 84px;font-family:"Nunito";font-weight:800;font-size:20px;
    color:var(--purple-dark);text-align:center;border:2px solid var(--purple-soft);
    border-radius:11px;padding:7px 8px;width:84px;min-height:0;height:auto;background:#fff;}
  .nw-step input.nb-type:focus{border-color:var(--purple);}
  .nw-step input.nb-type:disabled{opacity:1;color:var(--green-dark);border-color:var(--green-dark);
    background:#fff;}
  /* the child's own sheet: full width, under the words of the step that owns it */
  .nw-pic{flex:1 0 100%;margin:6px 0 2px;}
  .nw-svg{display:block;width:100%;max-height:150px;}
  .nw-empty{margin:2px 0 0;font-size:15px;font-weight:800;color:var(--purple-soft-ink,#9b8fc7);}
  /* ⚠ stroked ON, not simply present — the same claim the paper pages make about drawing. Only
     the newest circle carries a non-zero offset, so the ones already there do not redraw
     themselves every time another is added. */
  .nw-ring{transition:stroke-dashoffset .45s ease;}
  @media (prefers-reduced-motion:reduce){ .nw-ring{transition:none;} }
  .nw-halo{transition:opacity .18s ease;}
  .nw-c.nw-tap{cursor:pointer;}
  .nw-c.nw-tap:focus{outline:none;}
  .nw-c.nw-tap:focus-visible .nw-halo{opacity:.3;}
  .nw-c.nw-tap:hover .nw-ring{stroke-width:4.4;}
  /* add / take away, and the running count of what has been drawn */
  .nw-tools{display:flex;gap:7px;flex:0 0 auto;}
  .nw-add,.nw-less{font-family:"Nunito";font-weight:800;font-size:14px;border:none;
    border-radius:11px;padding:8px 12px;cursor:pointer;}
  .nw-add{background:var(--purple);color:#fff;box-shadow:0 3px 0 var(--purple-dark);}
  .nw-less{background:var(--card);color:var(--purple-dark);box-shadow:0 3px 0 var(--purple-soft);}
  .nw-add:active,.nw-less:active{transform:translateY(2px);box-shadow:none;}
  .nw-add:focus-visible,.nw-less:focus-visible{outline:3px solid var(--purple-dark);outline-offset:2px;}
  .nw-add:disabled,.nw-less:disabled{opacity:.45;cursor:default;box-shadow:none;transform:none;}
  .nw-tally{flex:0 0 auto;font-size:15px;font-weight:800;color:var(--purple-dark);}
  /* finishing, and the way on — the biggest thing on the page once it is earned */
  .nw-done{display:flex;align-items:center;gap:16px;flex-wrap:wrap;margin-top:12px;
    padding:15px 18px;border-radius:16px;background:var(--green-soft);border:3px solid var(--green-dark);}
  /* ⚠ a class with a `display` beats the browser's own [hidden] rule — see .nw-step above */
  .nw-done[hidden]{display:none;}
  .nw-tick{font-size:52px;line-height:1;font-weight:900;color:var(--green-dark);}
  .nw-done-text{flex:1 1 200px;margin:0;font-size:21px;font-weight:800;color:var(--green-dark);}
  .nw-next{font-family:"Nunito";font-weight:800;font-size:21px;border:none;border-radius:14px;
    padding:14px 24px;cursor:pointer;background:var(--purple);color:#fff;
    box-shadow:0 4px 0 var(--purple-dark);}
  .nw-next[hidden]{display:none;}
  .nw-next:active{transform:translateY(3px);box-shadow:none;}
  .nw-next:focus-visible{outline:3px solid var(--purple-dark);outline-offset:3px;}

  /* numbered "what to do" steps on a lesson page */
  /* ⚠ The step TEXT must match .gdef exactly — same size, leading, colour and weight. It was
     16px/600 against the paragraphs' 19.2px/normal, which read as a different kind of text on
     the same page. Only the numbered badge is styled; the words are just words. */
  /* ⚠ The steps run ACROSS the row, two or three to a line, rather than one per line down the
     page. auto-fit gives three columns at the 740px lesson width and drops to two, then one, on
     narrower screens. The numbered badge keeps the reading order unambiguous.
     ⚠ This saves less than it looks: at a third of the width the longer steps wrap to three
     lines, so a five-step list goes from ~212px to ~198px. It is a tidier shape, not a fix for
     a page that does not fit. */
  .gsteps{margin:14px 0 4px;padding:0;list-style:none;counter-reset:gstep;
    display:grid;grid-template-columns:repeat(auto-fit,minmax(300px,1fr));gap:0 18px;}
  .gsteps li{counter-increment:gstep;position:relative;padding:0 0 12px 44px;
    font-size:19.2px;line-height:1.5;color:var(--ink);}
  .gsteps li:last-child{padding-bottom:2px;}
  .gsteps li::before{content:counter(gstep);position:absolute;left:0;top:1px;
    width:29px;height:29px;border-radius:50%;background:var(--purple);color:#fff;
    font-weight:800;font-size:16px;display:flex;align-items:center;justify-content:center;}
  /* the restart button sits beside play, quieter than it */
  .nr-restart{display:inline-flex;align-items:center;gap:8px;background:var(--card);
    color:var(--purple-dark);font-family:"Nunito";font-weight:800;font-size:15px;border:none;
    border-radius:14px;padding:10px 16px;box-shadow:0 4px 0 var(--purple-soft);cursor:pointer;}
  .nr-restart:active{transform:translateY(2px);box-shadow:none;}

  /* ---- WRITING INTRO: the parts as drawers, and what the colours mean ----
     The four part names are red and every other bold word green, asked for 2026-09-21
     so a child can see at a glance which words are the parts of a story and which are
     the ideas about writing. Both colours are the tokens already proved for contrast
     on white (--red = clay-600, --green-dark = green-700). */
  .wpname{color:var(--red);font-weight:800;}
  b.wkey,.wkey{color:var(--green-dark);font-weight:800;}
  .ggroup-name .wpname{color:var(--red);}
  .wpart-lead{margin:2px 0 10px;font-weight:700;}
  /* Writing menu: drawers whose rows are SPELLING's part rows (user 2026-10-02) -- the plain .gsub-btn card,
     its size, its "Start →" badge; only the name's alignment and the one-line meta are set here. (They were
     slim outlined rows from 2026-09-28 until then.) */
  #wmenu-list .ggroup{margin-bottom:0;}
  .wmenu-rows{display:flex;flex-direction:column;gap:10px;margin-top:12px;padding-bottom:8px;}   /* room for the last row's shadow */
  #wmenu-list .wmenu-row{width:100%;box-sizing:border-box;}
  #wmenu-list .wmenu-row .gsub-name{flex:1;min-width:0;text-align:left;}
  #wmenu-list .wmenu-row .gsub-meta{flex-direction:row;align-items:center;gap:8px;white-space:nowrap;}
  .wmenu-note{font-size:12px;font-weight:700;color:var(--muted);}
  @media (max-width:560px){
    #wmenu-list .ggroup{padding:12px 10px;}
    #wmenu-list .wmenu-row{padding:12px 10px 12px 12px;}
    #wmenu-list .wmenu-row .gsub-name{font-size:15px;}
    #wmenu-list .wmenu-row .gsub-score, .wmenu-note{display:none;}
  }
  .wpart-drawers{display:flex;flex-direction:column;gap:10px;margin:6px 0 14px;}
  .wpart-drawers .ggroup{margin:0;}
  .wpart-drawers .ggroup-head{padding:10px 14px;margin:0;}
  .wpart-drawers .ggroup-icon{font-size:26px;}
  .wpart-drawers .ggroup-name{font-size:19px;}
  /* the explanation inside a drawer is set larger than the 13px map row it replaces */
  .wpart-detail{margin:10px 2px 2px;font-size:18.5px;line-height:1.55;color:var(--ink);font-weight:500;}
  /* the labelled story mountain fills the card, unlike the 300px thumbnails */
  .wintro-svg-big{width:100%;max-width:620px;}

  /* a drawer heading IS a part name, so it takes the part colour -- this has to beat
     .ggroup .ggroup-name, which paints every group heading purple */
  .wpart-drawers .ggroup-name.wpname{color:var(--red);}

  /* ---- WRITING INTRO: breathing room, and one box height for every page ----
     Asked for 2026-09-21 once the busy page was split and the pages had room to spare.
     Spacing is looser than a lesson page (line 1.62, paragraphs 24px apart); the box
     itself is brought up to the height of the tallest intro page by wIntroEvenBox(),
     which adds the difference above the dots, so Back / Next never move. */
  #wintro-body .gdef{line-height:1.62;margin:0 0 24px;}
  #wintro-body h2{margin:0 0 14px;}
  #wintro-body .gintro-list{margin:4px 0 20px;}
  #wintro-body .gintro-list li{line-height:1.62;margin:0 0 18px;}
  #wintro-body .wmodel{margin:6px 0 24px;}
  /* the "open each part" lead sits close to the drawers it introduces */
  #wintro-body .wpart-lead{margin:2px 0 12px;}
  #wintro-body .wintro-graphic{margin:4px auto 10px;}
  /* a phone has the least height to spare and scrolls anyway, so it keeps closer spacing */
  @media (max-width:600px){
    #wintro-body .gdef{line-height:1.55;margin:0 0 16px;}
    #wintro-body .gintro-list li{line-height:1.55;margin:0 0 10px;}
  }

  /* persuasive page 1 opinion-and-reasons picture, and page 2 train a little bigger than page 4 */
  #wintro-body .wintro-svg-mid{width:100%;max-width:500px;}
  /* 680, not 700: page 2 now carries four lines, and must still fit a 1024x768 iPad */
  /* 640: page 2 now carries the three part boxes over the train, and must fit a 1024x768 iPad */
  #wintro-body .wtrain-large{max-width:640px;}
  /* narrative page 2 (the story mountain): one sentence per box above the picture, so the
     picture gives up a little height to keep the page on a 1024x768 iPad */
  #wintro-body .gintro-list + .wintro-graphic svg{max-width:255px;}
  /* ...and since 2026-09-23 the picture leads that page instead, larger, over the boxes */
  #wintro-body .wintro-graphic-top .wintro-graphic{margin:-10px auto 2px;}
  #wintro-body .wintro-graphic-top svg{width:100%;max-width:360px;}
  /* its boxes sit closer together, so the larger picture keeps the page on a 1024x768 iPad */
  #wintro-body .wintro-graphic-top + .gintro-list{margin:0 0 6px;}
  #wintro-body .wintro-graphic-top + .gintro-list li{margin:0 0 7px;padding-top:7px;padding-bottom:7px;}
  /* the four part drawers (page 3) are less tall, so an open drawer still fits the screen */
  #wintro-body .wpart-drawers{gap:8px;}
  #wintro-body .wpart-drawers .ggroup{padding:6px 14px;}
  #wintro-body .wpart-drawers .ggroup-head{padding:4px 10px;}
  #wintro-body .wpart-drawers .wpart-detail{margin:6px 2px 4px;}
  /* the space above the dots gives way as a drawer opens, at the drawer's own pace */
  #wintro-body .gdots{transition:margin-top .38s cubic-bezier(.4,0,.2,1);}
  /* one idea per line (persuasive page 2): closer than paragraphs, then the usual gap */
  #wintro-body .gdef.wintro-line{margin:0 0 8px;}
  #wintro-body .gdef.wintro-line:last-of-type{margin-bottom:22px;}

  /* a model shown as cards: each card carries its place in the reading order */
  .wcard-n{display:inline-grid;place-items:center;width:26px;height:26px;border-radius:50%;background:var(--purple);
    color:#fff;font:800 14px/1 Fredoka,"Baloo 2",sans-serif;margin:0 9px 0 0;vertical-align:2px;}

  /* ---- ONE POINT, ONE BOX (Writing house style, 2026-09-21) ----
     Any list of separate points -- a Remember summary, the parts of the train, the
     orientation's four questions -- shows each point in its own light box, the drawers'
     surface made quieter, and no bullet. */
  #wintro-body .gintro-list{list-style:none;padding:0;margin:4px 0 16px;display:flex;flex-direction:column;gap:10px;}
  #wintro-body .gintro-list li, .wpoint{margin:0;padding:11px 16px;background:#fbf9ff;
    border:2px solid #ece4fb;border-radius:14px;line-height:1.5;}
  #wintro-body .gintro-list li{margin:0;}
  .wpoints{display:flex;flex-direction:column;gap:10px;margin:0 0 16px;}
  /* scoped to the page ids: #wintro-body .gdef (24px gap, 1.62 lines) outranks a bare class */
  #wintro-body .wpoints .gdef.wpoint, #wlesson .wpoints .gdef.wpoint{margin:0;line-height:1.5;}
  .wpoints.wpoints-row{display:grid;grid-template-columns:repeat(3,1fr);gap:10px;}
  .wpoints-row .wpoint{text-align:center;}
  @media (max-width:600px){
    #wintro-body .gintro-list li, .wpoint{padding:9px 12px;}
    .wpoints.wpoints-row{grid-template-columns:1fr;}
    .wpoints-row .wpoint{text-align:left;}
  }
  /* ---- NARRATIVE INTRO, user review 2026-09-30 ----
     Page 1: the example sentence is red, bold and larger than the description above it,
     with its note set quietly underneath. Page 2: the opening sentence is bold and the
     three that follow are plain bullet points under it, not boxes. */
  #wintro-body .wmodel-strong p{font-size:22px;line-height:1.4;font-weight:800;color:var(--red);}
  #wintro-body .wmodel-strong p.wmodel-note{font-size:15.5px;line-height:1.5;font-weight:600;color:var(--muted);margin-top:6px;}
  /* the taller example takes its height from the gap and the picture under it, so page 1
     stays inside the shared box height and every intro page still fits a 1024x768 iPad */
  #wintro-body .wmodel-strong{margin-bottom:10px;}
  #wintro-body .wmodel-strong + .wintro-graphic svg{max-width:240px;}
  #wintro-body .gdef.wintro-strong{font-weight:800;margin:0 0 10px;}
  #wintro-body .gintro-list.wbullets{display:block;list-style:disc;padding:0 0 0 30px;margin:0 0 12px;}
  #wintro-body .gintro-list.wbullets li{background:none;border:0;border-radius:0;padding:0 0 0 4px;margin:0 0 10px;
    font-size:18.5px;line-height:1.5;}
  #wintro-body .gintro-list.wbullets li::marker{color:var(--purple);}
  /* An intro page with its text beside the picture ("graphicSide" in js/07, the lesson pages' .wpage-side): the
     persuasive Remember page, 2026-10-03. Its bullets are spaced further apart (user: "there is a lot of space on
     the page") -- only here, the narrative story-mountain bullets keep 10px. Stacks on a phone. */
  #wintro-body .wintro-side{display:flex;align-items:center;gap:22px;margin:0 0 28px;}
  #wintro-body .wintro-side-text{flex:1 1 0;min-width:0;}
  #wintro-body .wintro-side-text .gdef:last-child,#wintro-body .wintro-side-text .gintro-list:last-child{margin-bottom:0;}
  #wintro-body .wintro-side .wintro-graphic{flex:0 0 auto;margin:0;}
  #wintro-body .wintro-side .wintro-graphic svg{width:300px;max-width:300px;height:auto;}
  #wintro-body .wintro-side .wintro-graphic:not(.wintro-scene) svg{width:350px;max-width:350px;}
  #wintro-body .wintro-scene svg{overflow:visible;}
  #wintro-body .wintro-side .gintro-list.wbullets li{margin:0 0 26px;line-height:1.6;}
  #wintro-body .wintro-side .gintro-list.wbullets li:last-child{margin-bottom:0;}
  @media (max-width:620px){
    #wintro-body .wintro-side{flex-direction:column;gap:6px;}
    #wintro-body .wintro-side .wintro-graphic svg{width:100%;max-width:260px;}
  }
  #wintro-body h2 b.wkey{font-weight:inherit;}
  /* Writing: the "what you will learn" page that opens a part -- two short sentences
     beside a character (WLESSON_SVG in js/07-writing.js). Stacks on a phone. */
  .wlesson-hero{display:flex;align-items:center;gap:28px;margin:6px 0 10px;}
  .wlesson-hero-text{flex:1 1 0;min-width:0;}
  #wlesson .wlesson-hero-text .gdef{font-size:21px;line-height:1.55;margin:0 0 14px;}
  .wlesson-art{flex:0 0 auto;}
  .wlesson-svg{display:block;width:280px;height:auto;}
  @media (max-width:600px){
    .wlesson-hero{flex-direction:column;gap:8px;}
    .wlesson-svg{width:190px;margin:0 auto;}
  }
  /* Writing: the WHO / WHAT / WHERE / WHEN / HINT badges (wQIcons in js/07-writing.js) --
     small, at the right of a point box, a table's first cell, or a sentence row */
  .wq-icons{display:inline-flex;align-items:center;gap:5px;flex:0 0 auto;}
  .wq-ico{display:block;width:30px;height:30px;}
  #wlesson .wpoints .gdef.wpoint.has-q{display:flex;align-items:center;justify-content:space-between;gap:12px;padding-top:7px;padding-bottom:7px;}
  .wq-cell{display:flex;align-items:center;justify-content:space-between;gap:10px;}
  .wq-cell .wq-ico{width:26px;height:26px;}
  /* one sentence per line: tight rows, and a short sentence keeps its chip + note on the
     same line (they wrap under it only when the sentence is long) */
  .ph-cards.wcard-rows{grid-template-columns:1fr;gap:6px;margin:8px 0;}
  .ph-cards.wcard-rows .ph-card{padding:6px 12px;}
  .wcard.has-q{flex-direction:row;align-items:center;justify-content:space-between;gap:12px;}
  .wcard-main{display:flex;flex-wrap:wrap;align-items:center;column-gap:12px;row-gap:2px;min-width:0;}
  .wcard-rows .wcard-text{font-size:16px;line-height:1.35;}
  .wcard-rows .wcard-foot{gap:6px;}
  .wcard.has-q .wq-icons{gap:4px;}
  /* Writing: a page's WHO / WHAT / WHERE / WHEN / HINT points as five picture cards in a
     row, the scene on top (`qScenes`, wQScene in js/07-writing.js). One per row on a phone,
     scene at the right. */
  #wlesson .wpoints.wq-cards{display:grid;grid-template-columns:repeat(5,1fr);gap:10px;}
  #wlesson .wpoints.wq-cards.wq-n4{grid-template-columns:repeat(4,1fr);}
  /* three picture cards (the persuasive Introduction's jobs): centred, not stretched to the full width */
  #wlesson .wpoints.wq-cards.wq-n3{grid-template-columns:repeat(3,1fr);max-width:560px;margin-left:auto;margin-right:auto;}
  #wlesson .wpoints.wq-cards .gdef.wpoint.wq-card{display:flex;flex-direction:column;align-items:stretch;gap:8px;margin:0;padding:7px 7px 11px;text-align:center;line-height:1.35;border-radius:24px;}
  .wq-scene{display:block;}
  /* the scene is a round blob with things popping out of it: never clip the picture */
  .wq-scene svg{display:block;width:100%;height:auto;overflow:visible;}
  /* a page's `picture`: centred between the paragraph and the sentences. 180px is what the
     tightest page (Y5 Complication p3 on an iPad) allows; a phone scrolls, so it gets more */
  #wlesson .wpage-pic{display:flex;justify-content:center;margin:6px 0 2px;}
  #wlesson .wpage-pic svg{display:block;width:var(--wpic,180px);height:auto;overflow:visible;}
  @media (max-width:600px){ #wlesson .wpage-pic svg{width:200px;} }
  /* a page's `pictures`: the level's line pictures in one row */
  #wlesson .wpage-pics{display:grid;grid-template-columns:repeat(4,1fr);gap:10px;max-width:400px;margin:6px auto 2px;}
  #wlesson .wpage-pics-one svg{display:block;width:100%;height:auto;overflow:visible;}
  /* `pictureSide`: the page's picture BESIDE its paragraphs, for a busy page (a table under it) */
  #wlesson .wpage-side{display:flex;align-items:center;gap:20px;margin:0 0 8px;}
  #wlesson .wpage-side-text{flex:1 1 0;min-width:0;}
  #wlesson .wpage-side .wpage-pic{flex:0 0 auto;margin:0;}
  /* `pictureSide:"table"`: the picture beside the TABLE, for a page whose paragraphs are too long to share their row */
  #wlesson .wpage-side-tbl{align-items:center;gap:16px;margin:0 0 4px;}
  #wlesson .wpage-side-tbl .gtable{margin:0;}
  @media (max-width:600px){ #wlesson .wpage-side{flex-direction:column;gap:4px;} }
  @media (min-width:1200px){ #wlesson .wpage-pics{max-width:600px;} }
  #wlesson .wcard-dense .wcard-text{font-size:15px;}
  /* `big:true`: the two example sentences are the boldest thing on the page (user 2026-10-02) */
  #wlesson .wcard-big{gap:14px;margin:12px 0 14px;}
  #wlesson .wcard-big .ph-card{padding:14px 18px;border:2px solid #cdbdf2;background:#f3ecff;box-shadow:0 3px 0 rgba(91,58,166,.12);}
  /* 21px: "make sentences little smaller" (they were 25px) */
  #wlesson .wcard-big .wcard-text{font-size:21px;font-weight:800;line-height:1.3;color:#1f1838;}
  #wlesson .wcard-big .wcard-text .hl{background:#ffe08a;padding:0 5px;}
  #wlesson .wcard-big .wcard-note{font-size:14.5px;}
  /* `table.sound` in a Writing lesson: the word is a SOUND CARD -- Spelling's tappable chip, in a white box and a
     bit larger (user 2026-10-02). Tap it to hear the word. */
  #wlesson .gtable td.wt-snd{padding:3px 4px 4px 8px;white-space:nowrap;width:1%;}
  /* a table with sound cards gives the card its width back from the cell padding, so the example still fits one line */
  #wlesson .gt-hassnd th, #wlesson .gt-hassnd td{padding-left:9px;padding-right:7px;}
  #wlesson .gt-hassnd th{white-space:nowrap;}
  #wlesson .gtable td.wt-snd .gt-snd{font-size:17px;font-weight:800;padding:4px 10px 4px 9px;gap:4px;margin:0;border-radius:11px;
    background:#fff;border:2px solid #cdbdf2;box-shadow:0 3px 0 rgba(91,58,166,.16);}
  #wlesson .gtable td.wt-snd .gt-snd .gt-snd-i{font-size:13px;opacity:.9;}
  /* a PHRASE on a card ("Every night", "As cold as ice") keeps one capital, not one per word; a little smaller, it is long */
  #wlesson .gtable td.wt-phrase .gt-snd{text-transform:none;font-size:16px;}
  /* `write`: the Orientation's "Your turn" box (one sentence, goals that tick, a model after) */
  #wlesson .wpw{margin:10px 0 4px;}
  #wlesson .wpw .wtextarea{min-height:58px;font-size:17px;}
  #wlesson .wpw-goals{margin:10px 0 0;}
  #wlesson .wpw-goals .wcheck-item{margin:4px 0;padding:5px 11px;}
  #wlesson .wpw-nav{display:flex;justify-content:flex-end;margin:8px 0 0;}
  #wlesson .wpw .wreveal{margin-top:8px;}
  /* PROOFREAD (tasks and lesson `write` boxes): the test's spelling/capital/full-stop analysis, no score */
  .wproof{background:#fff8e8;border:2px solid #f3d99a;border-radius:14px;padding:10px 14px;margin:10px 0 0;}
  .wproof.ok{background:#f0fff6;border-color:#b6ecca;}
  .wproof-label{display:block;font-weight:800;color:#8a5a00;font-size:11px;text-transform:uppercase;letter-spacing:.4px;margin-bottom:4px;}
  .wproof.ok .wproof-label{color:var(--green-dark);}
  .wproof ul{margin:0;padding-left:20px;}
  .wproof li,.wproof p{font-size:14px;font-weight:600;color:var(--ink);line-height:1.5;margin:2px 0;}
  /* `paras`: two paragraphs of a real story, one under the other, each with its picture on the right */
  #wlesson .wparas{display:flex;flex-direction:column;gap:18px;margin:10px 0 12px;}
  #wlesson .wpara-row{display:flex;align-items:center;gap:22px;}
  #wlesson .wpara-text{flex:1 1 0;min-width:0;margin:0;font-size:19px;line-height:1.6;color:#2c2340;text-indent:1.4em;}
  #wlesson .wpara-pic svg{display:block;width:150px;height:auto;overflow:visible;}
  @media (max-width:600px){ #wlesson .wpara-row{gap:10px;} #wlesson .wpara-text{font-size:17px;} #wlesson .wpara-pic svg{width:96px;} }
  /* a page's `qWords`: the questions as small red words instead of badges; on a phone they
     go under the sentence */
  /* a table row's page-2 picture (`qPics`): 70px is what the 5-row Orientation table allows on an iPad */
  #wlesson td .wq-row{display:flex;align-items:center;justify-content:space-between;gap:10px;}
  #wlesson td .wq-mini{display:block;flex:0 0 auto;width:70px;margin:-6px 0;}
  #wlesson td .wq-mini svg{display:block;width:100%;height:auto;overflow:visible;}
  .wq-words{font-size:13px;font-weight:700;letter-spacing:.02em;white-space:nowrap;flex:0 0 auto;}
  @media (max-width:600px){ .wcard.has-words{flex-direction:column;align-items:flex-start;gap:4px;} .wq-words{font-size:12px;} }
  @media (max-width:600px){
    #wlesson .wpoints.wq-cards,#wlesson .wpoints.wq-cards.wq-n4{grid-template-columns:1fr;}
    #wlesson .wpoints.wq-cards .gdef.wpoint.wq-card{flex-direction:row-reverse;align-items:center;justify-content:space-between;text-align:left;padding:6px 6px 6px 14px;}
    .wq-card .wq-scene svg{width:110px;}
  }
  /* THE TOPIC box (`topic`, user review 2026-10-02): what the child is writing about -- beside the picture on the
     topic page, and on top of the planning pages */
  #wlesson .wtopic{background:#fff7e6;border:2px solid #f3d99a;border-radius:16px;padding:9px 16px 11px;margin:0 0 12px;}
  #wlesson .wtopic-label{display:block;font-weight:800;color:#8a5a00;font-size:11.5px;text-transform:uppercase;letter-spacing:.5px;margin-bottom:2px;}
  #wlesson .wtopic p{margin:0;font-size:20px;line-height:1.4;font-weight:800;color:var(--ink);}
  #wlesson .wpage-side .wtopic{margin:8px 0 0;padding:14px 18px 16px;}
  #wlesson .wpage-side .wtopic p{font-size:24px;line-height:1.35;}
  /* PLANNING (`plan`): one short box per part of the plan, its name in red at the left, a tick at the right */
  #wlesson .wplan{display:flex;flex-direction:column;gap:6px;margin:0 0 2px;}
  #wlesson .wplan-row{display:flex;align-items:center;gap:10px;}
  #wlesson .wplan-k{flex:0 0 var(--wk,68px);font-size:15px;letter-spacing:.02em;}
  #wlesson .wplan-in{flex:1 1 0;min-width:0;height:38px;border:2px solid #e2d0ff;border-radius:12px;padding:0 12px;
    font-family:inherit;font-size:16.5px;font-weight:600;color:var(--ink);background:#fff;
    /* the app's global input[type=text] is a big centred answer box: undo what it sets */
    width:auto;margin:0;text-align:left;letter-spacing:0;}
  #wlesson .wplan-in::placeholder{color:#9a8fb5;font-weight:500;}
  #wlesson .wplan-in:focus{outline:none;border-color:var(--purple);}
  #wlesson .wplan-tick{flex:0 0 24px;height:24px;border-radius:50%;border:2px solid #e2d0ff;background:#fff;color:#fff;
    font:800 15px/20px Fredoka,"Baloo 2",sans-serif;text-align:center;}
  #wlesson .wplan-row.on .wplan-tick{background:var(--green);border-color:var(--green-dark);}
  #wlesson .wplan-row.on .wplan-tick::after{content:"\2713";}
  #wlesson .wplan-row.on .wplan-in{border-color:var(--green);background:var(--green-soft);}
  #wlesson .wplan-nav{display:flex;align-items:center;justify-content:space-between;gap:12px;margin:6px 0 0;}
  #wlesson .wplan-fb{font-size:15px;font-weight:700;color:var(--red);}
  #wlesson .wplan-fb.ok{color:var(--green-dark);}
  @media (max-width:600px){ #wlesson .wplan-k{flex-basis:58px;font-size:13.5px;} #wlesson .wplan-nav{flex-direction:column;align-items:stretch;} }
  /* the example plan (`planExample`, 2026-10-03): one green note BESIDE each of the child's own boxes, so showing
     it never makes the page taller; under the box on a phone */
  #wlesson .wplan.is-ex .wplan-w{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:12px;align-items:center;}
  #wlesson .wplan-ex{margin:0;font-size:15px;line-height:1.25;font-weight:700;color:var(--green-dark);}
  @media (max-width:600px){ #wlesson .wplan.is-ex .wplan-w{display:block;} #wlesson .wplan-ex{margin:2px 0 4px var(--wk,68px);font-size:14px;} }
  /* an example-only "Your turn" (`write.exampleOnly`): no goals, one example after a try */
  #wlesson .wpw-ex .wpw-nav{margin-top:10px;}
  #wlesson .wpw-ex-note{margin:6px 2px 0;font-size:15px;font-weight:600;color:var(--muted);}
  /* lg: the example sentences bigger than the paragraph round them (2026-10-03); --wlg on a crowded page */
  #wlesson .wcard-lg .wcard-text{font-size:var(--wlg,20px);font-weight:800;line-height:1.22;color:#1f1838;}
  #wlesson .wcard-lg .wcard-text .hl{background:#ffe08a;padding:0 5px;}
  #wlesson .wcard-lg .wcard-lgq{gap:1px;}
  #wlesson .wcard-lgq .wcard-foot .wq-words{margin-left:auto;}
  /* `picturesSide`: the row of line pictures beside the paragraph (2026-10-03) */
  #wlesson .wpage-side-row .wpage-pics{flex:0 0 auto;margin:0;}
  #wlesson .wpage-side-row .gdef{margin-bottom:0;}
  /* `pictureSide:"cards"`: the picture beside the example sentences (2026-10-03) */
  #wlesson .wpage-side-cards{align-items:center;gap:14px;margin:6px 0 8px;}
  #wlesson .wpage-side-cards .ph-cards{margin:0;}
  #wlesson .wpage-side-col{flex:0 0 auto;display:flex;flex-direction:column;align-items:stretch;gap:8px;}
  #wlesson .wpage-side-col .wpage-pic{margin:0 auto;}
  #wlesson .wpage-side-col .gtip{margin:0;font-size:14.5px;padding:8px 12px;}
  #wlesson .wpage-side-note{margin:0;font-size:16px;line-height:1.4;color:var(--ink);text-align:center;}
  /* `pictureSide:"float"` (2026-10-03): the picture top right, paragraph and sentences flow round it; a card is a
     flex box, so it narrows beside the float instead of running under it */
  #wlesson .wpage-float{float:right;margin:0 0 6px 14px;}
  #wlesson .wpage-float .wpage-pic{margin:0;}
  #wlesson .ph-cards.wcard-flow{display:block;}
  #wlesson .ph-cards.wcard-flow .ph-card{margin:0 0 6px;}
  /* `compact` cards (2026-10-03): chip + note on the sentence's own line when they fit */
  #wlesson .wcard-cmp{padding:5px 12px;}
  #wlesson .wcard-cmp-foot{display:inline-flex;align-items:center;gap:6px;margin-left:6px;vertical-align:1px;white-space:nowrap;}
  #wlesson .wcard-cmp-foot .wcard-note{font-size:13px;}
  #wlesson .wpage-float ~ .gdots, #wlesson .wpage-float ~ .gtip{clear:both;}
  /* a picture BESIDE its paragraph may be large (user review 2026-10-01: "para on left and graphic on right ...
     more visible and bigger"); on a phone it goes under the paragraph at its phone size */
  @media (max-width:600px){ #wlesson .wpage-side .wpage-pic svg{width:min(100%,260px);} }
  .wcard.has-q .wq-ico{width:25px;height:25px;}
  /* Narrative menu BY LEVEL (2026-09-30): level tabs, the level bar, the four part cards, Linking Ideas */
  .wlv-block{--lvc:#2f8f5b;--lvs:#e8f5ee;margin:4px 0 14px;}
  .wlv-block .lv-easy{--lvc:#2f8f5b;--lvs:#e8f5ee;}
  .wlv-block .lv-medium{--lvc:#b07b0c;--lvs:#fdf4e1;}
  .wlv-block .lv-hard{--lvc:#c0473a;--lvs:#fbe9e6;}
  .wlv-tabs{display:flex;gap:8px;margin:0 0 10px;}
  .wlv-tab{flex:1;min-width:0;text-align:left;background:#fff;border:2px solid #eadfce;border-radius:14px;padding:8px 12px;font:inherit;cursor:pointer;}
  .wlv-tab b{display:flex;align-items:center;gap:6px;font-size:16.5px;color:var(--lvc);}
  .wlv-tab span{display:block;font-size:12.5px;color:#6b6178;font-weight:600;}
  .wlv-tab.on{border:3px solid var(--lvc);background:var(--lvs);padding:7px 11px;}
  .wlv-dot{width:10px;height:10px;border-radius:50%;background:var(--lvc);display:inline-block;flex:none;}
  .wlv-bar{display:flex;justify-content:space-between;align-items:center;gap:10px;background:var(--lvs);border-radius:14px;padding:9px 14px;margin:0 0 10px;font-size:15px;color:#2b2342;}
  .wlv-bar b{color:var(--lvc);}
  .wlv-story{font-size:13px;color:#6b6178;text-align:right;max-width:48%;}
  .wlv-grid{display:grid;grid-template-columns:1fr 1fr;gap:10px;}
  .wlv-card{display:flex;flex-direction:column;gap:3px;text-align:left;background:#fff;border:2px solid #eadfce;border-radius:16px;padding:11px 14px;font:inherit;cursor:pointer;}
  .wlv-card:hover{border-color:var(--lvc);}
  .wlv-h{display:flex;align-items:center;gap:8px;}
  .wlv-num{flex:none;width:26px;height:26px;border-radius:50%;background:var(--lvc);color:#fff;font-weight:800;font-size:14px;display:inline-flex;align-items:center;justify-content:center;}
  .wlv-name{font-weight:800;font-size:16.5px;color:#2b2342;}
  .wlv-job{font-size:13.5px;font-weight:700;color:#4b416a;}
  .wlv-beat{font-size:13px;color:#7a7088;}
  .wlv-ft{display:flex;justify-content:space-between;align-items:center;gap:8px;margin-top:5px;}
  .wlv-go{font-size:13px;font-weight:800;padding:5px 12px;border-radius:999px;background:var(--lvc);color:#fff;white-space:nowrap;}
  .wlv-extra{margin-top:10px;width:100%;box-sizing:border-box;display:flex;justify-content:space-between;align-items:center;}
  .wlv-at{font-weight:600;color:#6b6178;}
  @media (max-width:640px){
    .wlv-grid{grid-template-columns:1fr;}
    .wlv-story{display:none;}
    .wlv-tab{padding:7px 8px;}.wlv-tab.on{padding:6px 7px;}
    .wlv-tab span{font-size:11.5px;}
  }
  /* Writing menu, Powerful Words drawer: two lessons to a line (user 2026-10-02, "to save space"). The name
     may wrap onto a second line; the "3/12 words" count gives its room to the name. */
  .wmenu-rows.wmenu-rows-2{display:grid;grid-template-columns:1fr 1fr;gap:10px;}
  #wmenu-list .wmenu-rows-2 .wmenu-row{min-width:0;height:100%;}
  #wmenu-list .wmenu-rows-2 .wmenu-row .gsub-name{font-size:16px;line-height:1.25;}
  #wmenu-list .wmenu-rows-2 .wmenu-row .gsub-meta{gap:6px;}
  @media (max-width:640px){ .wmenu-rows.wmenu-rows-2{grid-template-columns:1fr;} }
  /* Powerful Words example pages: three pairs of sentences, plain on the left and powerful on the right,
     under two small headings (a page's `cardHeads`) */
  #wlesson .wcard-heads{display:grid;grid-template-columns:1fr 1fr;gap:12px;margin:10px 0 0;}
  #wlesson .wcard-heads span{font-size:12.5px;font-weight:800;letter-spacing:.4px;text-transform:uppercase;color:#6b6178;padding:0 4px;}
  #wlesson .wcard-heads span + span{color:var(--green-dark);}
  #wlesson .ph-cards.wcard-pairs{grid-template-columns:1fr 1fr;gap:8px 12px;margin:5px 0 10px;}
  #wlesson .wcard-pairs .ph-card{padding:9px 14px;}
  #wlesson .wcard-pairs .ph-card:nth-child(odd){background:#f6f3fb;}
  #wlesson .wcard-pairs .ph-card:nth-child(even){border:2px solid #cdbdf2;background:#f3ecff;padding:7px 12px;}
  #wlesson .wcard-pairs .wcard-text{font-size:17.5px;line-height:1.32;}
  #wlesson .wcard-pairs .ph-card:nth-child(odd) .wcard-text{font-weight:600;color:#4b416a;}
  #wlesson .wcard-pairs .wcard-text .hl{background:#ffe08a;padding:0 5px;}
  @media (max-width:560px){
    #wlesson .wcard-heads{display:none;}
    #wlesson .ph-cards.wcard-pairs{grid-template-columns:1fr;gap:6px;}
    #wlesson .wcard-pairs .ph-card:nth-child(even){margin-bottom:8px;}
  }
  /* The typed word quiz that ends a Powerful Words lesson (js/07, WORD QUIZ) */
  .wswap-s{margin:2px 0 10px;font-size:23px;font-weight:800;line-height:1.35;color:#1f1838;}
  .wswap-s .hl{background:#ffe08a;border-radius:7px;padding:0 6px;}
  .wswap-s.is-right .hl{background:var(--green-soft,#e7f7ee);color:var(--green-dark);box-shadow:inset 0 0 0 2px var(--green);}
  .wswap-s.is-shown .hl{background:#fff;box-shadow:inset 0 0 0 2px var(--purple);color:var(--purple-dark);}
  .wswap-ask{margin:0 0 10px;font-size:17px;font-weight:600;color:var(--ink);}
  .wswap-ask b{font-weight:800;color:var(--purple-dark);}
  .wswap-hint{margin:0 0 14px;}
  .wswap-row{display:flex;gap:10px;align-items:center;}
  /* the app's global input[type=text] is a big centred answer box with a bottom margin: keep the look, fit the row */
  .wswap-row input[type=text].wswap-in{flex:1 1 0;min-width:0;margin:0;padding:10px 14px;font-size:24px;letter-spacing:1px;border-color:#cdbdf2;}
  .wswap-row input[type=text].wswap-in:focus{border-color:var(--purple);}
  .wswap-row input[type=text].wswap-in.is-right{border-color:var(--green);background:var(--green-soft,#e7f7ee);color:var(--green-dark);}
  .wswap-row input[type=text].wswap-in.is-wrong{border-color:#e2d0ff;background:#f6f3fb;color:#6b6178;}
  /* a REWRITE question (Similes): the child types a whole sentence, so the box reads like writing, not like one answer word */
  .wswap-row input[type=text].wswap-in.wswap-long{font-family:inherit;font-size:19px;font-weight:700;letter-spacing:0;text-align:left;padding:12px 14px;}
  .wswap-model{display:block;margin-top:8px;font-size:18px;font-weight:800;color:#1f1838;}
  .wswap-model-l{display:block;font-size:12px;font-weight:800;letter-spacing:.4px;text-transform:uppercase;color:#6b6178;margin-bottom:2px;}
  .wswap-model .hl{background:#ffe08a;border-radius:6px;padding:0 5px;}
  .wswap-row .gq-check{flex:none;min-width:120px;}
  .wswap-fb{margin-top:12px;background:#f6f3fb;}
  /* THE TASK ON THE FULL SCREEN (js/07 renderWTaskFull, user review 2026-10-02): the writing box on the left, the
     five plan boxes on the right. skin.css caps every screen at 820px with (2,2,0); this has to out-rank it. */
  .app > #screen-wquiz.wtp-full:not(#_):not(#__){max-width:none;}
  #wquiz-body .gq-card.wtp{padding:12px 18px 14px;}
  .wtp-head{display:flex;align-items:center;justify-content:space-between;gap:10px;margin:0 0 8px;}
  .wtp-head .gnav-btn.small{margin:0;padding:4px 12px;font-size:13px;min-height:0;}
  .wtp-topic{background:#fff7e6;border:2px solid #f3d99a;border-radius:16px;padding:6px 14px 8px;margin:0 0 10px;}
  .wtp-topic-l{display:block;font-weight:800;color:#8a5a00;font-size:11.5px;text-transform:uppercase;letter-spacing:.5px;margin-bottom:1px;}
  .wtp-topic-t{margin:0;font-size:19px;line-height:1.35;font-weight:800;color:var(--ink);}
  .wtp-prompt{margin:2px 0 0;font-size:15px;line-height:1.4;font-weight:600;color:var(--ink);}
  .wtp-cols{display:grid;grid-template-columns:minmax(0,3fr) minmax(0,2fr);gap:16px;align-items:stretch;}
  .wtp-write{display:flex;flex-direction:column;min-width:0;}
  .wtp-lab{display:flex;align-items:baseline;justify-content:space-between;gap:10px;margin:0 0 5px;}
  .wtp-lab>span:first-child{font-weight:800;color:var(--purple-dark,#4c2a9a);font-size:12.5px;text-transform:uppercase;letter-spacing:.5px;}
  .wtp-lab .wcount{margin:0;font-size:13px;}
  .wtp-note{font-size:12.5px;font-weight:600;color:var(--muted);}
  .wtp-write .wstarter{margin:0 0 8px;}
  /* its height is set by wTaskFit: whatever the screen has left */
  .wtp-write .wtextarea{flex:1 1 auto;min-height:170px;font-size:17px;line-height:1.6;resize:none;}
  .wtp-write .wwords{margin:8px 0 0;padding:7px 12px 9px;}
  .wtp-write .wwords-label{margin-bottom:4px;}
  .wtp-write .wwords-row{gap:6px;}
  .wtp-write .wword-chip{font-size:13px;padding:4px 10px;}
  .wtp-write .wtask-nav{margin-top:8px;}
  .wtp-write .wtask-nav .gnav-btn{padding:9px 20px;min-height:0;}
  .wtp-side{display:flex;flex-direction:column;gap:8px;min-width:0;}
  .wtp-plan{background:#f6f1ff;border:2px solid #e2d0ff;border-radius:16px;padding:8px 12px 10px;}
  .wtp-row{display:block;margin:0 0 5px;}
  .wtp-row:last-child{margin-bottom:0;}
  .wtp-k{display:flex;align-items:baseline;gap:7px;margin:0 0 1px;font-size:12px;font-weight:600;color:#6b5f8a;line-height:1.3;}
  .wtp-k b{font-size:14px;letter-spacing:.03em;}
  /* the app's global input[type=text] is a big centred answer box: undo what it sets */
  #wquiz-body .wtp input.wtp-in{display:block;width:100%;height:34px;border:2px solid #e2d0ff;border-radius:12px;padding:0 12px;box-shadow:none;
    font-family:inherit;font-size:15.5px;font-weight:600;color:var(--ink);background:#fff;margin:0;text-align:left;letter-spacing:0;box-sizing:border-box;}
  #wquiz-body .wtp input.wtp-in:focus{outline:none;border-color:var(--purple);}
  #wquiz-body .wtp input.wtp-in.has{border-color:var(--green);background:var(--green-soft);}
  .wtp-side .wgoals,.wtp-side .wclues{margin:0;}
  .wtp-side .wclues-dd:not(.open) ul{display:none;}
  .wtp-side .wclues-dd.open .ggroup-chev{transform:rotate(180deg);}
  .wtp-side .wclues-dd .wclues-label{margin-bottom:0;}
  .wtp-side .wclues-dd ul{margin-top:6px;}
  .wtp #wfeedback:not(:empty){margin-top:14px;}
  @media (max-width:760px){ .wtp-cols{grid-template-columns:1fr;} .wtp-side{order:-1;} .wtp-head{flex-wrap:wrap;} }
  /* The job box in a story part's page header (2026-10-03): the jobs the page teaches red, the rest grey. The
     negative margin keeps the header row its own height, so no page grows. */
  .wjobs{display:inline-flex;align-items:center;gap:4px;padding:3px;border:1.5px solid var(--line,#e2dccf);border-radius:12px;background:#fbf8f2;margin:-6px auto;}
  .wjob{font-weight:800;font-size:13px;line-height:1;padding:6px 11px;border-radius:9px;color:#a8a29a;letter-spacing:.01em;white-space:nowrap;}
  .wjob.on{color:#fff;background:var(--red);box-shadow:0 1px 2px rgba(0,0,0,.15);}
  @media (max-width:520px){ .wjobs{margin:0;gap:2px;} .wjob{font-size:11.5px;padding:5px 7px;} }
