// Comprehensive Settings — sub-nav with sections (Connection, Model & Provider, Agent, Routing, Voice, Display, Appearance, Chat, Notifications, Language)
const { useState, useEffect } = React;

// Theme registry — add an entry and it appears in the gallery automatically.
window.THEMES = [
  { id: "eclipse", name: "Eclipse", desc: "Refined indigo dark", bg: "#0e1018", surface: "#1c212e", accent: "#818cf8", text: "#eef1f8", dark: true },
  { id: "obsidian", name: "Obsidian", desc: "True pitch black · lime", bg: "#000000", surface: "#101014", accent: "#c6f24a", text: "#f3f4f8", dark: true },
  { id: "carbon", name: "Carbon", desc: "Warm graphite + amber", bg: "#100f0d", surface: "#221e1a", accent: "#f0b357", text: "#f3ede2", dark: true },
  { id: "daylight", name: "Daylight", desc: "Clean light + blue", bg: "#eef0f4", surface: "#ffffff", accent: "#3b6ef6", text: "#131722", dark: false },
];

// Accent overrides — "default" keeps each theme's own accent.
window.ACCENTS = {
  default: null,
  lime: { primary: "#c6f24a", strong: "#b6e639", fg: "#0a0f00" },
  cyan: { primary: "#3ee7d1", strong: "#27d4be", fg: "#001310" },
  electric: { primary: "#4d9bff", strong: "#3585f5", fg: "#00112a" },
  amber: { primary: "#f5b13d", strong: "#eaa125", fg: "#1a1200" },
  magenta: { primary: "#f25fd0", strong: "#e848c2", fg: "#16000f" },
  violet: { primary: "#8b95ff", strong: "#757fff", fg: "#06060c" },
};

// Provider cards (id/name/auth/envKey from SETTINGS-SPEC PROVIDER_CARDS).
const PROVIDERS = [
  { id: "ollama", name: "Ollama", sub: "Local", logo: "Ol", c: "#cbd2dd", status: "ready", auth: "none" },
  { id: "atomic-chat", name: "Atomic Chat", sub: "Local", logo: "AC", c: "#7c8cf8", status: "ready", auth: "none" },
  { id: "anthropic", name: "Anthropic", sub: "API key", logo: "A\\", c: "#d97757", status: "required", auth: "api_key", env: "ANTHROPIC_API_KEY" },
  { id: "nous", name: "Nous Portal", sub: "OAuth", logo: "No", c: "#cbd2dd", status: "oauth", auth: "oauth" },
  { id: "openai-codex", name: "OpenAI Codex", sub: "OAuth", logo: "Cx", c: "#10a37f", status: "oauth", auth: "oauth" },
  { id: "openrouter", name: "OpenRouter", sub: "API key", logo: "OR", c: "#a78bfa", status: "required", auth: "api_key", env: "OPENROUTER_API_KEY" },
  { id: "zai", name: "Z.AI / GLM", sub: "API key", logo: "Z", c: "#5b8def", status: "required", auth: "api_key", env: "GLM_API_KEY" },
  { id: "kimi-coding", name: "Kimi", sub: "API key", logo: "K", c: "#2dd4a0", status: "required", auth: "api_key", env: "KIMI_API_KEY" },
  { id: "minimax", name: "MiniMax", sub: "API key", logo: "M", c: "#f0883e", status: "required", auth: "api_key", env: "MINIMAX_API_KEY" },
  { id: "xiaomi", name: "Xiaomi MiMo", sub: "API key", logo: "X", c: "#cbd2dd", status: "required", auth: "api_key", env: "XIAOMI_API_KEY" },
  { id: "custom", name: "Custom", sub: "Base URL", logo: "C", c: "#c6f24a", status: "ready", auth: "api_key", env: "CUSTOM_API_KEY" },
];
// API-key provider rows (per-provider env key).
const API_KEY_PROVIDERS = PROVIDERS.filter((p) => p.auth === "api_key");

// ---------- helpers ----------
function lsGet(key, fallback) {
  try { const v = localStorage.getItem(key); return v == null ? fallback : JSON.parse(v); } catch { return fallback; }
}
function lsSet(key, val) {
  try { localStorage.setItem(key, JSON.stringify(val)); } catch { /* ignore */ }
}
// safe nested get: dig(obj, "agent.max_turns")
function dig(obj, path, fallback) {
  const v = path.split(".").reduce((o, k) => (o == null ? undefined : o[k]), obj);
  return v == null ? fallback : v;
}

