// ─────────────────────────────────────────────────────────────
// Settings & privacy
// ─────────────────────────────────────────────────────────────

const { useState: useS2, useEffect: useE2, useMemo: useM2 } = React;

const SECTIONS = [
  { id: 'account',       labelKey: 'settings.section_account' },
  { id: 'appearance',    labelKey: 'settings.section_appearance' },
  { id: 'privacy',       labelKey: 'settings.section_privacy', accent: true },
  { id: 'notifications', labelKey: 'settings.section_notifications' },
  { id: 'integrations',  labelKey: 'settings.section_integrations' },
  { id: 'billing',       labelKey: 'settings.section_billing' },
  { id: 'danger',        labelKey: 'settings.section_danger', danger: true },
];

// shared field/input shims (mirror invite.jsx)
function SField({ label, hint, children }) {
  const { c, fonts } = useLW();
  return (
    <label style={{ display: 'block' }}>
      <div style={{ display: 'flex', alignItems: 'baseline', justifyContent: 'space-between', marginBottom: 6 }}>
        <span style={{ fontFamily: fonts.body, fontSize: 12, fontWeight: 600, letterSpacing: '0.08em', textTransform: 'uppercase', color: c.textTertiary }}>{label}</span>
        {hint && <span style={{ fontFamily: fonts.body, fontSize: 12, color: c.textTertiary, fontStyle: 'italic' }}>{hint}</span>}
      </div>
      {children}
    </label>
  );
}

function SInput({ value, onChange, placeholder, type = 'text' }) {
  const { c, fonts, brutMode } = useLW();
  const isBrut = !!brutMode;
  const [focus, setFocus] = useS2(false);
  return (
    <input
      type={type}
      value={value}
      onChange={(e) => onChange(e.target.value)}
      onFocus={() => setFocus(true)}
      onBlur={() => setFocus(false)}
      placeholder={placeholder}
      style={{
        width: '100%',
        background: isBrut ? c.bg : c.bgSubtle,
        border: isBrut
          ? `1.5px solid ${c.ink || c.textPrimary}`
          : `1px solid ${focus ? c.borderStrong : c.borderSubtle}`,
        borderRadius: isBrut ? 2 : 10,
        padding: '11px 14px',
        fontFamily: fonts.body, fontSize: 15, color: c.textPrimary,
        outline: 'none',
        boxShadow: isBrut
          ? (focus ? `2px 2px 0 0 ${c.ink || c.textPrimary}` : 'none')
          : (focus ? `0 0 0 3px ${hexToRgba(c.accent, 0.15)}` : 'none'),
      }}
    />
  );
}

function SToggle({ on, onChange, label, hint }) {
  const { c, fonts, brutMode } = useLW();
  const isBrut = !!brutMode;
  return (
    <button type="button" onClick={() => onChange(!on)} style={{
      display: 'flex', alignItems: 'flex-start', gap: 14,
      background: 'transparent', border: 'none', padding: 0, cursor: 'pointer',
      textAlign: 'left', width: '100%',
    }}>
      <span style={{
        flexShrink: 0, marginTop: 2,
        width: 38, height: 22,
        borderRadius: isBrut ? 2 : 10,
        border: isBrut ? `1.5px solid ${c.ink || c.textPrimary}` : 'none',
        background: isBrut
          ? (on ? (c.ink || c.textPrimary) : c.bg)
          : (on ? c.accent : hexToRgba(c.textTertiary, 0.30)),
        position: 'relative', transition: 'background 150ms ease',
        boxSizing: 'border-box',
      }}>
        <span style={{
          position: 'absolute',
          top: isBrut ? 2 : 2,
          left: on ? (isBrut ? 18 : 18) : 2,
          width: isBrut ? 14 : 16,
          height: isBrut ? 14 : 16,
          borderRadius: isBrut ? 1 : '50%',
          background: isBrut ? (on ? c.bg : (c.ink || c.textPrimary)) : c.bg,
          transition: 'left 150ms ease',
          boxShadow: isBrut ? 'none' : '0 1px 3px rgba(0,0,0,0.3)',
        }} />
      </span>
      <span style={{ flex: 1 }}>
        <span style={{ display: 'block', fontFamily: fonts.body, fontSize: 14, fontWeight: 600, color: c.textPrimary, lineHeight: 1.35 }}>{label}</span>
        {hint && <span style={{ display: 'block', fontFamily: fonts.body, fontSize: 13, color: c.textSecondary, lineHeight: 1.45, marginTop: 2 }}>{hint}</span>}
      </span>
    </button>
  );
}

function SectionTitle({ eyebrow, title, sub }) {
  const { c, fonts, brutMode } = useLW();
  const isBrut = !!brutMode;
  if (isBrut) {
    return (
      <div style={{ marginBottom: 28 }}>
        {eyebrow && (
          <div style={{
            display: 'inline-block',
            fontFamily: fonts.body, fontSize: 10, fontWeight: 800,
            letterSpacing: '0.18em', textTransform: 'uppercase',
            color: c.bg,
            background: c.ink || c.textPrimary,
            padding: '3px 8px',
            marginBottom: 12,
          }}>[§ {eyebrow}]</div>
        )}
        <h2 style={{
          fontFamily: fonts.body,
          fontWeight: 800, fontSize: 26,
          letterSpacing: '-0.01em',
          margin: 0, lineHeight: 1.15,
          color: c.textPrimary,
          textTransform: 'uppercase',
        }}>{title}</h2>
        {sub && (
          <p style={{
            fontFamily: fonts.body,
            fontSize: 13, fontWeight: 500,
            color: c.textSecondary,
            margin: '10px 0 0',
            maxWidth: '60ch',
            lineHeight: 1.55,
            textTransform: 'none',
          }}>{sub}</p>
        )}
      </div>
    );
  }
  return (
    <div style={{ marginBottom: 24 }}>
      {eyebrow && <div style={{ fontFamily: fonts.body, fontSize: 11, fontWeight: 700, letterSpacing: '0.16em', textTransform: 'uppercase', color: c.textTertiary, marginBottom: 8 }}>{eyebrow}</div>}
      <h2 style={{ fontFamily: fonts.display, fontWeight: 500, fontSize: 30, letterSpacing: '-0.015em', margin: 0, lineHeight: 1.1, color: c.textPrimary }}>{title}</h2>
      {sub && <p style={{ fontFamily: fonts.display, fontStyle: 'italic', fontSize: 16, color: c.textSecondary, margin: '8px 0 0', maxWidth: '60ch', lineHeight: 1.55 }}>{sub}</p>}
    </div>
  );
}

