/* =============================================================================
   Atlas Academy — Design Tokens  ·  FINAL  ·  "ATLAS BRAND 2026-07"
   -----------------------------------------------------------------------------
   Offline, voice-first tutor. $100 Android, 720p TN panel, sunlight, old WebView,
   2-4GB RAM. Children 5-10, leveled by SKILL not age.

   Founder-approved register, 2026-07-26. The board this file systematizes is
   design/brand-2026-07/BRAND.md + its reference sheet.

   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   MIGRATION NOTE  —  read this before you re-skin anything
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   This REPLACES "Modern-Bright Expedition" (warm clay + teal + gold on warm
   paper, Rubik). That register was approved 2026-07-24 and is retired 2026-07-26
   by founder direction: the brand board at design/brand-2026-07/ was promoted
   from candidate direction to THE register.

   1. VALUES CHANGED, SEMANTIC NAMES STABLE. Every name that resolved before
      still resolves — 177 of them, checked. `--brand --accent-cool --correct
      --reward --ink --paper --card --hair --hairline --radius --text-* --tap-*
      --font-* --ease-* --lip-*` and the whole §WORLD art set keep their names.
      No property-name find-and-replace. Re-render and re-screenshot.

      Retired REGISTER names are ALIASED, not deleted: `--clay*` now points at
      the teal family and `--gold*` at the amber family, so nothing breaks while
      consumers migrate. See §RETIRED ALIASES.

   2. 🔴 THE ONE BREAKING PAIRING — a white mark on a bright fill.
      Measured, this register, sRGB:
          white on --teal    2.20:1     white on --amber   1.63:1
          white on --pink    3.82:1     white on --violet  4.20:1
      All four are BELOW the 4.5:1 floor; two are catastrophically below. The
      previous register's brights were dark enough to carry white (white on the
      old clay was 4.6:1), so `color:#fff` on a coloured fill was safe there and
      is NOT safe here. It appears in design/v2/final/ (e.g. lesson-hint-retry
      and pack-manager put `color:#fff` on `var(--teal)`).

      THE FIX IS MECHANICAL: on a bright fill the mark is NAVY, not white.
          navy on --teal 8.64  ·  --amber 11.66  ·  --pink 4.98  ·  --violet 4.52
      Two new names exist for exactly this, so the reskin is find-and-replace:
          --on-bright   (navy)  → any mark sitting on teal/amber/pink/violet
          --on-dark     (white) → any mark sitting on navy or violet-deep
      Replace `color:#fff` with `color: var(--on-bright)` wherever the ground is
      a bright, and with `var(--on-dark)` wherever the ground is navy.

   3. 🔴 THE SECOND BREAKING PAIRING — `--teal` is now a FILL, never text.
      Old `--teal` was #0e7c6b (a dark teal, text-safe on paper). New `--teal` is
      #00C4B3 and measures 2.00:1 on paper — invisible as text. Same for
      `--amber` at 1.48:1. If you need a bright AS TEXT on a light surface, use
      the `-deep` member (`--teal-deep` 6.00:1, `--amber-deep` 5.03:1,
      `--pink-deep` 6.75:1, `--violet-deep` 8.67:1) — or better, the semantic
      text names, which already point there: `--brand-text --correct-text
      --accent-cool-text`.

   4. NEW — TWO SURFACES, ONE REGISTER (§SURFACE). Navy for brand / home /
      chrome / adult surfaces; light for the lesson surface where a child reads
      numerals. `--paper` STAYS LIGHT, so every existing `--ink` on `--paper`
      consumer is untouched. The dark surface is opt-in and inherits:
          <div data-surface="navy"> … everything inside is on the dark register …
      Inside that subtree the SAME semantic names re-point (paper→navy,
      ink→white, card→navy-raised, hair→navy-hair). A component written once
      against the semantic names renders correctly on both surfaces with no
      branch. `data-surface="violet"` does the same for the violet ground.

   5. FONT — Rubik is gone; POPPINS is the family, per the board. It is BUNDLED
      here (§FONT), not linked: three subset woff2 files totalling 23,488 bytes
      in design/fonts/. `--font-journal` (the long-dead serif alias) still
      resolves. Poppins ships 100-900 but the board specifies THREE weights, so
      we bundle THREE — see §TYPOGRAPHY for what that does to --weight-heavy
      and --weight-black, because it is not nothing.

   6. THE PRESSABLE LIP SURVIVES, deliberately. The board is a flat marketing
      system and has no 3D lip anywhere. We keep it in the PRODUCT because it is
      the only wordless "this is pressable" affordance we have, and because a
      blur test already caught a decorative mark and a real button reading as
      the same object. Flat brand, lipped controls. Depths are UNCHANGED (3/4/5/
      6/7) so nothing shifts by a pixel.

   CONSTRAINTS BAKED IN (all carry over unchanged)
   -----------------------------------------------
   - Sunlight + TN panel => luminance contrast is FUNCTIONAL. Every pairing in
     this file is measured, not eyeballed; the table is at the bottom.
   - Colour is NEVER the sole signal. Pair with icon + shape + position + voice.
   - Motion is transform + opacity ONLY. Never animate shadow/filter/width/
     height/top/left in a hot path. Honour prefers-reduced-motion. 30fps cap,
     shedding to 15 at thermal MODERATE — a better phone gets the same product.
   - ONE bundled font, and the app must render truthfully if the webfont is
     absent (system-ui fallback in every stack below).
   - Tap floor 48px, and ≥2cm with generous spacing for the child's primary
     targets. BUG-7 is open on this — read it before you touch --tap-*.
   ========================================================================== */

