// Design tokens and primitives shared by every page: palette, radii, shadows, icons, buttons.

const FONT_PAIRS = {
  'Bricolage + Onest':   { display: "'Bricolage Grotesque', sans-serif", body: "'Onest', sans-serif" },
  'Onest only':          { display: "'Onest', sans-serif",               body: "'Onest', sans-serif" },
  'Schibsted + Nunito':  { display: "'Schibsted Grotesk', sans-serif",   body: "'Nunito Sans', sans-serif" },
  'Gabarito + Figtree':  { display: "'Gabarito', sans-serif",            body: "'Figtree', sans-serif" },
  'Source Serif + Onest':{ display: "'Source Serif 4', serif",           body: "'Onest', sans-serif" },
};

function makeTheme(t) {
  const pair = FONT_PAIRS[t.fonts] || FONT_PAIRS['Bricolage + Onest'];
  const a = t.accent;
  return {
    isDark: false,
    accent: a,
    accentUI: a,                                         // controls (buttons, active tab), dims in dark mode
    deep:  `color-mix(in oklab, ${a} 76%, #0c1620)`,   // darker accent (pressed / dark surfaces)
    heroA: (t.hero === 'Deep') ? `color-mix(in oklab, ${a} 76%, #0c1620)` : a, // hero start, Flat/Gradient: accent, Deep: dark
    heroDeep: (t.hero === 'Flat') ? a : `color-mix(in oklab, ${a} 76%, #0c1620)`, // hero end, Flat: accent (solid), else dark
    paper: '#FFFFFF',
    glass: 'rgba(255,255,255,0.92)',
    onAccent: '#FFFFFF',
    // secondary colors, bright, sun-lit family that matches the airy accent
    amber: '#F5B73F',
    amberInk: '#A87C0A',
    amberSoft: '#FEF3D9',
    red: '#E8655C',
    redInk: '#C2453D',
    redSoft: '#FDEEED',
    green: '#3DB47E',
    greenInk: '#1F7A50',
    greenSoft: '#E4F6EC',
    // neutrals carry a whisper of the accent hue so the whole UI re-tints together
    ink:   `color-mix(in oklab, ${a} 14%, #1f2729)`,
    mut:   `color-mix(in oklab, ${a} 16%, #64716f)`,
    faint: `color-mix(in oklab, ${a} 12%, #9aa6a4)`,
    bg:    `color-mix(in oklab, ${a} ${t.bgTint ?? 4.5}%, #f7f8f8)`,
    card: '#FFFFFF',
    line:  `color-mix(in oklab, ${a} 8%, #e9eceb)`,
    tint: (p, base = '#FFFFFF') => `color-mix(in oklab, ${a} ${p}%, ${base})`,
    tabMode: t.tabBar || 'Floating',
    premiumTone: t.premium || 'Gold',
    df: pair.display,
    bf: pair.body,
  };
}

// Dark variant, same token names, night values. deep becomes a LIGHT accent
// (it's used as accent-strong text); heroDeep keeps gradients dark.

// Dark variant, same token names, night values. deep becomes a LIGHT accent
// (it's used as accent-strong text); heroDeep keeps gradients dark.
function makeDarkTheme(t) {
  const pair = FONT_PAIRS[t.fonts] || FONT_PAIRS['Bricolage + Onest'];
  const a = t.accent;
  const base = '#121A1F';
  return {
    isDark: true,
    accent: a,
    accentUI: `color-mix(in oklab, ${a} 72%, #101a21)`,
    deep:  `color-mix(in oklab, ${a} 50%, #E5EEF3)`,
    heroA: (t.hero === 'Flat') ? `color-mix(in oklab, ${a} 72%, #101a21)` : (t.hero === 'Deep') ? `color-mix(in oklab, ${a} 28%, #0a1115)` : `color-mix(in oklab, ${a} 58%, #0e161c)`,
    heroDeep: (t.hero === 'Flat') ? `color-mix(in oklab, ${a} 72%, #101a21)` : `color-mix(in oklab, ${a} 28%, #0a1115)`,
    paper: '#10171B',
    glass: 'rgba(18,25,29,0.92)',
    onAccent: '#FFFFFF',
    amber: '#F5B73F',
    amberInk: '#F2CC85',
    amberSoft: `color-mix(in oklab, #F5B73F 17%, ${base})`,
    red: '#E8655C',
    redInk: '#F49B94',
    redSoft: `color-mix(in oklab, #E8655C 16%, ${base})`,
    green: '#3DB47E',
    greenInk: '#8BDDB4',
    greenSoft: `color-mix(in oklab, #3DB47E 16%, ${base})`,
    ink: '#ECF2F5',
    mut: '#9FB1BB',
    faint: '#697A85',
    bg: `color-mix(in oklab, ${a} ${(t.bgTint ?? 4.5) + 1.5}%, #0D1317)`,
    card: '#171F25',
    line: 'rgba(255,255,255,0.09)',
    // tint wells sit on the #171F25 card, so mix over a base LIGHTER than the card
    // (the old #121A1F base sank every low-tint chip into the card surface)
    tint: (p, base2) => `color-mix(in oklab, ${a} ${Math.min(p + 7, 100)}%, ${base2 || '#27323A'})`,
    tabMode: t.tabBar || 'Floating',
    premiumTone: t.premium || 'Gold',
    df: pair.display,
    bf: pair.body,
  };
}

