/* ============================================================================
 * site/styles/tokens.css — runtime token subset
 * Cascade position 1 of 5 (tokens → base → components → sections → responsive).
 *
 * PUBLISH ROOT: `site/` is the only publishable directory in this repository.
 * Nothing under `site/` may reference, import, link to, or embed anything from
 * the private research directories, the repository-root legacy page, the older
 * landing seeds, or the raw design deliveries. Two accepted repository-root
 * packages feed this tree — `design-system/` (tokens and contracts) and
 * `landing-content/` (authored copy, claim IDs, fixture values, asset
 * provenance) — and both feed it by *copy at authoring time*, never by a
 * runtime import. This file in particular takes its values from
 * `design-system/` alone; `landing-content/` carries no token. All paths inside
 * `site/` are relative.
 *
 * ---------------------------------------------------------------------------
 * SOLE TOKEN CARRIER
 * ---------------------------------------------------------------------------
 * This is the ONLY file under `site/` that carries token *values*. Every other
 * stylesheet, and every inline style, must reference these roles through
 * `var(--role)` and must never restate a literal that has a token. The three
 * media-query width literals in `responsive.css` are the single documented
 * exception, for the reason recorded there.
 *
 * ---------------------------------------------------------------------------
 * PROVENANCE AND TRACE (acceptance criterion 4)
 * ---------------------------------------------------------------------------
 * Source: `design-system/tokens.css` v2.0.0 (2026-08-01), the accepted
 * normalized GeoSense launch system. Copied verbatim, role name and value
 * identical, no value re-derived and no new value introduced here.
 *
 * The accepted package declares 154 roles with 1:1 name-and-value parity
 * between `design-system/tokens.css` and `design-system/tokens.json`
 * (leaf `cssVar`). This runtime subset ships **147** of them.
 *
 * Every role below traces to an accepted `design-system/tokens.json` group,
 * named in the section comment that introduces it, and to the identically
 * named custom property in `design-system/tokens.css`.
 *
 * EXCLUDED — 7 roles, the whole `tokens.json → breakpoint` group
 * (`--bp-floor`, `--bp-mobile`, `--bp-tablet`, `--bp-desktop-sm`,
 * `--bp-desktop`, `--bp-reference`, `--bp-ceiling`).
 * They are documentation values, not runtime values: `design-system/tokens.css`
 * labels them as such in-source, and `design-system/RESPONSIVE.md` states that
 * CSS media queries cannot reference custom properties, so a breakpoint token
 * can never be consumed by the runtime that needs it. Shipping them would put
 * seven unreadable values in every visitor's stylesheet. `responsive.css`
 * records the literal-to-role correspondence instead.
 *
 * No other role is withheld: every remaining role is consumed, or is contracted
 * to be consumed, by `base.css`, `components.css`, `sections.css`,
 * `responsive.css`, or `scripts/landing.js` under `design-system/COMPONENTS.md`,
 * `RESPONSIVE.md` and `MOTION.md`. Task 06 leaves one of the 147 —
 * `--state-disabled-text` — declared but no longer consumed at runtime; the
 * alias block at the foot of this file records why, and the role keeps its
 * accepted name and value so the Task 07 parity trace is unaffected.
 *
 * ADDED BY TASK 06 — 2 aliases, `--state-disabled-label` and
 * `--state-visited-on-ink`. Each is a reference to an accepted role, not a
 * value: this file still originates nothing.
 *
 * ---------------------------------------------------------------------------
 * OWNERSHIP
 * ---------------------------------------------------------------------------
 * 260802 Task 02 owns bilingual local font faces, package unicode ranges, and
 * the sole `:lang(vi)` token-value override. Task 03 local-font provenance is
 * preserved as history. Tasks 04–05 consume it without editing it. Task 06 may
 * add state/accessibility aliases. Any added role must first exist in
 * the accepted `design-system/` package — this file may never originate a
 * value.
 *
 * Responsive steps are exposed as explicit `*-tablet` / `*-mobile` roles and
 * this file holds no media queries, exactly as the accepted package does;
 * `responsive.css` performs the switch.
 * ========================================================================= */

/* Task 01 v4 correction — local, pinned design-system copies. Package
 * unicode-range declarations below are eligibility metadata, never glyph
 * capability evidence; tools/verify-font-routes.mjs checks every production
 * NFC scalar against the exact WOFF2 CMAP and Chromium PostScript identity.
 * The fallback stacks in the
 * family tokens below preserve the canonical metrics until each face arrives;
 * `font-display: swap` keeps text available and `font-synthesis: none` makes a
 * missing local byte observable instead of silently manufacturing a weight or
 * style.  These URLs are relative to site/styles/, so they stay inside the
 * publish root and cannot become a CDN fallback. */
