/* ================================================================
   BAUDE OS — tokens.css v1.0
   Central design token file — Brand Book May 2023
   ----------------------------------------------------------------
   HOW TO USE:
   Link this file from every Baude digital touchpoint:
   <link rel="stylesheet" href="tokens.css">
   Then use CSS variables (--color-text, --font-display, etc.)
   in all component and page styles.
   Never hardcode colors, sizes, or fonts — always use a token.
   ================================================================ */


/* ================================================================
   FONTS
   ================================================================ */

/*
   Franklin Gothic ATF — primary display font
   ─────────────────────────────────────────────
   PREFERRED: Adobe Typekit embed
   Get the kit at https://fonts.adobe.com/fonts/franklin-gothic-atf
   Then uncomment and replace YOUR_KIT_ID:

   @import url('https://use.typekit.net/YOUR_KIT_ID.css');

   CSS font-family name via Typekit: 'franklin-gothic-atf'
*/

/* Franklin Gothic ATF — Shopify CDN fallback (live Baude store fonts) */
@font-face {
  font-family: 'Franklin Gothic ATF';
  src: url('https://cdn.shopify.com/s/files/1/0804/5166/6208/files/FranklinGothicATF-Heavy.woff2') format('woff2'),
       url('https://cdn.shopify.com/s/files/1/0804/5166/6208/files/FranklinGothicATF-Heavy.svg#FranklinGothicATF-Heavy') format('svg');
  font-weight: 900;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Franklin Gothic ATF';
  src: url('https://cdn.shopify.com/s/files/1/0804/5166/6208/files/FranklinGothicATF-Bold.woff2') format('woff2'),
       url('https://cdn.shopify.com/s/files/1/0804/5166/6208/files/FranklinGothicATF-Bold.svg#FranklinGothicATF-Bold') format('svg');
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}

/* News Gothic BT — body/UI font (Shopify CDN) */
@font-face {
  font-family: 'NewsGoth Dm BT';
  src: url('https://cdn.shopify.com/s/files/1/0804/5166/6208/files/NewsGothicBT-Demi.woff2') format('woff2'),
       url('https://cdn.shopify.com/s/files/1/0804/5166/6208/files/NewsGothicBT-Demi.svg#NewsGothicBT-Demi') format('svg');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'NewsGoth Dm BT';
  src: url('https://cdn.shopify.com/s/files/1/0804/5166/6208/files/NewsGothicBT-DemiItalic.woff2') format('woff2'),
       url('https://cdn.shopify.com/s/files/1/0804/5166/6208/files/NewsGothicBT-DemiItalic.svg#NewsGothicBT-DemiItalic') format('svg');
  font-weight: 400;
  font-style: italic;
  font-display: swap;
}
@font-face {
  font-family: 'NewsGoth BT';
  src: url('https://cdn.shopify.com/s/files/1/0804/5166/6208/files/NewsGothicBT-Bold.woff2') format('woff2'),
       url('https://cdn.shopify.com/s/files/1/0804/5166/6208/files/NewsGothicBT-Bold.svg#NewsGothicBT-Bold') format('svg');
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}


/* ================================================================
   LAYER ARCHITECTURE
   Controls cascade precedence — edit in this order only.
   ================================================================ */
@layer tokens, base, components, utilities;


/* ================================================================
   1. PRIMITIVE TOKENS
   Raw named values. Never reference these directly in components.
   All primitives live here — semantic tokens reference them below.
   ================================================================ */
@layer tokens {
  :root {

    /* ── Neutral Primitives ─────────────────────────────── */
    --prim-black:       #231f20;   /* brand black — brand brief */
    --prim-rich-black:  #0f0f10;   /* full ink black — text */
    --prim-white:       #ffffff;
    --prim-grey-50:     #f7f7f7;
    --prim-grey-100:    #f0f0f0;
    --prim-grey-200:    #e0e0e0;
    --prim-grey-400:    #9e9e9e;
    --prim-grey-600:    #555555;

    /* ── Evergreen Brand Palette — Brand Book p.49 ──────── */
    --prim-yellow:      #F1EFB7;   /* off-optimism — corrected to Baude team library + brand deck (was #eeea77, confirmed bug) */
    --prim-violet:      #4c4084;   /* Pantone 7672 C — creativity   */
    --prim-plum:        #72246c;   /* Pantone 255 C  — depth        */
    --prim-indigo:      #606eb2;   /* Pantone 7456 C — neutral accent */

    /* ── Y1 Collection Hero Colors — Brand Book p.50–51 ─── */
    --prim-darkwave:    #64a70b;   /* FW23 — Darkwave Utopia  (Pantone 369 C) */
    --prim-bdsm-disco:  #4c4084;   /* SS24 — BDSM Disco       (= evergreen violet) */
    --prim-holy-hall:   #dc3513;   /* FW24 — Holy Hallucinations (Pantone 3516 C) */
    --prim-alien-vac:   #890c58;   /* W24  — Alien Vacation   (Pantone 228 C) */

    /* ── Extended Color Library — Brand Book p.51 ───────── */
    --prim-lib-red:         #ef4623;   /* Pantone 3516 C */
    --prim-lib-deep-plum:   #66004b;   /* Pantone 2357 C */
    --prim-lib-acid-green:  #adcf00;   /* Pantone 3507 C */
    --prim-lib-periwinkle:  #6f7cbc;   /* Pantone 2115 C */
    --prim-lib-lime:        #dfe670;   /* Pantone 2296 C */
    --prim-lib-purple:      #7c53a2;   /* Pantone 2082 C */
    --prim-lib-ice-blue:    #a7c5ed;   /* Pantone 2727 C */
    --prim-lib-forest:      #44a041;   /* Pantone 7738 C */
    --prim-lib-ballet:      #f5c6dd;   /* Pantone 217 C  */
    --prim-lib-royal:       #3c50a2;   /* Pantone 2368 C */
    --prim-lib-fuchsia:     #c63d96;   /* Pantone 240 C  */
    --prim-lib-tangerine:   #f99d22;   /* Pantone 3588 C */
    --prim-lib-emerald:     #009d4e;   /* Pantone 2418 C */
    --prim-lib-sky:         #8ad5ec;   /* Pantone 629 C  */
    --prim-lib-lavender:    #b9b0d7;   /* Pantone 2092 C */
    --prim-lib-butter:      #fff26f;   /* Pantone 2003 C */

    /* ── Spacing Primitives — 4pt grid ──────────────────── */
    --prim-sp-1:    4px;
    --prim-sp-2:    8px;
    --prim-sp-3:    12px;
    --prim-sp-4:    16px;
    --prim-sp-5:    20px;
    --prim-sp-6:    24px;
    --prim-sp-8:    32px;
    --prim-sp-10:   40px;
    --prim-sp-12:   48px;
    --prim-sp-16:   64px;
    --prim-sp-20:   80px;
    --prim-sp-24:   96px;
    --prim-sp-32:   128px;
    --prim-sp-40:   160px;
  }
}