/* ===========================================================================
   §FONT — Poppins, bundled. The app is offline; there is no CDN in any path.
   ---------------------------------------------------------------------------
   LICENCE: SIL Open Font License 1.1. Verified 2026-07-26 against BOTH
   google/fonts `ofl/poppins/OFL.txt` ("Copyright 2020 The Poppins Project
   Authors (https://github.com/itfoundry/Poppins) … licensed under the SIL Open
   Font License, Version 1.1") and `ofl/poppins/METADATA.pb` (`license: "OFL"`).
   Full text committed at design/fonts/OFL.txt.

   NO RESERVED FONT NAME. The copyright line carries no RFN designation — the
   only occurrence of the phrase in the licence is its own definition clause —
   so our subset may keep the name "Poppins". OFL permits bundling inside a
   commercially sold application; it forbids selling the font by itself. That is
   resell-clean under constraint 4, on the same footing as Rubik, which this
   repo already ships under OFL at app/assets/fonts/OFL.txt.

   SUBSET: Latin + Spanish diacritics + Spanish punctuation. 217 cmap entries
   each; ¿ ¡ á é í ó ú ü ñ and their capitals verified present in all three
   files, 0-9 verified present. 7900 + 7740 + 7848 = 23,488 bytes total.

   `font-display: swap` is deliberate: a bundled local file resolves in one
   frame, and if the file is ever missing the child reads system-ui immediately
   instead of staring at nothing.

   `font-synthesis: none` on the root is NOT optional — see §TYPOGRAPHY.
   =========================================================================== */
@font-face {
  font-family: "Poppins";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("fonts/Poppins-400.woff2") format("woff2");
}
@font-face {
  font-family: "Poppins";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("fonts/Poppins-500.woff2") format("woff2");
}
@font-face {
  font-family: "Poppins";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("fonts/Poppins-700.woff2") format("woff2");
}

