/* ============================================================
   ERULIA DESIGN TOKENS — v1 (2026-07-18)
   Canonical drop-in for: official erulia site, Revula, Lurest.
   Derived from field research: Quizlet, Anki, Notion, Goodnotes,
   Duolingo, Knowt, RemNote, Khan Academy, Linear (measured live).
   Spec + rationale: ERULIA-DESIGN.md  (do not fork values ad hoc)
   ============================================================ */

/* Fonts — web usage (marketing site, apps). Artifacts embed instead.
@import url('https://fonts.googleapis.com/css2?family=Hanken+Grotesk:wght@400..800&family=Inter:wght@400..700&display=swap');
*/

:root {
  /* ---- type ---- */
  --font-display: 'Hanken Grotesk', 'Inter', -apple-system, 'Segoe UI', sans-serif; /* headlines: the Anki font */
  --font-ui: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; /* everything else: the Notion/RemNote font */
  /* Anchors/timestamps. A system stack on purpose: it is the one shared token role
     that costs a network request if it names a webfont, and a mono utility face is
     invisible to the user. Byte-identical in Revula and Lurest (P-APP5a). */
  --font-mono: ui-monospace, 'SF Mono', 'Cascadia Mono', Menlo, Consolas, monospace;

  /* ---- IN-APP TYPE ROLES (P-APP2) — the bounded table for Revula + Lurest ----
     The marketing scale above (.display/h1/h2/h3/.lead/.small/.caption) governs the
     SITE. Apps had no type law at all, which is how Revula reached 17 rendered sizes
     on its five core surfaces and Lurest 23 (incl. fractional ones from an `0.8em`
     anchor rule). These seven roles are the whole in-app vocabulary.

     Rules this table is built to satisfy, so don't "tidy" it without re-checking:
       · exactly 7 roles (an 8th needs written justification; the Phase-3 `kbd` glyph
         is pre-authorized as a TREATMENT of --fs-mono, not a new role)
       · 13px floor — nothing in either app renders below it, which also satisfies
         "≥13px for anything conveying content or state" without a case-by-case call
       · weights ⊆ {400,500,600,650,700}
       · one line-height per role; 4 distinct values total; monotonically
         non-increasing as size increases (13→1.6 … 112→0.90)
       · shared roles measure IDENTICAL in both apps (P-APP5e) — that is why these
         live here and are copied verbatim into each app's token block.
     Eyebrow is a declared TREATMENT of the meta role (same size/family/line-height,
     weight 600 + uppercase + 0.08em), not an eighth role. */
  --fs-hero:    112px;  --lh-hero:    0.90;  --tr-hero:    -0.03em;   /* the ONE data number per screen (X3) — display face */
  --fs-display:  38px;  --lh-display: 1.05;  --tr-display: -0.022em;  /* full-screen headlines — display face, >=28px so Hanken is sanctioned */
  --fs-title:    20px;  --lh-title:   1.30;  --tr-title:   -0.015em;  /* panel / card / modal titles — UI face */
  --fs-body:     15px;  --lh-body:    1.60;  --tr-body:     0;        /* prose, long-form (45-75ch) */
  --fs-ui:       14px;  --lh-ui:      1.60;  --tr-ui:       0;        /* controls, nav, labels — matches .btn-app */
  --fs-meta:     13px;  --lh-meta:    1.60;  --tr-meta:     0;        /* captions, secondary; eyebrow treatment adds 0.08em + uppercase */
  --fs-mono:     13px;  --lh-mono:    1.60;  --tr-mono:     0.02em;   /* anchors, timestamps — --font-mono */

  /* ---- neutrals (cool undertone — Quizlet #282E3E / RemNote #292936 family) ---- */
  --bg: #FFFFFF;
  --bg-soft: #F7F8FB;      /* alternating sections, app canvas */
  --bg-tint: #EDF7F3;      /* accent-tinted band (Quizlet's periwinkle move, in our green) */
  --ink: #1E2430;          /* headings + primary text — never pure #000 */
  --ink-2: #4B5364;        /* secondary text */
  --ink-3: #5D6575;        /* captions, placeholders, meta — see the elevation note below */
  --line: #E7E9F0;         /* default 1px borders */
  --line-strong: #D6DAE3;  /* input borders, hover borders */

  /* ---- app-shell elevation (Revula/Lurest only; the site never leaves --bg/--bg-soft) ----
     These lived only inside Revula's own <style> block, which is how --ink-3 got
     validated against three backgrounds and shipped failing on two others. A token
     you can't see from here is a token nobody can check.
     --ink-3 history: #7C8496 → #677082 (site gate 2026-07-19, ~3.4:1 on --bg-tint)
     → #5D6575 (2026-07-24). #677082 measured 4.49:1 on --surface-2 and 4.14:1 on
     --surface-3 — the SAME failure one elevation step up, found only because Revula
     had already patched it locally as --fg-dim: #5D6575. That local patch is now the
     token, so Lurest inherits the fix instead of re-discovering the defect.
     Measured for #5D6575: bg 5.86 · bg-soft 5.52 · bg-tint 5.36 · surface-2 5.28 ·
     surface-3 4.87 — all ≥4.5:1. Re-measure all FIVE if you touch it again. */
  --surface-2: #F1F3F8;    /* raised rows, inset panels */
  --surface-3: #E7EAF2;    /* chips, kbd glyphs, scrollbar thumbs */

  /* ---- accent: Erulia viridian (sage-signal heritage, saturated + light-theme tuned;
          deliberately NOT Quizlet/Notion/Khan blue, Duolingo green, or Knowt teal) ---- */
  --accent-50: #E9F6F1;
  --accent-100: #D2EDE2;
  --accent-500: #129B75;   /* large fills, white text >=18px bold, rings, charts */
  --accent-600: #0E7D5F;   /* primary buttons + links (5.1:1 on white) */
  --accent-700: #0B644C;   /* hover / pressed */
  --on-accent: #FFFFFF;

  /* ---- semantic (light-tuned; apps map capture states here) ---- */
  --ok: var(--accent-600);
  --warn: #B45309;
  --danger: #C0362C;
  --muted: var(--ink-3);

  /* ---- spacing (the only scale: 4/8/12/16/20/24/28/32/40/48/64 + the section clamp) ----
     ERULIA-DESIGN §2 has declared this scale since the 2026-07-19 site gate, but only
     in PROSE — this block was a header with nothing under it, so every app re-derived
     the scale by eye and none of them landed on it. Measured in Revula 2026-07-26:
     ten distinct section gaps, five of them (26/30/36/44/56) OFF-SCALE, and every one
     sitting exactly midway between two legal steps — the signature of eyeballing.
     Same failure mode as --ink-3 (fixed 2026-07-24): a rule that lives only in prose
     is a rule each downstream app gets to miss. Tokens are the enforcement.
     Named by VALUE, not by t-shirt size, so an off-scale number cannot be spelled. */
  --space-4:  4px;
  --space-8:  8px;
  --space-12: 12px;
  --space-16: 16px;
  --space-20: 20px;
  --space-24: 24px;
  --space-28: 28px;
  --space-32: 32px;
  --space-40: 40px;
  --space-48: 48px;
  --space-64: 64px;
  --space-section: clamp(80px, 10vw, 128px);  /* marketing section rhythm only */

  /* ---- radii (the only five allowed) ---- */
  --r-sm: 8px;    /* inputs, chips, small controls */
  --r-md: 12px;   /* in-app buttons, list rows */
  --r-lg: 16px;   /* cards */
  --r-xl: 24px;   /* screenshot frames, modals, hero media */
  --r-pill: 999px;/* marketing CTAs, tags, toggles */

  /* ---- elevation ---- */
  --shadow-1: 0 1px 2px rgba(23, 26, 36, .05);
  --shadow-2: 0 4px 12px -2px rgba(23, 26, 36, .08);
  --shadow-3: 0 16px 32px -12px rgba(23, 26, 36, .18); /* hover-lift only */

  /* ---- motion (translate/scale/opacity only; nothing bounces) ---- */
  --ease-out: cubic-bezier(.22, .72, .24, 1);
  --t-fast: 150ms;   /* color/border swaps */
  --t-base: 220ms;   /* lifts, reveals */
  --t-slow: 420ms;   /* section scroll-reveals */
}

