/* ==========================================================================
   Vagora Design System — Tier 1 primitives + Tier 2 semantic tokens
   v5.0 · The single source of truth. Nothing else defines a raw value.

   v5.0 IS A REBRAND. The dark page theme, the lime accent, the brand serif
   and the drawn construction grid are all withdrawn (design.md changelog).
   The system is now:

     · WHITE-FIRST. #FFFFFF canvas; #000000 is the one dramatic surface —
       full-bleed fields and big cards — never a page theme.
     · TWO COLOURS. Ink (#0F0F0F) does text, buttons and chrome. Secondary
       text is 45% OPACITY of the surface's primary, so one token composites
       correctly on every background. Status hues survive only where
       operational truth needs them (Console, status pills).
     · ONE TYPEFACE. Switzer, weights 400/500/600. On dark fields every
       weight above 400 steps down one — the swap lives in the weight
       tokens, applied by the field scope, never by hand.
     · SOFT GEOMETRY. The radius law (§12): one-line capsules are pills;
       content containers take 12/16/24 by size; anchored edges stay square.
     · DEPTH IS FROST AND LIFT, not borders. Frosted panels over imagery,
       an inverted lift shadow for floating cards, a float shadow for
       overlays and the dock. Hairlines are demoted to utility (tables,
       the rare divider) — construction is whitespace.

   Token NAMES are stable across the rebrand wherever the meaning survived,
   so Tier 3 re-skins instead of breaking. Mirror OS keeps its own scope:
   dark by physics, AA by policy, its v4 geometry intact until Phase 3.
   ========================================================================== */

