/* ═══════════════════════════════════════════════════════════════════════════
   keelbase Viewer — Design Tokens (SSOT projection)
   ───────────────────────────────────────────────────────────────────────────
   This is the framework-agnostic, plain-CSS projection of the keelbase Design
   Guide token layer. CANONICAL SOURCE:  designGuide/src/styles/theme.css
   (Primitive → Semantic → Scales, lines 6–123 there).

   • The viewer is a no-build app — it cannot run the Tailwind `@theme inline`
     / `@custom-variant` / `@layer base` parts of theme.css. Those are consumed
     only by the React "islands" track (which runs Tailwind). This file carries
     ONLY the plain-CSS semantic layer, whose VALUES are kept byte-identical to
     theme.css so a sync check (P5) can assert they have not drifted.
   • Theming: `[data-theme="light"|"dark"]` on <html> flips the semantic tokens;
     `[data-density="compact"]` tightens the density scale. Both consumers
     (this file + the islands' theme.css) share the same attribute contract, so
     one toggle themes the whole product.
   • Do NOT hardcode colors / spacing / radius in component CSS — use these
     tokens (Design Guide §2 철칙).
   ═══════════════════════════════════════════════════════════════════════════ */

/* Web fonts — same sources as designGuide/src/styles/fonts.css.
   CDN-hosted; the --font-ui / --font-mono stacks below fall back to
   system fonts if the network is unavailable (offline-safe). */
@import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600&display=swap');
@import url('https://cdn.jsdelivr.net/gh/orioncactus/pretendard@v1.3.9/dist/web/static/pretendard.min.css');

/* ─── Primitive ramps + scales (theme-independent) ───────────────────────── */
:root {
  /* Neutral ramp */
  --gray-0:   #ffffff; --gray-25:  #fbfcfd; --gray-50:  #f6f8fa;
  --gray-100: #eef1f4; --gray-150: #e3e8ee; --gray-200: #d6dde5;
  --gray-300: #b8c2cd; --gray-400: #94a1b0; --gray-500: #6b7888;
  --gray-600: #515d6b; --gray-700: #3c4651; --gray-800: #28303a;
  --gray-900: #161b22; --gray-950: #0d1117;

  /* Brand teal-cyan */
  --brand-50:  #e6f7fb; --brand-100: #c4ecf3; --brand-200: #95dde9;
  --brand-300: #5fc8da; --brand-400: #2bacc4; --brand-500: #0891b2;
  --brand-600: #0a7591; --brand-700: #0d5d75; --brand-800: #114a5e;

  /* Status */
  --green-500:#16a34a; --green-100:#dcfce7;
  --amber-500:#d97706; --amber-100:#fef3c7;
  --red-500:  #dc2626; --red-100:  #fee2e2;
  --blue-500: #2563eb; --blue-100: #dbeafe;

  /* Data-viz categorical */
  --viz-1:#16a34a; --viz-2:#2563eb; --viz-3:#d97706; --viz-4:#dc2626;
  --viz-5:#7c3aed; --viz-6:#0891b2; --viz-7:#db2777; --viz-8:#65a30d;

  /* Fonts */
  --font-ui:   "Pretendard", "Pretendard Variable", -apple-system, "Segoe UI", system-ui, sans-serif;
  --font-mono: "JetBrains Mono", "Consolas", ui-monospace, monospace;

  /* Type scale */
  --text-xs: 11px; --text-sm: 12px; --text-md: 13px; --text-lg: 15px;
  --text-xl: 18px; --text-2xl: 24px; --text-3xl: 30px;
  --fw-regular: 400; --fw-medium: 500; --fw-semibold: 600; --fw-bold: 700;
  --lh-tight: 1.2; --lh-snug: 1.35; --lh-normal: 1.5;

  /* Spacing (4/8px grid) */
  --space-1: 4px;  --space-2: 8px;  --space-3: 12px; --space-4: 16px;
  --space-5: 24px; --space-6: 32px; --space-7: 48px; --space-8: 64px;

  /* Radius */
  --radius-xs: 3px; --radius-sm: 5px; --radius-md: 8px;
  --radius-lg: 12px; --radius-xl: 16px; --radius-full: 999px;

  /* Motion */
  --dur-instant: 80ms; --dur-fast: 140ms; --dur-normal: 200ms; --dur-slow: 320ms;
  --ease-out:    cubic-bezier(0.2, 0.8, 0.2, 1);
  --ease-in-out: cubic-bezier(0.4, 0, 0.2, 1);
  --ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);

  /* Density */
  --row-h: 28px; --control-h: 30px; --tab-h: 36px; --pad-panel: 16px;

  /* Z-index */
  --z-panel: 100; --z-toolbar: 160; --z-overlay: 200;
}

