/* ==========================================================================
   The Treatment Tapes — Brand Tokens v1.1  (single source of truth)
   Direction 01 "Dossier", palette "Frost on Linen":
   warm linen canvas, pastel ice band, midnight navy, oxidised ink.
   Spectral (display) + Figtree (interface) + General Sans (labels).

   Sister brand to TeleTonicMD. What crosses over is the *method*, not the hue:
   a rationed palette with one job per colour, hairlines instead of shadows,
   one accent per view, one metallic, a single motion curve, and AA-checked
   pairs. What changes is everything on the surface — pine becomes navy, cream
   becomes linen, brass becomes oxidised ink, pills become rectangles.

   Figtree is the one literal thread between the two brands: same interface
   voice, different display face.

   This file is the canonical token layer for thetreatmenttapes.com. It is the
   only place a colour, radius, duration or type step may be defined.
   When a value changes, change it HERE and propagate — never fork.

   Palette history. v1.0 "Porcelain + Oat" shipped 2026-09-08 and was retired
   2026-09-09; the ground was warm-neutral throughout and the alternating band
   read flat and greyish on screen. v1.1 "Frost on Linen" keeps the navy, the
   accent, the type and the motion, and replaces only the surface layer.
   The retired palette, its screenshots and restore steps live in
   archive/2026-09-09-porcelain-oat/ (git tag design/2026-09-09-porcelain-oat).
   ========================================================================== */