:root {
  /* ---------------------------------------------------------------------------
     1. REGISTER PRIMITIVES — verbatim from design/brand-2026-07/BRAND.md
        Navy carries roughly half the composition. The four brights are used
        ONE PER ELEMENT — never blended, never gradiented into each other.
        There is no fifth hue. Inventing one is a bug.
     ------------------------------------------------------------------------ */
  --navy:   #0D0B2E;   /* the primary ground. Deep indigo, near-black          */
  --teal:   #00C4B3;   /* primary accent — the through-line, progress, correct */
  --amber:  #FFC107;   /* reward — sellos, stars, earned stops. RATIONED       */
  --pink:   #E83E8C;   /* emphasis, and the gentle nudge                       */
  --violet: #7B61FF;   /* place — regions, territories, the world              */
  --paper:  #F2F4F7;   /* the LIGHT ground: the lesson surface                 */

  /* Derived members. Each bright gets exactly three: the bright (a FILL), a
     -deep (text-safe on light + the 3D lip), and a -tint (a light wash). */
  --navy-deep:   #07061E;  /* lip under a navy pressable                       */
  --navy-raised: #211D57;  /* a raised panel ON navy (white clears 15.24:1)    */
  --navy-hair:   #312C6B;  /* hairline / divider on navy                       */

  --teal-deep:   #00695C;  /* teal-as-text on light, 6.00:1 · and the teal lip */
  --teal-tint:   #D6F5F1;
  --amber-deep:  #8A6100;  /* amber-as-text on light, 5.03:1 · and the lip     */
  --amber-tint:  #FFF1CC;
  --pink-deep:   #A11B5B;  /* pink-as-text on light, 6.75:1 · and the lip      */
  --pink-tint:   #FCDDEB;
  --violet-deep: #412BB0;  /* ALSO a usable dark GROUND — white clears 9.56:1  */
  --violet-tint: #E5E0FF;

  /* Ink and surfaces on the LIGHT register. */
  --ink:      var(--navy);  /* every numeral / label / stroke. 17.26:1 on paper */
  --ink-soft: #535B6B;      /* secondary text — 6.19:1 on paper (AA+)           */
  --card:     #FFFFFF;      /* white cards — objects pop off paper              */
  --hair:     #DDE3EC;      /* hairline dividers / faint structure              */

  /* Ink on the DARK register. Named separately so a component can address both
     without a branch; §SURFACE swaps them in automatically. */
  --ink-on-dark:      #FFFFFF;  /* 19.01:1 on navy                              */
  --ink-soft-on-dark: #C3C7D6;  /* 11.28:1 on navy — secondary on dark          */

  /* 🔴 THE TWO NAMES THAT MAKE THE RESKIN MECHANICAL. Read migration note §2.
     A mark on a BRIGHT fill is navy. A mark on a DARK ground is white. There is
     no third answer, and `color:#fff` on a bright is always wrong here. */
  --on-bright: var(--ink);          /* teal 8.64 · amber 11.66 · pink 4.98 · violet 4.52 */
  --on-dark:   var(--ink-on-dark);  /* navy 19.01 · violet-deep 9.56             */

  --nudge: var(--pink);   /* the gentle miss. NEVER red, NEVER a buzzer.
                             Pink because it is the only bright not already
                             carrying a state (teal=correct, amber=earned,
                             violet=place). It is NEVER the sole signal — the
                             voice says "Casi." and the manipulative re-counts.  */

  --ui: "Poppins", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;

  /* ---------------------------------------------------------------------------
     2. SEMANTIC ALIASES  (stable names — what 135 files import)
        The old vocabulary, re-pointed at the new register. Nothing renamed.
     ------------------------------------------------------------------------ */
  --paper-raised:     var(--card);
  --hairline:         var(--hair);

  --brand:            var(--teal);        /* the "Atlas" through-line           */
  --brand-deep:       var(--teal-deep);
  --brand-text:       var(--teal-deep);   /* 6.00:1 on paper — safe as text     */
  --brand-tint:       var(--teal-tint);

  /* --accent-cool was teal (the credible/professional anchor). In this register
     NAVY is that anchor — it is the chrome, the parent surface, the brand
     ground. The MEANING is unchanged; only the hue moved. */
  --accent-cool:      var(--navy);
  --accent-cool-deep: var(--navy-deep);
  --accent-cool-text: var(--navy);        /* 17.26:1 on paper                   */

  --correct:          var(--teal);        /* success / mastered                 */
  --correct-text:     var(--teal-deep);
  --reward:           var(--amber);       /* sellos, stars — earned, rationed   */
  --reward-deep:      var(--amber-deep);

  /* Interactive surfaces */
  --choice-bg:        var(--card);
  --choice-ink:       var(--ink);         /* CHANGED: was --clay. A teal numeral
                                             on a white tile is 2.20:1. The
                                             answer numeral is navy, 19.01:1.   */
  --choice-selected:  var(--teal);
  --drop-zone:        #E4E9F1;            /* neutral cool target for drag zones */

  /* Decorative slot colours for a row of answer tiles — see DESIGN-SPEC §5.
     Keyed to POSITION (slot 1/2/3), identical on every item forever, so they
     carry ZERO information. They colour the tile's LIP, never its face, because
     the face is what feedback recolours. */
  --slot-1: var(--teal);
  --slot-2: var(--amber);
  --slot-3: var(--pink);

  /* Fonts (stable names → Poppins). No serif voice in this register.           */
  --font-ui:      var(--ui);
  --font-display: var(--ui);
  --font-num:     var(--ui);
  --font-journal: var(--ui);              /* DEPRECATED alias — was the serif   */

  /* ---------------------------------------------------------------------------
     §RETIRED ALIASES — the previous register's RAW names, kept resolving.
        `--clay*` and `--gold*` name hues that no longer exist. They are aliased
        rather than deleted so no consumer shows a hole mid-migration. Migrate to
        the name on the right when you touch a rule; we delete this block by
        agreement once the consumer sweep reports zero.
     ------------------------------------------------------------------------ */
  --clay:      var(--teal);         /* was the dominant hue → teal is now that  */
  --clay-deep: var(--teal-deep);
  --clay-tint: var(--teal-tint);
  --gold:      var(--amber);
  --gold-deep: var(--amber-deep);

  /* Region / roster tints — four identity washes, one per bright. IDENTITY BY
     POSITION, never state. A theme reskins all four together. */
  --tint-highland: var(--teal-tint);
  --tint-clay:     var(--amber-tint);
  --tint-valley:   var(--violet-tint);
  --tint-river:    var(--pink-tint);

  /* ---------------------------------------------------------------------------
     3. THE SKETCHIE ICON BRIDGE
        The bundled SVG pack (viewBox 0 0 96 96, flat fills under ink) reads
        these four vars. Setting them here puts the WHOLE library on-register.
        The board draws each feature icon in ONE bright (teal / amber / pink /
        violet); an authoring layer sets --sk-c1 per icon to do that.
     ------------------------------------------------------------------------ */
  --sk-ink:   var(--ink);          /* icon outline stroke                       */
  --sk-paper: var(--card);         /* CHROME icon interior — white, pops off paper */
  --sk-c1:    var(--teal);         /* icon primary region                       */
  --sk-c2:    var(--violet);       /* icon secondary region                     */

  /* SPECIMEN PALETTE — a counting object is NOT a chrome icon.
     A chrome icon wants a white interior so it pops off paper. A counting object
     wants a SATURATED BODY: the child counts the THING, and a white-bodied apple
     on a white tray is the palest, least countable version of it. Retuned to the
     board's green apple. An authoring layer overrides these PER OBJECT (a ball
     sets --specimen-body blue, etc). Deliberately NOT themeable — see §WORLD. */
  --specimen-body:   #8BC34A;      /* object body — saturated, never --card     */
  --specimen-ink:    #4A7C1F;      /* its outline                               */
  --specimen-accent: #558B2F;      /* leaf / secondary part                     */
  --specimen-stem:   #7A5600;      /* stem / stalk                              */

  /* ---------------------------------------------------------------------------
     4. TYPOGRAPHY  —  Poppins. Sizes UNCHANGED from the previous register.
        Scale is stable so no consumer relayouts; only the family moved.
        "guided" (default) is the base; scaffold rescales --text-numeral /
        --text-display / --text-body only.

        🔴 WEIGHTS: we bundle THREE files (400/500/700), per the board. Poppins
        publishes 100-900, but a weight we do not ship gets SYNTHESISED by the
        engine — a faux-bold that thickens strokes unpredictably and smears on a
        720p TN panel, which is the exact surface we are protecting. So
        --weight-heavy and --weight-black now BOTH resolve to 700 (they were 800
        and 900). Their names survive; their differentiation does not.
        HIERARCHY IS CARRIED BY SIZE AND TRACKING, which is how the brand board
        itself does it — nothing on that sheet steps by weight above Bold.
        Set `font-synthesis: none` so a missing weight fails visibly rather than
        silently smearing. If the hero numeral turns out to need more weight,
        adding Poppins ExtraBold 800 costs ~8 KB — decide that by LOOKING at a
        real 720p panel in sun, not from the source.
     ------------------------------------------------------------------------ */
  --text-caption: 13px;  /* parent-report fine print / adult register          */
  --text-micro:   11px;  /* eyebrow caps ("MI ATLAS"), map legends             */
  --text-label:   15px;  /* labels, sub-instructions, region sub               */
  --text-body:    18px;  /* secondary instruction ("Cuenta las manzanas.")     */
  --text-title:   20px;  /* header name, region name                          */
  --text-display: 38px;  /* screen headline / prompt ("¿Cuántos hay?")        */
  --text-numeral: 64px;  /* the big answer numerals — the arithmetic itself    */

  --weight-reg:   400;   /* NEW — long-form / adult body (Poppins Regular)      */
  --weight-med:   500;   /* UI body (Poppins Medium)                           */
  --weight-semi:  500;   /* labels / secondary — same face, see note above     */
  --weight-bold:  700;   /* sub-headings                                       */
  --weight-heavy: 700;   /* headings / names / numerals  (was 800)             */
  --weight-black: 700;   /* hero numeral / current-stop numeral  (was 900)     */
  --leading-tight: 1.05;
  --leading-body:  1.4;
  --tracking-caps: 0.22em;  /* eyebrow small-caps ("MI ATLAS", "REGIÓN 3 DE 4") */
  --tracking-wordmark: 0.34em; /* NEW — the "ACADEMY" lockup under the wordmark */

  /* ---------------------------------------------------------------------------
     5. SPACING & LAYOUT   (8px base; roomy — clutter is illegible in sunlight)
     ------------------------------------------------------------------------ */
  --space-1: 4px;   --space-2: 8px;   --space-3: 12px;  --space-4: 16px;
  --space-5: 24px;  --space-6: 32px;  --space-7: 48px;  --space-8: 64px;
  --gutter:  20px;        /* screen edge padding                                */
  --viewport-max: 480px;  /* clamp on larger screens; designed at 360           */

  /* ---------------------------------------------------------------------------
     6. TAP TARGETS   (the #1 usability lever for small hands + washed panels)
        FUNCTIONAL (scaffold-driven), never an age aesthetic. Floor 48px.
        ⚠️ BUG-7 is OPEN on the ≥2cm requirement. 2cm ≈ 76px at a typical
        360-CSS-px phone's density, so --tap 88 and --tap-primary 104 clear it
        and --tap-icon 64 does NOT. That is a real gap, it is unchanged by this
        register, and it is not design's to close silently — see the WI.
     ------------------------------------------------------------------------ */
  --tap-min:     48px;    /* NEVER smaller than this, any scaffold              */
  --tap:         88px;    /* default primary target (guided)                    */
  --tap-primary: 104px;   /* the main answer choices (guided)                   */
  --tap-icon:    64px;    /* secondary icon buttons (replay/audio/back)         */
  --tap-gap:     20px;    /* min space between two targets (fat-finger guard)   */
  --choice-max-w: 150px;  /* max width of ONE answer/choice card                */
  --manip-size:   74px;   /* a drawn manipulative / count object                */
  --manip-size-compare: 48px; /* smaller object when two groups share one card  */
  --replay-size: 60px;    /* the always-present replay control                  */

  /* ---------------------------------------------------------------------------
     7. RADII & OUTLINE  —  confident MEDIUM rounding (no maximal baby-rounding)
        Unchanged. The board's rounded-square swatches, app icon and answer
        chips sit in this same range.
     ------------------------------------------------------------------------ */
  --radius-sm:   14px;
  --radius:      16px;    /* confident medium — the base                        */
  --radius-lg:   20px;    /* cards / header                                     */
  --radius-xl:   22px;    /* answer choices                                     */
  --radius-2xl:  26px;    /* the specimen tray                                  */
  --radius-pill: 999px;
  --radius-phone: 34px;   /* device frame in the mockups                        */
  --outline-w:      3px;  /* the ONE uniform ink edge (icons, specimens)        */
  --outline-w-bold: 4px;  /* hero objects                                       */

  /* ---------------------------------------------------------------------------
     8. PRESSABLE  —  the chunky 3D bottom lip. KEPT, deliberately (note §6).
        Every primary control sits on a solid bottom-lip box-shadow of its own
        DEEP colour. On :active it translates DOWN by the lip depth and the lip
        collapses:
          .btn        { box-shadow: 0 var(--lip) 0 var(--teal-deep), <ambient>; }
          .btn:active { transform: translateY(var(--lip)); box-shadow: 0 0 0 var(--teal-deep); }
        White pressables (answer tiles) use --card-lip + an inset hairline.
        Measured lip steps (fill vs its lip): teal 3.01 · amber 3.40 · pink 1.95
        · violet 2.27 — all visible on a washed panel.
     ------------------------------------------------------------------------ */
  --lip-sm:      3px;     /* small chips (avatar, stamp count)                  */
  --lip:         4px;     /* icon buttons (audio, replay)                       */
  --lip-md:      5px;     /* banners (region), locked nodes                     */
  --lip-lg:      6px;     /* done nodes (amber)                                 */
  --lip-primary: 7px;     /* answer tiles, the current stop                     */
  --card-lip:      #C2C9D6;  /* the cool bottom edge under white pressables     */
  --card-hair-inset: #E2E7EF;/* inset hairline on white pressables              */
  --teal-lip:      #A9E5DE;  /* bottom edge under a teal-TINT (quiet) button    */
  --press: transform .1s ease, box-shadow .1s ease; /* the press transition     */

  /* Ambient shadows (soft weight under floating cards — decorative, not state).
     Retoned from warm brown to the navy the register actually casts. */
  --shadow-card:  0 6px 18px rgba(13,11,46,.14), 0 0 0 1px rgba(13,11,46,.06);
  --shadow-tray:  0 12px 26px rgba(13,11,46,.10);
  --shadow-lift:  0 12px 20px rgba(13,11,46,.22);

  /* ---------------------------------------------------------------------------
     9. MOTION   (transform + opacity ONLY; short; interruptible) — UNCHANGED.
        Calm is the DEFAULT. Routes DRAW on, stamps SNAP down. Exactly ONE
        reserved celebration spring (--ease-pop) — the stamp thunk.
     ------------------------------------------------------------------------ */
  --motion-fast:      150ms;
  --motion-base:      240ms;
  --motion-draw:      420ms;  /* a route drawing onto the map                   */
  --motion-celebrate: 480ms;  /* the one reserved summit beat                   */
  --pulse-dur:        2.2s;   /* the current-stop attention ring                */
  --ease-out:    cubic-bezier(0.22, 1, 0.36, 1);   /* calm settle (default)     */
  --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
  --ease-draw:   cubic-bezier(0.65, 0, 0.35, 1);    /* trail stroke draw-on     */
  --ease-stamp:  cubic-bezier(0.34, 1.4, 0.5, 1);   /* weighty stamp settle     */
  --ease-pop:    cubic-bezier(0.34, 1.56, 0.64, 1); /* RESERVED: celebration    */
  --motion-amp:  1;          /* scaffold multiplier for amplitude (calm base)   */

  /* ---------------------------------------------------------------------------
     10. LABEL VISIBILITY & GUIDE SIZE   (functional, scaffold-driven)
     ------------------------------------------------------------------------ */
  --label-display: block;    /* guided + independent show labels; full hides    */
  --guide-scale:   1;        /* size multiplier for the on-map guide figure      */

  /* ---------------------------------------------------------------------------
     11. BACK-COMPAT ALIASES for the SHIPPED player  (verified against player/)
        Not new design surface — they re-point old vocabulary at this register.
        NOTE: `--character-recede` is intentionally still GONE; use --guide-scale.
     ------------------------------------------------------------------------ */
  --replay-bg:      var(--teal);       /* the replay/audio control              */
  --replay-ink:     var(--on-bright);  /* CHANGED: was #fff. White on teal is
                                          2.20:1 — the glyph vanished in sun.
                                          Navy on teal is 8.64:1.               */
  --sticker-offset: var(--lip-lg);     /* old flat offset  → the pressable lip  */
  --sticker-color:  var(--card-lip);   /* old ink offset   → the register's lip */
  --tracking-head:  -0.01em;           /* headline/numeral optical tightening   */

  /* ===========================================================================
     §WORLD — flat-vector world tokens (THEMEABLE)
     Drive every SVG fill in the map/world off these. An alternate theme
     overrides ONLY this block + the register palette to reskin the entire
     platform with ZERO structural change.

     RETONED to the board's world language: the sheet's LatAm map is flat
     territory shapes in the brights on a light ground, joined by dashed
     connectors. So land is a TEAL TINT LADDER, water is the violet family, and
     🔴 THE TRAIL SPINE IS NAVY, not the brand hue. That is a deliberate change:
     in the previous register the trail was the dominant hue on green land and
     read at distance; here a teal trail on teal land would disappear. Navy on
     any tint clears 14.9-16.9:1 — unmissable in sunlight, and it is also the
     right SEMANTIC choice, because the trail is the curriculum spine and navy
     is this register's structural colour.
     =========================================================================== */
  --sky-top:    #E8F9F6;  --sky-bottom: #F2F4F7;   /* the airy sky              */
  --peak-far:   #B9BFD4;  --peak-near:  #9AA1BC;   /* cool distance (navy-tinted)*/
  --snow:       #FFFFFF;                            /* summit snow               */
  --cloud:      #FFFFFF;  --cloud-2:    #E9EEF6;    /* soft clouds               */
  --bird:       #8A93A5;                            /* distant birds             */
  --hill-1:     #D6F5F1;  --hill-2:     #B3EDE6;  --hill-3: #7FE0D5; /* land bands*/
  --hill-1-deep:#C4F0EA;  --hill-2-deep:#9BE5DC;   /* the depth edge on a band  */
  --hill-shade: var(--hill-2-deep);                 /* alias (kept for stability)*/
  --river:      #9E8CFF;  --river-deep: #7B61FF;  --river-hi: #C4B9FF;
  --hill-4:     #4FD8CA;                            /* deepest foreground band   */
  /* twilight variants (the hasta-mañana goodbye scene). Kept LIGHT-grounded on
     purpose: --ink sits on all three at ≥14.8:1, so a consumer that puts text
     on the goodbye scene does not break. A dark twilight is a screen decision,
     made with data-surface="navy", not a token change.                          */
  --dusk-top:   #FFE6A8;  --dusk-mid:   #FFD9E8;  --dusk-bottom: #E5E0FF;
  --sun:        #FFC107;  --dusk-cloud: #FFFFFF;  --dusk-bird:   #7B61FF;
  --dusk-peak-far: #B9AEE8;  --dusk-peak-near: #9A8AD6;
  --tree:       #00A695;  --tree-deep:  #00786D;  --tree-round: #00C4B3;
  --trunk:      #7A5600;  --tree-shadow:#00695C;
  --path:        var(--navy);        /* the traveled trail spine (see note)      */
  --path-edge:   #312C6B;            /* trail outer casing (a hair lighter)      */
  --path-ahead:  #C9D0DC;            /* dashed route to the horizon              */

  /* Map/UI state colors a THEME must also be able to move. Kept here (not in the
     register block) because they are scene-adjacent, not brand-semantic.        */
  --locked:      #DDE2EA;            /* a locked stop's disc                     */
  --locked-deep: #C2C9D6;            /* its 3D bottom lip                        */
  --locked-ink:  #737C8E;            /* the padlock glyph — 3.23:1 on its disc.
                                        Locked is signalled by the PADLOCK SHAPE
                                        and the absent lip; the low-contrast
                                        glyph is not carrying the message alone. */
  --lab-lip:     var(--card-lip);    /* lip under the current-stop label pill    */
  --stamp-bg:    var(--amber-tint);  /* the header star-count chip ground        */
  --stamp-ring:  #FFD866;            /* its inset ring                           */
  --av-grad:     #A99BFF;            /* avatar gradient light stop → --violet    */
  --region-sub:  var(--teal);        /* subtitle on the NAVY region banner.
                                        CHANGED: the banner ground moved teal →
                                        navy, so the subtitle moved to teal
                                        (8.64:1 on navy). Differentiate a
                                        subtitle by SIZE and WEIGHT, never by
                                        lowering contrast — a faded subtitle on
                                        a TN panel in sun is an absent subtitle. */

  /* THE GUIDE — the board's llama in a hoodie and headphones (founder direction).
     PLACEHOLDER TIER: the final character is named and face-validated WITH
     Peruvian children (PRD-0 §10), never chosen in a chat. Tokenized so the
     guide is ONE character on every screen and a theme can dress it. Never
     re-colour the guide inline.
     ⚠️ TENSION, FLAGGED NOT RESOLVED: the board places the llama on the greeting
     screen, i.e. on CHROME. Constraint 9 says the character is world-anchored
     and never on chrome. See DESIGN-SPEC §11 — this is a founder call, and the
     tokens support either placement.                                            */
  --guide-coat:      #7B61FF;  --guide-coat-deep: #5D45D6;   /* the hoodie      */
  --guide-skin:      #E9DCC6;                                /* llama fleece    */
  --guide-pants:     #412BB0;  --guide-pants-2:   #35218F;
  --guide-boot:      #0D0B2E;  --guide-boot-2:    #07061E;
  --guide-hat:       #00C4B3;  --guide-hat-2:     #00A695;  --guide-hat-band: #E83E8C;
  --guide-strap:     #FFC107;
  --guide-ink:       #0D0B2E;  --guide-mouth:     #E83E8C;
  --guide-shadow:    #A9B4C6;  /* neutral cool — reads as shadow on any light
                                  ground (was a green, tuned to green hills)     */
}