/* ─── Semantic tokens — light (default) ──────────────────────────────────── */
:root, [data-theme="light"] {
  --surface-base:    var(--gray-50);
  --surface-1:       var(--gray-0);
  --surface-2:       var(--gray-100);
  --surface-sunken:  var(--gray-150);
  --surface-overlay: rgba(255,255,255,0.86);
  --on-surface:        var(--gray-900);
  --on-surface-muted:  var(--gray-500);
  --on-surface-dim:    var(--gray-400);
  --on-accent:         var(--gray-0);
  --interactive:        var(--brand-500);
  --interactive-hover:  var(--brand-600);
  --interactive-active: var(--brand-700);
  --interactive-subtle: var(--brand-50);
  --focus-ring:         rgba(8,145,178,0.40);
  --border-base:        var(--gray-200);
  --border-strong:      var(--gray-300);
  --border-accent:      rgba(8,145,178,0.45);
  --status-ok:          var(--green-500); --status-ok-bg:     var(--green-100);
  --status-warn:        var(--amber-500); --status-warn-bg:   var(--amber-100);
  --status-danger:      var(--red-500);   --status-danger-bg: var(--red-100);
  --status-info:        var(--blue-500);  --status-info-bg:   var(--blue-100);
  --viz-lod0: var(--viz-1); --viz-lod1: var(--viz-2);
  --viz-lod2: var(--viz-3); --viz-lod3: var(--viz-4);
  --shadow-color: 220 40% 12%;
  --elev-1: 0 1px 2px hsl(var(--shadow-color)/0.10), 0 1px 3px hsl(var(--shadow-color)/0.08);
  --elev-2: 0 4px 8px -2px hsl(var(--shadow-color)/0.12), 0 2px 4px -2px hsl(var(--shadow-color)/0.08);
  --elev-3: 0 12px 24px -6px hsl(var(--shadow-color)/0.16), 0 4px 8px -4px hsl(var(--shadow-color)/0.10);
}

/* ─── Semantic tokens — dark ──────────────────────────────────────────────── */
[data-theme="dark"] {
  --surface-base:    var(--gray-950);
  --surface-1:       var(--gray-900);
  --surface-2:       var(--gray-800);
  --surface-sunken:  #0a0e14;
  --surface-overlay: rgba(13,17,23,0.86);
  --on-surface:        #e6e9ed;
  --on-surface-muted:  var(--gray-400);
  --on-surface-dim:    var(--gray-500);
  --on-accent:         #04222b;
  --interactive:        var(--brand-300);
  --interactive-hover:  var(--brand-200);
  --interactive-active: var(--brand-100);
  --interactive-subtle: rgba(8,145,178,0.16);
  --focus-ring:         rgba(95,200,218,0.45);
  --border-base:        rgba(255,255,255,0.10);
  --border-strong:      rgba(255,255,255,0.18);
  --border-accent:      rgba(95,200,218,0.45);
  --status-ok:      #4ade80; --status-ok-bg:     rgba(22,163,74,0.18);
  --status-warn:    #fbbf24; --status-warn-bg:   rgba(217,119,6,0.18);
  --status-danger:  #f87171; --status-danger-bg: rgba(220,38,38,0.18);
  --status-info:    #60a5fa; --status-info-bg:   rgba(37,99,235,0.18);
  --viz-lod0:#4ade80; --viz-lod1:#60a5fa; --viz-lod2:#fbbf24; --viz-lod3:#f87171;
  --shadow-color: 220 60% 2%;
  --elev-1: 0 1px 2px hsl(var(--shadow-color)/0.30), 0 1px 3px hsl(var(--shadow-color)/0.20);
  --elev-2: 0 4px 8px -2px hsl(var(--shadow-color)/0.40), 0 2px 4px -2px hsl(var(--shadow-color)/0.24);
  --elev-3: 0 12px 24px -6px hsl(var(--shadow-color)/0.50), 0 4px 8px -4px hsl(var(--shadow-color)/0.30);
}

/* ─── Density — compact ──────────────────────────────────────────────────────
   SSOT contract, primitive-scoped. The density scale is consumed by the Track-A
   primitives (styles/primitives.css .dg-* heights) + the harness, and shipped as
   the canonical [data-density] contract both tracks honor. It is deliberately NOT
   wired to the live app rows (panel-header / panel-tab / .pt-row): .pt-row's 22px
   height is coupled to TreeVirtualScroll's JS row-height math, so tokenising it
   would desync the virtual scroller. Real-app rows keep their px; these tokens
   stay as the SSOT + new-vanilla-UI vocabulary (execution intentionally unwired). */
[data-density="compact"] {
  --row-h: 22px; --control-h: 26px; --tab-h: 30px; --pad-panel: 8px;
}