function SubHead({ children }) {
  const { c, fonts } = useLW();
  return <h3 style={{ fontFamily: fonts.display, fontWeight: 500, fontSize: 18, color: c.textPrimary, margin: '0 0 14px' }}>{children}</h3>;
}

function CardBlock({ children, style }) {
  const { c, brutMode } = useLW();
  const isBrut = !!brutMode;
  if (isBrut) {
    return (
      <div style={{
        background: c.bg,
        border: `1.5px solid ${c.ink || c.textPrimary}`,
        borderRadius: 2,
        boxShadow: `4px 4px 0 0 ${c.ink || c.textPrimary}`,
        padding: 24,
        ...style,
      }}>{children}</div>
    );
  }
  return <div style={{ background: c.card, border: `1px solid ${c.borderSubtle}`, borderRadius: 14, padding: 22, ...style }}>{children}</div>;
}

// ── Account section ──
const TIMEZONES = [
  { v: 'Pacific/Honolulu',     label: 'Honolulu',                  off: -10 },
  { v: 'America/Anchorage',    label: 'Anchorage',                 off: -8 },
  { v: 'America/Los_Angeles',  label: 'Los Angeles · Vancouver',   off: -7 },
  { v: 'America/Denver',       label: 'Denver · Phoenix',          off: -6 },
  { v: 'America/Chicago',      label: 'Chicago · Mexico City',     off: -5 },
  { v: 'America/New_York',     label: 'New York · Toronto',        off: -4 },
  { v: 'America/Sao_Paulo',    label: 'São Paulo',                 off: -3 },
  { v: 'Atlantic/Azores',      label: 'Azores',                    off: 0 },
  { v: 'Europe/London',        label: 'London · Lisbon · Dublin',  off: 1 },
  { v: 'Europe/Berlin',        label: 'Berlin · Paris · Madrid',   off: 2 },
  { v: 'Europe/Athens',        label: 'Athens · Helsinki',         off: 3 },
  { v: 'Europe/Moscow',        label: 'Moscow · Istanbul',         off: 3 },
  { v: 'Asia/Dubai',           label: 'Dubai',                     off: 4 },
  { v: 'Asia/Karachi',         label: 'Karachi',                   off: 5 },
  { v: 'Asia/Kolkata',         label: 'Mumbai · Delhi',            off: 5.5 },
  { v: 'Asia/Bangkok',         label: 'Bangkok · Jakarta',         off: 7 },
  { v: 'Asia/Singapore',       label: 'Singapore · Hong Kong',     off: 8 },
  { v: 'Asia/Tokyo',           label: 'Tokyo · Seoul',             off: 9 },
  { v: 'Australia/Sydney',     label: 'Sydney · Melbourne',        off: 10 },
  { v: 'Pacific/Auckland',     label: 'Auckland',                  off: 12 },
];
function detectTz() {
  try { return Intl.DateTimeFormat().resolvedOptions().timeZone; } catch { return 'America/Los_Angeles'; }
}
function tzLabel(v) {
  const found = TIMEZONES.find(t => t.v === v);
  if (found) return found;
  // fallback — compute offset from current Date in that zone
  try {
    const now = new Date();
    const localStr = now.toLocaleString('en-US', { timeZone: v, hour12: false });
    const utcStr = now.toLocaleString('en-US', { timeZone: 'UTC', hour12: false });
    const off = Math.round((new Date(localStr) - new Date(utcStr)) / 3600000);
    return { v, label: v.replace(/_/g, ' ').split('/').pop(), off };
  } catch { return { v, label: v, off: 0 }; }
}
function fmtUtc(off) {
  const sign = off >= 0 ? '+' : '−';
  const abs = Math.abs(off);
  const h = Math.floor(abs);
  const m = Math.round((abs - h) * 60);
  return `UTC ${sign}${h}${m ? ':' + String(m).padStart(2,'0') : ''}`;
}
function TimezonePicker({ value, onChange }) {
  const { c, fonts, brutMode } = useLW();
  const isBrut = !!brutMode;
  const detected = useM2(() => detectTz(), []);
  const meta = tzLabel(value);
  const isDetected = value === detected;
  return (
    <div>
      <div style={{ position: 'relative' }}>
        <select
          value={value}
          onChange={(e) => onChange(e.target.value)}
          style={{
            width: '100%', appearance: 'none', WebkitAppearance: 'none',
            background: isBrut ? c.bg : c.bgSubtle,
            border: isBrut
              ? `1.5px solid ${c.ink || c.textPrimary}`
              : `1px solid ${c.borderSubtle}`,
            borderRadius: isBrut ? 2 : 10,
            padding: '11px 40px 11px 14px',
            fontFamily: fonts.body, fontSize: 15, color: c.textPrimary,
            outline: 'none', cursor: 'pointer',
          }}
        >
          {!TIMEZONES.find(t => t.v === detected) && (
            <option value={detected}>{`${meta.label} · ${fmtUtc(meta.off)}`}</option>
          )}
          {TIMEZONES.map(t => (
            <option key={t.v} value={t.v}>{`${t.label} · ${fmtUtc(t.off)}`}</option>
          ))}
        </select>
        <span aria-hidden style={{ position: 'absolute', right: 14, top: '50%', transform: 'translateY(-50%)', color: c.textTertiary, pointerEvents: 'none', fontSize: 11 }}>▾</span>
      </div>
      <div style={{ marginTop: 6, fontFamily: fonts.body, fontSize: 12, color: c.textTertiary, fontStyle: 'italic' }}>
        {isDetected ? `Detected from your browser · ${fmtUtc(meta.off)}` : (
          <span>
            Browser detected <button type="button" onClick={() => onChange(detected)} style={{ background: 'transparent', border: 'none', color: c.accent, cursor: 'pointer', fontStyle: 'italic', padding: 0, font: 'inherit' }}>{tzLabel(detected).label} ({fmtUtc(tzLabel(detected).off)})</button> — switch?
          </span>
        )}
      </div>
    </div>
  );
}