:root {
  /* ── Primitives · colour ──────────────────────────────────────────────
     The whole brand palette. There is deliberately nothing else.         */
  --vg-white:     #FFFFFF;   /* the canvas                                */
  --vg-black:     #000000;   /* big fields: section bgs, big card bgs     */
  --vg-ink:       #0F0F0F;   /* text, buttons, the dock                   */
  --vg-ink-2:     #1F1F1F;   /* active dock item, button hover, brand cell*/
  --vg-alt-light: #F9F9F8;   /* container alt bg on white                 */
  --vg-alt-dark:  #0A0A0A;   /* container alt bg INSIDE black cards only —
                                on a #000000 section it is 1.05:1 and
                                invisible (§8.5)                          */

  /* Status hues — Console and status pills only. Never brand, never
     marketing decoration. Calibrated for white surfaces (all ≥ 4.5:1).   */
  --vg-status-success:  #0F7A52;
  --vg-status-warning:  #8A5A00;
  --vg-status-critical: #C0342E;
  --vg-status-info:     #2B5BD7;
  --vg-status-success-bg:  #EAF5F0;
  --vg-status-warning-bg:  #F7F0E2;
  --vg-status-critical-bg: #FAECEB;
  --vg-status-info-bg:     #EBF0FC;
  --vg-status-neutral:     #6F6F6F;
  --vg-status-neutral-bg:  var(--vg-alt-light);

  /* ── Tier 2 · surfaces and text (light is the only page theme) ──────── */
  --vg-surface-canvas:  var(--vg-white);
  --vg-surface-default: var(--vg-white);
  --vg-surface-alt:     var(--vg-alt-light);
  --vg-surface-field:   var(--vg-black);      /* use via .vg-field-dark    */
  --vg-surface-overlay: var(--vg-white);

  --vg-text-primary:    var(--vg-ink);
  /* 45% of the SURFACE'S primary — composites on white, alt, black and
     alt-dark alike. ≈ 3.1:1 on white: a documented aesthetic exception,
     MARKETING SURFACES ONLY (§8.4). */
  --vg-text-secondary:  color-mix(in srgb, var(--vg-text-primary) 45%, transparent);
  /* The AA secondary — Console and every operational surface. 5.3:1.     */
  --vg-text-secondary-aa: #6A6A6A;
  --vg-text-tertiary:   var(--vg-text-secondary-aa);
  --vg-text-muted:      var(--vg-text-secondary-aa);
  --vg-text-disabled:   color-mix(in srgb, var(--vg-text-primary) 28%, transparent);
  --vg-text-on-ink:     var(--vg-white);

  /* Actions — ink on light; the field scope inverts them.                */
  --vg-action-primary-bg:      var(--vg-ink);
  --vg-action-primary-fg:      var(--vg-white);
  --vg-action-primary-hover:   var(--vg-ink-2);
  --vg-action-primary-pressed: #2A2A2A;

  --vg-state-hover:    color-mix(in srgb, var(--vg-ink) 5%, transparent);
  --vg-state-pressed:  color-mix(in srgb, var(--vg-ink) 9%, transparent);
  --vg-state-selected: color-mix(in srgb, var(--vg-ink) 7%, transparent);
  --vg-state-disabled-bg: color-mix(in srgb, var(--vg-ink) 5%, transparent);

  /* Lines — UTILITY, not construction (§12.5). Tables, the rare divider. */
  --vg-border-width-hair: 1px;   /* utility lines; Mirror component borders */
  --vg-border-subtle:  color-mix(in srgb, var(--vg-ink) 8%, transparent);
  --vg-border-default: color-mix(in srgb, var(--vg-ink) 14%, transparent);
  --vg-border-strong:  color-mix(in srgb, var(--vg-ink) 24%, transparent);
  --vg-border-focus:   var(--vg-ink);

  /* ── Tier 1 · depth: frost, lift, float (§13) ─────────────────────────
     frost  — translucent panel over imagery, with backdrop blur. The
              default frost is dark (ink-tinted, white text), as on
              photography; the light frost is for pale imagery.
     lift   — the inverted shadow: a card lifted from below. Subtle, for
              white cards that must float on the white canvas.
     float  — real elevation: the dock, menus, dialogs.                   */
  --vg-dock-fg:     var(--vg-white);
  --vg-dock-hover:  rgba(255, 255, 255, 0.08);
  --vg-scrim:       rgba(15, 15, 15, 0.40);
  --vg-frost-dark:  rgba(15, 15, 15, 0.35);   /* the GLASS is the blur, not the
                                                 fill — at 55% this read as a
                                                 smoked slab (v5.0.1)          */
  --vg-frost-light: rgba(255, 255, 255, 0.55);
  --vg-frost-blur:  36px;
  /* Edge fade for a horizontally scrolling band. A mask is geometry, not
     palette — but it is still a literal, so it lives here in Tier 1.       */
  --vg-mask-edge-fade: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
  --vg-shadow-lift:  0 -4px 16px rgba(0, 0, 0, 0.05);
  --vg-shadow-float: 0 12px 32px rgba(0, 0, 0, 0.22), 0 2px 8px rgba(0, 0, 0, 0.14);

  /* ── Tier 1 · the radius law (§12.1) ──────────────────────────────────
     A single line of content in a capsule is a pill. Anything that holds
     a content area takes a fixed radius that grows with the container.
     Anchored edges stay square. Never pill a multi-line container.       */
  --vg-radius-control:   12px;   /* buttons                               */
  --vg-radius-input:     16px;   /* inputs — borderless, tinted           */
  --vg-radius-object:    16px;   /* standard cards, grid media            */
  --vg-radius-object-lg: 24px;   /* large cards, feature tiles, hero media,
                                    the black contact card, dialogs       */
  --vg-radius-pill:    9999px;   /* the dock, tags, chips, toggles        */
  --vg-radius-circle:  9999px;   /* avatars, dots, spinner                */
  --vg-radius-structure:   0;    /* anchored edges, table cells, bleeds   */

  /* ── Primitives · type ────────────────────────────────────────────────
     Switzer only. Hierarchy comes from SIZE and tight leading, not from
     weight (the Jeton discipline): 600 is the ceiling, and dark fields
     step every weight above 400 down one via the weight tokens.          */
  --vg-font-sans: "Switzer", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --vg-font-mono: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, Consolas, monospace;

  --vg-weight-regular:  400;
  --vg-weight-semibold: 600;
  /* Semantic weights — what components reference. The dark field scope
     redefines these; nothing else may. */
  --vg-w-display: 600;
  --vg-w-heading: 600;
  --vg-w-medium:  500;

  /* THE LADDER (§9.3). Every step is FLUID from 1280 to 2560 and clamped at
     both ends. Nothing caps out at 1440, which is the fault this replaces:
     the old scale reached its maximum by 1280 and then froze, so from there
     to a 27-inch display the type stayed put while the page doubled — and
     type that does not grow with its page reads as type that is shrinking.

     The steps widen as they climb (≈1.12 between the small sizes, ≈1.4 at
     the top). That is what an editorial ladder looks like: the bottom of a
     scale is read at a glance and needs only to be distinguishable, while
     the top is read as composition and needs real distance. The old scale
     had seven values inside 13–28px, several a single pixel apart — which
     is not a hierarchy, it is noise.

     Hierarchy comes from SIZE and tight leading, never from weight. */
  --vg-text-display:    clamp(2.75rem, 3.25rem + 3.125vw, 8.25rem);   /* 92 → 132 */
  --vg-text-h1:         clamp(2.25rem, 2.25rem + 2.031vw, 5.5rem);   /* 62 → 88 */
  --vg-text-h2:         clamp(1.875rem, 1.75rem + 1.406vw, 4rem);   /* 46 → 64 */
  --vg-text-h3:         clamp(1.5rem, 1.125rem + 0.9375vw, 2.625rem);   /* 30 → 42 */
  --vg-text-h4:         clamp(1.25rem, 1rem + 0.625vw, 2rem);   /* 24 → 32 */
  --vg-text-lede:       clamp(1.125rem, 0.875rem + 0.5469vw, 1.75rem);   /* 21 → 28 */
  --vg-text-body:       clamp(1.031rem, 0.8438rem + 0.3125vw, 1.344rem);   /* 17.5 → 21.5 */
  --vg-text-small:      clamp(0.9375rem, 0.75rem + 0.2734vw, 1.188rem);   /* 15.5 → 19 */
  --vg-text-label:      clamp(0.8438rem, 0.6875rem + 0.2344vw, 1.062rem);   /* 14 → 17 */
  --vg-text-caption:    clamp(0.7812rem, 0.625rem + 0.1953vw, 0.9375rem);   /* 12.5 → 15 */
  --vg-text-metric:     clamp(2.75rem, -0.25rem + 5.312vw, 8.25rem);   /* 64 → 132 */

  /* Display leading is tight and non-negotiable (0.95–1.06); tracking is
     slightly negative at display, slightly positive at label sizes —
     Switzer is a neo-grotesque, not Jeton's geometric, so the display
     correction runs the other way while the small-size one matches.      */
     EVERY STEP CARRIES ITS OWN LEADING AND TRACKING, one token each, named
     for the step. Three generic values (display / heading / body) could not
     express a ten-step ladder, so components filled the gap by hardcoding a
     number or by declaring nothing at all — and declaring nothing means
     inheriting body leading, which is how one 26.7px heading rendered at 1.5
     next to an identical one at 1.25. A size and its leading and its tracking
     are one decision. Set them together or the ladder is a suggestion.       */
  --vg-leading-display: 0.98;   --vg-tracking-display: -0.02em;
  --vg-leading-h1:      1.02;   --vg-tracking-h1:      -0.02em;
  --vg-leading-h2:      1.06;   --vg-tracking-h2:      -0.01em;
  --vg-leading-h3:      1.15;   --vg-tracking-h3:      -0.01em;
  --vg-leading-h4:      1.25;   --vg-tracking-h4:      -0.01em;
  --vg-leading-lede:    1.4;    --vg-tracking-lede:    -0.005em;
  --vg-leading-body:    1.5;    --vg-tracking-body:     0em;
  --vg-leading-small:   1.5;    --vg-tracking-small:    0em;
  --vg-leading-label:   1.2;    --vg-tracking-label:    0.01em;
  --vg-leading-caption: 1.45;   --vg-tracking-caption:  0em;

  /* A control is the third role. A button, a nav item, a pill, a table cell:
     all UI text, and they should read as one system rather than as five
     components that each decided for themselves. Leading 1.2 (a capsule is
     fixed-height and flex-centred, so it is free there and correct in a
     table row); tracking matches the label step. */
  --vg-leading-control:  1.2;
  --vg-tracking-control: var(--vg-tracking-label);

  /* Uppercase is a separate role, not a variant of caption: caps lose the
     word-shape a reader navigates by, and letterspacing is what gives it
     back (§9.6). Only .vg-eyebrow and .vg-navgroup may use it.             */
  --vg-tracking-eyebrow: 0.04em;

  /* Kept as an alias so the Mirror and console scopes keep resolving; new
     work names the step, never the family. */
  --vg-leading-heading: var(--vg-leading-h2);
  --vg-tracking-heading: var(--vg-tracking-h2);

  --vg-measure-prose: 68ch;

  /* ── Primitives · space (unchanged from v4) ───────────────────────────*/
  --vg-space-0: 0;      --vg-space-0-5: 2px;  --vg-space-1: 4px;
  --vg-space-1-5: 6px;  --vg-space-2: 8px;    --vg-space-3: 12px;
  --vg-space-4: 16px;   --vg-space-5: 20px;   --vg-space-6: 24px;
  --vg-space-8: 32px;   --vg-space-10: 40px;  --vg-space-12: 48px;
  --vg-space-16: 64px;  --vg-space-20: 80px;  --vg-space-24: 96px;
  --vg-space-32: 128px; --vg-space-40: 160px;

  /* ── Primitives · layout ──────────────────────────────────────────────
     One container. Sections separate by whitespace, never by rules.      */
  /* THE ROW (§11.1) — the page has ONE margin and ONE left edge.
     The margin is a FRACTION of the viewport, not a clamped pixel value, so
     the page keeps its proportions instead of its pixel dimensions: at every
     width the edge is 3% of the screen. A clamped inset does the opposite —
     it caps out and the page grows more crowded at the edges exactly where
     there is most room (measured on the v5.3 page: 3.8% at 1280 falling to
     1.9% at 2560).

     --vg-row is expressed against 100% of the parent, not 100vw, because
     100vw includes the scrollbar in most engines: a 100vw full-bleed element
     overflows horizontally the moment a scrollbar appears. Percentages of the
     block never do, so no scrollbar-width variable is needed.

     There is NO max width on the row. The row is a layout boundary, not a
     reading boundary — line length is set per element in `ch` (§9.5). A cap
     is what created two different left edges on one page. */
  --vg-gutter:  max(3vw, 20px);
  --vg-row:     calc(100% - var(--vg-gutter) * 2);
  --vg-inset:   var(--vg-gutter);   /* alias — components read this name */
  --vg-container-wide: 1440px;   /* Console working region                */
  --vg-container-prose: 680px;
  --vg-section: clamp(96px, 12vw, 160px);
  --vg-dock-h:  68px;
  /* One baseline for everything that floats at the bottom of a page — the
     dock and any chrome sitting beside it (§24.1). */
  /* Tighter than the side gutter on purpose: the dock is fixed, so every
     pixel of bottom margin is viewport it holds for the whole session. */
  --vg-dock-inset: max(1.6vw, 16px);

  /* ── Primitives · motion (unchanged from v4) ──────────────────────────*/
  --vg-dur-1: 120ms;  --vg-dur-2: 180ms;  --vg-dur-3: 240ms;
  --vg-dur-4: 320ms;  --vg-dur-5: 480ms;  --vg-dur-6: 720ms;
  --vg-ease-standard: cubic-bezier(.2, 0, 0, 1);
  --vg-ease-enter:    cubic-bezier(.05, .7, .1, 1);
  --vg-ease-exit:     cubic-bezier(.3, 0, .8, .15);
  --vg-stagger: 40ms;

  /* ── Primitives · z ───────────────────────────────────────────────────*/
  --vg-z-base: 0;     --vg-z-sticky: 100;  --vg-z-scrim: 200;
  --vg-z-modal: 300;  --vg-z-popover: 400; --vg-z-dock: 450;
  --vg-z-toast: 500;  --vg-z-tooltip: 600;
}