/* ================================================================
   2. SEMANTIC TOKENS
   Intent-based aliases. Use ONLY these in all component styles.
   Changing a primitive here cascades everywhere automatically.
   ================================================================ */
@layer tokens {
  :root {

    /* ── Surfaces ─────────────────────────────────────────── */
    --color-bg:           var(--prim-white);       /* default page background */
    --color-bg-secondary: var(--prim-grey-50);     /* subtle background tint */
    --color-bg-dark:      var(--prim-black);       /* callouts, emphasis blocks, full-bleed panels */
    --color-bg-overlay:   rgba(35, 31, 32, 0.88);  /* modal/drawer overlay */

    /* ── Text ─────────────────────────────────────────────── */
    --color-text:         var(--prim-rich-black);  /* primary body text */
    --color-text-soft:    var(--prim-grey-600);    /* secondary, captions */
    --color-text-faint:   var(--prim-grey-400);    /* disabled, placeholder */
    --color-text-on-dark: var(--prim-white);       /* text on dark backgrounds */
    --color-text-accent:  var(--prim-yellow);      /* accent text — on dark only */

    /* ── Brand (evergreen) ───────────────────────────────── */
    --color-brand-black:  var(--prim-black);
    --color-brand-yellow: var(--prim-yellow);
    --color-brand-violet: var(--prim-violet);
    /* ── TEXT-SAFE SEMANTIC COLOURS ─────────────────────────────────
       🔴 MEASURED 2026-08-25 10:35PM EDT, ON A REAL RENDER: the semantic
       colours are fine as fills and borders and FAIL as small text on paper.
           --color-brand-yellow  #F1EFB7   1.18:1   invisible
           --color-text-faint    #9e9e9e   2.68:1   illegible
           --prim-lib-emerald    #009d4e   3.54:1   low
           --prim-lib-red        #ef4623   3.77:1   low
       WCAG needs 4.5:1 for body text. The AMBER state is the one that means
       "she has to decide", and at 1.18:1 it was not there at all.

       ⭐ HER HUE AND SATURATION ARE UNCHANGED — only lightness drops until
         each clears 4.5:1. Yellow is still yellow, so "colour = meaning"
         survives intact; it just becomes legible.
       ⚠️ DERIVED, NOT CHOSEN BY HER. Three new hexes, and they are hers to
          accept or replace. Her palette contains NO amber or green that
          passes as text — that is a design-system gap, not a page bug.
       ⛔ USE THESE ONLY FOR TEXT. Fills, borders and rock colours keep the
         brand primaries, where contrast is not the constraint. */
    --text-pending:  #787517;   /* from --prim-yellow      · 4.82:1 */
    --text-approved: #008441;   /* from --prim-lib-emerald · 4.80:1 */
    --text-killed:   #d93210;   /* from --prim-lib-red     · 4.76:1 */

    /* ── TYPE OF WORK — ONE map for /glance blocks + item edges (#1054) ──
       Monica, 2026-10-26 9:29AM EDT: "the color coding of blocks should align
       with the type of work". Keyed off the block NAME, never the Google colour.
       The edge is the colour; a block's fill is it mixed ~30% into --paper.
       ⚠️ Picked by Jules from her library to match her 9:29a mock (yellow ·
          lilac · green · peach); hers to correct in one line. */
    --wt-money:      #b5ad1f;   /* her yellow, deepened so the edge reads */
    --wt-delegation: var(--prim-lib-purple);
    --wt-consulting: var(--prim-lib-emerald);
    --wt-projects:   var(--prim-lib-tangerine);
    --wt-content:    var(--prim-lib-fuchsia);
    --wt-outside:    var(--prim-lib-royal);
    --wt-review:     var(--prim-grey-600);
    --wt-os:         var(--ink);
    --wt-email:      var(--prim-lib-periwinkle);   /* Email · the Answer-emails block (hers 2:00p) */   /* Baude OS, black (hers 10/26/26 1:48p) */
    --wt-personal:   #7cc4ef;   /* sky blue, the grid's personal (hers 12:55p "Tag?" list) */
    --wt-none:       var(--prim-grey-400);

    /* ── THE CARD — a component's own tokens ────────────────────────
       Monica, 2026-08-25 11:25PM EDT: "But I think we'd need to build those
       design tokens." She is right — the card anatomy was going in as raw
       values, which would make the newest component in the OS the one that
       does not participate in the design system.

       ⚠️ VALUES ARE PROVISIONAL. Derived from Glance V2 and tuned on a phone
          2026-08-25; they are expected to move. ⭐ THE POINT IS THE NAMES —
          she retunes the whole card from these six lines instead of hunting
          through row.css.
       ⭐ REFERENCE THE SCALE, DO NOT REDEFINE IT. Where a shared token fits,
         these point at it, so there is one type scale and not two.
       ⛔ Do not fold these back into --text-*: they are a component's tokens. */
    /* ⭐ THE LABEL RAIL. A FIXED column width so every title starts at the
       same x and the labels stack into a scannable left edge. That rail is the
       visual signature of the approved mock — with the label inline instead,
       every row indents by the length of its own word and the list reads
       ragged. Measured on the live page before this: title x=11 without a
       label, x=71 with one. */
    /* The KPI tile value. 22.4px is the approved mock's size, measured off
       767b5a3c — not chosen. --text-subhead resolved to 18px here, which read
       small against the mock's 22.4 and let the labels crowd the numbers.
       🔴 1.6rem, NOT 1.4rem. THE ROOT FONT-SIZE ON THESE PAGES IS 14px
          (css/layout.css: `html, body { font-size: 14px }`), so a rem is 14px
          and 1.4rem draws 19.6. I wrote 1.4rem on 8/26 from the mock's px
          figure assuming a 16px root, and it shipped 2.8px short. Any px
          measurement taken off an artifact must be divided by 14 here. */
    --metric-val:  1.6rem;   /* = 22.4px at the 14px root */
    /* 🔴 NARROWED 5.2rem → 3.6rem, 2026-09-27 10:39PM EDT. Hers, with a
       screenshot: "The left alignment on the ticket name and the notes area is
       not good. Should all be aligned. The ticket name can move closer to left
       and notes area to right. Meet somewhere in the middle."
       ⭐ 3.6rem still holds "T-1234" at --card-meta without wrapping; 5.2rem
       was sized for a word like INTERACTION that the rail no longer prints.
       ⚠️ SHARED BY EVERY SURFACE THAT USES THE ROW COMPONENT — which is her own
       rule: "anytime we update one of them, all of them should update." */
    --label-col:   3.6rem;
    --card-name:   var(--text-subhead);  /* the hanging name — display, caps */
    --card-body:   var(--text-read);     /* the paragraph she actually reads */
    /* 🔴 12px IS A DECISION, NOT A DEFAULT. It exists because --text-micro is
       9px and unusable on a phone — the actions are tap targets too.
       ⛔ Do not "tidy" this back to the shared token. See #533. */
    --card-meta:   var(--text-label);
    /* ⭐ THE SECOND LEFT EDGE — the inner margin everything but the name hangs
       off. Without a token this is a magic number repeated in five rules. */
    /* 🔴 THE OPEN CARD NOW STARTS EXACTLY UNDER THE TITLE. It was --space-lg
       (24px) while the title began at --label-col + --space-md, so the two
       left edges never agreed — the misalignment in her 10:38PM screenshot.
       ⭐ DERIVED, NOT A SECOND MAGIC NUMBER: change the rail width and the
       indent follows on its own. */
    --card-indent: calc(var(--label-col) + var(--space-md));
    --card-pad:    var(--space-lg);      /* the "generous" of 11:11PM */
    --card-gap:    var(--space-sm);      /* name -> tags -> body -> meta -> actions */

    /* ── ROCK COLOURS ───────────────────────────────────────────────
       Monica, 2026-08-25 9:13PM EDT: "The color should coordinate with the
       rocks though. And grey if undetermined or unassigned."

       🔴 A LEFT BORDER IS ALWAYS A ROCK AND NEVER A STATUS. Status lives in
         the text and the tags. This has to be a stated rule because the
         palettes genuinely collide — holy-hall sits near the semantic
         "killed" red and darkwave near "approved" green. The disambiguator
         is POSITION, exactly like the row-action rule: found by where it is,
         not by what colour it is.
       ⭐ NAMED PER ROCK so a rock can be recoloured in ONE line. ⛔ Never a
         raw hex in a component, and never --prim-* directly.
       ⭐ --rock-none IS DOING REAL WORK. Unassigned is a true state, and how
         much grey is on the glance measures how much of her work sits
         outside her four bets. ⛔ Never default a row to a rock to tidy it. */
    --rock-ads:      var(--prim-holy-hall);
    --rock-content:  var(--prim-indigo);
    --rock-samples:  var(--prim-darkwave);
    --rock-website:  var(--prim-plum);
    --rock-none:     var(--prim-grey-400);

    /* ── CHANNEL COLOURS ────────────────────────────────────────────
       Monica, 2026-10-10 12:23AM EDT (via Ellis): one channel colour palette,
       used everywhere a channel shows. ⭐ NAMED PER CHANNEL so a channel is
       recoloured in ONE line. On /content: the full colour is the card's left
       bar, a light tint (color-mix with --paper) is its background, and the
       text stays --ink on the tint. ⛔ Never a raw hex in a component. */
    --ch-ig:     #e0479e;   /* Instagram — feed, reels, stories */
    --ch-tt:     #0f9d9a;   /* TikTok */
    --ch-em:     #f07a1a;   /* Email */
    --ch-ss:     #8a5a00;   /* Substack */
    --ch-pa:     #5b3cc4;   /* Partnerships + PR */
    --ch-popup:  #2e9e44;   /* Pop-ups / in person */
    --ch-ads:    #1f78d1;   /* Paid ads */
    --ch-gift:   #e0b400;   /* Gifting */
    --ch-press:  #d32f2f;   /* Press */
    --ch-none:   var(--prim-grey-400);   /* a channel with no colour of its own */
    --ch-tint:   16%;       /* how much channel colour goes into a card's background */

    --color-brand-plum:   var(--prim-plum);
    --color-brand-indigo: var(--prim-indigo);

    /* ── Collection Slot ─────────────────────────────────── */
    /* Default = evergreen violet. Override with data-collection="[name]"
       on any element — scoped, can be applied at component level. */
    --color-coll-hero:    var(--prim-violet);
    --color-coll-text:    var(--prim-yellow);

    /* ── UI / Structural ─────────────────────────────────── */
    --color-border:       var(--prim-rich-black);
    --color-border-light: var(--prim-grey-200);
    --color-border-dark:  var(--prim-white);
    --color-border-coll:  var(--color-coll-hero);
    --color-focus:        var(--prim-violet);

    /* ── Typography: Font Stacks ─────────────────────────── */
    /* Typekit name first, CDN fallback second, then system */
    --font-display: 'franklin-gothic-atf', 'Franklin Gothic ATF',
                    'Franklin Gothic Heavy', 'Arial Narrow Bold',
                    Impact, sans-serif;
    --font-body:    'NewsGoth Dm BT', 'NewsGoth BT', 'News Gothic',
                    'Franklin Gothic Book', Arial, sans-serif;
    --font-mono:    'SFMono-Regular', 'Consolas', 'Liberation Mono', monospace;

    /* ── Typography: Size Scale (fluid) ─────────────────────────────────
       REPLACED 2026-08-11 7:20pm ET. #411. Monica delegated it: "i will
       comment on mobile and desktop so just do something."

       ⚠️ THE OLD SCALE IS KEPT AT THE BOTTOM OF THIS BLOCK, per the
       never-replace rule. Do not delete it until she has lived with this.

       WHAT WAS WRONG: every role scaled in its OWN viewport window, so the
       RELATIONSHIPS between them changed with screen width. Headline was
       2.5x body on a phone and 3.2x on a laptop; subhead was frozen at
       16->17px across a 50px window while display travelled 30px. No single
       component was at fault, which is exactly why it read as "everything is
       slightly off on mobile" rather than as a bug she could point at.
       And body at 12px on a phone is below comfortable reading — she built
       /library specifically to read long documents on a phone.

       THE FIX: ONE SHARED WINDOW, 390px to 1440px, so the ratios hold.
       Verified at both ends before shipping, not eyeballed.

       role      phone -> desktop     ratio to body, phone -> desktop
       display     28 -> 48px          1.87x -> 3.00x   (drifts ON PURPOSE)
       headline    22 -> 32px          1.47x -> 2.00x   (drifts on purpose)
       subhead     18 -> 21px          1.20x -> 1.31x
       read        17 -> 18px          1.13x -> 1.12x   ← holds
       body        15 -> 16px            —
       small       13 -> 14px          0.87x -> 0.88x   ← holds

       ⭐ THE READING ROLES NOW HOLD THEIR RATIO — read and small drift by
       0.01x. Display and headline still travel, and that is deliberate:
       restraint on a phone, drama on a laptop. Do not "fix" those two.
       ─────────────────────────────────────────────────────────────────── */
    --text-display:  clamp(1.75rem,   calc(20.57px + 1.905vw),   3rem);     /* 28→48px  H1 */
    --text-headline: clamp(1.375rem,  calc(18.29px + 0.9524vw),  2rem);     /* 22→32px  H2 */
    --text-subhead:  clamp(1.125rem,  calc(16.89px + 0.2857vw),  1.312rem); /* 18→21px  H3 */

    /* ⭐ H4 · SG-H — 2026-08-15 1:05pm ET, MH: "H4 — match to SG-H".
       ⚠️ SG-H WAS NEVER 12px, WHICH IS WHY IT LOOKS BIGGER THAN A LABEL.
       `.sg-h` was declared `font-size: var(--h3)`, and --h3 is defined ONLY in
       static/css/layout.css — which kit pages never load (_base_kit.html pulls
       css/kit/sg-bundle.css, whose 10 imports define no --h3). An undefined var
       makes the declaration invalid at computed-value time, so font-size fell
       back to INHERIT and every component title rendered at body size.
       MH, 1:04pm: "it looks bigger on the page than label ui - am i crazy?" —
       she was reading the screen correctly and the comment above was reading a
       file the page does not load.
       So this token does not change what is on screen. It NAMES it, and gives
       H4 a real rung between H3 (18→21) and H5 (12). */
    --text-sgh:      clamp(0.9375rem, calc(14.63px + 0.09524vw), 1rem);     /* 15→16px  H4 / SG-H — component titles */
    --text-read:     clamp(1.062rem,  calc(16.63px + 0.09524vw), 1.125rem); /* 17→18px  LONG-FORM PROSE */
    --text-body:     clamp(0.9375rem, calc(14.63px + 0.09524vw), 1rem);     /* 15→16px  UI body */
    --text-small:    clamp(0.8125rem, calc(12.63px + 0.09524vw), 0.875rem); /* 13→14px  small */

    /* ⭐ --text-read IS NEW and answers her pass-4 note "let's make the body
       long form = 'body small' and body a tad bigger". Long-form prose
       (/library, any document surface) uses READ. Dense UI keeps BODY. */

    /* FIXED, and correctly non-fluid — a UI label should not change size with
       the window, or a button grows while the thing beside it does not.
       ⭐ This also settles her question "--text-small and --text-label are the
       same 0.75rem but the comments claim 11px and 12px": they are now two
       different values with two different jobs and two stated reasons. */
    /* ⭐ SMALL BODY + CAPTION — 2026-08-15 1:12pm ET, MH:
       "Small Body - match to line items in sidebar (under headers)" and
       "Captions/subtitles = same size as small body but lighter grey."
       MEASURED, not assumed — the sidebar line items on /styleguide-kit compute
       to 11px (they were var(--b2)). So small body is 11px, NOT --text-small's
       13→14px, which is where I first mapped them. Caption is the same 11px and
       differs only in colour: --ink-soft #555, which tokens.css already
       annotates "secondary, captions". Fixed like the labels above, for the
       same reason — secondary copy should not resize under a heading that does not.
    ⚠️ ABSOLUTE PX ON PURPOSE. The root font-size on these pages is 14px, not
       16px, so 0.6875rem renders 9.625px — SMALLER than the 11px she pointed at.
       Measured, after shipping it wrong once. --text-label has the same issue
       (0.75rem renders 10.5px, not 12px) but that is pre-existing, not mine to
       change without her. */
    --text-smallbody: 11px;                            /* 11px  small body — sidebar line items */
    --text-caption:   11px;                            /* 11px  captions/subtitles, --ink-soft */
    /* ⚠️ ABSOLUTE PX, 2026-08-15 1:20pm ET. These were 0.75rem and 0.5625rem and
       their comments claimed 12px and 9px. THE ROOT FONT-SIZE ON THESE PAGES IS
       14px, NOT 16px, so they actually rendered 10.5px and 7.9px — every rem
       token on the kit is 12.5% smaller than the number printed beside it on the
       type-hierarchy page. MH, 1:18pm: "it doesn't feel like the items on this
       page are using the actual token." Correct, and this is half the reason.
       A fixed role must not depend on the root, or the spec sheet lies. */
    --text-label:    12px;                             /* 12px  UI labels, buttons, table heads */
    --text-micro:    9px;                              /* 9px   micro caps (was 7px, unreadably small) */

    /* SUPERSEDED 2026-08-11, kept per the never-replace rule:
       --text-display:  clamp(3.125rem, 8vw, 5rem);       ~50–80px
       --text-headline: clamp(1.875rem, 5vw, 3rem);       ~30–48px
       --text-subhead:  clamp(1rem, 2vw, 1.0625rem);      ~16–17px
       --text-body:     clamp(0.75rem, 1.2vw, 0.9375rem); ~12–15px
       --text-small:    0.75rem;
       --text-micro:    0.5313rem;                        7px             */

    /* ── Typography: Weights ──────────────────────────────── */
    --weight-heavy:   900;   /* Franklin Gothic ATF Heavy */
    --weight-bold:    700;   /* Franklin Gothic ATF Bold / News Gothic Bold */
    --weight-demi:    400;   /* News Gothic Demi (body default) */
    --weight-regular: 400;

    /* ── Typography: Leading ─────────────────────────────── */
    /* From Brand Book p.48 proportions */
    --leading-tight:   1.0;   /* display / large type */
    --leading-heading: 1.05;  /* headlines */
    --leading-snug:    1.15;  /* small headlines */
    --leading-body:    1.2;   /* body copy */
    --leading-loose:   1.51;   /* long-form, fine print */

    /* ── Typography: Tracking ────────────────────────────── */
    /* From Brand Book p.48 */
    --tracking-display: -0.021em;      /* display — no tracking at scale */
    --tracking-heading: -0.017em;   /* heading — slight open */
    --tracking-caps:    0.038em;   /* all-caps labels */
    --tracking-body:    0.01em;   /* subtle body tracking */
    --tracking-micro:   0.076em;   /* micro caps */

    /* ── Spacing: Semantic Aliases ───────────────────────── */
    --space-xs:  var(--prim-sp-1);   /*   4px — tight inline gaps */
    --space-sm:  var(--prim-sp-2);   /*   8px — compact spacing */
    --space-md:  var(--prim-sp-4);   /*  16px — base unit */
    --space-lg:  var(--prim-sp-6);   /*  24px — component padding */
    --space-xl:  var(--prim-sp-8);   /*  32px — section element gaps */
    --space-2xl: var(--prim-sp-12);  /*  48px — large breathing room */
    --space-3xl: var(--prim-sp-16);  /*  64px — section separators */
    --space-4xl: var(--prim-sp-20);  /*  80px — hero / page sections */
    --space-5xl: var(--prim-sp-24);  /*  96px — max section padding */
    --space-6xl: var(--prim-sp-32);  /* 128px — fullscreen spacing */

    /* ── Layout ──────────────────────────────────────────── */
    /* 2026-08-13 (Jules) — Monica: "page margins dont' scale past a certain
       window size. this shoul dbe able to scale larger because of how we have to
       view it." A 7-column tracker on a wide monitor was being squeezed into
       1280px with empty gutters either side. --container-wide is for dense
       working surfaces; the reading widths below are unchanged, because prose
       genuinely should not run to 2000px. */
    /* ⭐ ONE DESKTOP WIDTH FOR THE APP SURFACES. Monica, 2026-09-15 9:00AM EDT,
       with three screenshots taken at the same browser width: "I want them all
       to match the width that is shown for /comms page. So wider than
       /experiments is now, and narrower than what comms is now too. and metrics
       should be narrower too."
       MEASURED at that width: /experiments capped at 430px (`.xp-wrap` — built
       phone-first, "the mock is the device"), /comms at 1080px, /metrics
       uncapped because `--container-lg` 1280px is wider than her viewport.
       Three surfaces, three different answers, none of them shared.
       ⛔ A TOKEN, NOT THREE PAGE RULES — the same reason page-header padding is
         a token: one value, every page, so it cannot be shaved off a single
         page by someone optimising that page alone.
       ⚠️ 1024px satisfies all three of her constraints literally, and it is the
          value `--container-md` already holds — a named alias rather than a new
          number, so the scale does not grow a fourth reading width. */
    --container-app: 1024px;

    --container-wide: 2000px;
    --container-max: 1440px;
    --container-lg:  1280px;
    --container-md:  1024px;
    --container-sm:   768px;
    --grid-gap:       var(--space-md);

    /* ── Borders ─────────────────────────────────────────── */
    /* 🔴 THESE FIVE ARE SHORTHANDS, NOT WIDTHS — AND THE NAME DOES NOT SAY SO.
       `border-top: var(--border-thin)` is correct. `border-left:
       var(--border-thick) solid var(--rock-none)` expands to TWO `solid`
       keywords and TWO colours, which is invalid, so the browser throws the
       WHOLE declaration away — silently. It cost the row left-border on
       /glance on 2026-08-25, and the same mistake was made and caught with
       --border-thin two hours earlier the same evening.
       ⭐ USE THE `-w` WIDTHS BELOW WHENEVER YOU NEED YOUR OWN COLOUR.
       ⚠️ A token whose name does not say its SHAPE is a trap. Checked by
          tools/check_css_tokens.py, which fails the build on a recurrence. */
    --border-thin-w:    1px;
    --border-thick-w:   3px;

    --border-thin:      1px solid var(--color-border);
    --border-thick:     3px solid var(--color-border);
    --border-soft:      1px solid var(--color-border-light);
    --border-dark:      1px solid var(--color-border-dark);
    --border-coll:      1px solid var(--color-coll-hero);

    /* ── Radius ──────────────────────────────────────────── */
    --radius-none: 0px;       /* default — hard editorial edges */
    --radius-sm:   2px;       /* near-zero — barely there */
    --radius-pill: 9999px;    /* pill — tags only */

    /* ── Buttons ─────────────────────────────────────────── */
    --btn-h-sm:     32px;
    --btn-h-md:     40px;
    --btn-h-lg:     56px;
    --btn-px-sm:    var(--space-md);   /* 16px */
    --btn-px-md:    var(--space-xl);   /* 32px */
    --btn-px-lg:    var(--space-2xl);  /* 48px */
    --btn-font:     var(--font-display);
    --btn-size:     var(--text-label); /* 12px */
    --btn-weight:   var(--weight-heavy);
    --btn-tracking: var(--tracking-caps);
    --btn-radius:   var(--radius-none);
    --btn-max-w:    209px;
    /* Brand signature hover: font-style italic + text-transform uppercase */

    /* ── Shadows ─────────────────────────────────────────── */
    --shadow-none:    none;
    --shadow-sm:      0 1px 3px rgba(35, 31, 32, 0.08);
    --shadow-md:      0 4px 16px rgba(35, 31, 32, 0.10);
    --shadow-product: 0 8px 40px rgba(35, 31, 32, 0.12);

    /* ── Motion ──────────────────────────────────────────── */
    --ease-standard: cubic-bezier(0.25, 0.10, 0.25, 1.00);
    --ease-out:      cubic-bezier(0.00, 0.00, 0.20, 1.00);
    --ease-spring:   cubic-bezier(0.34, 1.56, 0.64, 1.00);
    --dur-fast:   120ms;
    --dur-med:    240ms;
    --dur-slow:   400ms;

    /* ── Z-Index ─────────────────────────────────────────── */
    --z-base:     0;
    --z-raised:   10;
    --z-dropdown: 100;
    --z-overlay:  200;
    --z-modal:    300;
    --z-toast:    400;
  }
}