/* ============ base ============ */
* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font-ui);
  font-size: 17px;              /* app surfaces: 14px */
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
::selection { background: var(--accent-100); }
:focus-visible { outline: 2px solid var(--accent-500); outline-offset: 2px; border-radius: var(--r-sm); }

/* ============ type scale (marketing) ============ */
.display, h1, h2, h3 { font-family: var(--font-display); color: var(--ink); margin: 0; text-wrap: balance; }
.display { font-size: clamp(44px, 6vw, 68px); line-height: 1.04; letter-spacing: -0.025em; font-weight: 750; }
h1 { font-size: clamp(38px, 5vw, 48px); line-height: 1.08; letter-spacing: -0.02em; font-weight: 700; }
h2 { font-size: clamp(30px, 4vw, 38px); line-height: 1.12; letter-spacing: -0.018em; font-weight: 700; }
h3 { font-size: 23px; line-height: 1.25; letter-spacing: -0.012em; font-weight: 650; }
.lead { font-size: 20px; line-height: 1.55; color: var(--ink-2); }
.small { font-size: 15px; }
.caption { font-size: 13px; color: var(--ink-3); }
.eyebrow {
  font-family: var(--font-ui); font-size: 13px; font-weight: 600;
  letter-spacing: .08em; text-transform: uppercase; color: var(--accent-600);
}
.tnum { font-variant-numeric: tabular-nums; } /* every score / countdown / stat */