/* ===========================================================================
   §SURFACE — TWO GROUNDS, ONE REGISTER.
   ---------------------------------------------------------------------------
   Navy for brand / home / chrome / adult surfaces. LIGHT for the lesson surface
   where a child reads numerals. This is the board's own split: its home and
   greeting screens are dark, and its counting screen ("¿Cuántos hay?" with the
   apples and the 6/7/8 tiles) is on a LIGHT ground with dark text.

   ⚠️ THE REASON IS DESIGN REASONING, NOT MEASUREMENT. On a cheap TN panel in
   Andean sunlight a light surface should hold legibility better, because white
   pixels sit at maximum luminance against reflected glare while a dark surface
   competes with the reflection at the panel's weakest output. VOL-06 §6.1
   assumes sunlight use on a ~450-nit panel. But eval/budget/device-tiers.json
   states plainly: "No physical device of any tier has been tested." NOBODY HAS
   PUT ANY OF THIS IN THE SUN. Do not repeat this paragraph as a measurement.
   One low-end handset outdoors settles it in ten minutes.

   HOW IT WORKS: the same semantic names re-point inside the subtree, so a
   component written once renders on both grounds with no branch and no new
   class. Custom properties inherit, so this covers the whole subtree.

       <section data-surface="navy">   … dark chrome …
       <section data-surface="violet"> … the greeting / place surface …

   🔴 ON DARK, ELEVATION CANNOT BE A FILL STEP. --navy-raised is only 1.25:1
   against --navy, which is invisible on a washed panel. A raised panel on navy
   MUST be separated by --hair (1.54:1) or by its lip. This is the dark-surface
   equivalent of "never state-by-colour-alone".
   =========================================================================== */