@font-face {
  font-family: 'Inter Tight';
  src: url('../assets/fonts/inter-tight-latin.woff2') format('woff2');
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  font-synthesis: none;
  unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}

@font-face {
  font-family: 'Inter Tight';
  src: url('../assets/fonts/inter-tight-vietnamese.woff2') format('woff2');
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  font-synthesis: none;
  unicode-range: U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+0300-0301,U+0303-0304,U+0308-0309,U+0323,U+0329,U+1EA0-1EF9,U+20AB;
}

@font-face {
  font-family: 'Inter';
  src: url('../assets/fonts/inter-latin.woff2') format('woff2');
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  font-synthesis: none;
  unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}

@font-face {
  font-family: 'Inter';
  src: url('../assets/fonts/inter-vietnamese.woff2') format('woff2');
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  font-synthesis: none;
  unicode-range: U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+0300-0301,U+0303-0304,U+0308-0309,U+0323,U+0329,U+1EA0-1EF9,U+20AB;
}

@font-face {
  font-family: 'DM Mono';
  src: url('../assets/fonts/dm-mono-regular-latin.woff2') format('woff2');
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  font-synthesis: none;
  unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}

@font-face {
  font-family: 'DM Mono';
  src: url('../assets/fonts/dm-mono-medium-latin.woff2') format('woff2');
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  font-synthesis: none;
  unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}