/* ==========================================================================
   THE DARK FIELD — a surface scope, not a page theme (§8.3).
   Apply data-surface="dark" (or .vg-field-dark) to a black section or big
   black card. Text inverts, secondary stays 45%-of-primary (≈ 4.4:1 here),
   actions invert, and EVERY WEIGHT ABOVE 400 STEPS DOWN ONE — light on
   dark blooms, so the same weight reads heavier on black.
   ========================================================================== */
[data-surface="dark"],
.vg-field-dark,
.vg-card--field {   /* the big black card IS a field — it carries the scope,
                       so no one can paint one without inverting its text */
  background: var(--vg-black);
  color: var(--vg-white);

  /* Nested "canvas"/alt surfaces resolve dark inside the field, so a
     component that paints its surface does not punch a white hole in it. */
  --vg-surface-canvas:  var(--vg-black);
  --vg-surface-default: var(--vg-black);
  --vg-surface-overlay: var(--vg-ink);

  --vg-text-primary:   var(--vg-white);
  --vg-text-on-ink:    var(--vg-ink);
  --vg-surface-alt:    var(--vg-alt-dark);

  /* EVERY DERIVED TEXT TOKEN IS RE-DECLARED HERE — it cannot be inherited.
     A custom property whose value references another custom property is
     resolved at the element where it is DECLARED, then inherits as a fixed
     value. So `45% of --vg-text-primary` declared once on :root stays 45%
     of INK for the life of the document, and lands as invisible ink-on-
     black inside this scope. This is the one place in the system where DRY
     loses to correctness; the `legible` gate holds the line. */
  --vg-text-secondary:  color-mix(in srgb, var(--vg-text-primary) 45%, transparent); /* ≈4.43:1 on black */
  --vg-text-secondary-aa: #9B9B9B;   /* 7.6:1 — captions, legal, the functional lines */
  --vg-text-tertiary:   var(--vg-text-secondary-aa);
  --vg-text-muted:      var(--vg-text-secondary-aa);
  --vg-text-disabled:   color-mix(in srgb, var(--vg-text-primary) 28%, transparent);

  --vg-action-primary-bg:      var(--vg-white);
  --vg-action-primary-fg:      var(--vg-ink);
  --vg-action-primary-hover:   var(--vg-alt-light);
  --vg-action-primary-pressed: #E8E8E7;

  --vg-state-hover:   rgba(255, 255, 255, 0.08);
  --vg-state-pressed: rgba(255, 255, 255, 0.12);
  --vg-border-subtle:  rgba(255, 255, 255, 0.10);
  --vg-border-default: rgba(255, 255, 255, 0.16);
  --vg-border-focus:   var(--vg-white);

  --vg-w-display: 500;
  --vg-w-heading: 500;
  --vg-w-medium:  450;
}