// Resize an image File to a square `size`px JPEG dataURL at the given quality.
// Center-crops on the shorter axis. Used for avatar uploads to keep RTDB
// payloads small (~30–50KB at 256px / quality 0.82).
function compressToDataURL(file, size = 256, quality = 0.82) {
  return new Promise((resolve, reject) => {
    const img = new Image();
    img.onload = () => {
      const minDim = Math.min(img.width, img.height);
      const sx = (img.width - minDim) / 2;
      const sy = (img.height - minDim) / 2;
      const canvas = document.createElement('canvas');
      canvas.width = size; canvas.height = size;
      const ctx = canvas.getContext('2d');
      ctx.drawImage(img, sx, sy, minDim, minDim, 0, 0, size, size);
      try { resolve(canvas.toDataURL('image/jpeg', quality)); }
      catch (e) { reject(e); }
    };
    img.onerror = () => reject(new Error('Image load failed'));
    const reader = new FileReader();
    reader.onload = (e) => { img.src = e.target.result; };
    reader.onerror = () => reject(new Error('File read failed'));
    reader.readAsDataURL(file);
  });
}

function AppearanceSection() {
  const { c, fonts, t, brutMode } = useLW();
  const isBrut = !!brutMode;
  // Brutalism's own theme setter; when active we drive both keys from this
  // toggle so 'lw_coach_brutmode' (drives the actual paint) stays in sync.
  const brutSetter = (window.LWBrutal && window.LWBrutal.useBrutMode)
    ? window.LWBrutal.useBrutMode()[1]
    : null;
  // Read current values from useTweaks-managed prefs (localStorage source of truth).
  const [prefs, setPrefs] = useS2(() => {
    try { return JSON.parse(localStorage.getItem('lw_coach_prefs') || '{}'); } catch { return {}; }
  });
  // React to changes from anywhere (TweaksPanel, other tabs, etc).
  useE2(() => {
    const on = () => {
      try { setPrefs(JSON.parse(localStorage.getItem('lw_coach_prefs') || '{}')); } catch {}
    };
    window.addEventListener('storage', on);
    window.addEventListener('tweakchange', on);
    return () => { window.removeEventListener('storage', on); window.removeEventListener('tweakchange', on); };
  }, []);

  const setKey = (key, value) => {
    const next = { ...prefs, [key]: value };
    setPrefs(next);
    try { localStorage.setItem('lw_coach_prefs', JSON.stringify(next)); } catch {}
    // Mirror to RTDB
    if (window.LWAuth && window.LWFB) {
      const u = window.LWAuth.currentCoach();
      if (u) window.LWFB.db.ref(`/coaches/${u.uid}/preferences`).update({ [key]: value }).catch(() => {});
    }
    // Custom event so the rest of the page reacts (theme provider, lang.js).
    window.dispatchEvent(new CustomEvent('tweakchange', { detail: { [key]: value } }));
    // Mode toggles must also drive the brutalism layer, which paints the
    // entire portal via window.__brutMode + lw_coach_brutmode. Without this
    // hook the click was silently a no-op while brutalism was active.
    if (key === 'mode' && brutSetter && (value === 'dark' || value === 'light')) {
      brutSetter(value);
    }
  };

  const accents = [
    { v: '#3EC08D', labelKey: 'settings.accent_emerald' },
    { v: '#5D8CE8', labelKey: 'settings.accent_midnight' },
    { v: '#E85D8C', labelKey: 'settings.accent_rose' },
    { v: '#E8943A', labelKey: 'settings.accent_ember' },
  ];
  const langs = [
    { v: 'en', labelKey: 'settings.language_en' },
    { v: 'ru', labelKey: 'settings.language_ru' },
  ];
  const modes = [
    { v: 'dark',  labelKey: 'settings.theme_dark' },
    { v: 'light', labelKey: 'settings.theme_light' },
  ];

  const radio = (group, current, opts) => (
    <div style={{ display: 'flex', gap: isBrut ? 8 : 6, flexWrap: 'wrap' }}>
      {opts.map(o => {
        const active = current === o.v;
        return (
          <button key={o.v}
            onClick={() => setKey(group, o.v)}
            style={{
              padding: '9px 14px',
              borderRadius: isBrut ? 2 : 9,
              border: isBrut
                ? `1.5px solid ${c.ink || c.textPrimary}`
                : `1px solid ${active ? c.accent : c.borderDefault}`,
              background: isBrut
                ? (active ? (c.ink || c.textPrimary) : c.bg)
                : (active ? c.accentMuted : 'transparent'),
              color: isBrut
                ? (active ? c.bg : (c.ink || c.textPrimary))
                : (active ? c.textPrimary : c.textSecondary),
              boxShadow: isBrut && active ? `2px 2px 0 0 ${c.ink || c.textPrimary}` : 'none',
              fontFamily: fonts.body, fontSize: 13, fontWeight: 700,
              letterSpacing: isBrut ? '0.04em' : 0,
              textTransform: isBrut ? 'uppercase' : 'none',
              cursor: 'pointer',
            }}>{t(o.labelKey)}</button>
        );
      })}
    </div>
  );
  const swatchRow = (group, current, opts) => (
    <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap' }}>
      {opts.map(o => {
        const active = current === o.v;
        return (
          <button key={o.v}
            onClick={() => setKey(group, o.v)}
            title={t(o.labelKey)}
            style={{
              display: 'inline-flex', alignItems: 'center', gap: 8,
              padding: '8px 12px',
              borderRadius: isBrut ? 2 : 9,
              border: isBrut
                ? `1.5px solid ${c.ink || c.textPrimary}`
                : `1px solid ${active ? c.accent : c.borderDefault}`,
              background: isBrut
                ? (active ? c.bg : c.bg)
                : (active ? c.accentMuted : 'transparent'),
              color: c.textPrimary,
              boxShadow: isBrut && active ? `2px 2px 0 0 ${c.ink || c.textPrimary}` : 'none',
              fontFamily: fonts.body, fontSize: 13, fontWeight: 700,
              letterSpacing: isBrut ? '0.04em' : 0,
              textTransform: isBrut ? 'uppercase' : 'none',
              cursor: 'pointer',
            }}>
            <span style={{
              width: 14, height: 14,
              borderRadius: isBrut ? 1 : '50%',
              background: o.v,
              border: isBrut ? `1.5px solid ${c.ink || c.textPrimary}` : 'none',
              boxShadow: isBrut ? 'none' : 'inset 0 0 0 1px rgba(0,0,0,0.2)',
            }} />
            {t(o.labelKey)}
          </button>
        );
      })}
    </div>
  );

  return (
    <div>
      <SectionTitle eyebrow={t('settings.section_appearance')} title={t('settings.appearance_title')} sub={t('settings.appearance_sub')} />
      <CardBlock>
        <SField label={t('settings.language')}>{radio('lang',   prefs.lang   || 'en',     langs)}</SField>
        <div style={{ height: 18 }} />
        <SField label={t('settings.theme_mode')}>{radio('mode', isBrut ? (brutMode || 'light') : (prefs.mode || 'dark'), modes)}</SField>
        <div style={{ height: 18 }} />
        <SField label={t('settings.accent')}>{swatchRow('accent', prefs.accent || '#3EC08D', accents)}</SField>
      </CardBlock>
    </div>
  );
}