:root {
  font-synthesis: none;

  /* trace: tokens.json → color.surface (9 roles) */
  --surface-bone: #fbfaf9;
  --surface-card: #FFFFFF;
  --surface-cream: #FBF5E6;
  --surface-cream-strong: #F2EBD6;
  --surface-ink: #1b181c;
  --surface-ink-panel: #12101A;
  --surface-ink-raised: #221D2E;
  --surface-ink-glow-from: #2C2545;
  --surface-ink-glow-to: #17141F;

  /* trace: tokens.json → color.text (7 roles) */
  --text-primary: #111111;
  --text-secondary: #46484d;
  --text-muted: #6E6A78;
  --text-on-ink: #F7F5FA;
  --text-on-ink-secondary: #BFBACB;
  --text-on-ink-muted: #9A95A6;
  --text-on-accent: #111111;

  /* trace: tokens.json → color.line (5 roles) */
  --line-default: #E7E3DB;
  --line-strong: #8C8578;
  --line-on-ink: rgba(247,245,250,0.12);
  --line-on-ink-strong: rgba(247,245,250,0.22);
  --line-ink-panel: #2A2537;

  /* trace: tokens.json → color.accent (4 roles) */
  --accent: #ff5d30;
  --accent-strong: #B23F10;
  --accent-on-ink: #FF9A6B;
  --accent-tint: #FCE7DA;

  /* trace: tokens.json → color.data (6 roles) */
  --data-primary: #2A5FD0;
  --data-on-ink: #9DBBFF;
  --data-series-a: #E4571F;
  --data-series-b: #2A5FD0;
  --data-series-c: #8A6BC4;
  --data-series-d: #C9A227;

  /* approved public-platform identity colors; identification only */
  --platform-gemini-blue: #4285F4;
  --platform-gemini-purple: #9B72CB;
  --platform-gemini-pink: #D96570;
  --platform-perplexity: #20808D;
  --platform-reddit: #FF4500;
  --platform-quora: #B92B27;
  --platform-facebook: #1877F2;
  --platform-instagram-purple: #833AB4;
  --platform-instagram-pink: #E1306C;
  --platform-instagram-orange: #F77737;
  --platform-wikipedia: #FFFFFF;
  --platform-youtube: #FF0000;
  --platform-openai: #101010;
  --platform-linkedin: #0A66C2;
  --platform-anthropic: #191919;
  --platform-deepseek: #5786FE;
  --platform-qwen: #6950EF;
  --platform-tiktok: #000000;
  --platform-threads: #000000;
  --platform-snapchat: #FFFC00;

  /* trace: tokens.json → color.state (15 roles) */
  --state-hover-surface: #F2EEE7;
  --state-active-surface: #E8E2D8;
  --state-hover-ink: rgba(247,245,250,0.08);
  --state-active-ink: rgba(247,245,250,0.14);
  --state-disabled-text: #8E8A97;
  --state-disabled-surface: #EFEBE4;
  --state-disabled-border: #D8D2C7;
  --state-success: #1F7A35;
  --state-success-tint: #DFEFE1;
  --state-success-on-ink: #79D08F;
  --state-warning: #8A5A0B;
  --state-warning-tint: #F7E7C9;
  --state-error: #B3261E;
  --state-error-tint: #F7E0DE;
  --state-visited-link: #8A3A5B;

  /* trace: tokens.json → color.signal (2 roles) — SYNTHETIC tags */
  --signal-text: #7E4A11;
  --signal-tint: #F7E7C9;

  /* trace: tokens.json → color.focus (2 roles) */
  --focus-ring: #16141A;
  --focus-ring-on-ink: #F7F5FA;

  /* trace: tokens.json → font.family (3 roles). Task 02 ships the declared
   * local Latin/Vietnamese WOFF2 subsets only; no remote font request exists. */
  --font-display: 'Inter Tight', 'Helvetica Neue', Arial, sans-serif;
  --font-sans: 'Inter', 'Helvetica Neue', Arial, sans-serif;
  --font-mono: 'DM Mono', 'SFMono-Regular', Consolas, monospace;
  --font-mono-ui: var(--font-mono);
  --font-mono-data: var(--font-mono);

  /* trace: tokens.json → font.weight (4 roles) */
  --weight-regular: 400;
  --weight-medium: 500;
  --weight-semibold: 600;
  --weight-bold: 700;

  /* trace: tokens.json → font.size (15 roles) */
  --text-h1-size: 68px;
  --text-h1-size-tablet: 50px;
  --text-h1-size-mobile: 38px;
  --text-h2-size: 50px;
  --text-h2-size-tablet: 38px;
  --text-h2-size-mobile: 31px;
  --text-h3-size: 20px;
  --text-h4-size: 17px;
  --text-sub-size: 18px;
  --text-body-lg-size: 16px;
  --text-body-size: 15px;
  --text-caption-size: 13px;
  --text-mono-label-size: 12px;
  --text-mono-data-size: 13px;
  --text-tag-size: 12px;

  /* trace: tokens.json → font.lineHeight (7 roles) */
  --text-h1-lh: 1.06;
  --text-h2-lh: 1.08;
  --text-h3-lh: 1.3;
  --text-sub-lh: 1.55;
  --text-body-lh: 1.6;
  --text-prose-lh: 1.7;
  --text-tight-lh: 1.2;

  /* trace: tokens.json → font.tracking (4 roles) */
  --tracking-display: -0.032em;
  --tracking-heading: -0.02em;
  --tracking-normal: 0;
  --tracking-label: 0.08em;

  /* trace: tokens.json → space (21 roles) — 4px scale plus page-rhythm roles */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 20px;
  --space-6: 24px;
  --space-7: 32px;
  --space-8: 40px;
  --space-9: 56px;
  --space-10: 80px;
  --space-11: 96px;
  --space-12: 120px;
  --section-y: 80px;
  --section-y-tablet: 76px;
  --section-y-mobile: 56px;
  --gutter: 24px;
  --gutter-mobile: 18px;
  --band-inset: 20px;
  --band-inset-mobile: 10px;
  --card-pad: 28px;
  --card-pad-mobile: 20px;

  /* Task 05 semantic rhythm aliases. These name the measured contract while
   * retaining the canonical 4px spacing scale as the value authority. */
  --rhythm-card-head-to-fixture: var(--space-2);
  --rhythm-head-stack: var(--space-2);
  --rhythm-section-head-to-content: var(--space-5);
  --rhythm-section-transition: var(--space-10);

  /* trace: tokens.json → container (3 roles) */
  --container-content: 1160px;
  --container-text: 640px;
  --container-wide: 1360px;

  /* trace: tokens.json → radius (7 roles) — band 36 → panel 28 → card 22 →
   * fixture 16 → chip 8; a child never has a larger radius than its parent */
  --radius-pill: 999px;
  --radius-band: 36px;
  --radius-panel: 28px;
  --radius-card: 22px;
  --radius-fixture: 16px;
  --radius-control: 12px;
  --radius-chip: 8px;

  /* trace: tokens.json → border (5 roles) — --border-control is the interactive
   * boundary on every surface; the hairline roles are decoration only */
  --border-hairline: 1px solid #E7E3DB;
  --border-control: 1.5px solid #8C8578;
  --border-accent: 1.5px solid #E4571F;
  --border-on-ink: 1px solid rgba(247,245,250,0.12);
  --border-on-ink-strong: 1px solid rgba(247,245,250,0.22);

  /* trace: tokens.json → shadow (5 roles) — --shadow-none inside ink bands */
  --shadow-none: none;
  --shadow-nav: 0 12px 30px rgba(22,20,26,0.09);
  --shadow-card: 0 14px 38px rgba(22,20,26,0.06);
  --shadow-panel: 0 24px 60px rgba(22,20,26,0.08);
  --shadow-float: 0 10px 24px rgba(22,20,26,0.13);

  /* trace: tokens.json → z (7 roles) */
  --z-base: 0;
  --z-raised: 10;
  --z-sticky: 90;
  --z-header: 100;
  --z-overlay: 200;
  --z-modal: 300;
  --z-toast: 400;

  /* trace: tokens.json → motion.duration (7 roles) */
  --duration-fast: 120ms;
  --duration-base: 200ms;
  --duration-gentle: 320ms;
  --duration-reveal: 480ms;
  --duration-loop-slow: 48s;
  --duration-loop-base: 42s;
  --duration-loop-fast: 36s;

  /* trace: tokens.json → motion.easing (4 roles) */
  --ease-standard: cubic-bezier(0.2, 0.7, 0.2, 1);
  --ease-enter: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-exit: cubic-bezier(0.4, 0, 1, 1);
  --ease-linear: linear;

  /* trace: tokens.json → motion.distance (2 roles) */
  --reveal-distance: 12px;
  --press-distance: 1px;

  /* trace: tokens.json → focus (3 roles) */
  --focus-width: 2px;
  --focus-offset: 2px;
  --focus-style: solid;

  /* ------------------------------------------------------------------------
   * TASK 06 — state and accessibility aliases
   *
   * The only edit this file is open to after Task 02, and only in this shape:
   * an alias whose VALUE is a reference to a role already declared above, so
   * nothing here originates a value and every existing role keeps the value
   * Task 02 traced to `design-system/tokens.css` v1.0.0. No role above was
   * changed, renamed or removed.
   * --------------------------------------------------------------------- */

  /* trace: tokens.json → color.text.secondary (`--text-secondary`, #4A4752).
   *
   * The accessible label colour for an INACTIVE control whose label must still
   * be read. `--state-disabled-text` (#8E8A97) on `--state-disabled-surface`
   * (#EFEBE4) measures **2.84:1** — WCAG 2.2 1.4.3 does exempt text inside an
   * inactive user-interface component, so that pair is defensible in general
   * and the role is retained above unchanged for exactly that use.
   *
   * It is declined here for one control. `Book a demo` is the page's single
   * primary conversion action and its configured mailto destination appears
   * in the header, mobile menu, hero, marketplace, closing band, and footer.
   * Its label is the only statement of what the page wants the visitor to do.
   * `DESIGN.md` §6.4 invariant 2 also forbids a
   * withheld state from taking a lower-contrast or de-emphasised treatment,
   * and a 2.84:1 label is precisely that. This alias measures **7.64:1** on
   * the same surface, so the label clears AA as ordinary text without relying
   * on the exemption.
   *
   * Raising the label does not weaken the disabled affordance, which is
   * carried non-chromatically as well as chromatically: the `disabled`
   * attribute and `aria-disabled="true"`, `cursor: not-allowed`, the muted
   * `--state-disabled-surface` fill where the enabled primary carries an ink
   * or accent fill, the `--state-disabled-border` where the enabled primary
   * has no border at all, and `--shadow-none`. `components.css` records the
   * `--state-disabled-border` boundary measurement and its 1.4.11
   * inactive-component exemption beside the rule that applies it. */
  --state-disabled-label: var(--text-secondary);

  /* trace: tokens.json → color.text.onInkSecondary (`--text-on-ink-secondary`,
   * #BFBACB).
   *
   * The visited role for a link on an ink surface. `--state-visited-link`
   * (#8A3A5B) is a light-surface value — 6.98:1 on `--surface-bone`, but 1.9:1
   * composited on `--surface-ink` — so the one link the system places on ink,
   * the announcement link, has no visited value in the accepted set. This
   * alias steps it from its `--accent-on-ink` rest colour to the secondary
   * on-ink text role: 9.39:1 on `--surface-ink`, clearly distinct from rest,
   * and still obviously a link because the underline is permanent. */
  --state-visited-on-ink: var(--text-on-ink-secondary);
}

/* Task 02 is the sole runtime token owner for Vietnamese-bearing UI roles. */
:lang(vi) { --font-mono-ui: var(--font-sans); }