/* ================================================================
   3. COLLECTION THEMES
   Apply via data-collection="[name]" on <body>, <section>,
   or any wrapper. Scoped — component-level theming works fine.

   Usage:
   <body data-collection="darkwave">  ← whole page
   <section data-collection="holy-hallucinations">  ← section only
   ================================================================ */
@layer tokens {

  [data-collection="darkwave"] {
    --color-coll-hero: var(--prim-darkwave);   /* #64A70B acid green */
    --color-coll-text: var(--prim-yellow);
  }

  [data-collection="bdsm-disco"] {
    --color-coll-hero: var(--prim-bdsm-disco); /* #4C4084 violet */
    --color-coll-text: var(--prim-yellow);
  }

  [data-collection="holy-hallucinations"] {
    --color-coll-hero: var(--prim-holy-hall);  /* #DC3513 red-orange */
    --color-coll-text: var(--prim-yellow);
  }

  [data-collection="alien-vacation"] {
    --color-coll-hero: var(--prim-alien-vac);  /* #890C58 deep magenta */
    --color-coll-text: var(--prim-yellow);
  }
}


/* ================================================================
   4. BASE RESET
   Minimal reset — use token values from day one.
   ================================================================ */
@layer base {
  *, *::before, *::after {
    box-sizing: border-box;
    margin: 0;
    padding: 0;
  }

  html {
    -webkit-text-size-adjust: 100%;
    scroll-behavior: smooth;
  }

  body {
    background-color: var(--color-bg);
    color: var(--color-text);
    font-family: var(--font-body);
    font-size: var(--text-body);
    font-weight: var(--weight-demi);
    line-height: var(--leading-body);
    letter-spacing: var(--tracking-body);
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
  }

  h1, h2, h3, h4, h5, h6 {
    font-family: var(--font-display);
    font-weight: var(--weight-heavy);
    line-height: var(--leading-tight);
    letter-spacing: var(--tracking-display);
    text-transform: uppercase;
    color: var(--color-text);
  }

  h1 { font-size: var(--text-display);  line-height: var(--leading-tight); }
  h2 { font-size: var(--text-headline); line-height: var(--leading-heading); }
  h3 { font-size: var(--text-subhead);  line-height: var(--leading-snug); letter-spacing: var(--tracking-heading); }
  h4 { font-size: var(--text-label);    line-height: var(--leading-body); letter-spacing: var(--tracking-caps); }
  h5 { font-size: var(--text-micro);    line-height: var(--leading-body); letter-spacing: var(--tracking-micro); }

  p {
    font-family: var(--font-body);
    font-size: var(--text-body);
    line-height: var(--leading-body);
    color: var(--color-text);
  }

  a {
    color: inherit;
    text-decoration: none;
  }

  img, svg {
    display: block;
    max-width: 100%;
  }

  :focus-visible {
    outline: 2px solid var(--color-focus);
    outline-offset: 2px;
  }
}


