/* Tempelhof palette · dark + light modes · liquid-glass tokens.
   THEME is a live object. ToggleTheme(mode) rewrites its keys in place
   so all components reading THEME.X pick up new values on next render. */

const PALETTE = {
  periwinkle: '#6986BF',   // primary brand blue. Periwinkle
  periwinkleLight: '#8FA4D0',
  periwinkleDeep: '#4E6DA8',
  navy: '#2A3640',         // primary dark
  navyDeep: '#1A232C',
  navyDeeper: '#121921',
  yellow: '#F2E857',       // soft citrus highlight
  honey: '#F2C53D',        // warm accent / warn
  amber: '#D99036',        // deep warm / CTA accent
  coral: '#E5645E',        // error / danger — locked 2026-06-30 (replaces the "secret amber")
  white: '#D7DEE2',
  /* Light-mode paper tones. Pulled darker on 2026-05-02 ("not blinding mode either").
     paper is the page bg; paperElev is for raised surfaces; paperDeep is for
     recessed/secondary panels. Old values were #F6F4EE / #FBFAF5 / #EEEBE2. */
  paper: '#E8E2D2',        // warm light bg, slightly tanned
  paperElev: '#F0EBDC',
  paperDeep: '#DED7C4',
  ink: '#1A232C',          // near-black on light
  inkDim: '#3B4754',
};

/* Start in dark mode by default. Rewritten by setThemeMode(). */
const THEME = {
  mode: 'dark',
  // filled by setThemeMode. See below
};

function buildTokens(mode) {
  const dark = mode === 'dark';
  return {
    mode,

    // surfaces
    bg:        dark ? PALETTE.navyDeep    : PALETTE.paper,
    bgDeep:    dark ? PALETTE.navyDeeper  : PALETTE.paperDeep,
    bgElev:    dark ? '#23303D'           : PALETTE.paperElev,
    bgElev2:   dark ? '#2E3C4B'           : '#D7DEE2',
    panel:     dark ? 'rgba(30,42,56,0.72)' : 'rgba(255,255,255,0.72)',
    panelSolid:dark ? '#23303D'           : '#D7DEE2',

    // glass layers. For backdrop-filter surfaces
    glass:        dark ? 'rgba(42,54,64,0.55)'      : 'rgba(255,255,255,0.55)',
    glassElev:    dark ? 'rgba(58,72,86,0.65)'      : 'rgba(255,255,255,0.7)',
    glassSubtle:  dark ? 'rgba(42,54,64,0.35)'      : 'rgba(255,255,255,0.4)',
    glassBorder:  dark ? 'rgba(255,255,255,0.08)'   : 'rgba(42,54,64,0.08)',
    glassHi:      dark ? 'rgba(255,255,255,0.06)'   : 'rgba(255,255,255,0.7)',

    // lines
    line:       dark ? 'rgba(255,255,255,0.08)'  : 'rgba(42,54,64,0.10)',
    lineSoft:   dark ? 'rgba(255,255,255,0.05)'  : 'rgba(42,54,64,0.06)',
    lineStrong: dark ? 'rgba(255,255,255,0.14)'  : 'rgba(42,54,64,0.16)',

    // text
    text:     dark ? '#F2F4F8'                : PALETTE.ink,
    // textHeader: section / eyebrow headers. Brighter than textDim, not full
    // text. Used for uppercase tracked labels above content groups so they
    // read clearly without competing with body content.
    textHeader: dark ? 'rgba(242,244,248,0.82)' : 'rgba(26,35,44,0.82)',
    textDim:  dark ? 'rgba(242,244,248,0.70)' : 'rgba(26,35,44,0.72)',
    textMute: dark ? 'rgba(242,244,248,0.42)' : 'rgba(26,35,44,0.48)',
    textFaint:dark ? 'rgba(242,244,248,0.24)' : 'rgba(26,35,44,0.28)',

    // brand. Tempelhof blue
    blue:     PALETTE.periwinkle,
    blueDim:  PALETTE.periwinkleDeep,
    blueSoft: dark ? 'rgba(105,134,191,0.18)' : 'rgba(105,134,191,0.14)',
    accent:   dark ? PALETTE.periwinkleLight  : PALETTE.periwinkleDeep,
    // On-pill brand text. Raw brand blue fails AA on the soft-blue pill in both
    // modes; this is the AA-safe periwinkle-family text color for pill chips —
    // lighter on dark, deeper on light (same approach as warnText).
    blueOnSoft: dark ? PALETTE.periwinkleLight : '#3E5489',

    // status. Mapped from palette
    success:  '#5BA773',                                  // green balanced against the warm palette
    successSoft: dark ? 'rgba(91,167,115,0.15)' : 'rgba(91,167,115,0.12)',
    warn:     PALETTE.honey,
    /* warnText: ADA-compliant text color for warning UI. The base warn (#F2C53D)
       fails 4.5:1 contrast against light backgrounds. warnText is darker in light
       mode (deep ochre, ~5.5:1 against white) and lighter in dark mode. */
    warnText: dark ? '#F2D560' : '#7A5208',
    warnSoft: dark ? 'rgba(242,197,61,0.16)' : 'rgba(242,197,61,0.14)',
    /* Error / danger. Locked to CORAL 2026-06-30 (was PALETTE.amber — the
       "secret amber" the mobile audit flagged: the desktop system had no true
       red; danger was a warm ochre indistinguishable from warn). Now unified
       with mobile-ds.jsx (errBase/errSoft/errText) so both systems share one
       error color. danger = the base fill/icon/border coral (mode-independent,
       same as amber was); dangerText = the AA-safe text coral (lighter on dark,
       deeper on light) for red TEXT — mirrors mobile errText. */
    danger:   PALETTE.coral,
    dangerSoft: dark ? 'rgba(229,100,94,0.18)' : 'rgba(229,100,94,0.14)',
    dangerText: dark ? '#F2938E' : '#B23A34',
    highlight:PALETTE.yellow,

    // raw
    palette: PALETTE,
  };
}