/* ============ layout ============ */
.container { max-width: 1120px; margin: 0 auto; padding: 0 24px; }
.section { padding: clamp(80px, 10vw, 128px) 0; }
.section-soft { background: var(--bg-soft); }
.section-tint { background: var(--bg-tint); }

/* ============ buttons ============ */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  font-family: var(--font-ui); font-size: 16px; font-weight: 600; line-height: 1;
  padding: 14px 28px; border-radius: var(--r-pill); border: 1px solid transparent;
  background: var(--accent-600); color: var(--on-accent);
  cursor: pointer; text-decoration: none;
  transition: background var(--t-fast) var(--ease-out), transform var(--t-fast) var(--ease-out), box-shadow var(--t-fast) var(--ease-out), border-color var(--t-fast) var(--ease-out);
}
.btn:hover { background: var(--accent-700); transform: translateY(-1px); box-shadow: var(--shadow-2); }
.btn:active { transform: translateY(0); box-shadow: var(--shadow-1); }
.btn-lg { padding: 17px 34px; font-size: 17px; }
.btn-secondary { background: var(--bg); color: var(--ink); border-color: var(--line-strong); }
.btn-secondary:hover { background: var(--bg-soft); border-color: var(--ink-3); }
.btn-app { border-radius: var(--r-md); padding: 10px 18px; font-size: 14px; } /* inside Revula/Lurest */
a.link { color: var(--accent-600); text-decoration: none; font-weight: 500; }
a.link:hover { text-decoration: underline; text-underline-offset: 3px; }

/* ============ inputs ============ */
.input {
  font-family: var(--font-ui); font-size: 16px; color: var(--ink);
  background: var(--bg); border: 1px solid var(--line-strong); border-radius: var(--r-md);
  padding: 13px 16px; width: 100%;
  transition: border-color var(--t-fast), box-shadow var(--t-fast);
}
.input::placeholder { color: var(--ink-3); }
.input:focus { outline: none; border-color: var(--accent-500); box-shadow: 0 0 0 3px var(--accent-50); }

/* ============ cards & frames ============ */
.card {
  background: var(--bg); border: 1px solid var(--line); border-radius: var(--r-lg);
  box-shadow: var(--shadow-1); padding: 28px;
}
.card-hover { transition: transform var(--t-base) var(--ease-out), box-shadow var(--t-base) var(--ease-out), border-color var(--t-base) var(--ease-out); }
.card-hover:hover { transform: translateY(-4px); box-shadow: var(--shadow-3); border-color: var(--line-strong); }
.frame { /* product screenshots — the Quizlet 24px pattern */
  background: var(--bg); border: 1px solid var(--line); border-radius: var(--r-xl);
  box-shadow: var(--shadow-2); overflow: hidden;
}

/* ============ nav ============ */
.nav {
  position: sticky; top: 0; z-index: 50; height: 64px;
  background: rgba(255, 255, 255, .86); backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--line);
}
.nav-link { font-size: 15px; font-weight: 500; color: var(--ink-2); text-decoration: none; transition: color var(--t-fast); }
.nav-link:hover { color: var(--ink); }

/* ============ scroll reveal (use once per section, not per element) ============ */
.reveal { opacity: 0; transform: translateY(14px); transition: opacity var(--t-slow) var(--ease-out), transform var(--t-slow) var(--ease-out); }
.reveal.in { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { transition-duration: .01ms !important; animation-duration: .01ms !important; }
  .reveal { opacity: 1; transform: none; }
}
