/* =============================================================
   intentfirst.ai — Design Tokens
   =============================================================
   Direction: Vercel Geist (Light + Dark)
   Migrated from F-Dark / F3 Muted Echo on 2026-04-21.

   USAGE:
     <link rel="stylesheet" href="/assets/css/tokens.css">
     (adjust path: "../assets/css/tokens.css" from subdirectories)

     Light mode (default): just use the variables
     Dark mode: add class "dark" to <html> or <body>,
                or use for Hero/CTA sections with class "sec-dark"

   SEMANTIC COLORS:
     Three meaning-colors derived from illustration palette.
     Each has a full-saturation "illustration" variant and
     a muted "UI" variant.

     Grammar / Tokens  → Blue
     Brain / Memory     → Purple
     Intent / Dials     → Ochre
   ============================================================= */

/* ─── FONTS ─── */
/* Geist Sans + Geist Mono are loaded via CDN <link> in each page <head>. */
/* Satoshi is no longer used as primary; kept as fallback only for legacy. */

:root {
  /* ═══ Font Stack ═══ */
  --font-sans:  'Satoshi', 'Geist Sans', 'Geist', 'Noto Sans JP', -apple-system, system-ui, sans-serif;
  --font-ui:    'Geist', 'Geist Sans', 'Noto Sans JP', sans-serif;
  --font-mono:  'Geist Mono', 'SF Mono', ui-monospace, Menlo, monospace;
  /* Tabular numerics — apply via .num utility OR by extending mono-using selectors */
  --num-feat:   "tnum" 1, "calt" 0;
  --font-jp:    'Noto Sans JP', sans-serif;

  /* ═══ Font Weight Map ═══
     Hero title:       500
     Section title:    500
     Body:             500
     Subtle/sub:       300
     Labels (mono):    500
     Strong emphasis:  600
  */

  /* ═══ Typography Scale ═══
     Manage ALL font sizes, weights, and key colors from here.
     Pages reference these variables so changes propagate sitewide.
  */
  /* Hero (dark bg sections at top of each page) */
  --hero-eyebrow-size:    clamp(11px, 0.85vw, 13px);
  --hero-eyebrow-weight:  500;
  --hero-title-size:      clamp(32px, 4.5vw, 58px);
  --hero-title-weight:    500;
  --hero-title-tracking:  -2px;
  --hero-sub-size:        clamp(17px, 1.4vw, 22px);
  --hero-sub-weight:      400;
  --hero-sub-color-dark:  rgba(240, 236, 228, 0.82); /* subtitle on dark hero */
  --hero-sub-color-light: rgba(26, 24, 22, 0.70);    /* subtitle on light hero */

  /* Section titles (light bg content sections) */
  --sec-title-size:       clamp(30px, 3.5vw, 48px);
  --sec-title-weight:     500;
  --sec-title-tracking:   -1.5px;
  --sec-desc-size:        clamp(16px, 1.15vw, 19px);
  --sec-desc-weight:      500;
  --sec-desc-color:       var(--text-2);

  /* Card / component body text */
  --card-title-size:      clamp(20px, 1.55vw, 26px);
  --card-title-weight:    500;
  --card-body-size:       clamp(16px, 1.15vw, 19px);
  --card-body-weight:     500;

  /* ═══ Minimum-legibility tokens (added 2026-05-07) ══════════════
     Hard floors for in-card meta text. NEVER drop below these in
     any new component. The earlier 11–13px floor was too small —
     stage cards, force cards, chips, and example lines all read as
     noise. Bumped ~125% across the board.

     ANY new card-style component (stage-card, force-card, vs-card,
     domain-card, dep-card, qa-item, …) MUST source its eyebrow /
     name / description / example sizes from these tokens, not from
     hand-rolled clamp() values. If you find yourself reaching for
     11px / 12px / 13px in a content area, stop and use one of these.
     ═══════════════════════════════════════════════════════════════ */
  --card-eyebrow-size:    clamp(14px, 1.05vw, 17px);   /* mono chips/labels above a card title */
  --card-eyebrow-weight:  500;
  --card-name-size:       clamp(26px, 2.2vw, 34px);    /* short concept names inside cards */
  --card-name-weight:     500;
  --card-desc-size:       clamp(17px, 1.2vw, 19px);    /* card paragraph / description */
  --card-desc-weight:     400;
  --card-example-size:    clamp(15px, 1.05vw, 17px);   /* card example / footnote line */
  --card-example-weight:  400;

  /* Illustration / image widths (use for .sec-illust in pages) */
  --illust-max-w:         800px;   /* standard section illustration */
  --illust-max-w-card:    100%;    /* inside a card */
  --illust-max-w-inline:  360px;   /* inline / tutorial thumbnails */

  /* ═══ Easing ═══ */
  --ease:       cubic-bezier(0.16, 1, 0.3, 1);
  --ease-out:   cubic-bezier(0.2, 0, 0, 1);

  /* ═══ Phase-2 Motion Vocabulary (added 2026-04-25)
     Use these across all UI artifacts. Animate opacity + transform only.
     Trigger entrance animations via IntersectionObserver, fire once. ═══ */
  --ease-out-soft:    cubic-bezier(0.22, 1, 0.36, 1);   /* entrances, reveals */
  --ease-in-out-soft: cubic-bezier(0.65, 0, 0.35, 1);   /* on-screen morphs   */
  --ease-hover:       cubic-bezier(0.4, 0, 0.2, 1);     /* hover, color flip  */
  --dur-micro:        120ms;   /* hover, color, opacity */
  --dur-base:         220ms;   /* element entrance, fade-up */
  --dur-stage:        360ms;   /* multi-element morph (composer fusion, dial cascade) */
  --dur-epic:         600ms;   /* one-off "aha" moment per screen, max once */

  /* ═══ Sub-12px label minimum (Phase-2 audit fix)
     CLAUDE.md mandates 12px label minimum. Mono labels were
     drifting to 9–10px across portfolio. Use these tokens. ═══ */
  --text-mono-xs:     11px;    /* smallest permitted mono label */
  --text-mono-sm:     12px;
  --text-mono-md:     13px;

  /* ═══ Layout ═══ */
  --max-w:      min(1440px, 90vw);
  --max-w-wide: min(1600px, 95vw);

  /* ═══ Reading-Width Tier System (added 2026-04-30)
     Use these to constrain content to reading-optimal columns.
     Apply max-width: var(--read-w-prose) to any prose container. ═══ */
  --read-w-prose:  min(720px, 92vw);    /* paragraphs, subtitles, ~64ch */
  --read-w-card:   min(960px, 94vw);    /* code blocks, tables, demos */
  --read-w-wide:   min(1280px, 95vw);   /* card grids, visual comparisons */
  --read-w-bleed:  100%;                  /* hero animations, full visuals */

  /* ═══════════════════════════════════════
     LIGHT MODE — Vercel Geist (default)
     ═══════════════════════════════════════ */
  --bg:         #ffffff;
  --bg-2:       #fafafa;
  --bg-3:       #f4f4f5;
  --bg-card:    #fafafa;
  --bg-inverse: #0a0a0a;
  /* Feature / Spotlight background — story-rhythm accent for non-technical
     story moments (PMB, lawfirm, future hero sections). NOT for Backstage. */
  --bg-feature: #f0e8d8;
  --bg-feature-text: #1a1816;

  --text:       #0a0a0a;
  --text-2:     #525252;    /* gray-600, contrast 7.6:1 */
  --text-3:     #737373;    /* gray-500, contrast 4.6:1 */

  --border:       rgba(10, 10, 10, 0.08);
  --border-hover: rgba(10, 10, 10, 0.14);

  /* ── Geist Neutral Scale (added 2026-04-21) ── */
  --gray-50:    #fafafa;
  --gray-100:   #f4f4f5;
  --gray-200:   #e4e4e7;
  --gray-300:   #d4d4d8;
  --gray-400:   #a1a1aa;
  --gray-500:   #737373;
  --gray-600:   #525252;
  --gray-700:   #404040;
  --gray-800:   #27272a;
  --gray-900:   #18181b;
  --gray-950:   #09090b;

  /* ── Brand ── */
  --color-brand:  #30c969;   /* ISO green — primary brand accent */

  /* ── Primary (neutral dark — no single accent color) ── */
  --accent:       #0a0a0a;

  /* ── Semantic: Muted UI variants (contrast-corrected 2026-04-12) ── */
  --color-grammar:  #4a6a90;   /* Blue  — was #6889b4 — contrast 5.2:1 */
  --color-brain:    #6a4a90;   /* Purple — was #8a6ab0 — contrast 5.8:1 */
  --color-intent:   #7a5520;   /* Ochre — was #a07040 — contrast 6.5:1 */
  --color-success:  #3a6a3a;   /* Green — was #6b8a6b — contrast 5.5:1 */
  --color-label:    #5a4a38;   /* Muted brown — was #8a7a68 — contrast 6.8:1 */

  /* ── Semantic: Full-saturation illustration variants ── */
  --illust-blue:    #3B82F6;   /* Token cards, SVG strokes */
  --illust-purple:  #8B5CF6;   /* Brain, SVG fills */
  --illust-amber:   #D97706;   /* Intent/Dials, SVG fills */
  --illust-green:   #059669;   /* Autonomy, success states */
  --illust-red:     #dc2626;   /* Error, challenge states */
  --illust-bg:      #F0F0EE;   /* SVG background */

  /* ── Chip / Badge backgrounds (light tints) ── */
  --chip-blue-bg:     #e8f0fe;
  --chip-blue-text:   #2563eb;
  --chip-purple-bg:   #f3eeff;
  --chip-purple-text: #6D28D9;
  --chip-amber-bg:    #fef3e0;
  --chip-amber-text:  #92400e;
  --chip-green-bg:    #ecfdf5;
  --chip-green-text:  #065f46;
  --chip-red-bg:      #fef2f2;
  --chip-red-text:    #b91c1c;

  /* ── Gradient Text (hero "ask" / "need") ── */
  --grad-from:  #6889b4;
  --grad-mid:   #a07040;
  --grad-to:    #8a6ab0;

  /* ── Accent (Quiet Premium / Graphite) ── */
  --color-accent:        #525252;
  --color-accent-muted:  rgba(82, 82, 82, 0.10);
  --color-accent-border: rgba(82, 82, 82, 0.22);

  /* ── Glow (subtle background radials) ── */
  --glow: rgba(26, 24, 22, 0.02);
}

