/* Design tokens — the only place a colour, size or spacing value is declared.
 * Spec: feature/crm-website/DESIGN.md. Ratios there are marked (I) and are regenerated by
 * tests/check-contrast.mjs; do not hand-edit a ratio into a comment here. */

/* ── Font ──────────────────────────────────────────────────────────────────────
 * Self-hosted Inter subset. The app imports Inter from Google Fonts
 * (web/src/app/globals.css) — exactly the external request AC3 bans — so the site
 * self-hosts the same face, which also keeps the product mockups truthful.
 * The metric-override block is what makes font-display: swap shift-free (AC17). */
@font-face {
  font-family: "Inter";
  /* RELATIVE to this stylesheet, not root-absolute. D16 namespaces the whole
   * bundle under /site/, so "/assets/…" 404'd in production and the face never
   * loaded — every visitor since launch has read the page in the Arial fallback,
   * silently, because a missing @font-face src is not an error anywhere a human
   * would see it. Relative keeps it correct wherever the bundle is mounted. */
  src: url("../assets/inter-var-latin.woff2") format("woff2");
  font-weight: 400 700;
  font-display: swap;
  unicode-range: U+0000-00FF, U+2000-206F, U+2190-21BB, U+2212;
}
@font-face {
  font-family: "Inter Fallback";
  src: local("Arial");
  size-adjust: 107.12%;
  ascent-override: 90.2%;
  descent-override: 22.48%;
  line-gap-override: 0%;
}

:root {
  --font-sans: "Inter", "Inter Fallback", system-ui, -apple-system, sans-serif;

  /* ── Type scale — marketing amplitude, app vocabulary ────────────────────────
   * The app's scale tops out at 30px with 14px body (docs/DESIGN-SYSTEM.md §2.1):
   * correct for dense data UI, wrong for a marketing page. Names are the app's;
   * values are not. Display line-height tracks its own clamp — 1.05 is right at
   * 72px and jams the hero at the 40px floor, which is where a 320px phone lands. */
  /* 40 → 60px. Capped at 3.75rem, not 4.5rem: the hero H1 lives in a 7-of-12 column,
   * so a clamp tuned to the viewport oversizes it — at 1112px it rendered 66px across a
   * 602px box and wrapped to four lines. 60px is also JustLogin's own H1 size. */
  --fs-display-1: clamp(2.5rem, 1.5rem + 3vw, 3.75rem);
  --lh-display-1: 1.05;
  --fs-display-2: clamp(2rem, 1.5rem + 2vw, 3rem);
  --lh-display-2: 1.15;
  --fs-heading-2: clamp(1.75rem, 1.4rem + 1.2vw, 2.25rem); /* the rung the scale lacked */
  --fs-heading-3: 1.5rem;
  --fs-heading-4: 1.125rem;
  --fs-lede: clamp(1.125rem, 1.05rem + 0.3vw, 1.3125rem);
  --fs-body: 1rem;
  --fs-small: 0.875rem;
  --fs-label: 0.8125rem; /* 13px, uppercase only — floor */
  --fs-figure: clamp(2rem, 1.4rem + 2.4vw, 3.5rem);

  --lh-tight: 1.25;
  --lh-body: 1.6;
  --lh-lede: 1.5;

  --fw-normal: 400;
  --fw-medium: 500;
  --fw-semibold: 600;
  --fw-bold: 700;

  --tracking-label: 0.08em;
  --tracking-table: 0.02em; /* comparison-table headers — tracking is a width tax there */

  /* ── Spacing — 8pt, marketing amplitude ─────────────────────────────────────
   * The app's inter-section gap is 24px. Section padding is the strongest signal
   * separating a marketing page from an admin screen, and the value most often
   * left at app defaults. */
  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --space-4: 1rem;
  --space-6: 1.5rem;
  --space-8: 2rem;
  --space-10: 2.5rem;
  --space-12: 3rem;
  --space-16: 4rem;
  --space-20: 5rem;
  --space-24: 6rem;
  --space-32: 8rem;
  --section-y: clamp(4rem, 2rem + 6vw, 8rem);

  /* ── Containers ─────────────────────────────────────────────────────────────── */
  --w-prose: 66ch;
  --w-content: 70rem; /* 1120px */
  --w-wide: 82.5rem; /* 1320px */
  --gutter: 1.25rem;

  /* ── Radius, border, shadow ─────────────────────────────────────────────────── */
  --radius-sm: 0.25rem;
  --radius-md: 0.375rem;
  --radius-lg: 0.5rem;
  --radius-xl: 0.75rem;
  --radius-2xl: 1.25rem; /* pricing cards, mockup frames */
  --radius-full: 9999px;
  --stroke: 1.5px; /* one weight across every diagram */

  /* ── Colour — light ─────────────────────────────────────────────────────────── */
  --bg-page: #ffffff;
  --bg-raised: #f7f6f4; /* warm: the site's ground is warmer than the product's, so
                           mockup frames don't dissolve into the page */
  --bg-surface: #ffffff;
  --bg-inverse: #0f172a;

  --text-primary: #1e293b;
  --text-secondary: #334155;
  --text-muted: #475569;
  --text-subtle: #64748b; /* lowest allowed for body text on white */
  --text-icon-muted: #94a3b8; /* 2.56:1 — decorative strokes only, never text, and
                                 below 1.4.11's 3:1 so never a functional icon */

  --accent: #4f46e5; /* fill */
  --accent-hover: #4338ca;
  --accent-text: #4f46e5; /* links */
  --accent-label: #ffffff; /* label on --accent */

  --border: #e2e8f0;
  --border-strong: #cbd5e1;

  --shadow-card: 0 1px 2px rgb(0 0 0 / 0.04);
  --shadow-frame: 0 1px 2px rgb(0 0 0 / 0.04), 0 12px 32px -8px rgb(0 0 0 / 0.12);

  /* Semantic roles — inherited unchanged from docs/DESIGN-SYSTEM.md §1.2 so charts here
     read as the same system as the product's forecast card. */
  --won: #10b981;
  --best-case: #f59e0b;
  --commit: #3b82f6;
  --weighted: #a855f7;
  --pipeline: #94a3b8;
}