function setThemeMode(mode) {
  const t = buildTokens(mode);
  // rewrite in place so all refs see new values
  Object.keys(THEME).forEach(k => { delete THEME[k]; });
  Object.assign(THEME, t);
  if (typeof document !== 'undefined') {
    document.documentElement.dataset.theme = mode;
    document.body.style.background = t.bg;
    document.body.style.color = t.text;
  }
}

// initialize — honor the site-wide theme saved by the marketing site (shared
// 'hellocourt-theme' key) so light/dark carries across pages; default dark.
(function () {
  var saved = 'dark';
  try {
    var v = localStorage.getItem('hellocourt-theme');
    if (v === 'light' || v === 'dark') saved = v;
  } catch (e) {}
  setThemeMode(saved);
})();

/* ─── DESIGN SYSTEM ─────────────────────────────────────────────────────────
   Single source of truth for buttons. Every CTA on the demo should use
   <Btn> rather than inline styles, so the visual language stays consistent.
   Aligned with Phase 2 dedup target 1 spec (locked 2026-05-08):
   1. ALL Btn variants are pill-shaped (border-radius: 999px) EXCEPT
      mobile-block + mobile-block-secondary (added 2026-05-15 / 2026-05-16)
      which use rounded-rectangle radius (12px / 14px) because iOS full-width
      CTAs read as blocks, not pills. The 14px on the secondary is intentional
      — pairs visually with mobile-block when stacked, but is large enough to
      read as the "softer" partner so the eye picks the primary first.
   2. Real <button type="button"> element — keyboard, focus, screen reader
      semantics native.
   3. Six kinds: primary (dark navy CTA), accent (brand-blue CTA),
      secondary (outlined), ghost (transparent + faint border, low-emphasis),
      mobile-block (full-width 50px iOS-style accent CTA · added 2026-05-15),
      mobile-block-secondary (full-width 48px transparent paired-secondary
      for mobile-block · added 2026-05-16).
   4. NO arrow / chevron icons inside buttons.
   5. Text always centered, white-space: nowrap, ≤4 word labels.
   6. accent kept as alias for primary with brand-blue bg (legacy callers).
   7. Disabled = aria-disabled + cursor not-allowed + opacity 0.55.
   8. mobile-block contrast (verified 2026-05-15 with sRGB relative-luminance math):
      Pure white (#FFFFFF) on periwinkle-deep (#4E6DA8) = 5.15:1.
      WCAG AA NORMAL TEXT pass (≥4.5:1) in both modes — variant deliberately
      uses periwinkle-deep in BOTH light and dark to keep the contrast bar
      consistent across modes. (Earlier inline call sites used periwinkle
      #6986BF + #D7DEE2 which was only 2.68:1 — AA-FAIL. The new variant fixes
      that as a side-effect of shipping the canonical.)
      Shadow tint stays THEME.blue (#6986BF) for brand cohesion on the glow.
   9. mobile-block-secondary contrast (verified 2026-05-16):
      Dark mode: #F2F4F8 on transparent over navy-deep bg → reads as 14.8:1.
      Light mode: #1A232C on transparent over paper bg → reads as 16.2:1.
      Both pass AA-normal comfortably. Outline is mode-aware:
      rgba(255,255,255,0.18) on dark / rgba(26,35,44,0.16) on light —
      ≥3:1 for non-text UI components per WCAG 1.4.11.
      Stacks below mobile-block (primary above, secondary below) — the
      transparent fill keeps weight off the secondary so the primary leads.
   ──────────────────────────────────────────────────────────────────────── */