function AccountSection() {
  const { c, fonts, t, brutMode } = useLW();
  const isBrut = !!brutMode;
  const [coach, setCoach] = useS2(null); // null = loading
  const [name, setName] = useS2('');
  const [email, setEmail] = useS2('');
  const [title, setTitle] = useS2('');
  const [tz, setTz] = useS2('');
  const [savingState, setSavingState] = useS2(null); // null | 'saving' | 'saved' | 'error'

  useE2(() => {
    if (!window.LWAuth) return;
    return window.LWAuth.onAuthChanged((u) => {
      setCoach(u);
      if (!u) return;
      const p = u.profile || {};
      setName(p.displayName || '');
      setEmail(u.email || '');
      setTitle(p.title || '');
      setTz(p.timezone || detectTz());
    });
  }, []);

  const save = async () => {
    if (!coach) return;
    setSavingState('saving');
    try {
      await window.LWAuth.writeCoachProfile(coach.uid, {
        displayName: name.trim() || coach.email,
        initials: window.LWAuth.initialsOf(name.trim() || coach.email),
        title: title.trim(),
        timezone: tz,
      });
      setSavingState('saved');
      setTimeout(() => setSavingState(null), 1600);
    } catch (e) {
      console.warn('[settings] save', e);
      setSavingState('error');
    }
  };

  const initials = window.LWAuth ? window.LWAuth.initialsOf(name || email || '·') : '·';
  const photoUrl = coach && coach.profile && coach.profile.avatarUrl;
  const [uploading, setUploading] = useS2(false);

  const handleFile = async (e) => {
    const file = e.target.files && e.target.files[0];
    if (!file || !coach) return;
    setUploading(true);
    try {
      const dataUrl = await compressToDataURL(file, 256, 0.82);
      await window.LWAuth.writeCoachProfile(coach.uid, { avatarUrl: dataUrl });
      // Force the in-page coach reference to pick up the new url. Refresh
      // happens via onAuthStateChanged listener emitting a new profile snap on
      // the next read; trigger by directly re-reading.
      const fresh = await window.LWAuth.readCoachProfile(coach.uid);
      setCoach({ ...coach, profile: fresh });
    } catch (err) {
      console.warn('[avatar]', err);
      alert('Upload failed: ' + (err && err.message || err));
    } finally {
      setUploading(false);
      e.target.value = '';
    }
  };

  return (
    <div>
      <SectionTitle eyebrow={t('settings.section_account')} title={t('settings.account_title')} sub={t('settings.account_sub')} />
      <CardBlock>
        <div style={{ display: 'flex', alignItems: 'center', gap: 18, paddingBottom: 22, marginBottom: 22, borderBottom: `1px solid ${c.borderSubtle}` }}>
          <Avatar name={name || email} initials={initials} hue={150} size={64} photoUrl={photoUrl} />
          <div style={{ flex: 1 }}>
            <div style={{ fontFamily: fonts.body, fontSize: 14, fontWeight: 600, color: c.textPrimary }}>{t('settings.profile_photo')}</div>
            <div style={{ fontFamily: fonts.body, fontSize: 13, color: c.textSecondary, marginTop: 2 }}>{t('settings.photo_hint')}</div>
          </div>
          <label style={{
            padding: '9px 16px',
            borderRadius: isBrut ? 2 : 9,
            border: isBrut
              ? `1.5px solid ${c.ink || c.textPrimary}`
              : `1px solid ${c.borderDefault}`,
            background: isBrut ? c.bg : 'transparent',
            color: isBrut ? (c.ink || c.textPrimary) : c.textSecondary,
            boxShadow: isBrut ? `2px 2px 0 0 ${c.ink || c.textPrimary}` : 'none',
            cursor: uploading ? 'progress' : 'pointer',
            fontFamily: fonts.body, fontSize: 12, fontWeight: 700,
            letterSpacing: isBrut ? '0.06em' : 0,
            textTransform: isBrut ? 'uppercase' : 'none',
          }}>
            {uploading ? t('settings.uploading') : (photoUrl ? t('settings.replace') : t('settings.upload'))}
            <input type="file" accept="image/png,image/jpeg,image/webp" onChange={handleFile} style={{ display: 'none' }} disabled={uploading} />
          </label>
          {photoUrl && (
            <button onClick={async () => {
              if (!coach) return;
              setUploading(true);
              try {
                await window.LWAuth.writeCoachProfile(coach.uid, { avatarUrl: null });
                const fresh = await window.LWAuth.readCoachProfile(coach.uid);
                setCoach({ ...coach, profile: fresh });
              } finally { setUploading(false); }
            }} style={{
              padding: '9px 14px',
              borderRadius: isBrut ? 2 : 9,
              border: isBrut
                ? `1.5px solid ${c.error}`
                : `1px solid ${hexToRgba(c.error, 0.30)}`,
              background: isBrut ? c.bg : 'transparent',
              color: c.error,
              boxShadow: isBrut ? `2px 2px 0 0 ${c.error}` : 'none',
              cursor: 'pointer',
              fontFamily: fonts.body, fontSize: 12, fontWeight: 700,
              letterSpacing: isBrut ? '0.06em' : 0,
              textTransform: isBrut ? 'uppercase' : 'none',
            }}>{t('settings.remove')}</button>
          )}
        </div>
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(240px, 1fr))', gap: 18 }}>
          <SField label={t('settings.full_name')}><SInput value={name} onChange={setName} /></SField>
          <SField label={t('settings.email')} hint={t('settings.email_hint')}><SInput value={email} onChange={() => {}} type="email" /></SField>
          <SField label={t('settings.public_title')} hint={t('settings.public_title_hint')}><SInput value={title} onChange={setTitle} placeholder="ICF-PCC · Career & wellbeing" /></SField>
          <SField label={t('settings.timezone')} hint={t('settings.timezone_hint')}><TimezonePicker value={tz} onChange={setTz} /></SField>
        </div>
        <div style={{ display: 'flex', gap: 10, alignItems: 'center', marginTop: 18 }}>
          <Button variant="primary" size="md" onClick={save} disabled={!coach || savingState === 'saving'}>
            {savingState === 'saving' ? t('settings.saving') : savingState === 'saved' ? t('settings.saved') : t('settings.save')}
          </Button>
          {savingState === 'error' && (
            <span style={{ fontFamily: fonts.body, fontSize: 13, color: c.error }}>{t('settings.save_error')}</span>
          )}
        </div>
      </CardBlock>
      <div style={{ marginTop: 18 }}>
        <CardBlock>
          <SubHead>{t('settings.session')}</SubHead>
          <div style={{ display: 'flex', gap: 10, flexWrap: 'wrap', alignItems: 'center' }}>
            <Button variant="ghost" size="sm" onClick={() => {
              if (!window.LWAuth) return;
              window.LWAuth.signOut().then(() => { (window.LWRouter ? window.LWRouter.go('Login.html') : (window.location.href = 'Login.html')); });
            }}>{t('nav.sign_out')}</Button>
            {coach && (
              <span style={{ fontFamily: fonts.body, fontSize: 13, color: c.textTertiary }}>
                {t('settings.signed_in_as')} <strong style={{ color: c.textSecondary }}>{coach.email}</strong>
              </span>
            )}
          </div>
        </CardBlock>
      </div>
    </div>
  );
}

