// Arbiter Design Tokens — single source of truth.
// Exposes:
//   window.ArbiterTokens  — JS object (backward compatible with every existing component).
//   window.ArbiterTheme   — { mode, density, setMode, setDensity, subscribe } runtime controller.
//   :root CSS custom properties — consumable from plain CSS, print, non-React surfaces.
//
// Design goals
//   - Light and dark parity. Every semantic role has a pair.
//   - Density modes: compact | comfortable | touch. Spacing + line-height shift; colors do not.
//   - Semantic > raw. Components bind to semantic roles (text.primary, bg.card), not raw hex.

(function () {
  // ── Raw palette (immutable) ─────────────────────────────────────────────
  const palette = {
    ivory:  { 50:'#FEFDFB', 100:'#FAF8F5', 200:'#F5F2ED', 300:'#EBE7E0', 400:'#D9D4CB' },
    navy:   { 900:'#0A1628', 800:'#111D35', 700:'#1A2844', 600:'#243356', 500:'#2E3F68',
              400:'#4A5A80', 300:'#6E7D9E', 200:'#96A3BD', 100:'#C2CAD9', 50:'#E6EAF2' },
    status: { active:'#1B7A4A', activeBg:'#E8F5EE',
              warning:'#B8860B', warningBg:'#FFF8E7',
              critical:'#C23030', criticalBg:'#FEF0F0',
              pending:'#4A5A80', pendingBg:'#F0F2F6' },
    accent: { blue:'#2563EB', blueBg:'#EFF4FF' },
  };

  // ── Semantic role maps — light / dark ───────────────────────────────────
  const roles = {
    light: {
      text: { primary:'#0A1628', secondary:'#4A5A80', tertiary:'#6E7D9E',
              inverse:'#FAF8F5', muted:'#96A3BD' },
      bg:   { primary:'#FAF8F5', secondary:'#F5F2ED', tertiary:'#EBE7E0',
              sidebar:'#0A1628', card:'#FEFDFB', hover:'#F5F2ED', overlay:'rgba(10,22,40,0.48)' },
      border: { light:'#EBE7E0', medium:'#D9D4CB', dark:'#1A2844', focus:'#2563EB' },
      status: palette.status,
      accent: palette.accent,
    },
    dark: {
      text: { primary:'#F5F2ED', secondary:'#C2CAD9', tertiary:'#96A3BD',
              inverse:'#0A1628', muted:'#6E7D9E' },
      bg:   { primary:'#0A1628', secondary:'#111D35', tertiary:'#1A2844',
              sidebar:'#050B17', card:'#111D35', hover:'#1A2844', overlay:'rgba(0,0,0,0.64)' },
      border: { light:'#243356', medium:'#2E3F68', dark:'#4A5A80', focus:'#60A5FA' },
      status: { active:'#4ADE80', activeBg:'rgba(74,222,128,0.12)',
                warning:'#F0C330', warningBg:'rgba(240,195,48,0.12)',
                critical:'#F87171', criticalBg:'rgba(248,113,113,0.12)',
                pending:'#C2CAD9', pendingBg:'rgba(194,202,217,0.08)' },
      accent: { blue:'#60A5FA', blueBg:'rgba(96,165,250,0.12)' },
    },
  };

  // ── Typography, spacing, radius, shadow, motion ─────────────────────────
  const font = {
    family: '-apple-system, BlinkMacSystemFont, "SF Pro Display", "SF Pro Text", "Helvetica Neue", Helvetica, Arial, sans-serif',
    mono:   '"SF Mono", "Fira Code", "Fira Mono", Menlo, Consolas, monospace',
    size:   { xs:'11px', sm:'12px', base:'13px', md:'14px', lg:'16px', xl:'20px', xxl:'24px', hero:'32px' },
    weight: { normal:400, medium:500, semibold:600, bold:700 },
    tracking:{ tight:'-0.02em', normal:'0', wide:'0.04em', caps:'0.08em' },
  };
  const density = {
    compact:     { scale:0.85, space:{ xs:'3px', sm:'6px', md:'9px', lg:'12px', xl:'16px', xxl:'20px', xxxl:'26px' }, rowHeight:'28px', lineHeight:1.35 },
    comfortable: { scale:1.00, space:{ xs:'4px', sm:'8px', md:'12px', lg:'16px', xl:'20px', xxl:'24px', xxxl:'32px' }, rowHeight:'36px', lineHeight:1.5  },
    touch:       { scale:1.18, space:{ xs:'6px', sm:'10px', md:'14px', lg:'20px', xl:'24px', xxl:'30px', xxxl:'40px' }, rowHeight:'44px', lineHeight:1.6  },
  };
  const radius  = { sm:'4px', md:'6px', lg:'8px', xl:'12px', pill:'999px' };
  const shadow  = {
    light: { sm:'0 1px 2px rgba(10,22,40,0.05)', md:'0 2px 8px rgba(10,22,40,0.08)', lg:'0 4px 16px rgba(10,22,40,0.12)' },
    dark:  { sm:'0 1px 2px rgba(0,0,0,0.30)',   md:'0 2px 8px rgba(0,0,0,0.45)',   lg:'0 4px 16px rgba(0,0,0,0.60)' },
  };
  const motion  = {
    duration: { instant:'0ms', fast:'120ms', base:'200ms', slow:'320ms' },
    easing:   { standard:'cubic-bezier(0.2,0,0,1)', emphasized:'cubic-bezier(0.3,0,0,1)' },
  };
  const z = { base:0, sticky:10, dropdown:100, overlay:1000, modal:1100, toast:1200, palette:1300 };

  // ── Emit CSS custom properties ──────────────────────────────────────────
  function toVars(obj, prefix) {
    const out = [];
    for (const k in obj) {
      const v = obj[k];
      const key = `${prefix}-${k.replace(/[A-Z]/g,m=>'-'+m.toLowerCase())}`;
      if (v && typeof v === 'object') out.push(toVars(v, key));
      else out.push(`${key}: ${v};`);
    }
    return out.join('\n  ');
  }
  function buildCss(mode, dens) {
    const r = roles[mode];
    const sh = shadow[mode];
    const sp = density[dens];
    return `
      color-scheme: ${mode};
      ${toVars({ text:r.text, bg:r.bg, border:r.border, status:r.status, accent:r.accent },'--color')}
      ${toVars({ size:font.size, weight:font.weight, tracking:font.tracking },'--font')}
      --font-family: ${font.family};
      --font-mono: ${font.mono};
      ${toVars(sp.space,'--space')}
      --row-height: ${sp.rowHeight};
      --line-height: ${sp.lineHeight};
      ${toVars(radius,'--radius')}
      ${toVars(sh,'--shadow')}
      ${toVars(motion.duration,'--duration')}
      ${toVars(motion.easing,'--easing')}
    `;
  }
  function installStylesheet() {
    let el = document.getElementById('arbiter-tokens');
    if (!el) { el = document.createElement('style'); el.id = 'arbiter-tokens'; document.head.appendChild(el); }
    el.textContent = `
      :root { ${buildCss('light','comfortable')} }
      :root[data-theme="dark"] { ${buildCss('dark','comfortable')} }
      :root[data-density="compact"] { ${toVars(density.compact.space,'--space')} --row-height:${density.compact.rowHeight}; --line-height:${density.compact.lineHeight}; }
      :root[data-density="touch"]   { ${toVars(density.touch.space,'--space')}   --row-height:${density.touch.rowHeight};   --line-height:${density.touch.lineHeight};   }
      @media (prefers-reduced-motion: reduce) {
        *, *::before, *::after {
          animation-duration: 1ms !important; animation-iteration-count: 1 !important;
          transition-duration: 1ms !important; scroll-behavior: auto !important;
        }
      }
      .sr-only {
        position:absolute; width:1px; height:1px; padding:0; margin:-1px;
        overflow:hidden; clip:rect(0,0,0,0); white-space:nowrap; border:0;
      }
      .skip-link {
        position:absolute; top:-40px; left:8px; z-index:${z.palette};
        background:#0A1628; color:#FAF8F5; padding:8px 12px; border-radius:6px;
        font-size:13px; text-decoration:none; transition:top 120ms;
      }
      .skip-link:focus { top:8px; outline:2px solid #60A5FA; outline-offset:2px; }
      :focus-visible { outline:2px solid var(--color-border-focus); outline-offset:2px; border-radius:2px; }

      /* ── Bloomberg-grade numerics: fixed-width, tabular, lining digits ── */
      .arb-num, [data-arb-num], [data-num] {
        font-variant-numeric: tabular-nums lining-nums;
        font-feature-settings: "tnum" 1, "lnum" 1, "cv11" 1;
        font-family: var(--font-mono);
      }
      /* Apple-like caps labels */
      .arb-caps {
        text-transform: uppercase;
        letter-spacing: 0.08em;
        font-weight: 600;
        font-size: 10px;
        color: var(--color-text-tertiary);
      }
      /* Soft-elevation utility — inspired by macOS sheet */
      .arb-elev-1 { box-shadow: 0 1px 2px rgba(10,22,40,0.04), 0 0 0 1px var(--color-border-light); }
      .arb-elev-2 { box-shadow: 0 2px 8px rgba(10,22,40,0.06), 0 0 0 1px var(--color-border-light); }
      .arb-elev-3 { box-shadow: 0 8px 24px rgba(10,22,40,0.10), 0 0 0 1px var(--color-border-medium); }
      /* Keyboard shortcut badge */
      kbd, .arb-kbd {
        display: inline-block;
        padding: 1px 5px;
        font-size: 10px;
        line-height: 1.3;
        color: var(--color-text-secondary);
        background: var(--color-bg-tertiary);
        border: 1px solid var(--color-border-light);
        border-radius: 3px;
        font-family: var(--font-mono);
        box-shadow: 0 1px 0 var(--color-border-light);
      }
      /* Data row hover — subtler than hover fill */
      .arb-row { transition: background 120ms var(--easing-standard, ease); }
      .arb-row:hover { background: var(--color-bg-hover); }
      /* Apple-style input: clean focus ring, no ugly default */
      .arb-input {
        background: var(--color-bg-card);
        border: 1px solid var(--color-border-medium);
        border-radius: 6px;
        padding: 6px 10px;
        font-family: var(--font-family);
        font-size: 12px;
        color: var(--color-text-primary);
        outline: none;
        transition: border-color 120ms, box-shadow 120ms;
      }
      .arb-input:focus {
        border-color: var(--color-border-focus);
        box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-border-focus) 22%, transparent);
      }
      /* Animated in-view fade-slide for mount */
      @keyframes arb-fade-in { from { opacity: 0; transform: translateY(2px); } to { opacity: 1; transform: none; } }
      .arb-enter { animation: arb-fade-in 200ms var(--easing-standard, ease) both; }
    `;
  }

  // ── Runtime theme controller ────────────────────────────────────────────
  const subs = new Set();
  const prefersDark = typeof matchMedia !== 'undefined' && matchMedia('(prefers-color-scheme: dark)').matches;
  const saved = (typeof localStorage !== 'undefined') ? localStorage.getItem('arbiter:theme') : null;
  const savedDensity = (typeof localStorage !== 'undefined') ? localStorage.getItem('arbiter:density') : null;
  const state = { mode: saved || (prefersDark ? 'dark' : 'light'), density: savedDensity || 'comfortable' };

  function apply() {
    if (typeof document === 'undefined') return;
    document.documentElement.setAttribute('data-theme', state.mode);
    document.documentElement.setAttribute('data-density', state.density);
    rebuildLegacyTokens();
    subs.forEach(fn => { try { fn(state); } catch(e){} });
  }
  function setMode(m)    { state.mode = m; try{localStorage.setItem('arbiter:theme',m);}catch{} apply(); }
  function setDensity(d) { state.density = d; try{localStorage.setItem('arbiter:density',d);}catch{} apply(); }
  function subscribe(fn) { subs.add(fn); return () => subs.delete(fn); }

  // ── Backward-compatible JS token object ─────────────────────────────────
  // Existing components read window.ArbiterTokens (often aliased as `T`) on module load.
  // Keep the same shape; rebuild in place on theme changes so references stay valid.
  const ArbiterTokens = { color:{}, font, space:{}, radius, shadow:{} };
  function rebuildLegacyTokens() {
    const r  = roles[state.mode];
    const sh = shadow[state.mode];
    const sp = density[state.density];
    // Raw palette kept on color for legacy reads (navy900, ivory100, etc.)
    Object.assign(ArbiterTokens.color,
      { ivory50:palette.ivory[50], ivory100:palette.ivory[100], ivory200:palette.ivory[200],
        ivory300:palette.ivory[300], ivory400:palette.ivory[400],
        navy900:palette.navy[900], navy800:palette.navy[800], navy700:palette.navy[700],
        navy600:palette.navy[600], navy500:palette.navy[500], navy400:palette.navy[400],
        navy300:palette.navy[300], navy200:palette.navy[200], navy100:palette.navy[100],
        text:r.text, bg:r.bg, border:r.border, status:r.status, accent:r.accent });
    Object.assign(ArbiterTokens.space, sp.space);
    Object.assign(ArbiterTokens.shadow, sh);
    ArbiterTokens.mode = state.mode;
    ArbiterTokens.density = state.density;
    ArbiterTokens.motion = motion;
    ArbiterTokens.z = z;
  }
  rebuildLegacyTokens();

  window.ArbiterTokens = ArbiterTokens;
  window.ArbiterTheme  = {
    get mode()    { return state.mode; },
    get density() { return state.density; },
    setMode, setDensity, subscribe,
    palette, roles, density, font, radius, shadow, motion, z,
  };

  if (typeof document !== 'undefined') {
    if (document.readyState === 'loading') {
      document.addEventListener('DOMContentLoaded', () => { installStylesheet(); apply(); });
    } else { installStylesheet(); apply(); }
  }
})();