const DS = {
  btn: {
    base: {
      borderRadius: 999,
      fontSize: 13,
      fontWeight: 600,
      cursor: 'pointer',
      display: 'inline-flex',
      alignItems: 'center',
      justifyContent: 'center',
      textAlign: 'center',
      fontFamily: 'inherit',
      lineHeight: 1.2,
      whiteSpace: 'nowrap',
      letterSpacing: 0.05,
      transition: 'background 0.18s ease, color 0.18s ease, box-shadow 0.18s ease, opacity 0.18s ease, border-color 0.18s ease, transform 0.12s ease',
      userSelect: 'none',
      outline: 'none',
      // Native <button> defaults to system styling — reset.
      appearance: 'none',
      WebkitAppearance: 'none',
      MozAppearance: 'none',
    },
    primary: {
      padding: '10px 20px',
      background: '#1A2230',
      color: '#F2F4F8',
      // Navy fill + light-opacity YELLOW hairline. Locked for desktop 2026-07-02
      // (James's desktop decision sheet: primary CTA = navy-yellow, match mobile).
      // Now identical to `mobile-primary`; both kinds kept for call-site clarity.
      border: '1px solid rgba(215,203,167,0.55)',
    },
    /* Mobile design-system CTAs (James, 2026-06-30). Mobile-only kinds so the
       shared desktop `primary` is untouched. mobile-primary = the same navy fill
       with a light-opacity TAN hairline; mobile-danger = coral error. */
    'mobile-primary': {
      padding: '10px 20px',
      background: '#1A2230',
      color: '#F2F4F8',
      border: '1px solid rgba(215,203,167,0.55)',
    },
    'mobile-danger': {
      padding: '10px 20px',
      background: 'rgba(229,100,94,0.18)',
      color: '#F2938E',
      border: '1px solid #E5645E',
    },
    accent: {
      padding: '10px 20px',
      background: '', // injected from THEME.blue at render time
      color: '#D7DEE2',
      border: '1px solid rgba(255,255,255,0.10)',
    },
    secondary: {
      padding: '10px 18px',
      background: 'transparent',
      color: '#F2F4F8',
      border: '1px solid rgba(255,255,255,0.22)',
      fontWeight: 500,
    },
    ghost: {
      padding: '10px 18px',
      background: 'transparent',
      color: 'rgba(242,244,248,0.78)',
      border: '1px solid rgba(255,255,255,0.10)',
      fontWeight: 500,
    },
    /* Mobile-block. Full-width iOS-style primary CTA (added 2026-05-15).
       Rectangle (12px radius, not pill), 50px min-height, periwinkle-deep bg,
       15px label / 600 weight, pure-white text. AA-normal: 5.15:1 verified.
       Used for sticky bottom CTAs on phone surfaces.
       Background is injected from THEME.blueDim at render time. */
    'mobile-block': {
      width: '100%',
      minHeight: 50,
      padding: '0 18px',
      borderRadius: 12,
      background: '', // injected from THEME.blueDim at render time
      color: '#FFFFFF',
      border: 'none',
      fontSize: 15,
      fontWeight: 600,
    },
    /* Mobile-block-secondary. Full-width transparent paired-secondary for
       mobile-block (added 2026-05-16). Same width + nowrap discipline as
       mobile-block, slightly shorter (48px vs 50px) so the primary above
       carries more visual weight. 14px radius pairs visually with the 12px
       primary above without looking like a perfect twin. Border + text are
       mode-aware — injected from THEME at render time below. */
    'mobile-block-secondary': {
      width: '100%',
      minHeight: 48,
      padding: '0 18px',
      borderRadius: 14,
      background: 'transparent',
      color: '',  // injected from THEME at render time
      border: '', // injected from THEME at render time
      fontSize: 14,
      fontWeight: 500,
    },
    disabled: {
      padding: '10px 20px',
      background: 'rgba(20, 28, 40, 0.30)',
      color: 'rgba(242,244,248,0.40)',
      border: '1px solid rgba(255,255,255,0.10)',
      cursor: 'not-allowed',
      opacity: 0.55,
    },
  },
};