function InfoTip({ text }) {
  const { c, fonts, brutMode } = useLW();
  const isBrut = !!brutMode;
  const [open, setOpen] = useS2(false);
  useE2(() => {
    if (!open) return;
    const close = () => setOpen(false);
    const t = setTimeout(() => window.addEventListener('click', close), 0);
    return () => { clearTimeout(t); window.removeEventListener('click', close); };
  }, [open]);
  return (
    <span style={{ position: 'relative', display: 'inline-flex', alignItems: 'center' }}>
      <button
        type="button"
        aria-label="More info"
        onClick={(e) => { e.stopPropagation(); setOpen(o => !o); }}
        style={{
          width: 16, height: 16,
          borderRadius: isBrut ? 1 : '50%',
          border: isBrut
            ? `1.5px solid ${c.ink || c.textPrimary}`
            : `1px solid ${open ? c.accent : c.borderStrong}`,
          background: isBrut
            ? (open ? (c.ink || c.textPrimary) : c.bg)
            : (open ? c.accentMuted : 'transparent'),
          color: isBrut
            ? (open ? c.bg : (c.ink || c.textPrimary))
            : (open ? c.accent : c.textTertiary),
          fontFamily: fonts.body, fontSize: 10, fontWeight: 700,
          fontStyle: isBrut ? 'normal' : 'italic',
          cursor: 'pointer', padding: 0, lineHeight: 1,
          display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
        }}
      >i</button>
      {open && (
        <span style={{
          position: 'absolute', top: 24, left: -10, zIndex: 50,
          width: 280, padding: '12px 14px',
          background: isBrut ? c.bg : c.bgElevated,
          border: isBrut
            ? `1.5px solid ${c.ink || c.textPrimary}`
            : `1px solid ${c.borderStrong}`,
          borderRadius: isBrut ? 2 : 10,
          boxShadow: isBrut
            ? `4px 4px 0 0 ${c.ink || c.textPrimary}`
            : '0 8px 24px rgba(0,0,0,0.10)',
          fontFamily: fonts.body, fontSize: 12, color: c.textSecondary, lineHeight: 1.5,
          fontStyle: 'normal', fontWeight: 400, textTransform: 'none', letterSpacing: 0,
        }}>{text}</span>
      )}
    </span>
  );
}

// ── Privacy section ──
// SHARE_ITEMS uses i18n keys; the rendering site resolves via t().
const SHARE_ITEMS = [
  { key: 'wheel',   labelKey: 'settings.share_wheel',   hintKey: 'settings.share_wheel_hint' },
  { key: 'goals',   labelKey: 'settings.share_goals',   hintKey: 'settings.share_goals_hint' },
  { key: 'mood',    labelKey: 'settings.share_mood',    hintKey: 'settings.share_mood_hint' },
  { key: 'who5',    labelKey: 'settings.share_who5',    hintKey: 'settings.share_who5_hint',
    info: 'WHO-5 is a 5-question wellbeing scale developed by the World Health Organization. Total score is 0–100. Below 50 suggests poor wellbeing; below 28 is a clinical screening flag for depression — a cue to refer out, not diagnose.' },
  { key: 'habits',  labelKey: 'settings.share_habits',  hintKey: 'settings.share_habits_hint' },
  { key: 'journal', labelKey: 'settings.share_journal', hintKey: 'settings.share_journal_hint', sensitive: true },
  { key: 'whoop',   labelKey: 'settings.share_whoop',   hintKey: 'settings.share_whoop_hint',  sensitive: true },
];