/* ================================================================
   5. BASE COMPONENTS
   Bare-bones component patterns using tokens.
   Override in your component stylesheets.
   ================================================================ */
@layer components {

  /* ── Buttons ─────────────────────────────────────────── */
  .btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    height: var(--btn-h-md);
    padding: 0 var(--btn-px-md);
    max-width: var(--btn-max-w);
    font-family: var(--btn-font);
    font-size: var(--btn-size);
    font-weight: var(--btn-weight);
    letter-spacing: var(--btn-tracking);
    border-radius: var(--btn-radius);
    cursor: pointer;
    transition: color var(--dur-fast) var(--ease-out),
                background-color var(--dur-fast) var(--ease-out),
                border-color var(--dur-fast) var(--ease-out);
    white-space: nowrap;
    text-decoration: none;
  }

  /* Brand signature hover — italic uppercase */
  .btn:hover {
    font-style: italic;
    text-transform: uppercase;
  }

  /* Primary — black fill */
  .btn-primary {
    background-color: var(--color-brand-black);
    color: var(--prim-white);
    border: 1px solid var(--color-brand-black);
  }
  .btn-primary:hover {
    background-color: var(--prim-rich-black);
    border-color: var(--prim-rich-black);
  }

  /* Secondary — outline */
  .btn-secondary {
    background-color: transparent;
    color: var(--color-text);
    border: 1px solid var(--color-border);
  }
  .btn-secondary:hover {
    background-color: var(--color-text);
    color: var(--prim-white);
  }

  /* Ghost — on dark backgrounds */
  .btn-ghost {
    background-color: transparent;
    color: var(--color-text-on-dark);
    border: 1px solid var(--color-border-dark);
  }
  .btn-ghost:hover {
    background-color: var(--prim-white);
    color: var(--prim-black);
  }

  /* Collection — uses current collection hero color */
  .btn-collection {
    background-color: var(--color-coll-hero);
    color: var(--color-coll-text);
    border: 1px solid var(--color-coll-hero);
  }
  .btn-collection:hover {
    filter: brightness(0.9);
  }

  /* Sizes */
  .btn-sm { height: var(--btn-h-sm); padding: 0 var(--btn-px-sm); max-width: none; }
  .btn-lg { height: var(--btn-h-lg); padding: 0 var(--btn-px-lg); max-width: none; }

  /* ── Typography utilities ─────────────────────────────── */
  .type-display  { font-family: var(--font-display); font-size: var(--text-display);  font-weight: var(--weight-heavy); line-height: var(--leading-tight);   text-transform: uppercase; }
  .type-headline { font-family: var(--font-display); font-size: var(--text-headline); font-weight: var(--weight-heavy); line-height: var(--leading-heading);  text-transform: uppercase; }
  .type-subhead  { font-family: var(--font-display); font-size: var(--text-subhead);  font-weight: var(--weight-heavy); line-height: var(--leading-snug);    text-transform: uppercase; letter-spacing: var(--tracking-heading); }
  .type-body     { font-family: var(--font-body);    font-size: var(--text-body);     font-weight: var(--weight-demi);  line-height: var(--leading-body); }
  .type-small    { font-family: var(--font-body);    font-size: var(--text-small);    font-weight: var(--weight-demi);  line-height: var(--leading-loose); }
  .type-label    { font-family: var(--font-body);    font-size: var(--text-label);    font-weight: var(--weight-demi);  line-height: 1; letter-spacing: var(--tracking-caps); text-transform: uppercase; }
  /* 2026-08-13 (Jules) — .type-micro WAS MISSING FROM THE SCALE. The token
     --text-micro has existed since the type rewrite and h5 uses it, but the
     UTILITY class only existed in static/css/wholesale.css — a stylesheet most
     pages never load. So every page using .type-micro outside wholesale rendered
     it as unstyled default text: not a crash, not a warning, just type quietly
     out of the system. Found while building /company, which had shipped it.
     ⚠️ check_dead_selectors cannot catch this shape — it finds CSS rules that
     match no markup, and this is the mirror, markup with no rule. Worth a
     second check one day. Display face + micro tracking, per the Figma
     foundations frame ("MICRO CAPS · caps · tracking 0.076em"). */
  .type-micro    { font-family: var(--font-display); font-size: var(--text-micro);    font-weight: var(--weight-heavy); line-height: var(--leading-body); letter-spacing: var(--tracking-micro); text-transform: uppercase; }
  /* ⭐ H4 · SG-H — the component-title rung. Display face, caps, between H3 and the UI label. */
  .type-sgh      { font-family: var(--font-display); font-size: var(--text-sgh);      font-weight: var(--weight-heavy); line-height: var(--leading-snug); letter-spacing: var(--tracking-caps); text-transform: uppercase; }
  /* ⭐ SMALL BODY — MH 2026-08-15: "Small Body - match to line items in sidebar
     (under headers)". The size a sidebar entry sits at, in full-strength ink. */
  .type-smallbody { font-family: var(--font-body); font-size: var(--text-smallbody); font-weight: var(--weight-demi); line-height: var(--leading-body); color: var(--ink); }
  /* ⭐ CAPTION / SUBTITLE — MH: "same size as small body but lighter grey."
     Same rung, one step down in weight of VOICE not of size. The grey is
     --ink-soft (#555), which tokens.css already annotates "secondary, captions". */
  .type-caption  { font-family: var(--font-body); font-size: var(--text-caption); font-weight: var(--weight-demi); line-height: var(--leading-body); color: var(--ink-soft); }

  /* ── Dark surface ─────────────────────────────────────── */
  .surface-dark {
    background-color: var(--color-bg-dark);
    color: var(--color-text-on-dark);
  }

  /* ── Collection surface ───────────────────────────────── */
  .surface-collection {
    background-color: var(--color-coll-hero);
    color: var(--color-coll-text);
  }

  /* ── Dividers ─────────────────────────────────────────── */
  .rule       { border: none; border-top: var(--border-thin); }
  .rule-thick { border: none; border-top: var(--border-thick); }
  .rule-soft  { border: none; border-top: var(--border-soft); }
}


