/* ==========================================================================
   tokens.css — design tokens & global accessibility rules
   Layer 1 of 2. MUST load before frame.css. Contains variables + the three
   self-hosted @font-face blocks + the two global a11y blocks at the bottom.
   No layout, no components.

   Design idea: Obys studio print aesthetic. Warm paper white ground, ink
   black display type, one signal color — safety orange-red — used the way
   print uses a spot color: sparingly, on numbers, prompts, hovers and the
   selection. Corners are sharp (radii 0); the personality comes from scale
   contrast (giant display vs tiny mono labels) and the ink/paper inversion
   at footer and marquee, not from ornament.

   Contrast is authored, not assumed. Measured ratios (WCAG relative
   luminance) are annotated on each token.
   ========================================================================== */

/* ---- Self-hosted machine voice: IBM Plex Mono (latin subset) --------------
   400 = regular, 600 = semibold. License: SIL OFL 1.1 (fonts/FONT-LICENSE.txt).
   font-display: swap — system mono renders first, Plex swaps in when ready. */
@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/ibm-plex-mono-latin-400-normal.woff2") format("woff2");
}

@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("../fonts/ibm-plex-mono-latin-600-normal.woff2") format("woff2");
}

/* ---- Self-hosted display voice: Archivo Black (latin subset) ---------------
   The Obys giant type. Single-weight family registered as `400 900`: any
   heavy request maps onto the real glyph set (no synthetic bold smear), and
   CJK text falling through the stack renders in a true system heavy cut.
   License: SIL OFL 1.1 (fonts/FONT-LICENSE.txt). ~18KB. */
@font-face {
  font-family: "Archivo Black";
  font-style: normal;
  font-weight: 400 900;
  font-display: swap;
  src: url("../fonts/archivo-black-latin-400-normal.woff2") format("woff2");
}