/* ═══════════════════════════════════════
   DARK MODE — Vercel Geist (Black)
   Apply via class="dark" on html/body,
   or class="sec-dark" on individual sections
   ═══════════════════════════════════════ */
.dark,
.sec-dark,
[data-theme="dark"] {
  --bg:         #0a0a0a;
  --bg-2:       #111111;
  --bg-3:       #1a1a1a;
  --bg-card:    #111111;
  --bg-inverse: #ffffff;

  --text:       #ededed;
  --text-2:     #a1a1aa;    /* gray-400 */
  --text-3:     #737373;    /* gray-500 */

  --border:       rgba(255, 255, 255, 0.08);
  --border-hover: rgba(255, 255, 255, 0.14);

  --accent:       #ededed;

  /* ── Brand (unchanged in dark mode) ── */
  --color-brand:  #30c969;

  /* ── Semantic: Muted UI (brighter for dark bg) ── */
  --color-grammar:  #7a9bc4;
  --color-brain:    #a080c0;
  --color-intent:   #b8884e;
  --color-success:  #7aaa7a;
  --color-label:    #8a8078;

  /* ── Illustration colors stay the same ── */

  /* ── Chip / Badge (dark mode tints) ── */
  --chip-blue-bg:     rgba(59, 130, 246, 0.12);
  --chip-blue-text:   #60a5fa;
  --chip-purple-bg:   rgba(139, 92, 246, 0.12);
  --chip-purple-text: #a78bfa;
  --chip-amber-bg:    rgba(217, 119, 6, 0.12);
  --chip-amber-text:  #fbbf24;
  --chip-green-bg:    rgba(5, 150, 105, 0.12);
  --chip-green-text:  #34d399;
  --chip-red-bg:      rgba(220, 38, 38, 0.12);
  --chip-red-text:    #f87171;

  /* ── Gradient Text ── */
  --grad-from:  #7a9bc4;
  --grad-mid:   #b8884e;
  --grad-to:    #a080c0;

  --glow: rgba(240, 236, 228, 0.03);

  /* ── Accent (Quiet Premium / Silver - dark mode) ── */
  --color-accent:        #e4e4e7;
  --color-accent-muted:  rgba(228, 228, 231, 0.10);
  --color-accent-border: rgba(228, 228, 231, 0.22);
}

