/* ═══════════════════════════════════════════════════════════════
   BUGATTI INSIGHTS — DESIGN TOKENS (task 3128)

   This file is the source of truth. If a colour, a type size, a
   spacing step or a radius appears anywhere in this codebase as a
   literal, it is a bug: it belongs here, and everything else
   references it with var().

   ── Why the file exists ──────────────────────────────────────────
   Before 3128 the same tokens were declared in five places that did
   not agree with each other:

     1. main.css :root                     — 48 tokens, 13 of them
                                             aliases of each other
     2. bugatti-dashboard.css              — 20 --bugatti-* tokens,
        .bugatti-dashboard-page              hard-coded hex
     3. bugatti-dashboard.css              — 27 --auth-* tokens
     4. BrandStyle.php print_css_vars()    — ~55 tokens, printed on
                                             wp_head priority 99
     5. dossier-template.php               — 10 tokens, own gold

   The practical consequence was that "what is the brand gold" had no
   answer: #E8C868, #c9a84c or a database value, depending on which
   page you were looking at and whether the Brand Style switch was on.

   ── The layer model, after 3128 ──────────────────────────────────
   There are now exactly three layers, in cascade order:

     tokens.css (this file)  the DEFAULTS. Loaded first, before any
                             other theme stylesheet, so every sheet
                             can rely on every token existing.

     BrandStyle.php          the OVERRIDE. Prints :root on wp_head
                             priority 99, i.e. after all stylesheets,
                             so the values an admin sets on the Brand
                             Style screen win. It overrides this file;
                             it no longer defines the system on its
                             own. The numbers below are the same
                             numbers as BrandStyle::defaults(), so
                             switching Brand Style off changes nothing
                             except who is in charge.

     dossier-template.php    a documented COPY. It is printed and
                             saved as a PDF outside the theme and
                             cannot reach this file, so it carries the
                             same numbers with a comment saying so.
                             That copy is the one exception, and it is
                             the only one.

   ── The --bi-* scale ─────────────────────────────────────────────
   The type/space/shape scale used to exist ONLY in BrandStyle.php,
   which meant that with Brand Style switched off the real design
   system was the 450 inline fallbacks in `var(--bi-x, 16px)`:
   invisible, ungreppable and impossible to change in one move. Every
   one of those fallbacks was measured against BrandStyle::defaults()
   before this file was written and all 450 agreed, so moving them
   here is a pure relocation: no rendered value changes.

   The fallbacks stay in place at the call sites on purpose. They are
   now documentation of the expected value rather than the mechanism.
   ═══════════════════════════════════════════════════════════════ */