// Small live/preview indicator. live===true -> live, live===false -> preview, null -> nothing yet.
function LiveBadge({ live }) {
  if (live == null) return <span className="badge"><span className="d" />syncing…</span>;
  return live
    ? <span className="badge ok"><span className="d" />live</span>
    : <span className="badge warn"><span className="d" />preview data</span>;
}

// Loads HERMES.claudeConfig() once; exposes config, live flag, and a save() that PATCHes.
function useClaudeConfig() {
  const [cfg, setCfg] = useState(null);   // null = loading
  const [live, setLive] = useState(null); // null=loading, true=backend, false=offline
  useEffect(() => {
    let alive = true;
    HERMES.claudeConfig()
      .then((res) => { if (alive) { setCfg((res && res.config) || res || {}); setLive(true); } })
      .catch(() => { if (alive) { setCfg({}); setLive(false); } });
    return () => { alive = false; };
  }, []);
  // patch = {config:{...}} and/or {env:{...}}; merges locally for instant UI feedback.
  const save = async (patch, toast) => {
    if (patch.config) setCfg((c) => deepMerge({ ...(c || {}) }, patch.config));
    if (live === false) { toast && toast("Preview — not connected to Hermes Agent"); return; }
    try { await HERMES.patchClaudeConfig(patch); toast && toast("Saved"); }
    catch (e) { toast && toast(e.message || "Save failed"); }
  };
  return { cfg, live, save, setCfg };
}
function deepMerge(target, src) {
  for (const k of Object.keys(src)) {
    if (src[k] && typeof src[k] === "object" && !Array.isArray(src[k])) {
      target[k] = deepMerge({ ...(target[k] || {}) }, src[k]);
    } else { target[k] = src[k]; }
  }
  return target;
}

function SetCard({ icon, title, desc, children, foot, head }) {
  return (
    <div className="card">
      <div className="set-card-head">
        <div className="ic"><Icon name={icon} size={18} /></div>
        <div style={{ flex: 1 }}><h2>{title}</h2><p>{desc}</p></div>
        {head}
      </div>
      {children}
      {foot && <div style={{ display: "flex", justifyContent: "flex-end", gap: 10, marginTop: 16 }}>{foot}</div>}
    </div>
  );
}

function Row({ title, sub, children }) {
  return (
    <div className="set-field">
      <div className="lbl"><b>{title}</b><span>{sub}</span></div>
      <div style={{ justifySelf: "end", width: "100%", maxWidth: 320 }}>{children}</div>
    </div>
  );
}
const RowToggle = ({ on, onChange }) => <div style={{ display: "flex", justifyContent: "flex-end" }}><Toggle on={on} onChange={onChange} /></div>;