[data-surface="navy"] {
  --paper:        var(--navy);
  --paper-raised: var(--navy-raised);
  --card:         var(--navy-raised);
  --hair:         var(--navy-hair);
  --hairline:     var(--navy-hair);
  --ink:          var(--ink-on-dark);
  --ink-soft:     var(--ink-soft-on-dark);
  --on-bright:    var(--navy);          /* a bright fill still takes a navy mark */
  /* Text-safe accents flip from the -deep members to the brights, because on
     navy the BRIGHT is the readable one and the deep one is not:
        teal 8.64 · amber 11.66 · pink 4.98   (deep members all fall under 4.5) */
  --brand-text:       var(--teal);
  --correct-text:     var(--teal);
  --accent-cool-text: var(--ink-on-dark);
  --choice-ink:       var(--ink-on-dark);
  --card-lip:         var(--navy-deep);
  --card-hair-inset:  var(--navy-hair);
  --drop-zone:        var(--navy-raised);
  --locked:           var(--navy-raised);
  --locked-deep:      var(--navy-deep);
  --locked-ink:       #7E86A8;
}

[data-surface="violet"] {
  --paper:        var(--violet-deep);   /* NOT --violet: see the note below      */
  --paper-raised: #4E36C9;
  --card:         #4E36C9;
  --hair:         #5D45D6;
  --hairline:     #5D45D6;
  --ink:          var(--ink-on-dark);   /* 9.56:1 on violet-deep                 */
  --ink-soft:     #D5CDFF;
  --on-bright:    var(--navy);
  --brand-text:       var(--teal);
  --correct-text:     var(--teal);
  --accent-cool-text: var(--ink-on-dark);
  --choice-ink:       var(--ink-on-dark);
  --card-lip:         #35218F;
  --card-hair-inset:  #5D45D6;
}
/* 🔴 WHY THE VIOLET GROUND IS --violet-deep AND NOT --violet.
   The board's greeting screen sets white text on #7B61FF. Measured, that is
   4.20:1 — BELOW the 4.5 floor, before any sunlight. #412BB0 carries white at
   9.56:1 and is the same hue. So --violet stays a FILL (icons, territories,
   the hoodie) and --violet-deep is the violet GROUND. This is the board being
   corrected by a number, not by taste. */