/* ═══════════════════════════════════════
   BASE RESETS
   ═══════════════════════════════════════ */
*, *::before, *::after {
  margin: 0; padding: 0; box-sizing: border-box;
}

html {
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-sans);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  font-size: clamp(16px, 1.1vw, 19px);   /* bumped from 15-18 → 16-19 for reading comfort */
  scroll-behavior: smooth;
}

body {
  overflow-x: hidden;
  background: var(--bg);
}

/* ═══════════════════════════════════════
   UTILITY CLASSES
   ═══════════════════════════════════════ */

/* Section with dark background (Hero, CTA) */
.sec-dark {
  background: var(--bg);
  color: var(--text);
}

/* Gradient text (use sparingly — hero only) */
.text-grad {
  background: linear-gradient(135deg, var(--grad-from) 0%, var(--grad-mid) 50%, var(--grad-to) 100%);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
}

/* Brand color utility */
.text-brand { color: var(--color-brand); }

/* Semantic section labels */
.label-grammar { color: var(--color-grammar); }
.label-brain   { color: var(--color-brain); }
.label-intent  { color: var(--color-intent); }
.label-default { color: var(--color-label); }

/* Brain layer dots */
.dot-grammar { background: var(--color-grammar); }
.dot-brain   { background: var(--color-brain); }
.dot-intent  { background: var(--color-intent); }
.dot-success { background: var(--color-success); }