/* ==========================================================================
   MIRROR OS — its own scope, untouched by the rebrand's surface rules.
   Dark by physics (the content is a person composited against dark; a
   white 49" panel on a shop floor is a lightbox), AA by policy —
   functional first. Geometry stays v4 (radii derived for 1.5–2 m viewing)
   until Phase 3 re-verifies it; the progressive stroke is now WHITE — the
   last lime in the product is withdrawn.
   Hardware constants (§30): 1080×1920 logical, 28px type floor, 480px
   persistent budget, 88px edge inset.
   ========================================================================== */
[data-theme="mirror"] {
  --vg-n-1000: #0D0D0C; --vg-n-975: #131211; --vg-n-925: #1F1E1C;
  --vg-n-900:  #272523; --vg-n-850: #2E2C2A;

  background: var(--vg-n-1000);
  color: #FFFFFF;

  --vg-surface-canvas:  var(--vg-n-1000);
  --vg-surface-default: var(--vg-n-975);
  --vg-surface-alt:     var(--vg-n-975);
  --vg-surface-raised:  var(--vg-n-925);
  --vg-surface-overlay: var(--vg-n-900);

  --vg-text-primary:   #FFFFFF;
  --vg-text-secondary: #D9D8D5;   /* AA everywhere on this hardware      */
  --vg-text-secondary-aa: #D9D8D5;
  --vg-text-tertiary:  #C1BFBB;
  --vg-text-muted:     #A7A39D;
  /* The re-declaration rule (§8.2) reaches here too: this was inherited as
     28%-of-INK and rendered an unavailable size chip INVISIBLE on the panel
     rather than merely de-emphasised — the one state a shopper most needs to
     read. 42% of white on #0D0D0C is ~3.4:1: quiet, still legible at 2 m. */
  --vg-text-disabled:  color-mix(in srgb, var(--vg-text-primary) 42%, transparent);

  --vg-border-subtle:  rgba(255, 255, 255, 0.10);
  --vg-border-default: rgba(255, 255, 255, 0.16);
  --vg-border-strong:  rgba(255, 255, 255, 0.28);
  /* The one confirmation device: a white progressive stroke.            */
  --vg-border-accent:  #FFFFFF;
  --vg-text-accent:    #FFFFFF;

  /* The product band sits over the live render, so it needs a ground of
     its own: a bottom-weighted scrim, not a panel. (Referenced by both
     Mirror surfaces since v4 and dropped from the palette in the v5
     rewrite — it resolved to nothing and the band floated on the render
     until v5.1.) */
  --vg-scrim-media: linear-gradient(to top,
                      rgba(0, 0, 0, 0.88) 0%,
                      rgba(0, 0, 0, 0.72) 45%,
                      rgba(0, 0, 0, 0) 100%);

  /* v4 geometry survives on this hardware until Phase 3 (§30.1).        */
  --vg-radius-control: 4px;
  --vg-radius-object:  6px;

  --vg-w-heading: 500;

  /* Interaction constants (§30.2) — unchanged.                          */
  --vg-mirror-arm:      2000ms;
  --vg-mirror-select:   3000ms;
  --vg-mirror-hold:     1200ms;
  --vg-mirror-countdown: 4000ms;
  --vg-mirror-qr-dwell: 18000ms;
  --vg-mirror-reset:    15000ms;
  --vg-mirror-rule:        6px;
  --vg-mirror-dot:        14px;
  --vg-mirror-sheet-max: 700px;
  --vg-mirror-qr:        400px;
  --vg-mirror-target:    160px;
  --vg-mirror-target-min: 120px;
  --vg-mirror-target-gap: 48px;
  --vg-mirror-text-min:   28px;
  --vg-mirror-ui-budget: 480px;
}