:root {
  /* ---- Paper — linen canvas, ice band -----------------------------------
     paper = page canvas · paper-alt = alternating band · card = raised only

     The temperature split is the whole idea. The canvas is warm linen — an
     off-white with enough yellow in it (hue 39) to read as paper rather than
     as screen. The alternating band is the opposite: a saturated pastel ice
     blue (hue 208, chroma high enough to be a colour, light enough to stay
     airy). Warm ground, cool band, navy anchor. Nothing in between is grey.

     A note for anyone tempted to desaturate the band: it was grey once. It
     read as dead screen-chrome and was rejected. If the band needs to change,
     it moves in hue or lightness, never toward zero chroma. */
  --paper:        #FCF7EE;   /* linen — hsl(39, 70%, 96%) */
  --paper-alt:    #D8ECFD;   /* ice   — hsl(208, 90%, 92%) */
  --card:         #FFFFFF;

  /* ---- Ink ramp — headlines, dark blocks, controls ---------------------- */
  --ink:          #111C2E;   /* midnight: headlines, footer, the dark band */
  --navy:         #1C3557;   /* buttons, active states, icon strokes */
  --navy-hover:   #27456E;   /* hovers, secondary strokes */
  --steel:        #4E6787;   /* tracked micro-labels (5.2:1 on paper) */
  --steel-deep:   #3B5271;   /* body copy (7.4:1 on paper) */

  /* ---- Tints — one job each ---------------------------------------------
     powder = interactive tints / row hover · mist = quiet washes
     Both are steps of the ice band, not of the linen canvas: mist sits
     between canvas and band, powder just under the band. Neither is ever
     used for text. */
  --powder:       #D3E8F8;
  --mist:         #ECF6FD;

  /* ---- Hairlines — every edge on the site ------------------------------- */
  --line:         #DCE4EA;
  --line-strong:  #C4D1DC;
  --line-ink:     rgba(198, 217, 232, 0.16);   /* hairline on the dark band */

  /* ---- the sky ----------------------------------------------------------
     One set of star colours for the whole property: the constellation map, the
     background field behind it, and the faint carry-over into the hero below.
     Defined here rather than inside sky.css so the two canvases and the SVG
     cannot drift apart — sky.js reads these at init.

     The three nebula values are the only hues on the site outside the palette.
     They exist at 4-8% alpha over midnight, where they are not seen so much as
     missed when removed: without them the band reads as a flat panel. Kept as
     bare `r,g,b` triples because they are only ever composed into rgba(). */
  /* A stellar palette. Real stars are not #FFF: the field is mostly warm
     white with a minority of blue-white and a scatter of amber and pale red,
     and the anchor stars carry the strongest colour because they are the ones
     the eye resolves as individuals. */
  --star-warm:    #F6F0DC;   /* warm white — the majority */
  --star-cool:    #DCE7F7;   /* cool blue-white */
  --star-amber:   #F1CDA0;
  --star-rose:    #F4B9A6;   /* pale red */
  --star-white:   #FFFFFF;   /* G class — the sun's colour, rarer than people expect */
  --star-blue:    #C6D5F0;   /* B class */
  --star-blue-o:  #B7C7F5;   /* O class — two in a hundred */

  /* The moon is a baked raster now (tools/render-moon.py), so its colour is
     in the render rather than in tokens. The two that survive are the ones
     the PAGE still decides: how big it is and where it sits. */
  --moon-k:        .20;    /* share of the VISIBLE sky it takes at rest */
  --moon-max:      152px;  /* ...capped, for a tall narrow window */
  --moon-hover:    2.5;
  --moon-x:        19%;
  --moon-y:        .47;   /* fraction of the VISIBLE sky, below the chrome */
  --star-pale:    #F2F6FA;   /* = on-ink; the topic stars, which are not the field */
  --star-ice:     #D8ECFD;   /* = paper-alt */
  --star-dim:     #A9C4DE;   /* an upcoming topic, at rest */
  --star-line:     rgba(220, 225, 245, 0.10);   /* an ordinary edge */
  --star-line-b:   rgba(220, 225, 245, 0.16);   /* one touching a beta/gamma */
  --star-line-a:   rgba(220, 225, 245, 0.22);   /* one touching an alpha */   /* a constellation line, at rest */
  --star-line-x:   rgba(220, 225, 245, 0.05);   /* crossing two clusters: a cross-reference, not a figure */
  --star-line-lit: rgba(255, 240, 210, 0.75);   /* and lit, warm, so the relationship is the warm thing
                                                   on a cool map */
  --hud-ink:       rgba(230, 225, 210, 0.42);   /* the map's legend — the one line you click */
  --hud-mute:      rgba(230, 225, 210, 0.50);   /* plate caption and note: read once, then ignored */
  --hud-dot:       rgba(230, 225, 210, 0.26);
  --neb-band:     140, 150, 200;   /* the Milky Way: dusty violet, 8% at its brightest */
  --neb-cream:    238, 230, 210;
  --neb-violet:   150, 142, 196;
  --neb-teal:     104, 166, 178;
  --line-ink-str: rgba(198, 217, 232, 0.26);

  /* ---- The accent — oxidised ink ---------------------------------------
     THE one accent. Case numbers, the rust tick above an eyebrow, the
     playhead, the "latest" marker, focus rings. One per view, never two. */
  --rust:         #9A4E33;   /* 5.4:1 on paper — safe for small text everywhere */
  --rust-pale:    #E5CABD;   /* borders and chips only */
  --rust-tint:    rgba(154, 78, 51, 0.09);
  --rust-ink:     #E0A88E;   /* the accent as it reads on the dark band */

  /* ---- The counterpoint surface — deep linen ----------------------------
     The band is cool now, so the counterpoint runs the other way: the canvas
     pushed two steps warmer and darker, so it reads as its own surface beside
     both the linen ground and the ice band without introducing a third hue.
     Its text is steel, not brown — the only warm thing here is the surface.
     the letter's block and nothing else. */
  --sand:         #F4EDE1;
  --sand-line:    #E5DACA;
  --sand-text:    #3B5271;   /* = steel-deep · 6.9:1 on deep linen */
  --sand-label:   #4E6787;   /* = steel      · 5.0:1 on deep linen */

  /* ---- The instrument ground ---------------------------------------------
     A SECOND dark, and the reason there are two is adjacency: on the home
     page the Atlas feature sits directly under the midnight band that carries
     the latest investigation. One ground for both would read as a single slab
     three screens tall.

     So midnight stays the FILM -- the episode plate, the footer, the sky --
     and this is the INSTRUMENT: the apparatus you read something off. It is
     half midnight's saturation (22% against 46%) and a step lighter (1.28:1
     between them), which is enough to register as a different material and
     nowhere near enough to stop being dark. Oxidised metal and lab glass
     rather than sky.

     The whole --on-ink text ramp clears AA on it unchanged -- 12.3:1, 9.1:1
     and 5.2:1 -- so this adds a ground and a hairline, not a second palette. */
  --slate:          #26303B;
  --slate-deep:     #1B232C;   /* the low end of the ground's gradient */
  --slate-line:     rgba(198, 217, 232, 0.14);
  --slate-line-str: rgba(198, 217, 232, 0.26);

  /* ---- Text on the dark band -------------------------------------------- */
  --on-ink:       #F2F6FA;   /* headlines on midnight */
  --on-ink-body:  #C8D6E6;   /* body on midnight */
  --on-ink-mute:  #8DA4BF;   /* labels on midnight (6.6:1) */
  --on-ink-faint: #7F97B3;

  /* ---- Semantic states — muted, never alarming -------------------------- */
  --ok:           #2C6B54;
  --ok-bg:        #E6F1EC;
  --note:         #8A5A2E;
  --note-bg:      #F8EEE4;
  --stop:         #9A4E33;   /* the accent doubles as the error tone */
  --stop-bg:      #F8EDE8;

  /* ---- Shadows — one card shadow, used sparingly ------------------------
     Cards separate by hairline and background, not elevation. Shadow is for
     hover and for the two floating elements (sticky player, mobile nav). */
  --shadow-card:  0 8px 28px rgba(17, 28, 46, 0.05);
  --shadow-lift:  0 14px 40px rgba(17, 28, 46, 0.09);
  --shadow-float: 0 -2px 30px rgba(17, 28, 46, 0.13);

  /* ---- Typefaces --------------------------------------------------------
     disp = Spectral, the display and dek voice (200-500)
     ui   = Figtree, body / navigation / buttons — carried over unchanged
     label = General Sans, every label, number, timestamp and caption
             (since 25 Sep 2026). Was IBM Plex Mono, then DM Mono, then
             Archivo. The brief is still a newspaper kicker -- tracked caps
             at nine to eleven pixels -- and General Sans draws a taller,
             narrower, cleaner capital for it than Archivo did.
             It has no tabular figures, and the slot's one hard requirement
             is tabular figures wherever numbers line up or tick. Those few
             rules use --label-figures, which takes ONLY the digits and the
             colon from a 5.8 KB cut of Archivo (see fonts.css) and every
             other character from General Sans.
             Its weight axis is steeper than Archivo's, so a label keeps its
             old weight by STEM, not by number: Archivo 300/400/500/600/700
             = General Sans 410/460/500/550/590 (I-stem 79/95/112/130/149
             units against 75@400, 110@500, 152@600). Nearly every label is
             500, where the two agree; the others carry the mapped value.
             Figtree stands behind General Sans for the two arrows it lacks
             (U+2193, and U+2192 through the system face), so a "Topics ↓"
             renders the same on every platform. */
  --disp:  'Spectral', Georgia, 'Times New Roman', serif;
  --ui:    'Figtree', system-ui, -apple-system, sans-serif;
  --label: 'General Sans', 'Figtree', 'Helvetica Neue', Arial, sans-serif;
  --label-figures: 'Label Figures', 'General Sans', 'Figtree', 'Helvetica Neue', Arial, sans-serif;

  /* display-grotesk = the Swiss grotesque register, and it has EXACTLY one
     job: the constellation map's metadata — the filter row, the plate
     caption, the upcoming-stars note and the tooltip's status line.

     Neue Haas Grotesk Display Pro is the face this is drawn for. It is NOT
     licensed for this site and is NOT self-hosted, so it leads the stack and
     resolves for anyone who has it while everyone else falls through to
     Helvetica Neue, which is the same skeleton — Neue Haas IS the Helvetica
     revival — at the same optical weight. No webfont file ships for this and
     no third-party request is made for it; if the licence is ever bought,
     dropping the woff2 into src/fonts/ and adding a @font-face is the whole
     change, and this token does not move.

     Weight 500. On the fallbacks that is a synthesised or nearest-weight
     medium, which at 9-10px tracked caps is the intended colour either way.

     This replaced a monospaced stack that held the same four slots for one
     afternoon. Mono gave the map a machine-set voice but a teletype one —
     wide, mechanical, and at odds with a plate that is meant to read as a
     printed star chart. A grotesque is what an actual planetarium chart is
     set in. */
  --display-grotesk: 'Neue Haas Grotesk Display Pro', 'Helvetica Neue',
                     Helvetica, Arial, system-ui, sans-serif;

  /* ---- Type scale (~1.33) ----------------------------------------------- */
  --t-xs:      0.75rem;      /* 12px */
  --t-sm:      0.875rem;     /* 14px */
  --t-body:    1rem;         /* 16px */
  --t-lead:    1.1875rem;    /* 19px */
  --t-h4:      1.25rem;
  --t-h3:      clamp(1.375rem, 1.2rem + 0.7vw, 1.625rem);
  --t-h2:      clamp(1.75rem, 1.3rem + 2vw, 2.75rem);
  --t-display: clamp(2.875rem, 1.6rem + 5.4vw, 6.5rem);

  /* mono label sizes — the Dossier voice */
  --t-label:   0.65625rem;   /* 10.5px — eyebrows, table heads, captions */
  --t-label-l: 0.75rem;      /* 12px — data cells, timestamps */

  --track-label:   0.19em;   /* mono micro-labels */
  --track-strip:   0.18em;   /* the masthead meta strip */
  --track-btn:     0.11em;   /* button text */

  /* ---- Spacing (8pt) ----------------------------------------------------- */
  --s-1: 0.5rem;  --s-2: 1rem;   --s-3: 1.5rem;
  --s-4: 2rem;    --s-6: 3rem;   --s-8: 4rem;   --s-12: 6rem;
  --section-y:  clamp(3rem, 6vw + 1rem, 5.75rem);
  --gutter:     clamp(1.125rem, 4vw, 2.75rem);
  --content:    1180px;
  --measure:    42rem;       /* ~68ch prose measure */
  --header-h:   70px;

  /* ---- Radius — sharp. The deliberate break from TeleTonicMD's pills ----
     Nothing on this site is round except the play button and the reel mark. */
  --r-round: 999px;   /* play buttons and the mark only */
  --r-lg:    6px;     /* buttons, large panels */
  --r:       3px;     /* cards, plates, media */
  --r-sm:    2px;     /* chips, tags, stamps */

  /* ---- Motion — one signature curve, tiered durations ------------------- */
  --ease:      cubic-bezier(0.22, 1, 0.36, 1);   /* the brand curve */
  --ease-inout:cubic-bezier(0.65, 0, 0.35, 1);
  --d-fast: 180ms;
  --d-base: 300ms;
  --d-slow: 600ms;
  --rise:   10px;            /* scroll-reveal travel */
  --stagger: 70ms;           /* step between items in one reveal batch */
  --reveal-delay: 0ms;       /* per-element, overwritten by tapes.js */

  /* ---- Paper grain — the tactile trick -------------------------- */
  --grain: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)'/%3E%3C/svg%3E");
  --grain-opacity: 0.035;
}