:root {
  /* Tells the browser this document is dark-themed so native form/UI chrome
     (select popups, scrollbars, disabled-state defaults) defaults to a dark
     palette instead of assuming light — without this, some browsers render
     parts of an open <select> list with light-mode defaults even though the
     option's own CSS colors say otherwise. */
  color-scheme: dark;

  /* ── Colour ────────────────────────────────────────────────────────────
     The five colours of the design document (13-08, Martien): #080D16,
     #060A10, #E8C868, #4D472E, #F1EDE4. No derived in-between shades — the
     raised-surface token is the same colour as the surface rather than an
     invented step between it and the ground.

     Two rules, from 3121, and they are the whole point of this block:

       1. Never write a colour as a literal. Opaque gold is var(--gold);
          gold at an opacity is hsl(var(--gold-hsl) / <a>).
       2. A colour that is deliberately NOT a token — a darker press state,
          a dim variant, a darkened gold for white paper — is DERIVED from
          one, e.g. color-mix(in srgb, var(--gold) 86%, #000). A hand-picked
          hex is a snapshot of what the token happened to be on the day it
          was picked, and it stops being a variant the moment the token
          moves.

     The channel triples are what hex_to_hsl_channels() in BrandStyle.php
     produces for the same hex, digit for digit, so the two layers describe
     the identical colour whichever one is in charge. */

  /* Core HSL channels — for the hsl(var(--x-hsl) / <alpha>) pattern. */
  --bg-hsl:     219 47% 6%;
  --sur-hsl:    216 45% 4%;
  --sur2-hsl:   216 45% 4%;
  --gold-hsl:   45 74% 66%;
  --fg-hsl:     42 32% 92%;

  /* Resolved values. */
  --bg:    #080D16;
  --sur:   #060A10;
  --sur2:  #060A10;
  --gold:  #E8C868;
  --fg:    #F1EDE4;

  /* Derived. --line is the fifth design colour, a solid olive, not gold at
     an opacity: it is the hairline that separates panels and rules. */
  --line:       #4D472E;
  /* (3216) One thickness for the decorative divider/hairline family — the
     hero timeline's bottom edge (3201), the search-section hairlines under
     it, the footer band dividers. Width only: each divider keeps its own
     colour. Not for button outlines (--bi-btn-bw, 3119), table cell
     borders, focus outlines (3124) or card borders. BrandStyle prints no
     override for this (no admin field), so this :root value is canonical. */
  --bi-hairline-w: 2px;
  --border:     var(--line);
  --muted:      hsl(var(--fg-hsl) / .65);
  --muted2:     hsl(var(--fg-hsl) / .4);
  --gold-dim:   hsl(var(--gold-hsl) / .34);
  --gold-faint: hsl(var(--gold-hsl) / .1);
  /* A gold that has been lifted, for hover/press on a gold ground. Derived
     rather than picked: BrandStyle used to print --gold-light as var(--gold)
     itself, which made the one hover state that uses it (.bi-tour__next) a
     no-op, and main.css declared a hand-picked hsl(45 84% 72%) that stopped
     tracking the gold the moment the gold moved. */
  --gold-light: color-mix(in srgb, var(--gold) 82%, #fff);

  /* Not gold, despite living in the same corner of the wheel, and
     deliberately not folded into it: the green/amber/red status triad below
     and the --auth-* provenance palette in bugatti-dashboard.css. Those
     encode meaning, not brand. */
  --status-ok:   #3ecf8e;
  --status-warn: #f59e0b;
  --status-bad:  #d9534f;

  /* ── Typography ────────────────────────────────────────────────────────
     These names are the theme's own font stacks, matching what
     functions.php actually enqueues. BrandStyle overrides them together
     with its own webfont enqueue (Tinos / Roboto Condensed by default), so
     the family and the font files it needs always change as a pair. Setting
     BrandStyle's families here would name fonts this theme never loads. */
  --f-display: 'Cormorant Garamond','Playfair Display',Georgia,serif;
  --f-label:   'Inter',system-ui,sans-serif;
  --f-dis:     var(--f-display);
  --f-serif:   var(--f-display);
  --f-body:    var(--f-label);
  --f-ui:      var(--f-label);

  /* ── Type scale (px), from the style guide page 9 ──────────────────────
     Button/link is 11. These were BrandStyle-only until 3128. */
  --bi-size-h1:       62px;
  --bi-size-h2:       56px;
  --bi-size-h3:       40px;
  --bi-size-h4:       28px;
  --bi-size-subtitle: 22px;
  --bi-size-overline: 12px;
  --bi-size-button:   11px;
  --bi-size-body-lg:  18px;
  --bi-size-body:     16px;
  --bi-size-body-sm:  14px;

  /* Letter-spacing. Joe's design notes 30-08: 1px tracking, not the guide's
     0.28/0.32em. */
  --bi-ls-overline: 1px;
  --bi-ls-button:   1px;

  /* ── Space and shape ──────────────────────────────────────────────────
     radius 0 is guide rule 1: straight corners. */
  --bi-space-y:  96px;
  --bi-space-x:  70px;
  --bi-gap:      36px;
  --bi-radius:   0px;

  /* Hero geometry. --bi-hero-split is the % width of the hero text panel;
     --bi-tl-h the height of the hero era timeline. */
  --bi-hero-split: 38%;
  --bi-tl-h:       118px;

  /* Guide rule 3: homepage hero / category-nav / featured-type-card photo
     crop, 1400x860 landscape (Lessy 13-08, resolving the 1400x1860 portrait
     figure as a transcript typo). One constant for the CSS aspect-ratio and
     the server-side crop derivatives in functions.php bi_crop_image(). */
  --bi-img-ratio: 1400/860;

  /* ── Header bar height (task 3336) ────────────────────────────────────
     The DECLARED height of .bi-nav__bar, one value for every width
     (Martien 11-09: 50px; was 80px desktop / 64px phone). Not to be
     confused with --bi-header-h, which is the header's MEASURED rendered
     height (header.php sets it at runtime: bar + notch safe-area padding +
     the open search row) and is what layout offsets consume. This token is
     what the bar itself renders at, and the value every static
     `var(--bi-header-h, …)` fallback should quote so first paint matches
     the post-measurement layout. */
  --bi-nav-bar-h: 50px;

  /* ── The page shell (task 3120) ────────────────────────────────────────
     One width and one gutter for every content column on the site, so the
     left edge of the text does not move when you scroll from one section
     into the next or navigate from one page to another.

     Before this there were two parallel shells that never agreed: the
     theme's 1400px/48px and the dashboard's 1440px/32px, plus 1400px/40px
     for the six .bdb-tp-* type panels and 1440px/clamp(24px,4vw,64px) for
     the BCC band. On a 1600px screen that put the content's left edge at
     148px, 112px, 140px and 144px respectively · four different vertical
     lines, on pages that link straight into each other.

     The gutter is a curve rather than a stack of breakpoints. It used to be
     re-declared at nine thresholds (1100, 860, 800, 768, 640, 540, 480,
     420, 400) in duplicated selector lists across two files, and those
     lists had drifted apart: .bi-types-section, .ch-bcc__inner and
     .site-header__search-inner appeared in none of them and kept the full
     48px gutter down to a 320px phone (27% of the screen spent on margins),
     while .bdb-wrap appeared in two and ended up with 16px at 860 but 20px
     at 768 · wider as the screen got narrower. A clamp cannot drift.

     clamp(1rem, 4vw, 3rem) reads: 16px up to 400px wide, 26px at 640px,
     32px at 800px, 44px at 1100px, and 48px from 1200px up. */
  --bi-shell-maxw:   1400px;
  --bi-shell-gutter: clamp(1rem, 4vw, 3rem);
  /* For full-bleed bars whose CONTENTS have to line up with the shell above
     and below them · a sticky section-nav, a banded strip. Percentages in a
     custom property resolve against the element that uses it, so on a
     full-width bar this reads "half the leftover space, plus the gutter",
     collapsing to just the gutter once the viewport is narrower than the
     shell. Do not put it on an element that is not full-width. */
  --bi-shell-inset:  max(var(--bi-shell-gutter), calc((100% - var(--bi-shell-maxw)) / 2 + var(--bi-shell-gutter)));

  /* ── Buttons (task 3119) ──────────────────────────────────────────────
     The reference height is measured, not invented: the homepage Explore
     Collection button renders at min-height 3.3rem = 52.8px, and every CTA
     inherits it. The horizontal pair comes from brand-home.css's 16px/36px,
     the vertical half of which is supplied by --bi-btn-h instead. 1px border
     read too thin on this exact button when tested live with Joe (01-09,
     869etqyp2), and every role shares the width so the three never differ by
     a hairline when they sit side by side. */
  --bi-btn-h:  3.3rem;
  --bi-btn-px: 36px;
  --bi-btn-bw: 2px;

  /* ── Focus (task 3124) ─────────────────────────────────────────────────
     Width and offset of the keyboard focus treatment. The treatment itself
     lives in focus.css; only its measurements are tokens. */
  --bi-focus-w:      2px;
  --bi-focus-offset: 3px;

  /* ── Shared photo grade ───────────────────────────────────────────────
     A single normalizing filter applied to photographic imagery across
     cards/heroes site-wide, so photos sourced from different places
     (different lighting, different colour casts) read as one curated
     archive instead of a patchwork. Tune once, here. */
  --photo-grade: saturate(.93) contrast(1.05) brightness(.97);
}

/* ── Phone gutter (3191) ────────────────────────────────────────────────
   On a phone every element is full-width, so the gutter IS the left edge
   of the page and nothing can hide a difference in it. Measured on the
   homepage at 430px before this: the header logo sat at 16px, the hero
   copy at 22px, and every section below at 17.2px. That third number is
   the clamp's 4vw middle segment, so it was not even a constant · it
   slid to 16px at 390px and 25.6px at 640px while the logo above it
   stayed put. That sliding is why the page read as aligned on one device
   and off on the next.

   One flat value puts the logo line and every section below it on the same
   vertical, and holds it there across the whole phone range. Redefining
   the token rather than the rules means --bi-shell-inset follows along,
   and the rules that used to hardcode 16px/22px/1.5rem now point here.

   The value is 22px, not the 18px this block shipped with (3193 · Martien,
   10-09, after seeing it): the hero copy already sat at 22px and it carries the
   largest type on the page, so it is the line the eye actually reads the
   page against. Matching the rest of the page to the hero is one move;
   moving the hero in to meet a smaller number is two, and leaves the
   biggest element as the one that had to give way.

   Desktop is deliberately untouched (Martien, 10-09: "ik denk dat desktop
   toch hetzelfde moet blijven · dus alleen mobiel zo doen"). Above 640px
   a centred 1400px column and a full-bleed hero cannot share a left line
   anyway, and the asymmetric hero padding there is a considered choice. */
@media (max-width: 640px) {
  :root { --bi-shell-gutter: 22px; }
}

/* ═══════════════════════════════════════════════════════════════
   THE --bugatti-* LAYER

   The dashboard heritage has its own token names, used 492 times
   across the register pages. They are an alias layer now: they name
   the same colours as above rather than carrying their own hex.

   Every one of them points at a brand token. Three of them used to
   carry their own near-duplicate hex instead · #070c14 against the
   brand ground's #080D16, #0d1623 against the surface's #060A10,
   #e8dfc8 against the foreground's #F1EDE4 · hues 212-216 sitting
   next to the brand's 219-220, close enough to look like a mistake
   and far enough to look like a different site.

   That collapse was already decided and already live. brand-home.css
   made exactly these substitutions for the chassis column and the
   propose/contact pages ("the dashboard's blue-shifted hues read as a
   different site next to the brand ground"), and main.css repeated the
   old literals a third time so the /types/ cards would keep matching
   the category page. So the register was rendering two different
   greys on pages that link straight into each other, depending on
   which of the three blocks reached the element first. What 3128 does
   is finish it: the decision is applied once, here, and the two
   partial copies are deleted as the no-ops they became.

   Note on the cascade: this block used to sit in bugatti-dashboard.css
   on this same selector, which is a DESCENDANT of :root, so it
   silently beat BrandStyle.php's :root --bugatti-* line. That is why
   the Brand Style screen appeared to have no effect on register pages.
   Now that every value here is a var() onto a brand token, the admin's
   settings flow through: the selector still wins, but what it wins
   with is the token BrandStyle just set.
   ═══════════════════════════════════════════════════════════════ */
.bugatti-dashboard-page {
  --bugatti-bg:            var(--bg);
  --bugatti-panel:         var(--sur);
  --bugatti-panel-2:       var(--sur2);
  --bugatti-text:          var(--fg);
  --bugatti-gold:          var(--gold);
  /* Hairlines: the brand line at the guide's weight. */
  --bugatti-border:        var(--line);
  --bugatti-border-bright: var(--gold-dim);
  /* Guide rule 1: square corners. The dashboard's 12px radius was the single
     most visible "this is an admin screen" tell on the public pages. */
  --bugatti-radius:        var(--bi-radius);
  --bugatti-green:         var(--status-ok);
  /* (3121) Was #8a6b2a, a hand-picked darkening of the OLD gold that stopped
     tracking it the moment the token changed. Derived now. */
  --bugatti-gold-dim:      color-mix(in srgb, var(--gold) 55%, #000);
  /* (3122) Was #6b7a95, the dashboard's default muted text, rendered 113
     times as the label on .bdb-cat-nav-card across /types/, type detail and
     category detail, plus every muted paragraph on the chassis, propose and
     contact pages. It failed WCAG AA on four of the six grounds it was used
     over. var(--muted) is the site's own warm muted, the foreground at .65,
     which passes on all six. */
  --bugatti-muted:         var(--muted);
}

/* The one deliberate exception, and it is an audience, not a taste. The
   internal dashboard at page-bugatti-dashboard.php is a working screen for
   the people who maintain the register, not a page a visitor arrives on, and
   both 3122 and 869entcc9 fenced it off for that reason ("the real
   dashboard, which must keep its own palette"). Before 3128 that fence was
   implicit · the public templates were the ones being pulled out of the
   dashboard palette one at a time, so whatever was left behind stayed
   behind. Now the default is the brand and the exception has a name.
   Removing this rule brings the dashboard along with everything else, which
   is a one-line change whenever that is wanted. */
.bugatti-dashboard-page.bdb-admin-shell {
  --bugatti-bg:            #070c14;
  --bugatti-panel:         #0d1623;
  --bugatti-text:          #e8dfc8;
  --bugatti-border:        hsl(var(--gold-hsl) / .14);
  --bugatti-border-bright: hsl(var(--gold-hsl) / .32);
  --bugatti-radius:        12px;
}
