/* hkf-system.css - the one design token contract for every Highkeyflair page.
 *
 * Status Phase 0 (20/09/2026): CREATED BUT LINKED NOWHERE. This file declares
 * tokens only. It contains no element selectors and no page rules, so linking
 * it changes zero pixels. Phases 1 to 5 adopt it page by page.
 *
 * Why this file exists: each of the 18 pages redeclares its own :root tokens.
 * Two pages define a z-index scale, ten define a dead --radius-full token that
 * zero pages consume, and potluck.html carries 152 hardcoded rgba() literals.
 * A contract that is not in one file drifts. This is the one file.
 *
 * Intended cascade (from Phase 1 on): link this file BEFORE each page's own
 * <style> blocks, so page deltas keep working by source order. This mirrors
 * the opposite choice in shared/hkf-mobile.css, which links AFTER page styles
 * because the mobile layer must win ties. The system file is a base, not an
 * override.
 *
 * Companion docs: docs/brand.md (Budgets plus ramp, states, contrast, accent),
 * docs/design/101-de-slop-full-plan.md (the phased plan), docs/audits/
 * 100-declaude-audit-2026-09-20.md (the Stage 1 measurement record).
 *
 * Presentation only. No IDs, routes, copy or behaviour are declared here.
 */
:root{
  /* ---------- surface ramp (verified 20/09/2026, same WCAG maths as
   * tests/a11y-contrast.test.js). Derived from --bg #0A0A0B by white overlay.
   * A step alone is 1.07:1 to 1.38:1 against its neighbour, so every step is
   * always paired with a border step. Ramp without border is invisible. */
  --hkf-s0:#0A0A0B; /* page. Existing --bg on all 18 pages. */
  --hkf-s1:#141414; /* card. 1.07:1 vs page. Existing --paper. */
  --hkf-s2:#1d1d1d; /* raised. 1.17:1 vs page. Existing --paper-2. */
  --hkf-s3:#252526; /* overlay. 1.29:1 vs page. NEW. Menus and dropdowns. */
  --hkf-s4:#2a2a2b; /* modal. 1.38:1 vs page. NEW. Dialogs and toasts. */

  /* ---------- border scale. Borders do the separation work the ramp cannot
   * do alone. Measured on #141414: line-2 1.22:1, line 1.46:1. */
  --hkf-line-2:rgba(255,255,255,.08);
  --hkf-line:rgba(255,255,255,.14);
  --hkf-line-strong:rgba(255,255,255,.16);

  /* ---------- layer to z-index binding. Reuses the scale studio-os.html and
   * ops.html already define. Higher z always sits on a higher surface. */
  --hkf-z-card:1;
  --hkf-z-chrome:10;
  --hkf-z-sticky:20;
  --hkf-z-overlay:100;
  --hkf-z-toast:200;

  /* ---------- focus. ONE value for all 18 pages (Phase 1 adopts it).
   * Solid turmeric gold: 8.17:1 on the page, 7.60:1 on #141414. Replaces four
   * competing values, three of which fail the 3:1 non-text floor:
   * --gold-border 2.48:1 (table.html), 45 percent crimson 1.63:1
   * (pricing.html, 404.html). Offset 3px is adopted from table.html so the
   * change reads as promotion, not invention. */
  --hkf-focus:#c9a05c;
  --hkf-focus-width:2px;
  --hkf-focus-offset:3px;

  /* ---------- accents, CORRECTED 20/09/2026 by measurement.
   * Gold is the single UI accent for emphasis: 8.17:1 on the page.
   * Crimson is the STATE colour, not a decorative second accent. Measured across all pages: 139
   * rules use it on a border and 134 as a background, and ZERO use it as a text colour - because
   * solid crimson is 3.93:1 on the page and 3.66:1 on a card. That clears the 3:1 NON-TEXT floor
   * and fails AA text, so confining it to borders and fills is exactly right, and
   * tests/a11y-contrast.test.js pins the split. The readable text form is --bronze-text (5.90:1).
   * The wording that used to sit here ("crimson is reserved for the wordmark and one selection
   * spine") described a site that does not exist, and nobody should build it: it would strip the
   * hover, focus and selected states from 139 rules. docs/design/103 item 6.4 read the 3.93:1
   * figure as a reason to RETIRE crimson; it is the reason crimson is confined to non-text. */
  --hkf-gold:#c9a05c;   /* 8.17:1 on page. Emphasis, rules, focus, selection. */
  --hkf-bronze:#c93a45; /* 3.93:1 page, 3.66:1 card. NON-TEXT only: borders and fills. */

  /* ---------- geometry. 2px default everywhere. 999px is allow-listed ONLY
   * for: status and live indicators, the seat chooser, category and department
   * filter chips, wizard step indicators, flush scrollbar thumbs, decorative
   * circles. Test: filter, indicate or choose (pill), or commit, navigate,
   * submit or meter (sharp)? Meters are never pills: 3px tall, 2px radius,
   * single hue. */
  /* The flat composite of the three soft crimson panel ramps that used to wash
   * .kpi.primary, #sec-pay and .seat.cta (10, 8 and 15 percent crimson ramping to
   * transparent over #141414). A panel tint is a SURFACE, so it is a step, not a
   * gradient: flat, one value, and always paired with the crimson border it already had. */
  --hkf-accent-surface:#1d1617;

  /* The RECESSED CONTROL wash, 20/09/2026. The canonical INPUTS block on twelve pages pinned
   * #101010 as a deliberate step DARKER than the card, so a field reads as cut into its surface.
   * The grey collapse initially merged it into --paper (#141414), which flattened that step, and
   * tests/ui-convergence.test.js caught it. This is the case docs/design/103 section 4 names:
   * a literal that maps to no token is not drift, it is a token the set does not have yet. */
  --hkf-field:#101010;

  /* ---------- the table material, hoisted 20/09/2026 (docs/design/105 section 2d).
   * potluck.html and table.html drew the table ground with a BYTE-IDENTICAL radial, and events.html
   * drew a cousin from the same three colours at different geometry (a card cover, not the table).
   * The disc is a sanctioned physical object (docs/brand.md:111) and it was drawn with TWO different
   * highlight values, #2e241a on potluck and #33261b on table. That is drift rather than intent, so
   * it is one value now. The disc highlight is the only rendered change from this hoist and
   * scripts/style-snapshot.mjs pins it to a single element. Colours once, gradients composed from
   * them, so a page cannot half-adopt the material. */
  --hkf-walnut-1:#2b2118;
  --hkf-walnut-2:#1a1512;
  --hkf-walnut-3:#100d0b;
  --hkf-walnut-4:#0b0a09;
  --hkf-disc-hi:#2e241a;
  --hkf-disc-mid:#1d1712;
  --hkf-disc-lo:#12100d;
  --hkf-table-ground:radial-gradient(900px 420px at 50% 34%,var(--hkf-walnut-1) 0%,var(--hkf-walnut-2) 38%,var(--hkf-walnut-3) 62%,var(--hkf-walnut-4) 100%);
  --hkf-disc-surface:radial-gradient(ellipse at 50% 42%,var(--hkf-disc-hi) 0%,var(--hkf-disc-mid) 55%,var(--hkf-disc-lo) 100%);

  /* The LIGHT CARD family: the cream seat and place cards that sit on the dark table. Hoisted
   * 20/09/2026 with the Phase 2 seat work. potluck.html and events.html carried three
   * near-identical literals (#f6f1e6 -> #ece4d3 and #ece4d2, a 1/255 difference nobody can see)
   * and the new hover step would have added two more. One family, one hover step, one border. */
  --hkf-seat-surface:linear-gradient(180deg,#f6f1e6,#ece4d3);
  --hkf-seat-surface-hover:linear-gradient(180deg,#fbf7ee,#f1ead9);
  --hkf-seat-line:rgba(28,26,23,.28);

  /* ---------- legacy aliases, 20/09/2026 (ledger 102 item 10). The page-level token names the
   * pages already use become ALIASES of the contract above, so there is one source of truth for
   * each concept instead of a duplicate declaration on 2 to 21 pages. Verified uniform first:
   * every declaring page carries the identical value (--radius 2px on 21, --line-2 on 16, the
   * four z steps on 2, identical to --hkf-*). These are the current palette, not the retired
   * warm-sand one; --sand, --cream, --espresso, --taupe, --faint, --straw and --bronze-link are
   * deliberately NOT aliased because they hold retired values and need a design decision. */
  --line-2:var(--hkf-line-2);
  --radius:var(--hkf-radius);
  --z-chrome:var(--hkf-z-chrome);
  --z-sticky:var(--hkf-z-sticky);
  --z-overlay:var(--hkf-z-overlay);
  --z-toast:var(--hkf-z-toast);
  --muted-light:#b3aa99;
  --papery:#f2ede4;
  --papery-ink:#1c1a17;
  --ok-text:#7fdcab;
  /* Near-consensus aliases: 8 of 9 declaring pages already write exactly this, and the ninth
   * writes the same VALUE by hand (#e06a6a is --danger, #6fcf97 is --ok). Same resolved colour,
   * so aliasing is a no-op that removes two more duplicated names. */
  --red:var(--danger);
  --green:var(--ok);
  --hkf-radius:2px;
  --hkf-radius-full:999px;

  /* ---------- motion. One duration, one curve. No bespoke timings. */
  --hkf-duration:150ms;
  --hkf-ease:cubic-bezier(.4,0,.2,1);

  /* ---------- state grammar (documented here, applied in Phase 1).
   * default:  transparent background, 1px --hkf-line-2.
   * hover:    surface steps up one level, border to --hkf-line. No shadow.
   * pressed:  1px translate, no blur.
   * selected: 1.5px gold border, surface up one level, plus a written marker.
   * disabled: 45 percent opacity, no pointer, no border change.
   * focus:    the single gold ring above. */

  /* ---------- shadow budget. Chrome gets two shadows and no more:
   * panel 0 1px 0 rgba(0,0,0,.35), dark card inset 0 1px 0
   * rgba(255,255,255,.06). No blurred glow on interactive states.
   * Sanctioned exceptions (physical hardware, not decor): the flap clock
   * digits (#slClock, .fdigit) and the table disc (.flat-disc). */
}

/* ---------- inherited site tokens, hoisted 20/09/2026 ---------------------------
 * This file used to carry only the new contract tokens. Below are the 55 tokens
 * that 8 or more of the 18 pages already declared with an identical value, declared
 * here once so the pages can stop repeating them. That is item 2 of docs/audits/102.
 *
 * Only TOP-LEVEL :root declarations are considered. Six :root blocks sit inside an
 * @media (potluck at 700px and 641px, studio-os at 1100px, print blocks in pricing,
 * privacy and terms); those are deliberate conditional overrides and stay in their
 * pages untouched.
 *
 * LATE ADDITIONS, 20/09/2026 (item 2B of docs/design/103). A measured re-check corrected the
 * note that used to sit here. It claimed seven pages "REFERENCE these tokens without declaring
 * them and lean on an inline var() fallback". That was wrong twice over: the references are BARE
 * var(--x) calls with no fallback at all, and --line-2 and --radius are declared on every page
 * that uses them, so neither was ever a defect. The real gap was narrower:
 *     privacy.html and terms.html referenced 7 tokens they never declared
 *       (--bronze-bg, --bronze-border, --bronze-text, --ok, --radius-full, --ease, --duration)
 *     events.html referenced --text-sm and --gold-border
 *     potluck.html and rsvp.html referenced --text-sm
 * A bare var() with no declaration is invalid at computed-value time, so the whole declaration
 * was silently dropped on those five pages. Every declaring page agreed on the value, so the
 * intended value was never in doubt. They are declared below. Because this link comes BEFORE
 * each page's own <style>, the thirteen pages that already declare these keep their identical
 * value: only the five broken pages change, and they change to the value the other pages use.
 *
 * Cascade: this link comes BEFORE each page own <style>, so a page that still declares
 * a token keeps winning. This step therefore changes nothing on its own, which is the
 * point: the page duplicates are removed next, and the sweep has to stay at zero moves.
 */
:root{
  --bronze:#c93a45;
  --ink:#f4f4f4;
  --ink-2:#d0d0d0;
  --line:rgba(255,255,255,.14);
  --muted:#a3a3a3;
  --paper:#141414;
  --font-mono:ui-monospace,'SF Mono','Cascadia Mono',Menlo,Consolas,monospace;
  --hair:rgba(255,255,255,.09);
  --body-copy:#d9d9d9;
  --paper-2:#1d1d1d;
  --ok-bg:rgba(111,207,151,.12);
  --focus-ring:0 0 0 3px var(--gold);
  --radius-lg:2px;
  --radius-sm:2px;
  --gold-bg:rgba(201,160,92,.14);
  --radius-md:2px;
  --radius-xl:2px;
  --danger-bg:rgba(224,106,106,.12);
  --shadow-lg:0 8px 32px rgba(0,0,0,.5);
  /* Added 20/09/2026: the popover step above --shadow-lg. Captured from the dropdown menus on
     potluck.html (0 22px 44px rgba(0,0,0,.55)) so adopting the scale changed no pixel. */
  --shadow-xl:0 22px 44px rgba(0,0,0,.55);
  --text-2xl:32px;
  --text-4xl:56px;
  --text-base:16px;
  --text-lg:20px;
  --text-xl:24px;
  --accent:var(--bronze);
  --accent-bg:var(--bronze-bg);
  --accent-border:var(--bronze-border);
  --bg:#0A0A0B;
  --bg-subtle:var(--paper-2);
  --card:transparent;
  --card-bg:var(--paper);
  --font-weight-bold:700;
  --font-weight-medium:500;
  --font-weight-normal:400;
  --font-weight-semibold:600;
  --green-bg:var(--ok-bg);
  --green-border:rgba(111,207,151,.3);
  --ink-secondary:var(--ink-2);
  --red-bg:var(--danger-bg);
  --red-border:rgba(224,106,106,.3);
  --shadow:var(--shadow-sm);
  --shadow-1:0 1px 0 rgba(0,0,0,.35);
  --shadow-focus:var(--focus-ring);
  --shadow-md:0 4px 16px rgba(0,0,0,.4);
  --shadow-sm:0 1px 2px rgba(0,0,0,.4);
  --shadow-xs:var(--shadow-1);
  --space-1:4px;
  --space-2:8px;
  --space-3:12px;
  --space-4:16px;
  --space-5:20px;
  --space-6:24px;
  --space-7:32px;
  --space-8:48px;
  --space-9:72px;
  /* ---------- late additions, 20/09/2026. Uniform across every page that declared them, so the
   * value is the consensus value and no page delta exists to preserve. See the note above for
   * which five pages were resolving these to nothing before this step. */
  --bronze-bg:rgba(201,58,69,.14);
  --bronze-border:rgba(201,58,69,.4);
  --bronze-text:#e06570; /* 5.90:1 on the page. Readable crimson for text. */
  --ok:#6fcf97;
  --text-sm:14px;
  --track-kicker:.22em;  /* GO-2 A2: one uppercase kicker/eyebrow voice */
  --track-meta:.14em;    /* GO-2 A2: one meta voice — spec strips, datelines, micro meta */
  --radius-full:999px;
  --ease:cubic-bezier(.4,0,.2,1);
  --duration:150ms;
  --gold-border:rgba(201,160,92,.45); /* 2.48:1. A hairline, never a focus ring. */

  /* ---------- tokens that tests/token-declared.test.js found referenced with NO declaration
   * anywhere. A bare var() whose token is never declared makes the whole declaration invalid at
   * computed-value time, so the browser drops it and the page renders without that value.
   * The --gold case was the worst of these: it is the focus colour, so privacy.html, rsvp.html,
   * terms.html, events.html, 404.html and sessions.html were rendering :focus-visible with NO
   * outline at all, which is a live WCAG 2.4.7 (Focus Visible) failure rather than a cosmetic one.
   * Values are the consensus of the pages that do declare them; none had a competing value. */
  --gold:#c9a05c;      /* declared by 12 pages, referenced by 16. Focus colour, 8.17:1. */
  --danger:#e06a6a;    /* declared by 11 pages, referenced by 13. Unanimous. */
  --ok-border:var(--green-border); /* one use (gallery.html:608 inline style). Aliased to the
                                      existing green border so there is one source of truth, the
                                      same way --green-bg aliases --ok-bg. */
  --text-xs:13px;      /* the site's helper-text size: 6 of 9 declaring pages use 13px, and the
                          Stage 1 survey found 86 of 103 .small.muted nodes at 13px. studio-os
                          keeps its own 14px and two pages keep 12px; those still declare their
                          own value and win. This declaration only rescues the pages that
                          referenced the token and declared nothing, potluck.html among them. */
}

/* ---------- Themed scrollbars for all pages -------------------------------
 * 8 published pages (pricing, terms, privacy, 404, ops, my-booking, events,
 * sessions) lack the global themed scrollbar that the other 11+ pages declare
 * inline. The value is the consensus across every page that already declares
 * it — byte-identical across home, book, gallery, client, equipment, studio-os,
 * client-portal, potluck, rsvp — so this is a no-op for those pages (their own
 * declaration wins by source order) and a net addition for the rest.
 * This avoids every default-browser scrollbar appearing unthemed on the dark
 * canvas, which measures at most 1.46:1 contrast (unstyled track on #0A0A0B).
 * The global thin scrollbar is fine for page-level scrollbars; horizontal
 * scrollers that intentionally suppress it use scrollbar-width:none locally. */
*{scrollbar-width:thin;scrollbar-color:rgba(255,255,255,.25) transparent}
::-webkit-scrollbar{width:10px;height:10px}
::-webkit-scrollbar-thumb{background:rgba(255,255,255,.22);border-radius:999px;border:2px solid transparent;background-clip:padding-box}
::-webkit-scrollbar-thumb:hover{background:rgba(255,255,255,.4);border:2px solid transparent;background-clip:padding-box}
::-webkit-scrollbar-track{background:transparent}

/* ---------- GO-3 (N3/B10): header contract + table scroll affordance ---------- */
/* Header rows never break mid-item: nav items, action chips and the wordmark stay whole. */
header nav a,header .header-actions a,header .header-actions .btn,header .brand-name,header .brand h1,header .brand p{white-space:nowrap}
/* Wrapped tables show they scroll: thin thumb, edge fade only where space is tight. */
.tablewrap,.table-wrap{scrollbar-width:thin;scrollbar-color:var(--line-2,rgba(255,255,255,.16)) transparent}
.tablewrap::-webkit-scrollbar,.table-wrap::-webkit-scrollbar{height:6px}
.tablewrap::-webkit-scrollbar-thumb,.table-wrap::-webkit-scrollbar-thumb{background:var(--line-2,rgba(255,255,255,.16));border-radius:2px}
@media(max-width:640px){.tablewrap,.table-wrap{-webkit-mask-image:linear-gradient(to right,#000 calc(100% - 24px),transparent 100%);mask-image:linear-gradient(to right,#000 calc(100% - 24px),transparent 100%)}}