/* ===========================================================================
   §SPECIMEN CONTEXT — the icon bridge, remapped for counting objects.
   ---------------------------------------------------------------------------
   The bundled Sketchie pack draws every object body in --sk-paper. That is RIGHT
   for chrome (a white-bodied gear pops off paper) and WRONG for a manipulative:
   a white apple on a white tray is the palest, least countable version of it,
   and this is the most-seen surface in the product — a child meets specimens
   every single lesson.

   So we do NOT change --sk-paper globally (that would wash out every chrome
   icon). We scope it: inside a specimen context the SAME pack icon inherits a
   saturated body. No icon is hand-edited — 121 of them re-render for free.

     <span class="specimen"><svg>…pack icon…</svg></span>

   PER-OBJECT: an authoring layer overrides the four vars on the element, so a
   ball is blue and a leaf is green without touching the pack:
     <span class="specimen" style="--specimen-body:#3b82c4; --specimen-accent:#2a628f">

   Deliberately NOT themeable — a themed apple grows a blue leaf. See
   DESIGN-SPEC §11.
   =========================================================================== */
.specimen, .tray svg, [data-role="specimen"] {
  --sk-paper: var(--specimen-body);
  --sk-ink:   var(--specimen-ink);
  --sk-c1:    var(--specimen-accent);
  --sk-c2:    var(--specimen-stem);
}