/* Chips (presentation slides) */
.chip-blue   { background: var(--chip-blue-bg);   color: var(--chip-blue-text); }
.chip-purple { background: var(--chip-purple-bg); color: var(--chip-purple-text); }
.chip-amber  { background: var(--chip-amber-bg);  color: var(--chip-amber-text); }
.chip-green  { background: var(--chip-green-bg);  color: var(--chip-green-text); }
.chip-red    { background: var(--chip-red-bg);    color: var(--chip-red-text); }

/* ═══════════════════════════════════════
   BRAND SELECTION HIGHLIGHT (MANDATORY global)
   Mouse/text selection uses the brand green.
   ═══════════════════════════════════════ */
::selection {
  background: var(--text-2);
  color: var(--bg);
}
::-moz-selection {
  background: var(--text-2);
  color: var(--bg);
}

/* ═══════════════════════════════════════
   .ui-caption — readable caption below any UI / figure.
   Used below iframes, images, concept panels. Design
   system baseline for "what is this thing?" labels.
   ═══════════════════════════════════════ */
.ui-caption {
  display: block;
  margin: 14px auto 0;
  max-width: 760px;
  padding: 0 8px;
  font-family: var(--font-sans);
  font-size: 14px;
  font-weight: 500;
  line-height: 1.55;
  letter-spacing: -0.1px;
  color: var(--text-2);
  text-align: center;
}
.ui-caption__kind {
  display: inline-block;
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 1.4px;
  text-transform: uppercase;
  color: var(--text-3);
  margin-right: 10px;
  padding: 2px 8px;
  background: var(--bg-2, rgba(0, 0, 0, 0.04));
  border-radius: 4px;
  vertical-align: 1px;
}
/* ═══════════════════════════════════════
   BACKSTAGE PALETTE — global tokens for `section--dark` / Backstage frames
   ───────────────────────────────────────
   These were previously redeclared inside each project's <style> block.
   Defined here so a single change propagates to every project page
   (P1, P2, P3, P4, P5, P6, future).

   Readability bump 2026-04-28:
     bts-text-2: 0.72 → 0.88  (lede / body on dark bg was hard to read)
     bts-text-3: 0.45 → 0.68  (mono labels were borderline invisible)
     bts-border: 0.18 → 0.24  (dashed frame edges)

   Per-page <style> blocks may still redeclare these — but defaults here
   mean any page that DROPS the redeclaration inherits the readable values.
   ═══════════════════════════════════════ */
:root {
  --bts-bg:      #08070b;
  --bts-text:    #f0ece4;
  --bts-text-2:  rgba(240, 236, 228, 0.88);
  --bts-text-3:  rgba(240, 236, 228, 0.68);
  --bts-yes:     #a4d4a8;
  --bts-engine:  #c4a8e0;
  --bts-string:  #e8b870;
  --bts-no:      #e89090;
  --bts-border:  rgba(240, 236, 228, 0.24);
}

/* Dark-section variant: readable on dark backgrounds.
   Covers: legacy `.sec-dark`, modern `.section--dark` (PORTFOLIO_GLOBAL_RULES §1),
   `[data-theme="dark"]`, and inline `style="background:#0a0a0a"` overrides. */
.sec-dark .ui-caption,
.section--dark .ui-caption,
[data-theme="dark"] .ui-caption,
[style*="background:#08070b"] .ui-caption,
[style*="background: #08070b"] .ui-caption,
[style*="background:#0a0a0a"] .ui-caption,
[style*="background: #0a0a0a"] .ui-caption {
  color: rgba(240, 236, 228, 0.78);
}
.sec-dark .ui-caption__kind,
.section--dark .ui-caption__kind,
[data-theme="dark"] .ui-caption__kind,
[style*="background:#08070b"] .ui-caption__kind,
[style*="background: #08070b"] .ui-caption__kind,
[style*="background:#0a0a0a"] .ui-caption__kind,
[style*="background: #0a0a0a"] .ui-caption__kind {
  color: rgba(240, 236, 228, 0.62);
  background: rgba(240, 236, 228, 0.08);
}