:root {
  color-scheme: light; /* native form controls & scrollbars render light */

  /* ---- Surfaces: warm paper neutrals, lightest to darkest ---------------- */
  --bg: #F2F0EA;            /* page background, warm paper white. Keep
                               <meta name="theme-color"> in sync (pages still
                               carry the old dark value — integrator TODO). */
  --surface: #FFFFFF;       /* raised panels: header bar, dropdowns, cards */
  --surface-2: #EAE6DC;     /* hover fills, nested raised panels */
  --border-color: #D9D5CA;  /* 1px hairlines: dividers, card outlines (1.3:1
                               vs --bg — structural lines, not text) */
  --border-strong: #141414; /* emphasized strokes: hover outlines, focused
                               fields, footer/marquee ink slabs (Obys hovers
                               stroke black, never grey). Same value as ink. */

  /* ---- Text: ink on paper -------------------------------------------------- */
  --text: #141414;          /* primary copy: 16.2:1 on --bg, 18.4:1 on
                               --surface. True ink, not soft black. */
  --text-dim: #6B675E;      /* secondary copy, captions, inactive nav:
                               4.9:1 on --bg (AA), 5.6:1 on --surface,
                               4.5:1 on --surface-2. Body-copy safe. */
  --text-faint: #807a67;    /* non-essential metadata, large sizes only:
                               3.8:1 on --bg, 4.3:1 on --surface. Below AA
                               for body copy — xs use is limited to uppercase
                               mono labels; never running text. */

  /* ---- The one accent: safety orange-red (two intensities) ----------------- */
  --accent: #FF4D00;        /* spot color: 2.9:1 on --bg. NOT body-text safe.
                               Reserve for display-size type accents, hover /
                               active states, the cursor, ::selection fill.
                               State must never ride on color alone — pair
                               with underline, weight or number. */
  --accent-dim: #C93D02;    /* body-size orange-red: 4.4:1 on --bg, 5.1:1 on
                               --surface, 4.1:1 on --surface-2. Use for small
                               orange text (.index-num, link hover, nav
                               counters) where --accent would fall under 4.5:1
                               and the type is not display-size. */
  --on-accent: #FFFFFF;     /* foreground on an --accent fill (::selection,
                               badges, accent buttons): 3.3:1 on #FF4D00 —
                               momentary highlight / large type only. */

  /* ---- Typography -----------------------------------------------------------
     Three voices. --font-display is the POSTER voice (Archivo Black; giant
     section heads, marquee; CJK falls through to the system heavy stack).
     --font-sans is the HUMAN voice (body copy, prose).
     --font-mono is the MACHINE voice (wordmark, nav, $ prompts, index
     numbers, metadata, inline code, the .term-cursor).
     CJK glyphs always fall back to system fonts; the Latin/digit shapes
     carry the brand. */
  --font-display: "Archivo Black", "Arial Black", "Segoe UI",
                  "PingFang SC", "Microsoft YaHei", "Noto Sans CJK SC", sans-serif;
  --font-sans: system-ui, -apple-system, "Segoe UI", Roboto, "PingFang SC",
               "Hiragino Sans GB", "Microsoft YaHei", "Noto Sans CJK SC", sans-serif;
  --font-mono: "IBM Plex Mono", ui-monospace, "Cascadia Code", "SF Mono", Menlo,
               Consolas, "Liberation Mono", monospace;

  /* Type scale, ratio 1.25. px values assume default 16px root.
     Body copy: --text-base (16px); lead paragraphs may use --text-md (20px,
     set line-height to var(--leading-body)). Component giants (.sec-head,
     .marquee-item) carry their own clamp() beyond this scale. */
  --text-xs: 0.75rem;       /* 12px: nav, .index-num, metadata, footer */
  --text-base: 1rem;        /* 16px: body copy */
  --text-md: 1.25rem;       /* 20px: lead paragraphs, marquee items */
  --text-lg: 1.5625rem;     /* 25px: h3 */
  --text-xl: 1.9375rem;     /* 31px: h2 (fixed contexts) */
  --text-2xl: 2.4375rem;    /* 39px: top of scale (fixed contexts) */

  /* Fluid heading sizes. clamp() endpoints land exactly on scale stops
     (25->31px and 31->39px across a 360->1140px viewport). Poster-scale
     headings use the .sec-head component clamp (36 -> 64px) instead. */
  --text-h1: clamp(1.5625rem, 1.39rem + 0.77vw, 1.9375rem);      /* 25 -> 31px, page H1 */
  --text-display: clamp(1.9375rem, 1.71rem + 1.03vw, 2.4375rem); /* 31 -> 39px, hero display */

  --leading-body: 1.6;      /* body copy (required by spec) */
  --leading-tight: 1.2;     /* headings */
  --leading-mono: 1.5;      /* mono lines, code, labels */

  /* ---- Spacing: 4px base scale. Token number = px / 4. -------------------
     No arbitrary margins/paddings anywhere. Section rhythm uses
     --space-section (64 -> 96px fluid) via frame.css .section. */
  --space-1: 0.25rem;       /*  4px: icon/text gaps */
  --space-2: 0.5rem;        /*  8px: intra-element padding */
  --space-3: 0.75rem;       /* 12px: chip padding, tight stacks */
  --space-4: 1rem;          /* 16px: default element gap, container gutter (mobile) */
  --space-6: 1.5rem;        /* 24px: grid gaps, grouped blocks, marquee item padding */
  --space-8: 2rem;          /* 32px: card padding, footer padding, desktop nav gap */
  --space-12: 3rem;         /* 48px: sub-section spacing */
  --space-16: 4rem;         /* 64px: section rhythm (mobile) */
  --space-24: 6rem;         /* 96px: section rhythm (desktop) */
  --space-section: clamp(4rem, 3rem + 4.2vw, 6rem); /* 64 -> 96px fluid */

  /* ---- Shape: sharp corners. The Obys edge is a right angle. -------------
     Keep 0 — do not round chips, cards or buttons. --radius-lg stays at 2px
     as a mercy for the rare floating layer (lightbox chrome) where a hard
     corner reads as a rendering artifact. */
  --radius-sm: 0;           /* inline code, chips, tags */
  --radius: 0;              /* default: panels, cards, buttons, media */
  --radius-lg: 2px;         /* modals / lightboxes only — rare */

  /* ---- Motion ------------------------------------------------------------- */
  --dur-fast: 120ms;        /* color / border / underline hover states */
  --dur-base: 180ms;        /* hover lift, menu open-close (spec band 150-200ms) */
  --dur-slow: 320ms;        /* rare, deliberate page-level reveals */
  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);    /* hovers, entrances */
  --ease-inout: cubic-bezier(0.65, 0, 0.35, 1);  /* state toggles both ways */

  /* ---- Stacking order ------------------------------------------------------ */
  --z-base: 0;              /* normal flow */
  --z-raised: 10;           /* content lifted above sibling backgrounds */
  --z-sticky: 100;          /* sticky site header */
  --z-overlay: 200;         /* mobile nav dropdown */
  --z-modal: 300;           /* modal / lightbox (models page viewer dialogs) */

  /* ---- Chrome metrics ------------------------------------------------------- */
  --header-height: 3.5rem;  /* 56px sticky header; scroll-padding compensates it */
  --container-max: 1140px;  /* spec: max content width */
}

/* ---- Global a11y: keyboard focus -------------------------------------------
   One visible focus style site-wide. Do not override per-component;
   if a component needs a custom ring, keep at least this contrast.
   Note: --accent on paper is 2.9:1, just under the 3:1 non-text bar —
   the 2px width + offset keep it visible; do not thin it further. */
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* ---- Global a11y: reduced motion --------------------------------------------
   Hard stop for every transition/animation, including the marquee scroll
   (frame.css re-declares a static state) and the terminal cursor blink
   (frame.css keeps it solidly visible). Components must never assume their
   animation always runs. */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}