// ── Tweak-driven helpers: corner-radius scale + shadow depth ─
// App sets window.__radScale / window.__shadowMode from Tweaks before render.

// ── Tweak-driven helpers: corner-radius scale + shadow depth ─
// App sets window.__radScale / window.__shadowMode from Tweaks before render.
function RAD(n) {
  const s = window.__radScale || 1;
  return s === 1 ? n : Math.round(n * s * 10) / 10;
}

function SH(v) {
  const m = window.__shadowMode || 'Soft';
  if (m === 'Soft' || !v || v === 'none') return v;
  if (m === 'Flat') return 'none';
  return v + ', 0 24px 48px rgba(8, 18, 26, 0.16)';
}
// Icon-well stroke gate. App sets window.__iconStroke from the Tweaks toggle.
// When off, every well border collapses to 'none'.

// Icon-well stroke gate. App sets window.__iconStroke from the Tweaks toggle.
// When off, every well border collapses to 'none'.
function WSTROKE(border) {
  return (window.__iconStroke === false) ? 'none' : border;
}

// Icon-container (well) size scale. App sets window.__icWellScale from the
// Tweaks slider (1 = default). Wrap a well's width/height numbers with IW().

// Icon-container (well) size scale. App sets window.__icWellScale from the
// Tweaks slider (1 = default). Wrap a well's width/height numbers with IW().
function IW(px) {
  const k = window.__icWellScale || 1;
  return k === 1 ? px : Math.round(px * k);
}

// ── Density helpers ─ App sets window.__denScale (1 = comfortable, 0.85 = compact).
// DEN scales numeric gaps/margins/spacers; PADS scales the vertical values
// inside a padding shorthand string ('14px 16px' → vertical 14px only).

// ── Density helpers ─ App sets window.__denScale (1 = comfortable, 0.85 = compact).
// DEN scales numeric gaps/margins/spacers; PADS scales the vertical values
// inside a padding shorthand string ('14px 16px' → vertical 14px only).
function DEN(n) {
  const k = window.__denScale || 1;
  return k === 1 ? n : Math.round(n * k * 10) / 10;
}

function PADS(s) {
  const k = window.__denScale || 1;
  if (k === 1 || typeof s !== 'string') return s;
  const parts = s.split(' ');
  return parts.map((p, i) => {
    const m = /^(\d*\.?\d+)px$/.exec(p);
    if (!m || i % 2 !== 0) return p;
    return Math.round(parseFloat(m[1]) * k * 10) / 10 + 'px';
  }).join(' ');
}

// ── Minimal stroke icon set ──────────────────────────────────