/* ═══════════════════════════════════════
   MINIMUM-LEGIBILITY ENFORCEMENT (added 2026-05-07)
   ───────────────────────────────────────
   Many pages locally redeclare card meta text at 11–14px and it
   reads as noise. These selectors set sitewide floors so existing
   pages get an automatic legibility lift, and new components
   inherit by name even if the page forgets to source the tokens.

   Override locally only with strong justification (e.g. badges
   that genuinely need uppercase 12px tracking).
   ═══════════════════════════════════════ */
.stage-num,
.force-num,
.dep-card-label,
.vs-chip,
.flow-arrow,
.step-chip,
.domain-dial-label,
.domain-dial-value {
  font-size: var(--card-eyebrow-size) !important;
}

.stage-name,
.force-name,
.flow-title,
.domain-name,
.dep-card-state {
  font-size: var(--card-name-size) !important;
}

.stage-desc,
.force-desc,
.flow-desc,
.dep-card-note,
.qa-a {
  font-size: var(--card-desc-size) !important;
  line-height: 1.65;
}

.stage-example,
.flow-example {
  font-size: var(--card-example-size) !important;
  line-height: 1.6;
}

.vs-name {
  font-size: var(--card-name-size) !important;
}
.vs-role {
  font-size: var(--card-desc-size) !important;
}
.vs-list li {
  font-size: var(--card-example-size) !important;
}

/* ═══════════════════════════════════════
   ANIMATION PRIMITIVES
   ═══════════════════════════════════════ */
.reveal {
  opacity: 0;
  transform: translateY(16px);
  transition: opacity 0.65s var(--ease), transform 0.65s var(--ease);
}
.reveal.visible {
  opacity: 1;
  transform: translateY(0);
}
.d1 { transition-delay: 0.05s; }
.d2 { transition-delay: 0.10s; }
.d3 { transition-delay: 0.15s; }
.d4 { transition-delay: 0.20s; }
.d5 { transition-delay: 0.25s; }
.d6 { transition-delay: 0.30s; }

@keyframes fadeUp {
  from { opacity: 0; transform: translateY(16px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* ─── Press states (Emil-style tactile feedback) ─── */
.btn:active,
.toc-card:active,
.cs-card:active,
.glance-pillar:active,
.journal-card:active {
  transform: scale(0.97) !important;
  transition-duration: 100ms !important;
}

/* ═══════════════════════════════════════
   GLOBAL INTERACTION STATES (added 2026-04-25 from Phase 2 audit)
   Buttons and links across the portfolio were missing hover /
   focus-visible / active states. These apply globally so any
   <button>, .cta-btn, .pro-btn, [role="button"], or <a> in
   content gets keyboard accessibility + tactile feedback.
   ═══════════════════════════════════════ */
button,
.cta-btn,
.pro-btn,
[role="button"] {
  transition:
    background-color var(--dur-micro) var(--ease-hover),
    color            var(--dur-micro) var(--ease-hover),
    filter           var(--dur-micro) var(--ease-hover),
    transform        100ms ease-out;
}

button:focus-visible,
a:focus-visible,
[role="button"]:focus-visible {
  outline: 2px solid var(--illust-amber);
  outline-offset: 2px;
  border-radius: inherit;
}

button:active,
[role="button"]:active {
  transform: translateY(1px);
}

@media (hover: hover) and (pointer: fine) {
  button:hover:not(:disabled),
  .cta-btn:hover,
  .pro-btn:hover {
    filter: brightness(1.05);
  }
}

/* ═══════════════════════════════════════
   TABULAR NUMERICS — auto-applied to common numeric stat classes.
   Stops layout shift when numbers update or animate.
   For new code, use the .num utility class.
   ═══════════════════════════════════════ */
.num,
[class$="-num"],
[class$="-val"],
[class$="-metric"],
[class*="-stat-v"],
[class*="-num--"],
[class*="-val--"] {
  font-variant-numeric: tabular-nums;
  font-feature-settings: var(--num-feat);
}

/* ─── Reduced motion ─── */
@media (prefers-reduced-motion: reduce) {
  .reveal {
    transition: opacity 0.3s ease;
    transform: none;
  }
  .reveal.visible { transform: none; }
  /* Collapse Phase-2 motion vocab to 0 — single source of motion truth */
  :root {
    --dur-micro: 0ms;
    --dur-base:  0ms;
    --dur-stage: 0ms;
    --dur-epic:  0ms;
  }
  * {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
  }
}