/* ==========================================================================
   Contrast ledger — computed, not assumed. WCAG 2.1 AA needs 4.5:1 for body
   text, 3:1 for large text (>=24px, or >=19px bold) and UI boundaries.
   Every pair the site actually renders is listed. Nothing here is below AA;
   the tightest pair in the whole system is 4.61:1.

   The ice band raised the stakes: a light band is easy, a *saturated* light
   band eats contrast. Every text colour was re-checked against it before this
   palette shipped, not after. If you darken the band, re-run these numbers.

     steel        #4E6787  on paper       #FCF7EE   5.45:1   AA 
     steel        #4E6787  on paper-alt   #D8ECFD   4.80:1   AA 
     steel        #4E6787  on card        #FFFFFF   5.81:1   AA 
     steel        #4E6787  on mist        #ECF6FD   5.30:1   AA 
     steel        #4E6787  on powder      #D3E8F8   4.61:1   AA 
     steel-deep   #3B5271  on paper       #FCF7EE   7.48:1   AAA
     steel-deep   #3B5271  on paper-alt   #D8ECFD   6.59:1   AA 
     steel-deep   #3B5271  on card        #FFFFFF   7.98:1   AAA
     steel-deep   #3B5271  on mist        #ECF6FD   7.28:1   AAA
     steel-deep   #3B5271  on powder      #D3E8F8   6.33:1   AA 
     rust         #9A4E33  on paper       #FCF7EE   5.60:1   AA 
     rust         #9A4E33  on paper-alt   #D8ECFD   4.94:1   AA 
     rust         #9A4E33  on card        #FFFFFF   5.98:1   AA 
     rust         #9A4E33  on mist        #ECF6FD   5.46:1   AA 
     rust         #9A4E33  on powder      #D3E8F8   4.75:1   AA 
     rust         #9A4E33  on sand        #F4EDE1   5.14:1   AA 
     ink          #111C2E  on paper       #FCF7EE  16.01:1   AAA
     ink          #111C2E  on paper-alt   #D8ECFD  14.10:1   AAA
     ink          #111C2E  on sand        #F4EDE1  14.68:1   AAA
     navy         #1C3557  on paper       #FCF7EE  11.60:1   AAA
     navy         #1C3557  on paper-alt   #D8ECFD  10.22:1   AAA
     navy         #1C3557  on card        #FFFFFF  12.38:1   AAA
     navy-hover   #27456E  on paper       #FCF7EE   9.10:1   AAA
     navy-hover   #27456E  on paper-alt   #D8ECFD   8.02:1   AAA
     on-ink       #F2F6FA  on ink         #111C2E  15.73:1   AAA
     on-ink-body  #C8D6E6  on ink         #111C2E  11.56:1   AAA
     on-ink-mute  #8DA4BF  on ink         #111C2E   6.67:1   AA 
     on-ink-faint #7F97B3  on ink         #111C2E   5.68:1   AA 
     rust-ink     #E0A88E  on ink         #111C2E   8.27:1   AAA
     sand-text    #3B5271  on sand        #F4EDE1   6.86:1   AA 
     sand-label   #4E6787  on sand        #F4EDE1   4.99:1   AA 

   card, line, line-strong, rust-pale, line-ink and the grain are surfaces and
   borders. They never carry text.

   A ledger checks token PAIRS. It cannot see what the cascade actually paints.
   The header CTA rendered at 2.14:1 for months while every number above was
   arithmetically correct, because an unscoped `.nav a` outranked `.btn--solid`
   and swapped the label colour — a pair no one would ever think to list. When
   you change a colour, re-measure the rendered page, not just this table.
   ========================================================================== */