@media (min-width: 48rem) {
  :root {
    --gutter: 2rem;
  }
}
@media (min-width: 80rem) {
  :root {
    --gutter: 3rem;
  }
}

/* ── Colour — dark ─────────────────────────────────────────────────────────────
 * grep -rl "dark:" web/src returns 0 files: there is no dark palette in this product
 * to inherit, so both themes are authored here. Two rules that fall out of the maths:
 *   · #94a3b8 is banned as text in light (2.56:1) and fine in dark (6.96:1). A single
 *     cross-theme ban would cost dark its muted tier for no accessibility gain.
 *   · The accent FILL is theme-varying. #4f46e5 on #0f172a is 2.84:1 — under WCAG
 *     1.4.11's 3:1 for the control's own boundary, on the primary conversion path.
 *     Checking only the label (6.29:1) was the wrong axis. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg-page: #0f172a;
    --bg-raised: #1c1a19; /* warm, matching the light theme's offset */
    --bg-surface: #1e293b;
    --bg-inverse: #020617;

    --text-primary: #e2e8f0;
    --text-secondary: #cbd5e1;
    --text-muted: #94a3b8;
    --text-subtle: #7c8aa0; /* a distinct tier, not a collapse onto --text-muted */
    --text-icon-muted: #64748b;

    --accent: #7c3aed;
    --accent-hover: #6d28d9;
    --accent-text: #818cf8;
    --accent-label: #ffffff;

    --border: #334155;
    --border-strong: #475569;

    --shadow-card: none; /* shadows are invisible on dark; borders do the work */
    --shadow-frame: none;
  }
}

/* Explicit override wins in both directions (AC7). */
:root[data-theme="dark"] {
  --bg-page: #0f172a;
  --bg-raised: #1c1a19;
  --bg-surface: #1e293b;
  --bg-inverse: #020617;
  --text-primary: #e2e8f0;
  --text-secondary: #cbd5e1;
  --text-muted: #94a3b8;
  --text-subtle: #7c8aa0;
  --text-icon-muted: #64748b;
  --accent: #7c3aed;
  --accent-hover: #6d28d9;
  --accent-text: #818cf8;
  --accent-label: #ffffff;
  --border: #334155;
  --border-strong: #475569;
  --shadow-card: none;
  --shadow-frame: none;
}

/* ── The inverse surface ───────────────────────────────────────────────────────
 * Four places sit on --bg-inverse: home §3 full-bleed, the closing CTA, the
 * "most popular" pricing card, and dark's own inverse band. Every ratio in DESIGN's
 * main table is computed against --bg-page, so none of them described these. Without
 * these roles the code phase hand-rolls `color: white` in four places, which is how a
 * token system rots in its first week. Remap, don't add new names. */
[data-surface="inverse"] {
  /* Re-establish `color` inside the scope. Remapping --text-primary is not enough:
   * body computes `color: var(--text-primary)` ONCE, and descendants inherit that
   * computed value, not the var reference. So an element that sets no colour of its
   * own keeps the LIGHT theme's text inside an inverse region. That is how the
   * "most popular" pricing card rendered its price at rgb(30,41,59) on rgb(15,23,42)
   * — about 1.2:1, effectively invisible — while the heading beside it was correct,
   * because headings do set color: var(--text-primary). */
  color: var(--text-primary);

  --bg-page: var(--bg-inverse);
  --bg-raised: #1e293b;
  --bg-surface: #1e293b;
  --text-primary: #f1f5f9;
  --text-secondary: #cbd5e1;
  --text-muted: #94a3b8;
  --text-subtle: #94a3b8;
  --accent-text: #a5b4fc;
  --accent: #7c3aed;
  --accent-label: #ffffff;
  --border: #334155;
  --border-strong: #475569;
  --shadow-card: none;
  --shadow-frame: none;
}