/* ===========================================================================
   SCAFFOLD — the ONLY axis that changes with the child. FUNCTIONAL ONLY.
   Drive off SKILL / reading level (mastery engine + profile), never age.
   NOTHING here touches colour, art, radius, or outline — that is the whole point.

   full        = non-reader / earliest skill : biggest targets, NO text labels
                 (voice-only operation), largest numerals, guide a touch bigger.
   (default)   = guided : the :root values above. Large targets, labels on.
   independent = fluent reader / higher skill : standard targets, labels on,
                 slightly denser, smaller guide. Same look, less hand-holding.
   =========================================================================== */

/* full — most support */
[data-scaffold="full"] {
  --text-body:    20px;
  --text-display: 42px;
  --text-numeral: 72px;
  --tap:         112px;
  --tap-primary: 120px;
  --tap-icon:    74px;
  --tap-gap:     24px;
  --choice-max-w: 168px;
  --manip-size:   88px;
  --manip-size-compare: 54px;
  --replay-size:  70px;
  --label-display: none;   /* NO required reading — the voice carries it        */
  --guide-scale:  1.14;    /* the guide is a touch more present on the map      */
}

/* guided — the base :root values already define this. (No overrides needed.) */

/* independent — least support (same register, less hand-holding) */
[data-scaffold="independent"] {
  --text-body:    16px;
  --text-display: 34px;
  --text-numeral: 56px;
  --tap:         72px;
  --tap-primary: 88px;
  --tap-icon:    56px;
  --tap-gap:     16px;
  --choice-max-w: 150px;
  --manip-size:   64px;
  --manip-size-compare: 40px;
  --replay-size:  52px;
  --motion-amp:  0.9;      /* a hair calmer / more precise                      */
  --label-display: block;
  --guide-scale:  0.86;    /* the guide recedes further into the world          */
}