// ---------- 0. CONNECTION ----------
function SecConnection({ toast }) {
  const [gateway, setGateway] = useState("");
  const [dashboard, setDashboard] = useState("");
  const [live, setLive] = useState(null);
  const [saving, setSaving] = useState(false);
  useEffect(() => {
    let alive = true;
    HERMES.connectionSettings()
      .then((r) => { if (alive) { setGateway(r.gateway || r.claudeUrl || ""); setDashboard(r.dashboard || r.dashboardUrl || ""); setLive(true); } })
      .catch(() => { if (alive) { setGateway("http://127.0.0.1:8642"); setDashboard("http://127.0.0.1:9119"); setLive(false); } });
    return () => { alive = false; };
  }, []);
  const onSave = async () => {
    if (live === false) { toast("Preview — connection unchanged offline"); return; }
    setSaving(true);
    try { await HERMES.setConnection({ gateway, dashboard }); await HERMES.gatewayReprobe().catch(() => {}); toast("Saved & reprobing capabilities…"); }
    catch (e) { toast(e.message || "Failed to update connection settings"); }
    finally { setSaving(false); }
  };
  return (
    <div className="set-section">
      <SetCard icon="cpu" title="Connection" desc="Point the workspace at your Hermes Agent services. Useful for Tailscale, LAN, or remote-server setups."
        head={<LiveBadge live={live} />}
        foot={<><button className="btn btn-ghost btn-sm" onClick={() => { setGateway("http://127.0.0.1:8642"); setDashboard("http://127.0.0.1:9119"); toast("Reset to defaults"); }}>Reset to defaults</button><button className="btn btn-primary btn-sm" disabled={saving} onClick={onSave}><Icon name="refresh" size={14} />Save &amp; reprobe</button></>}>
        <Row title="Gateway / Hermes Agent URL" sub="Core chat + completions + health (CLAUDE_API). Default http://127.0.0.1:8642."><input className="input mono" value={gateway} onChange={(e) => setGateway(e.target.value)} placeholder="http://127.0.0.1:8642" /></Row>
        <Row title="Dashboard URL" sub="Extended APIs — sessions, skills, config, jobs. Default http://127.0.0.1:9119."><input className="input mono" value={dashboard} onChange={(e) => setDashboard(e.target.value)} placeholder="http://127.0.0.1:9119" /></Row>
        <div style={{ marginTop: 14, padding: "12px 14px", border: "1px solid var(--line)", borderRadius: 10, background: "var(--surface-2)", fontSize: 12.5, lineHeight: 1.6, color: "var(--muted)" }}>
          <b style={{ color: "var(--text)" }}>Tailscale / remote tip:</b> set the gateway to its Tailscale IP (e.g. <span className="mono">http://100.x.y.z:8642</span>) and ensure it listens on <span className="mono">0.0.0.0</span>. No restart needed — capabilities reprobe on save.
        </div>
      </SetCard>
      <div className="card" style={{ display: "flex", alignItems: "center", gap: 10, color: "var(--muted)", fontSize: 13 }}>
        <Icon name="lock" size={16} className="faint" />If this workspace is password-protected, set <span className="mono">HERMES_PASSWORD</span> on the server and sign in before changing connection URLs.
      </div>
    </div>
  );
}

// ---------- 1. MODEL & PROVIDER ----------
function SecModel({ toast }) {
  const { cfg, live, save } = useClaudeConfig();
  const c = cfg || {};
  const activeProvider = dig(c, "provider", dig(c, "model.provider", "anthropic"));
  const [sel, setSel] = useState(null);
  const provider = sel || activeProvider;
  const dot = { ready: "var(--success)", required: "var(--danger)", oauth: "var(--primary)" };
  const customBase = dig(c, "providers.manifest.base_url", dig(c, "base_url", ""));
  const memEnabled = dig(c, "memory.memory_enabled", true) !== false;
  const profileEnabled = dig(c, "memory.user_profile_enabled", true) !== false;
  const [editKey, setEditKey] = useState(null); // env key currently being typed
  const [keyVal, setKeyVal] = useState("");

  const pickProvider = (id) => { setSel(id); save({ config: { provider: id } }, toast); };
  const submitKey = (p) => {
    if (!keyVal) { setEditKey(null); return; }
    save({ env: { [p.env]: keyVal } }, toast);
    setEditKey(null); setKeyVal("");
  };

  return (
    <div className="set-section">
      <SetCard icon="overview" title="Model & Provider" desc="Configure the default AI model for Hermes Agent. Config = ~/.hermes/config.yaml."
        head={<LiveBadge live={live} />}>
        <Row title="Model" sub="The model used for conversations."><input className="input mono" defaultValue={(() => { const m = dig(c, "model", ""); return typeof m === "string" ? m : (m && (m.default || m.model || m.name)) || ""; })()} onBlur={(e) => save({ config: { model: e.target.value } }, toast)} placeholder="e.g. claude-sonnet-4-6" /></Row>
      </SetCard>

      <SetCard icon="providers" title="Provider" desc="Select your AI provider. OAuth providers authenticate via browser." head={<LiveBadge live={live} />}>
        <div className="prov-grid">
          {PROVIDERS.map((p) => (
            <button key={p.id} className={cls("prov-tile", provider === p.id && "on")} onClick={() => pickProvider(p.id)}>
              <span className="pstat" style={{ background: dot[p.status] }} />
              <span className="badge-logo" style={{ background: `color-mix(in oklab, ${p.c} 20%, var(--surface-3))`, color: p.c }}>{p.logo}</span>
              <div><b>{p.name}</b><small>{p.sub}</small></div>
            </button>
          ))}
        </div>
        {provider === "custom" && (
          <div style={{ marginTop: 14 }}>
            <Row title="Custom base URL" sub="OpenAI-compatible endpoint for the custom provider."><input className="input mono" defaultValue={customBase} onBlur={(e) => save({ config: { model: { provider: "manifest" }, providers: { manifest: { type: "openai", base_url: e.target.value, key_env: "CUSTOM_API_KEY" } } } }, toast)} placeholder="http://127.0.0.1:38238/v1" /></Row>
          </div>
        )}
      </SetCard>

      <SetCard icon="lock" title="API Keys" desc="API keys stay in your local Hermes config (~/.hermes/.env) and are never sent to Studio." head={<LiveBadge live={live} />}>
        {API_KEY_PROVIDERS.map((p) => {
          const masked = dig(c, `maskedKeys.${p.env}`, null) || (Array.isArray(c.providers) ? null : dig(c, `env.${p.env}`, null));
          const set = !!masked;
          return (
            <div className="keyrow" key={p.id}>
              <span className="badge-logo" style={{ background: `color-mix(in oklab, ${p.c} 18%, var(--surface-3))`, color: p.c }}>{p.logo}</span>
              <div style={{ flex: 1, minWidth: 0 }}>
                <b style={{ fontSize: 13.5 }}>{p.name}</b>
                <div className="flex" style={{ gap: 5, fontSize: 12, color: set ? "var(--success)" : "var(--danger)" }}><Icon name={set ? "check" : "x"} size={12} />{set ? "Configured" : "Not configured"}</div>
              </div>
              {editKey === p.env ? (
                <>
                  <input className="input mono" type="password" autoFocus value={keyVal} onChange={(e) => setKeyVal(e.target.value)} onKeyDown={(e) => e.key === "Enter" && submitKey(p)} placeholder={`Paste ${p.env}`} style={{ maxWidth: 200 }} />
                  <button className="btn btn-primary btn-sm" onClick={() => submitKey(p)}><Icon name="check" size={13} />Save</button>
                </>
              ) : (
                <>
                  <span className="mono faint" style={{ fontSize: 12 }}>{set ? (typeof masked === "string" ? masked : "••••••") : "Not set"}</span>
                  <button className="btn btn-ghost btn-sm" onClick={() => { setEditKey(p.env); setKeyVal(""); }}>{set ? "Update" : "Add"}</button>
                </>
              )}
            </div>
          );
        })}
      </SetCard>

      <SetCard icon="memory" title="Memory" desc="Cross-session memory and user profile recall." head={<LiveBadge live={live} />}>
        <Row title="Memory" sub="Store & recall memories across sessions."><RowToggle on={memEnabled} onChange={(v) => save({ config: { memory: { memory_enabled: v } } }, toast)} /></Row>
        <Row title="User profile" sub="Remember preferences & context."><RowToggle on={profileEnabled} onChange={(v) => save({ config: { memory: { user_profile_enabled: v } } }, toast)} /></Row>
      </SetCard>
    </div>
  );
}

// ---------- 2. AGENT BEHAVIOR ----------
function SecAgent({ toast }) {
  const { cfg, live, save } = useClaudeConfig();
  const a = dig(cfg || {}, "agent", {});
  const maxTurns = dig(a, "max_turns", 50);
  const timeout = dig(a, "gateway_timeout", 120);
  const enforce = dig(a, "tool_use_enforcement", "auto");
  return (
    <div className="set-section">
      <SetCard icon="profiles" title="Agent Behavior" desc="Execution limits and tool access." head={<LiveBadge live={live} />}>
        <Row title="Max turns" sub="Maximum agent turns per request (1–100)."><input className="input mono" type="number" min="1" max="100" defaultValue={maxTurns} onBlur={(e) => save({ config: { agent: { max_turns: Math.max(1, Math.min(100, +e.target.value || 50)) } } }, toast)} /></Row>
        <Row title="Gateway timeout" sub="Seconds before timeout (10–600)."><input className="input mono" type="number" min="10" max="600" defaultValue={timeout} onBlur={(e) => save({ config: { agent: { gateway_timeout: Math.max(10, Math.min(600, +e.target.value || 120)) } } }, toast)} /></Row>
        <Row title="Tool enforcement" sub="When the agent must use tools."><select className="select" defaultValue={enforce} onChange={(e) => save({ config: { agent: { tool_use_enforcement: e.target.value } } }, toast)}><option value="auto">Auto</option><option value="required">Required</option><option value="none">None</option></select></Row>
      </SetCard>
    </div>
  );
}

// ---------- 3. SMART ROUTING ----------
function SecRouting({ toast }) {
  const { cfg, live, save } = useClaudeConfig();
  const r = dig(cfg || {}, "smart_model_routing", {});
  const enabled = dig(r, "enabled", true) !== false;
  const cheap = dig(r, "cheap_model", "");
  const maxChars = dig(r, "max_simple_chars", 200);
  const maxWords = dig(r, "max_simple_words", 30);
  const [models, setModels] = useState((window.DATA && window.DATA.models) || []);
  useEffect(() => {
    let alive = true;
    HERMES.listModels()
      .then((res) => { if (alive) { const m = (res && res.models) || res || []; setModels(m.map((x) => (typeof x === "string" ? x : x.id || x.name)).filter(Boolean)); } })
      .catch(() => { /* keep DATA fallback */ });
    return () => { alive = false; };
  }, []);
  return (
    <div className="set-section">
      <SetCard icon="swarm" title="Smart Routing" desc="Route simple queries to cheaper models." head={<LiveBadge live={live} />}>
        <Row title="Enable smart routing" sub="Auto-route simple queries."><RowToggle on={enabled} onChange={(v) => save({ config: { smart_model_routing: { enabled: v } } }, toast)} /></Row>
        <Row title="Cheap model" sub="Model for simple queries."><select className="select" defaultValue={cheap} disabled={!enabled} onChange={(e) => save({ config: { smart_model_routing: { cheap_model: e.target.value } } }, toast)}><option value="">Auto</option>{models.map((m) => <option key={m} value={m}>{m}</option>)}</select></Row>
        <Row title="Max chars" sub="Messages shorter use the cheap model (10–2000)."><input className="input mono" type="number" min="10" max="2000" defaultValue={maxChars} disabled={!enabled} onBlur={(e) => save({ config: { smart_model_routing: { max_simple_chars: Math.max(10, Math.min(2000, +e.target.value || 200)) } } }, toast)} /></Row>
        <Row title="Max words" sub="Messages with fewer words use the cheap model (1–500)."><input className="input mono" type="number" min="1" max="500" defaultValue={maxWords} disabled={!enabled} onBlur={(e) => save({ config: { smart_model_routing: { max_simple_words: Math.max(1, Math.min(500, +e.target.value || 30)) } } }, toast)} /></Row>
      </SetCard>
    </div>
  );
}

// ---------- 4. VOICE ----------
const STT_LANG_PLACEHOLDER = "auto";
function SecVoice({ toast }) {
  const { cfg, live, save } = useClaudeConfig();
  const c = cfg || {};
  const ttsProvider = dig(c, "tts.provider", "edge");
  const ttsVoice = dig(c, "tts.openai.voice", "nova");
  const sttEnabled = dig(c, "stt.enabled", true) !== false;
  const sttProvider = dig(c, "stt.provider", "local");
  const sttGroqModel = dig(c, "stt.groq.model", "whisper-large-v3-turbo");
  const sttLang = dig(c, "stt.language", "");
  return (
    <div className="set-section">
      <SetCard icon="mic" title="Text-to-Speech" desc="Spoken responses." head={<LiveBadge live={live} />}>
        <Row title="TTS provider" sub="Engine used to speak replies."><select className="select" defaultValue={ttsProvider} onChange={(e) => save({ config: { tts: { provider: e.target.value } } }, toast)}><option value="edge">Edge TTS</option><option value="elevenlabs">ElevenLabs</option><option value="openai">OpenAI TTS</option><option value="neutts">NeuTTS</option></select></Row>
        {ttsProvider === "openai" && (
          <Row title="Voice" sub="OpenAI TTS voice."><select className="select" defaultValue={ttsVoice} onChange={(e) => save({ config: { tts: { openai: { voice: e.target.value } } } }, toast)}>{["alloy", "echo", "fable", "onyx", "nova", "shimmer"].map((v) => <option key={v} value={v} style={{ textTransform: "capitalize" }}>{v}</option>)}</select></Row>
        )}
      </SetCard>

      <SetCard icon="mic" title="Speech-to-Text" desc="Dictate into the composer." head={<LiveBadge live={live} />}>
        <Row title="Enable STT" sub="Allow voice dictation."><RowToggle on={sttEnabled} onChange={(v) => save({ config: { stt: { enabled: v } } }, toast)} /></Row>
        <Row title="STT provider" sub="Transcription backend."><select className="select" defaultValue={sttProvider} disabled={!sttEnabled} onChange={(e) => save({ config: { stt: { provider: e.target.value } } }, toast)}><option value="local">Local (Whisper)</option><option value="openai">OpenAI Whisper API</option><option value="groq">Groq Whisper API</option></select></Row>
        {sttProvider === "groq" && (
          <Row title="Groq model" sub="Whisper model on Groq."><select className="select" defaultValue={sttGroqModel} disabled={!sttEnabled} onChange={(e) => save({ config: { stt: { groq: { model: e.target.value } } } }, toast)}>{["whisper-large-v3-turbo", "whisper-large-v3", "distil-whisper-large-v3-en"].map((m) => <option key={m} value={m}>{m}</option>)}</select></Row>
        )}
        {sttProvider === "groq" && (
          <Row title="Language" sub="Optional BCP-47 code, e.g. en or en-US."><input className="input mono" defaultValue={sttLang} disabled={!sttEnabled} onBlur={(e) => save({ config: { stt: { language: e.target.value } } }, toast)} placeholder={STT_LANG_PLACEHOLDER} /></Row>
        )}
      </SetCard>
    </div>
  );
}

// ---------- 5. DISPLAY (keep working density/motion props; add UI scale) ----------
// The whole UI is scaled via zoom on <html> (14px = 100%); the pre-paint script
// in index.html re-applies the saved value on every load.
function applyUiScale(v) {
  document.documentElement.style.zoom = v && v !== 14 ? String(v / 14) : "";
  // zoom changes both effective viewport axes; refresh --app-h/--app-w (see index.html).
  if (window.__applyAppH) window.__applyAppH();
}
function SecDisplay({ density, setDensity, motion, setMotion }) {
  const [font, setFont] = useState(() => lsGet("ui.fontSize", 14));
  const setF = (v) => { setFont(v); lsSet("ui.fontSize", v); applyUiScale(v); };
  return (
    <div className="set-section">
      <SetCard icon="overview" title="Display" desc="Layout density, motion, and text size.">
        <Row title="Density" sub="Spacing of cards and rows."><div className="seg">{["comfortable", "compact"].map((d) => <button key={d} className={cls(density === d && "on")} style={{ textTransform: "capitalize" }} onClick={() => setDensity(d)}>{d}</button>)}</div></Row>
        <Row title="Animations" sub="Page + micro transitions."><RowToggle on={motion === "on"} onChange={(v) => setMotion(v ? "on" : "off")} /></Row>
        <Row title="UI scale" sub={font === 14 ? "14px · default" : font + "px · scales the whole workspace"}><input type="range" min="12" max="18" step="1" value={font} onChange={(e) => setF(+e.target.value)} style={{ width: "100%", accentColor: "var(--primary)" }} /></Row>
      </SetCard>
    </div>
  );
}

// ---------- 6. APPEARANCE (kept exactly — theme gallery + accent) ----------
function SecAppearance({ theme, setTheme, accent, setAccent }) {
  return (
    <div className="set-section">
      <SetCard icon="sparkle" title="Theme" desc="Pick a palette. New themes show up here automatically as they're added.">
        <div className="theme-gallery">
          {window.THEMES.map((t) => (
            <button key={t.id} className={cls("theme-card", theme === t.id && "on")} onClick={() => setTheme(t.id)}>
              <div className="theme-prev" style={{ background: t.bg }}>
                <span className="pdot" style={{ background: t.accent }} />
                <span className="pbar" style={{ background: t.surface, width: 64, top: 16, left: 38 }} />
                <span className="pbar" style={{ background: t.surface, width: 46, top: 28, left: 38, opacity: .7 }} />
                <span className="pbar" style={{ background: t.accent, width: 30, bottom: 16, left: 12, opacity: .9 }} />
                <span className="pbar" style={{ background: t.surface, width: 70, bottom: 16, left: 48 }} />
              </div>
              <div className="theme-meta"><div><b style={{ color: "var(--text)" }}>{t.name}</b><div className="faint" style={{ fontSize: 11 }}>{t.desc}</div></div>{theme === t.id && <span className="chk"><Icon name="check" size={12} /></span>}</div>
            </button>
          ))}
        </div>
      </SetCard>

      <SetCard icon="bolt" title="Accent color" desc="Override the palette's accent with a striking contrast — great on Obsidian (try lime).">
        <div className="accent-row">
          <button className={cls("accent-sw", accent === "default" && "on")} onClick={() => setAccent("default")} title="Theme default" style={{ background: "var(--surface-3)", color: "var(--muted)" }}><Icon name="x" size={14} /></button>
          {Object.entries(window.ACCENTS).filter(([k]) => k !== "default").map(([k, v]) => (
            <button key={k} className={cls("accent-sw", accent === k && "on")} onClick={() => setAccent(k)} title={k} style={{ background: v.primary }}>
              {accent === k && <Icon name="check" size={15} style={{ color: v.fg }} />}
            </button>
          ))}
        </div>
        <p className="faint" style={{ fontSize: 12, marginTop: 12 }}>Current: <b className="mono" style={{ color: "var(--primary)", textTransform: "capitalize" }}>{accent}</b> · applies across the whole workspace.</p>
      </SetCard>
    </div>
  );
}

// ---------- 7. CHAT (UI-only prefs persisted to localStorage) ----------
const CHAT_DEFAULTS = { showToolMessages: false, showReasoningBlocks: false, soundOnChatComplete: false, enterBehavior: "send", chatWidth: "comfortable", sidebarHoverExpand: false };
function SecChat() {
  const [s, setS] = useState(() => ({ ...CHAT_DEFAULTS, ...lsGet("chat-settings", {}) }));
  const set = (k, v) => setS((prev) => { const n = { ...prev, [k]: v }; lsSet("chat-settings", n); if (k === "chatWidth") document.documentElement.setAttribute("data-chat-width", v); return n; });
  return (
    <div className="set-section">
      <SetCard icon="chat" title="Chat" desc="Message visibility and response loader style." head={<span className="badge warn"><span className="d" />preview</span>}>
        <Row title="Show tool messages" sub="Display tool call details in assistant responses."><RowToggle on={s.showToolMessages} onChange={(v) => set("showToolMessages", v)} /></Row>
        <Row title="Show reasoning blocks" sub="Display model reasoning blocks when available."><RowToggle on={s.showReasoningBlocks} onChange={(v) => set("showReasoningBlocks", v)} /></Row>
        <Row title="Sound on response complete" sub="Play a short sound when the agent finishes replying."><RowToggle on={s.soundOnChatComplete} onChange={(v) => set("soundOnChatComplete", v)} /></Row>
        <Row title="Enter key behavior" sub={s.enterBehavior === "newline" ? "Enter inserts a newline. Use ⌘/Ctrl+Enter to send." : "Enter sends the message. Use Shift+Enter for a newline."}><div className="seg">{[["send", "Send"], ["newline", "Newline"]].map(([k, l]) => <button key={k} className={cls(s.enterBehavior === k && "on")} onClick={() => set("enterBehavior", k)}>{l}</button>)}</div></Row>
        <Row title="Chat content width" sub="Maximum width of the conversation column."><select className="select" value={s.chatWidth} onChange={(e) => set("chatWidth", e.target.value)}><option value="comfortable">Comfortable (900px)</option><option value="wide">Wide (1200px)</option><option value="full">Full width</option></select></Row>
        <Row title="Expand sidebar on hover" sub="Collapsed sidebar expands temporarily on hover."><RowToggle on={s.sidebarHoverExpand} onChange={(v) => set("sidebarHoverExpand", v)} /></Row>
      </SetCard>
    </div>
  );
}

// ---------- 8. NOTIFICATIONS / ALERTS ----------
const ALERT_DEFAULTS = { notificationsEnabled: true, usageThreshold: 80 };
function SecNotifications() {
  const [s, setS] = useState(() => ({ ...ALERT_DEFAULTS, ...lsGet("alert-settings", {}) }));
  const set = (k, v) => setS((prev) => { const n = { ...prev, [k]: v }; lsSet("alert-settings", n); return n; });
  return (
    <div className="set-section">
      <SetCard icon="bell" title="Notifications" desc="Simple alerts and threshold controls." head={<span className="badge warn"><span className="d" />preview</span>}>
        <Row title="Enable alerts" sub="Show usage and status alerts."><RowToggle on={s.notificationsEnabled} onChange={(v) => set("notificationsEnabled", v)} /></Row>
        <Row title="Usage threshold" sub={"Alert when usage exceeds " + s.usageThreshold + "%."}><input type="range" min="50" max="100" step="1" value={s.usageThreshold} disabled={!s.notificationsEnabled} onChange={(e) => set("usageThreshold", +e.target.value)} style={{ width: "100%", accentColor: "var(--primary)" }} /></Row>
      </SetCard>
    </div>
  );
}

// ---------- 9. LANGUAGE ----------
const LOCALE_LABELS = [
  ["en", "English"], ["es", "Español"], ["fr", "Français"], ["de", "Deutsch"], ["zh", "中文（简体）"],
  ["zh-TW", "繁體中文"], ["ja", "日本語"], ["ko", "한국어"], ["pt", "Português"], ["ru", "Русский"], ["ar", "العربية"],
];
function SecLanguage({ toast }) {
  const [locale, setLocale] = useState(() => lsGet("hermes-workspace-locale", null) || (navigator.language || "en").slice(0, 2));
  const [dateFmt, setDateFmt] = useState(() => lsGet("ui.dateFormat", "Relative"));
  const [tz, setTz] = useState(() => lsGet("ui.timezone", (Intl.DateTimeFormat().resolvedOptions().timeZone) || "UTC"));
  const onLocale = (v) => { setLocale(v); try { localStorage.setItem("hermes-workspace-locale", JSON.stringify(v)); } catch { /* ignore */ } toast("Language preference saved"); };
  return (
    <div className="set-section">
      <SetCard icon="memory" title="Language &amp; region" desc="Choose the display language for the workspace UI." head={<span className="badge warn"><span className="d" />preview</span>}>
        <Row title="Interface language" sub="Translates navigation, labels, and buttons."><select className="select" value={locale} onChange={(e) => onLocale(e.target.value)}>{LOCALE_LABELS.map(([k, l]) => <option key={k} value={k}>{l}</option>)}</select></Row>
        <Row title="Date format" sub="How dates are displayed."><select className="select" value={dateFmt} onChange={(e) => { setDateFmt(e.target.value); lsSet("ui.dateFormat", e.target.value); }}><option>Relative</option><option>DD MMM YYYY</option><option>MM/DD/YYYY</option><option>YYYY-MM-DD</option></select></Row>
        <Row title="Timezone" sub="For schedules and logs."><select className="select" value={tz} onChange={(e) => { setTz(e.target.value); lsSet("ui.timezone", e.target.value); }}><option>UTC</option><option>Asia/Kolkata</option><option>America/New_York</option><option>America/Los_Angeles</option><option>Europe/London</option><option>Europe/Berlin</option><option>Asia/Tokyo</option></select></Row>
      </SetCard>
    </div>
  );
}

const SET_NAV = [
  { id: "connection", label: "Connection", icon: "cpu" },
  { id: "model", label: "Model & Provider", icon: "overview" },
  { id: "agent", label: "Agent Behavior", icon: "profiles" },
  { id: "routing", label: "Smart Routing", icon: "swarm" },
  { id: "voice", label: "Voice", icon: "mic" },
  { id: "display", label: "Display", icon: "kanban" },
  { id: "appearance", label: "Appearance", icon: "sparkle" },
  { id: "chat", label: "Chat", icon: "chat" },
  { id: "notifications", label: "Notifications", icon: "bell" },
  { id: "language", label: "Language", icon: "memory" },
];

function PageSettings(props) {
  const { toast, theme, setTheme, accent, setAccent, density, setDensity, motion, setMotion } = props;
  const [sec, setSec] = useState("appearance");
  const render = {
    connection: <SecConnection toast={toast} />,
    model: <SecModel toast={toast} />,
    agent: <SecAgent toast={toast} />,
    routing: <SecRouting toast={toast} />,
    voice: <SecVoice toast={toast} />,
    display: <SecDisplay density={density} setDensity={setDensity} motion={motion} setMotion={setMotion} />,
    appearance: <SecAppearance theme={theme} setTheme={setTheme} accent={accent} setAccent={setAccent} />,
    chat: <SecChat />,
    notifications: <SecNotifications />,
    language: <SecLanguage toast={toast} />,
  };
  return (
    <div className="page">
      <PageHead eyebrow="Workspace" title="Settings" sub="Connection, models, behavior, and appearance for Sylar's WorkSpace.">
        <span className="badge"><Icon name="check" size={12} />Saved automatically</span>
      </PageHead>
      <div className="settings-layout">
        <nav className="settings-nav">
          {SET_NAV.map((s) => (
            <button key={s.id} className={cls("set-navitem", sec === s.id && "on")} onClick={() => setSec(s.id)}>
              <Icon name={s.icon} size={16} />{s.label}
            </button>
          ))}
        </nav>
        <div key={sec}>{render[sec]}</div>
      </div>
    </div>
  );
}
window.PageSettings = PageSettings;