/* ================================================================
   6. UTILITY CLASSES
   Single-purpose helpers.
   ================================================================ */
@layer utilities {
  /* Spacing */
  .mt-xs  { margin-top: var(--space-xs); }
  .mt-sm  { margin-top: var(--space-sm); }
  .mt-md  { margin-top: var(--space-md); }
  .mt-lg  { margin-top: var(--space-lg); }
  .mt-xl  { margin-top: var(--space-xl); }
  .mt-2xl { margin-top: var(--space-2xl); }
  .mt-3xl { margin-top: var(--space-3xl); }

  .pt-xl  { padding-top: var(--space-xl); }
  .pb-xl  { padding-bottom: var(--space-xl); }

  /* Color */
  .text-accent  { color: var(--color-text-accent); }
  .text-soft    { color: var(--color-text-soft); }
  .text-on-dark { color: var(--color-text-on-dark); }
  .text-coll    { color: var(--color-coll-hero); }

  /* Channel — sets --chc to the channel's colour; a component reads --chc
     (left bar = var(--chc), tint = color-mix(in srgb, var(--chc) var(--ch-tint), var(--paper))).
     The JS helper window.PBChan(<channel label>) returns the class. 10/10/26. */
  .ch-ig    { --chc: var(--ch-ig); }
  .ch-tt    { --chc: var(--ch-tt); }
  .ch-em    { --chc: var(--ch-em); }
  .ch-ss    { --chc: var(--ch-ss); }
  .ch-pa    { --chc: var(--ch-pa); }
  .ch-popup { --chc: var(--ch-popup); }
  .ch-ads   { --chc: var(--ch-ads); }
  .ch-gift  { --chc: var(--ch-gift); }
  .ch-press { --chc: var(--ch-press); }
  .ch-none  { --chc: var(--ch-none); }

  /* Layout */
  .container {
    width: 100%;
    max-width: var(--container-lg);
    margin-inline: auto;
    padding-inline: var(--space-xl);
  }

  /* Visibility */
  .sr-only {
    position: absolute; width: 1px; height: 1px;
    padding: 0; margin: -1px; overflow: hidden;
    clip: rect(0,0,0,0); white-space: nowrap; border: 0;
  }
}