/* ===========================================================================
   ACCESSIBILITY: reduced motion. Kill decorative motion; keep a 1ms tick so
   JS that waits on transitionend still resolves.
   =========================================================================== */
@media (prefers-reduced-motion: reduce) {
  :root {
    --motion-fast: 1ms; --motion-base: 1ms; --motion-draw: 1ms;
    --motion-celebrate: 1ms; --pulse-dur: 0s; --motion-amp: 0;
  }
}

/* ===========================================================================
   CONTRAST REFERENCE — every pairing MEASURED in sRGB, 2026-07-26.
   Documentation. Do not delete; re-measure if you move a value.
   ---------------------------------------------------------------------------
   THE LIGHT SURFACE  (--paper #F2F4F7 / --card #ffffff)
     ink navy #0D0B2E on paper .................. 17.26:1  AAA  all text
     ink navy on white card ..................... 19.01:1  AAA  answer numerals
     ink-soft #535B6B on paper ...................  6.19:1  AA+  secondary text
     teal-deep  #00695C on paper .................  6.00:1  AA+  teal as text
     amber-deep #8A6100 on paper .................  5.03:1  AA   amber as text
     pink-deep  #A11B5B on paper .................  6.75:1  AA+  pink as text
     violet-deep #412BB0 on paper ................  8.67:1  AAA  violet as text
     ink on any tint (teal/amber/pink/violet) .... 14.88-16.94:1  AAA

   THE DARK SURFACE  (--navy #0D0B2E)
     white ...................................... 19.01:1  AAA
     ink-soft-on-dark #C3C7D6 ................... 11.28:1  AAA  secondary
     amber ...................................... 11.66:1  AAA
     teal .......................................  8.64:1  AAA
     pink ........................................  4.98:1  AA   large/short only
     violet ......................................  4.52:1  ⚠️ AT THE FLOOR —
       do NOT set violet text on navy. Violet is a FILL on this ground.
     white on violet-deep #412BB0 ................  9.56:1  AAA  (the violet ground)
     white on navy-raised #211D57 ................ 15.24:1  AAA

   🔴 MARKS ON A BRIGHT FILL — use --on-bright (navy), never white:
     navy on amber .............................. 11.66:1  |  white on amber  1.63:1
     navy on teal ...............................  8.64:1  |  white on teal   2.20:1
     navy on pink ...............................  4.98:1  |  white on pink   3.82:1
     navy on violet .............................  4.52:1  |  white on violet 4.20:1
     Right column: ALL FOUR FAIL. That is migration note §2.

   FILL-ONLY (never text, never a thin mark, on a light ground):
     teal on paper 2.00:1 · amber on paper 1.48:1  — these are FILLS.
     pink 3.47:1 and violet 3.81:1 on paper clear only the ≥3:1 large-text bar
     (≥24px bold) — never body text, never a label.

   STRUCTURE (not text; a visible-edge check, not a WCAG check):
     hair #DDE3EC vs paper ...... 1.17    card-lip #C2C9D6 vs card ..... 1.66
     navy-hair vs navy .......... 1.54    navy-raised vs navy .......... 1.25 ⚠️
     lip steps: teal 3.01 · amber 3.40 · pink 1.95 · violet 2.27

   RULE, unchanged and absolute: colour is NEVER the sole signal — always pair
   with icon + shape + position + voice.
   =========================================================================== */