function PrivacySection() {
  const { c, fonts, t, brutMode } = useLW();
  const isBrut = !!brutMode;
  const [shares, setShares] = useS2({ wheel: 'on', mood: 'on', who5: 'on', habits: 'on', goals: 'on', journal: 'opt-in', whoop: 'opt-in' });
  const [retention, setRetention] = useS2('keep');
  const [allowExport, setAllowExport] = useS2(true);
  const [seeOnDelete, setSeeOnDelete] = useS2(false);

  const opts = [
    { v: 'on',     label: t('settings.share_on'),    fg: c.accent,         bg: c.accentMuted },
    { v: 'opt-in', label: t('settings.share_optin'), fg: c.flame,          bg: hexToRgba(c.flame, 0.16) },
    { v: 'off',    label: t('settings.share_off'),   fg: c.textTertiary,   bg: hexToRgba(c.textTertiary, 0.14) },
  ];

  return (
    <div>
      <SectionTitle eyebrow={t('settings.section_privacy')} title={t('settings.privacy_title')} sub={t('settings.privacy_sub')} />

      <CardBlock>
        <div style={{ display: 'flex', flexDirection: 'column', gap: 4 }}>
          {SHARE_ITEMS.map((it, i) => (
            <div key={it.key} style={{
              display: 'flex', alignItems: 'center', gap: 14,
              padding: '14px 0',
              borderBottom: i < SHARE_ITEMS.length - 1 ? `1px solid ${c.borderSubtle}` : 'none',
            }}>
              <div style={{ flex: 1, minWidth: 0 }}>
                <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
                  <span style={{ fontFamily: fonts.body, fontSize: 14, fontWeight: 600, color: c.textPrimary }}>{t(it.labelKey)}</span>
                  {it.info && <InfoTip text={it.info} />}
                  {it.sensitive && <span style={{
                    fontFamily: fonts.body, fontSize: 10, fontWeight: 700,
                    letterSpacing: '0.14em', textTransform: 'uppercase',
                    color: isBrut ? c.bg : c.flame,
                    padding: '2px 7px',
                    background: isBrut ? c.flame : hexToRgba(c.flame, 0.14),
                    border: isBrut ? `1.5px solid ${c.flame}` : `1px solid ${hexToRgba(c.flame, 0.30)}`,
                    borderRadius: isBrut ? 1 : 999,
                  }}>{t('settings.share_sensitive')}</span>}
                </div>
                <div style={{ fontFamily: fonts.body, fontSize: 13, color: c.textSecondary, marginTop: 2 }}>{t(it.hintKey)}</div>
              </div>
              <div style={{
                display: 'inline-flex',
                background: isBrut ? c.bg : c.bgSubtle,
                border: isBrut
                  ? `1.5px solid ${c.ink || c.textPrimary}`
                  : `1px solid ${c.borderSubtle}`,
                padding: 0,
                borderRadius: isBrut ? 2 : 9,
                gap: 0,
              }}>
                {opts.map((o, oi) => {
                  const active = shares[it.key] === o.v;
                  return (
                    <button key={o.v} onClick={() => setShares({ ...shares, [it.key]: o.v })} style={{
                      padding: '7px 12px',
                      border: 'none',
                      borderLeft: isBrut && oi > 0 ? `1.5px solid ${c.ink || c.textPrimary}` : 'none',
                      background: isBrut
                        ? (active ? (c.ink || c.textPrimary) : c.bg)
                        : (active ? o.bg : 'transparent'),
                      color: isBrut
                        ? (active ? c.bg : (c.ink || c.textPrimary))
                        : (active ? o.fg : c.textSecondary),
                      borderRadius: 0,
                      fontFamily: fonts.body, fontSize: 11, fontWeight: 700,
                      letterSpacing: isBrut ? '0.06em' : 0,
                      textTransform: isBrut ? 'uppercase' : 'none',
                      cursor: 'pointer',
                    }}>{o.label}</button>
                  );
                })}
              </div>
            </div>
          ))}
        </div>
      </CardBlock>

      <div style={{ marginTop: 28 }}>
        <SubHead>{t('settings.leave_subhead')}</SubHead>
        <CardBlock>
          <div style={{ marginBottom: 18 }}>
            <div style={{ fontFamily: fonts.body, fontSize: 12, fontWeight: 600, letterSpacing: '0.08em', textTransform: 'uppercase', color: c.textTertiary, marginBottom: 10 }}>{t('settings.leave_eyebrow')}</div>
            <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
              {[
                { v: 'keep',     label: t('settings.leave_keep'),    desc: t('settings.leave_keep_desc') },
                { v: 'archive',  label: t('settings.leave_archive'), desc: t('settings.leave_archive_desc') },
                { v: 'delete',   label: t('settings.leave_delete'),  desc: t('settings.leave_delete_desc') },
              ].map(o => {
                const active = retention === o.v;
                return (
                  <button key={o.v} type="button" onClick={() => setRetention(o.v)} style={{
                    display: 'flex', alignItems: 'flex-start', gap: 12, textAlign: 'left',
                    padding: '12px 14px',
                    background: isBrut
                      ? (active ? c.bg : c.bg)
                      : (active ? c.accentMuted : 'transparent'),
                    border: isBrut
                      ? `1.5px solid ${c.ink || c.textPrimary}`
                      : `1px solid ${active ? c.borderStrong : c.borderSubtle}`,
                    borderRadius: isBrut ? 2 : 10,
                    boxShadow: isBrut && active ? `3px 3px 0 0 ${c.ink || c.textPrimary}` : 'none',
                    cursor: 'pointer',
                  }}>
                    <span style={{
                      flexShrink: 0, marginTop: 3,
                      width: 16, height: 16,
                      borderRadius: isBrut ? 1 : '50%',
                      border: isBrut
                        ? `1.5px solid ${c.ink || c.textPrimary}`
                        : `1.5px solid ${active ? c.accent : c.textTertiary}`,
                      background: isBrut ? c.bg : 'transparent',
                      display: 'flex', alignItems: 'center', justifyContent: 'center',
                    }}>
                      {active && <span style={{
                        width: 8, height: 8,
                        borderRadius: isBrut ? 0 : '50%',
                        background: isBrut ? (c.ink || c.textPrimary) : c.accent,
                      }} />}
                    </span>
                    <span style={{ flex: 1 }}>
                      <span style={{ display: 'block', fontFamily: fonts.body, fontWeight: 600, fontSize: 14, color: c.textPrimary, marginBottom: 2 }}>{o.label}</span>
                      <span style={{ display: 'block', fontFamily: fonts.body, fontSize: 13, color: c.textSecondary, lineHeight: 1.45 }}>{o.desc}</span>
                    </span>
                  </button>
                );
              })}
            </div>
          </div>
          <div style={{ display: 'flex', flexDirection: 'column', gap: 14, paddingTop: 18, borderTop: `1px solid ${c.borderSubtle}` }}>
            <SToggle on={allowExport} onChange={setAllowExport} label={t('settings.export_label')} hint={t('settings.export_hint')} />
            <SToggle on={seeOnDelete} onChange={setSeeOnDelete} label={t('settings.notify_delete_label')} hint={t('settings.notify_delete_hint')} />
          </div>
        </CardBlock>
      </div>
    </div>
  );
}

// ── Notifications section ──
function NotificationsSection() {
  const { t } = useLW();
  return (
    <ComingSoonBlock
      eyebrow={t('settings.section_notifications')}
      title={t('settings.notif_title')}
      sub={t('settings.notif_sub')}
    />
  );
}

// Shared coming-soon block for unbuilt settings sections. Tells the coach the
// feature is on the roadmap without rendering placeholder toggles/buttons that
// look real but do nothing.
function ComingSoonBlock({ eyebrow, title, sub }) {
  const { c, fonts, t, brutMode } = useLW();
  const isBrut = !!brutMode;
  return (
    <div>
      <SectionTitle eyebrow={eyebrow} title={title} sub={sub} />
      <CardBlock>
        <div style={{ display: 'flex', alignItems: 'flex-start', gap: 16 }}>
          <div style={{
            flexShrink: 0, width: 40, height: 40,
            borderRadius: isBrut ? 2 : 11,
            background: isBrut ? c.bg : hexToRgba(c.flame, 0.12),
            border: isBrut
              ? `1.5px solid ${c.flame}`
              : `1px solid ${hexToRgba(c.flame, 0.30)}`,
            boxShadow: isBrut ? `2px 2px 0 0 ${c.flame}` : 'none',
            display: 'flex', alignItems: 'center', justifyContent: 'center',
            color: c.flame, fontSize: 18,
            fontFamily: isBrut ? fonts.body : 'inherit',
            fontWeight: isBrut ? 700 : 400,
          }}>{isBrut ? '※' : '✦'}</div>
          <div style={{ flex: 1 }}>
            <div style={{ fontFamily: fonts.body, fontSize: 11, fontWeight: 700, letterSpacing: '0.16em', textTransform: 'uppercase', color: c.flame, marginBottom: 6 }}>
              {t('settings.coming_soon_eyebrow')}
            </div>
            <div style={{ fontFamily: fonts.body, fontSize: 14, lineHeight: 1.55, color: c.textSecondary }}>
              {t('settings.coming_soon_body')}
            </div>
          </div>
        </div>
      </CardBlock>
    </div>
  );
}