const Btn = ({ kind = 'primary', disabled, onClick, children, style: extra, type = 'button', ariaLabel }) => {
  const isLight = THEME.mode === 'light';
  const variant = disabled ? DS.btn.disabled : DS.btn[kind] || DS.btn.primary;
  const merged = { ...DS.btn.base, ...variant };

  // Light-mode color overrides per locked spec — primary stays dark on warm
  // paper, secondary uses navy outline + ink text, ghost uses ink at 0.72.
  if (isLight && !disabled) {
    if (kind === 'primary') {
      merged.background = '#2A3640';
      merged.color = '#F2F4F8';
      merged.border = '1px solid rgba(215,203,167,0.55)';  // yellow hairline in light too (2026-07-02)
    }
    if (kind === 'secondary') {
      merged.color = '#1A232C';
      merged.border = '1px solid rgba(20,30,50,0.32)';
    }
    if (kind === 'ghost') {
      merged.color = 'rgba(20,30,50,0.72)';
      merged.border = '1px solid rgba(20,30,50,0.18)';
    }
  }

  if (kind === 'accent' && !disabled) {
    merged.background = THEME.blue;
    merged.boxShadow = `0 4px 12px ${THEME.blue}40`;
  }

  // mobile-block. Full-width iOS-style accent CTA. Bg = periwinkle-deep
  // (THEME.blueDim) for WCAG AA-normal contrast with white label; shadow stays
  // tinted with THEME.blue for brand cohesion. Shadow tuned slightly taller
  // than accent (6px / 14px) for raised-block feel on phone surfaces.
  if (kind === 'mobile-block' && !disabled) {
    merged.background = THEME.blueDim;
    merged.boxShadow = `0 6px 14px ${THEME.blue}44`;
  }

  // mobile-block-secondary. Paired secondary that lives under a mobile-block
  // primary on phone surfaces. Text + outline are mode-aware: in dark mode the
  // label is the near-white #F2F4F8 with a 0.18-alpha white outline; in light
  // mode the label flips to ink (#1A232C) with a 0.16-alpha navy outline.
  // No shadow — transparent fills don't carry shadows well and the goal is to
  // sit visually quieter than the primary above. AA-normal verified for both
  // modes (see DS doc comment).
  if (kind === 'mobile-block-secondary' && !disabled) {
    merged.color = isLight ? '#1A232C' : '#F2F4F8';
    merged.border = `1px solid ${isLight ? 'rgba(26,35,44,0.16)' : 'rgba(255,255,255,0.18)'}`;
  }

  return (
    <button
      type={type}
      onClick={disabled ? undefined : onClick}
      disabled={disabled}
      aria-disabled={disabled || undefined}
      aria-label={ariaLabel}
      onMouseEnter={(e) => {
        if (disabled) return;
        if (kind === 'primary')      e.currentTarget.style.background = isLight ? '#3A4754' : '#232E3F';
        if (kind === 'secondary')    e.currentTarget.style.background = isLight ? 'rgba(20,30,50,0.06)' : 'rgba(255,255,255,0.06)';
        if (kind === 'ghost')        e.currentTarget.style.background = isLight ? 'rgba(20,30,50,0.04)' : 'rgba(255,255,255,0.04)';
        if (kind === 'accent')       e.currentTarget.style.boxShadow = `0 6px 16px ${THEME.blue}60`;
        if (kind === 'mobile-block') e.currentTarget.style.boxShadow = `0 8px 18px ${THEME.blue}66`;
        if (kind === 'mobile-block-secondary') e.currentTarget.style.background = isLight ? 'rgba(20,30,50,0.06)' : 'rgba(255,255,255,0.06)';
      }}
      onMouseLeave={(e) => {
        if (disabled) return;
        if (kind === 'primary')      e.currentTarget.style.background = isLight ? '#2A3640' : '#1A2230';
        if (kind === 'secondary')    e.currentTarget.style.background = 'transparent';
        if (kind === 'ghost')        e.currentTarget.style.background = 'transparent';
        if (kind === 'accent')       e.currentTarget.style.boxShadow = `0 4px 12px ${THEME.blue}40`;
        if (kind === 'mobile-block') e.currentTarget.style.boxShadow = `0 6px 14px ${THEME.blue}44`;
        if (kind === 'mobile-block-secondary') e.currentTarget.style.background = 'transparent';
      }}
      onFocus={(e) => {
        if (disabled) return;
        e.currentTarget.style.boxShadow = `0 0 0 2px ${THEME.bg}, 0 0 0 4px ${isLight ? '#4E6DA8' : '#9FB3FF'}`;
      }}
      onBlur={(e) => {
        if (disabled) return;
        if (kind === 'accent')             e.currentTarget.style.boxShadow = `0 4px 12px ${THEME.blue}40`;
        else if (kind === 'mobile-block')  e.currentTarget.style.boxShadow = `0 6px 14px ${THEME.blue}44`;
        else                                e.currentTarget.style.boxShadow = 'none';
      }}
      style={{ ...merged, ...(extra || {}) }}>
      {children}
    </button>
  );
};

window.THEME = THEME;
window.PALETTE = PALETTE;
window.setThemeMode = setThemeMode;
window.DS = DS;
window.Btn = Btn;