// ── Minimal stroke icon set ──────────────────────────────────
const IC_PATHS = {
  check:   <path d="M5 12.5l4.5 4.5L19 7" />,
  x:       <path d="M6.5 6.5l11 11M17.5 6.5l-11 11" />,
  chevR:   <path d="M9.5 5.5l6.5 6.5-6.5 6.5" />,
  chevD:   <path d="M5.5 9.5l6.5 6.5 6.5-6.5" />,
  arrowR:  <><path d="M4.5 12h15" /><path d="M13.5 6l6 6-6 6" /></>,
  download: <><path d="M12 3.5v11" /><path d="M7.5 10.5l4.5 4.5 4.5-4.5" /><path d="M4.5 16.5v2.5a1.5 1.5 0 001.5 1.5h12a1.5 1.5 0 001.5-1.5v-2.5" /></>,
  phone:   <><rect x="6.5" y="2.5" width="11" height="19" rx="2.8" /><path d="M10.5 18.5h3" /></>,
  lock:    <><rect x="5" y="11" width="14" height="9" rx="2.5" /><path d="M8.5 11V8a3.5 3.5 0 017 0v3" /></>,
  flame:   <path d="M12 3c.8 3.4-4.6 5.4-4.6 9.6a4.6 4.6 0 009.2 0c0-1.9-.9-3.2-1.9-4.6-.6 1.4-1.4 2-2.4 2 .8-2.3.5-4.7-.3-7z" />,
  cal:     <><rect x="4" y="5.5" width="16" height="15" rx="3" /><path d="M4 10.5h16M8.5 3v4M15.5 3v4" /></>,
  pin:     <><path d="M12 21s-7-5.6-7-11a7 7 0 0114 0c0 5.4-7 11-7 11z" /><circle cx="12" cy="10" r="2.4" /></>,
  target:  <><circle cx="12" cy="12" r="8" /><circle cx="12" cy="12" r="4" /><circle cx="12" cy="12" r="0.6" /></>,
  chart:   <path d="M5.5 19.5v-7M12 19.5V5.5M18.5 19.5v-10" />,
  book:    <><path d="M5 19.5V6.5a2.5 2.5 0 012.5-2.5H19v14H7.5A2.5 2.5 0 005 20.5z" /><path d="M5 20.5A2.5 2.5 0 007.5 23H19" transform="translate(0,-2.5)" /></>,
  home:    <path d="M4.5 10.5L12 4l7.5 6.5V20a1 1 0 01-1 1h-4.5v-5.5h-4V21H5.5a1 1 0 01-1-1v-9.5z" />,
  user:    <><circle cx="12" cy="8" r="3.8" /><path d="M4.5 20.5c1.5-3.8 4.7-5.3 7.5-5.3s6 1.5 7.5 5.3" /></>,
  crown:   <path d="M3.5 8.5l4.7 3.4L12 5.5l3.8 6.4 4.7-3.4-1.4 9.5H4.9L3.5 8.5z" />,
  clock:   <><circle cx="12" cy="12" r="8" /><path d="M12 7.5V12l3 2.2" /></>,
  leaf:    <><path d="M5.5 18.5C5.5 10.5 11.5 5 19.5 5c0 8-5.5 13.5-14 13.5z" /><path d="M5.5 18.5c2.8-4.5 6.5-8 10.5-10" /></>,
  search:  <><circle cx="11" cy="11" r="6" /><path d="M16.5 16.5L21 21" /></>,
  shield:  <path d="M12 3l7 2.8v6c0 4.6-3 7.6-7 9.2-4-1.6-7-4.6-7-9.2v-6L12 3z" />,
  refresh: <><path d="M19 12a7 7 0 11-2-4.9" /><path d="M19.5 4.5v3.6h-3.6" /></>,
  spark:   <path d="M12 5l1.8 5.4L19 12l-5.2 1.6L12 19l-1.8-5.4L5 12l5.2-1.6L12 5z" />,
  bookmark: <path d="M7 4.5h10a1 1 0 011 1V20.5l-6-4.5-6 4.5V5.5a1 1 0 011-1z" />,
  flag:    <><path d="M6 21V4.5" /><path d="M6 5h11.5l-2.6 3.5 2.6 3.5H6" /></>,
  bell:    <><path d="M18.5 16.5h-13c1.3-1.5 2.1-2.8 2.1-6.3a4.4 4.4 0 018.8 0c0 3.5.8 4.8 2.1 6.3z" /><path d="M10.3 19.5a1.9 1.9 0 003.4 0" /></>,
  timer:   <><circle cx="12" cy="13" r="7.5" /><path d="M12 9.5V13l2.4 1.8M10 2.5h4" /></>,
  info:    <><circle cx="12" cy="12" r="8" /><path d="M12 11v5M12 7.7v.2" /></>,
};

function Ic({ name, size = 20, c = 'currentColor', w = 1.8, style }) {
  const sz = Math.round(size * (window.__icSizeScale || 1));
  return (
    <svg width={sz} height={sz} viewBox="0 0 24 24" fill="none" style={style}
      stroke={c} strokeWidth={w * (window.__icScale || 1)} strokeLinecap="round" strokeLinejoin="round">
      {IC_PATHS[name]}
    </svg>
  );
}

// ── Striped illustration placeholder ─────────────────────────