// ── Integrations section ──
function IntegrationCard({ name, desc, status, accent }) {
  const { c, fonts, t, brutMode } = useLW();
  const isBrut = !!brutMode;
  const comingSoon = status === 'comingSoon';
  const connected = status === 'connected';
  const badgeLabel = comingSoon ? t('settings.integ_coming_soon')
                   : connected   ? t('settings.integ_connected')
                                 : t('settings.integ_not_connected');
  const badgeFg = comingSoon ? c.flame : (connected ? c.accent : c.textTertiary);
  const badgeBg = comingSoon ? hexToRgba(c.flame, 0.10)
                : connected   ? c.accentMuted
                              : hexToRgba(c.textTertiary, 0.12);
  const badgeBorder = comingSoon ? hexToRgba(c.flame, 0.30)
                    : connected   ? hexToRgba(c.accent, 0.30)
                                  : c.borderSubtle;
  return (
    <CardBlock style={{ display: 'flex', alignItems: 'flex-start', gap: 18, opacity: comingSoon ? 0.85 : 1 }}>
      <div style={{
        flexShrink: 0,
        width: 52, height: 52,
        borderRadius: isBrut ? 2 : 12,
        background: isBrut ? c.bg : hexToRgba(accent, 0.16),
        border: isBrut
          ? `1.5px solid ${c.ink || c.textPrimary}`
          : `1px solid ${hexToRgba(accent, 0.32)}`,
        boxShadow: isBrut ? `2px 2px 0 0 ${c.ink || c.textPrimary}` : 'none',
        display: 'flex', alignItems: 'center', justifyContent: 'center',
        fontFamily: isBrut ? fonts.body : fonts.display,
        fontStyle: isBrut ? 'normal' : 'italic',
        fontWeight: isBrut ? 800 : 500,
        fontSize: isBrut ? 24 : 22,
        color: isBrut ? (c.ink || c.textPrimary) : accent,
        textTransform: isBrut ? 'uppercase' : 'none',
      }}>{name[0]}</div>
      <div style={{ flex: 1 }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 4 }}>
          <span style={{ fontFamily: fonts.body, fontSize: 15, fontWeight: 700, color: c.textPrimary, letterSpacing: isBrut ? '0.02em' : 0, textTransform: isBrut ? 'uppercase' : 'none' }}>{name}</span>
          <span style={{
            fontFamily: fonts.body, fontSize: 10, fontWeight: 700,
            letterSpacing: '0.14em', textTransform: 'uppercase',
            color: isBrut ? c.bg : badgeFg,
            padding: '2px 8px',
            background: isBrut ? badgeFg : badgeBg,
            border: isBrut ? `1.5px solid ${badgeFg}` : `1px solid ${badgeBorder}`,
            borderRadius: isBrut ? 1 : 999,
          }}>{badgeLabel}</span>
        </div>
        <div style={{ fontFamily: fonts.body, fontSize: 13, color: c.textSecondary, lineHeight: 1.5 }}>{desc}</div>
      </div>
      <Button variant="ghost" size="sm" disabled>
        {comingSoon ? t('settings.integ_coming_soon') : (connected ? t('settings.integ_manage') : t('settings.integ_connect'))}
      </Button>
    </CardBlock>
  );
}

function IntegrationsSection() {
  const { t } = useLW();
  return (
    <div>
      <SectionTitle eyebrow={t('settings.section_integrations')} title={t('settings.integ_title')} sub={t('settings.integ_sub')} />
      <div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
        <IntegrationCard name={t('settings.integ_gcal')}   accent="#3EC08D" status="comingSoon" desc={t('settings.integ_gcal_desc')} />
        <IntegrationCard name={t('settings.integ_apple')}  accent="#E8943A" status="comingSoon" desc={t('settings.integ_apple_desc')} />
        <IntegrationCard name={t('settings.integ_stripe')} accent="#8C5DE8" status="comingSoon" desc={t('settings.integ_stripe_desc')} />
      </div>
    </div>
  );
}

// ── Billing section ──
function BillingSection() {
  const { t } = useLW();
  return (
    <ComingSoonBlock
      eyebrow={t('settings.section_billing')}
      title={t('settings.bill_title')}
    />
  );
}

function Usage({ label, value, max, unit = '', c, fonts }) {
  const pct = Math.min(100, (value / max) * 100);
  const isBrut = !!(typeof window !== 'undefined' && window.__brutMode);
  return (
    <div>
      <div style={{ display: 'flex', justifyContent: 'space-between', fontFamily: fonts.body, fontSize: 13, marginBottom: 6 }}>
        <span style={{ color: c.textSecondary, letterSpacing: isBrut ? '0.04em' : 0, textTransform: isBrut ? 'uppercase' : 'none', fontWeight: isBrut ? 700 : 400 }}>{label}</span>
        <span style={{ color: c.textPrimary, fontWeight: 700 }}>{value}{unit && ' ' + unit} <span style={{ color: c.textTertiary, fontWeight: 400 }}>/ {max}{unit && ' ' + unit}</span></span>
      </div>
      <div style={{
        height: isBrut ? 10 : 6,
        background: isBrut ? c.bg : c.bgSubtle,
        border: isBrut ? `1.5px solid ${c.ink || c.textPrimary}` : 'none',
        borderRadius: isBrut ? 0 : 3,
        overflow: 'hidden',
      }}>
        <div style={{
          width: `${pct}%`, height: '100%',
          background: isBrut ? (c.ink || c.textPrimary) : c.accent,
          borderRadius: 0,
        }} />
      </div>
    </div>
  );
}

// ── Danger zone ──
function DangerSection() {
  const { t } = useLW();
  return (
    <ComingSoonBlock
      eyebrow={t('settings.section_danger')}
      title={t('settings.danger_title')}
      sub={t('settings.danger_sub')}
    />
  );
}