// ── Striped illustration placeholder ─────────────────────────
function Stripes({ label, h = 220, T, dark = false, radius = 28, style }) {
  const c1 = dark ? 'rgba(255,255,255,0.05)' : T.tint(7);
  const c2 = dark ? 'rgba(255,255,255,0.09)' : T.tint(13);
  return (
    <div style={{
      height: h, borderRadius: RAD(radius), overflow: 'hidden',
      background: `repeating-linear-gradient(45deg, ${c1}, ${c1} 12px, ${c2} 12px, ${c2} 24px)`,
      display: 'flex', alignItems: 'center', justifyContent: 'center',
      border: dark ? '1px solid rgba(255,255,255,0.1)' : `1px solid ${T.tint(16)}`,
      ...style,
    }}>
      <span style={{
        fontFamily: 'ui-monospace, SFMono-Regular, Menlo, monospace', fontSize: 11.5,
        color: dark ? 'rgba(255,255,255,0.55)' : T.mut,
        background: dark ? 'rgba(0,0,0,0.25)' : 'rgba(255,255,255,0.72)',
        padding: '6px 12px', borderRadius: 99, letterSpacing: 0.2, textAlign: 'center',
      }}>{label}</span>
    </div>
  );
}

// ── Buttons ──────────────────────────────────────────────────

// ── Buttons ──────────────────────────────────────────────────
function Btn({ children, T, kind = 'primary', h = 56, fs = 17, icon, loading = false, style, onClick }) {
  const acc = T.accentUI || T.accent;
  const kinds = {
    primary: {
      background: acc, color: '#fff',
      boxShadow: SH(T.isDark
        ? `0 8px 20px rgba(0,0,0,0.35)`
        : `0 8px 20px color-mix(in oklab, ${T.accent} 28%, transparent)`),
      border: T.isDark ? `1px solid color-mix(in oklab, ${T.accent} 32%, transparent)` : 'none',
    },
    dark:    { background: '#fff', color: '#1C2B29', boxShadow: SH('0 8px 24px rgba(0,0,0,0.25)') },
    soft:    { background: T.tint(9), color: T.deep },
    ghost:   { background: 'transparent', color: T.mut },
    amber:   (T.premiumTone === 'Quiet')
      ? { background: T.isDark ? 'rgba(245,183,63,0.13)' : '#26323A', color: T.isDark ? '#F2CC85' : '#F5C766', border: '1px solid rgba(245,183,63,0.30)', boxShadow: 'none' }
      : T.isDark
        ? { background: `linear-gradient(180deg, color-mix(in oklab, ${T.amber} 78%, #18110a) 0%, color-mix(in oklab, ${T.amber} 60%, #18110a) 100%)`, color: '#fff', border: `1px solid color-mix(in oklab, ${T.amber} 30%, transparent)` }
        : { background: T.amber, color: '#3A2A08' },
  };
  return (
    <div className="hb-btn" onClick={onClick} style={{
      height: h, borderRadius: 99, display: 'flex', alignItems: 'center', justifyContent: 'center',
      gap: 8, fontFamily: T.bf, fontSize: fs, fontWeight: 650, letterSpacing: 0.1,
      cursor: 'pointer', opacity: loading ? 0.92 : 1, ...kinds[kind], ...style,
    }}>
      {loading ? (
        <>
          <span style={{
            width: fs, height: fs, borderRadius: '50%', display: 'inline-block',
            border: `${Math.max(2, fs/8)}px solid rgba(255,255,255,0.4)`,
            borderTopColor: kind === 'soft' || (kind === 'amber' && T.premiumTone === 'Quiet') ? T.accent : '#fff',
            animation: 'hb-spin 0.8s linear infinite',
          }}></span>
          {typeof children === 'string' ? children : 'Please wait…'}
        </>
      ) : (
        <>
          {children}
          {icon && <Ic name={icon} size={18} w={2.2} />}
        </>
      )}
    </div>
  );
}

// ── Small label chip ─────────────────────────────────────────

// ── Small label chip ─────────────────────────────────────────
function Tag({ children, T, color, bg, icon, style }) {
  return (
    <div style={{
      display: 'inline-flex', alignItems: 'center', gap: 5,
      padding: '5px 11px', borderRadius: 99,
      background: bg || T.tint(9), color: color || T.deep,
      border: `1px solid ${color ? `color-mix(in oklab, ${color} 22%, transparent)` : T.tint(20)}`,
      boxShadow: '0 1px 2px rgba(8,12,10,0.06), 0 2px 6px rgba(8,12,10,0.05)',
      fontFamily: T.bf, fontSize: 12.5, fontWeight: 700, letterSpacing: 0.2,
      ...style,
    }}>
      {icon && <Ic name={icon} size={13} w={2.4} />}
      {children}
    </div>
  );
}

Object.assign(window, { makeTheme, makeDarkTheme, RAD, SH, WSTROKE, IW, DEN, PADS, Ic, Stripes, Btn, Tag, FONT_PAIRS });