function DangerRow({ title, desc, action, destructive }) {
  const { c, fonts, brutMode } = useLW();
  const isBrut = !!brutMode;
  const accentCol = destructive ? c.error : (c.ink || c.textPrimary);
  return (
    <div style={{
      background: isBrut ? c.bg : c.card,
      border: isBrut
        ? `1.5px solid ${accentCol}`
        : `1px solid ${destructive ? hexToRgba(c.error, 0.30) : c.borderSubtle}`,
      borderRadius: isBrut ? 2 : 14,
      boxShadow: isBrut ? `4px 4px 0 0 ${accentCol}` : 'none',
      padding: 20,
      display: 'flex', alignItems: 'flex-start', gap: 18, flexWrap: 'wrap',
    }}>
      <div style={{ flex: 1, minWidth: 200 }}>
        <div style={{ fontFamily: fonts.body, fontSize: 15, fontWeight: 700, color: destructive ? c.error : c.textPrimary, marginBottom: 4, letterSpacing: isBrut ? '0.02em' : 0, textTransform: isBrut ? 'uppercase' : 'none' }}>{title}</div>
        <div style={{ fontFamily: fonts.body, fontSize: 13, color: c.textSecondary, lineHeight: 1.5 }}>{desc}</div>
      </div>
      <button style={{
        background: isBrut ? c.bg : 'transparent',
        border: isBrut
          ? `1.5px solid ${accentCol}`
          : `1px solid ${destructive ? hexToRgba(c.error, 0.40) : c.borderDefault}`,
        color: destructive ? c.error : (isBrut ? (c.ink || c.textPrimary) : c.textSecondary),
        boxShadow: isBrut ? `2px 2px 0 0 ${accentCol}` : 'none',
        padding: '9px 16px',
        borderRadius: isBrut ? 2 : 9,
        fontFamily: fonts.body, fontSize: 12, fontWeight: 700,
        letterSpacing: isBrut ? '0.06em' : 0,
        textTransform: isBrut ? 'uppercase' : 'none',
        cursor: 'pointer',
      }}>{action}</button>
    </div>
  );
}

// ── Settings page ──
function SettingsPage({ routeParams }) {
  const { c: cBase, fonts: fontsBase, t } = useLW();
  // Brutalism theme override
  const [brutMode, setBrutMode] = window.LWBrutal.useBrutMode();
  const c = window.LWBrutal.makeC(cBase, brutMode);
  const fonts = { ...fontsBase, ...window.LWBrutal.fonts };
  window.__brutMode = brutMode; window.__brutSetMode = setBrutMode;
  window.__brutC = c; window.__brutFonts = fonts;
  const { isMobile, isTablet } = useViewport();
  const stack = isMobile || isTablet;
  const [active, setActive] = useS2(() => {
    // SPA mode: tab is in route.params.tab. Legacy: location.hash.
    const fromRoute = routeParams && routeParams.tab;
    const fromHash  = (window.location.hash || '').replace('#','').replace(/^\//, '').split('/')[1] || (window.location.hash || '').replace('#','');
    const candidate = fromRoute || fromHash || '';
    return SECTIONS.find(s => s.id === candidate) ? candidate : 'account';
  });
  useE2(() => {
    if (window.LWRouter) {
      // Update the SPA route to /settings/<tab> so a refresh keeps the tab.
      window.LWRouter.navigate('settings', { tab: active }, { replace: true });
    } else {
      window.location.hash = active;
    }
  }, [active]);

  return (
    <PageShell active="settings">
      <div style={{
        display: 'grid',
        gridTemplateColumns: stack ? '1fr' : '240px 1fr',
        gap: stack ? 24 : 40,
        padding: stack ? '24px 16px 64px' : '36px 0 96px',
      }}>
        <aside style={{
          position: stack ? 'static' : 'sticky',
          top: stack ? 'auto' : 96,
          alignSelf: 'start',
        }}>
          <div style={{ fontFamily: fonts.body, fontSize: 11, fontWeight: 700, letterSpacing: '0.18em', textTransform: 'uppercase', color: c.textTertiary, marginBottom: 14, paddingLeft: 8 }}>{t('settings.eyebrow')}</div>
          <nav style={{ display: 'flex', flexDirection: stack ? 'row' : 'column', gap: stack ? 6 : 4, flexWrap: 'wrap', overflowX: stack ? 'auto' : 'visible' }}>
            {SECTIONS.map(s => {
              const isActive = s.id === active;
              const isBrut2 = !!brutMode;
              const fg = s.danger ? c.error : (isActive ? c.textPrimary : c.textSecondary);
              return (
                <button key={s.id} onClick={() => setActive(s.id)} style={{
                  textAlign: 'left',
                  padding: isBrut2 ? '10px 14px' : '9px 12px',
                  background: isBrut2
                    ? (isActive ? (c.ink || c.textPrimary) : c.bg)
                    : (isActive ? c.accentMuted : 'transparent'),
                  border: isBrut2
                    ? `1.5px solid ${c.ink || c.textPrimary}`
                    : (isActive ? `1px solid ${hexToRgba(c.accent, 0.30)}` : '1px solid transparent'),
                  borderRadius: isBrut2 ? 2 : 9,
                  boxShadow: isBrut2 && isActive ? `3px 3px 0 0 ${c.ink || c.textPrimary}` : 'none',
                  color: isBrut2
                    ? (s.danger ? c.error : (isActive ? c.bg : (c.ink || c.textPrimary)))
                    : fg,
                  fontFamily: fonts.body,
                  fontSize: isBrut2 ? 12 : 14,
                  fontWeight: 700,
                  letterSpacing: isBrut2 ? '0.06em' : 0,
                  textTransform: isBrut2 ? 'uppercase' : 'none',
                  cursor: 'pointer',
                  whiteSpace: 'nowrap',
                }}>{t(s.labelKey)}</button>
              );
            })}
          </nav>
        </aside>
        <main style={{ minWidth: 0, maxWidth: 760 }}>
          {active === 'account'       && <AccountSection />}
          {active === 'appearance'    && <AppearanceSection />}
          {active === 'privacy'       && <PrivacySection />}
          {active === 'notifications' && <NotificationsSection />}
          {active === 'integrations'  && <IntegrationsSection />}
          {active === 'billing'       && <BillingSection />}
          {active === 'danger'        && <DangerSection />}
        </main>
      </div>
    </PageShell>
  );
}

window.SettingsPage = SettingsPage;
