/* admin API management — saves provider keys to the live backend (/api/keys,
   admin-token gated, stored in Vercel KV) and reads real connection status from
   /api/config. When no backend is reachable (static-only), it falls back to the
   browser-local key store so the panel still works for the built-in agent.

   The AI provider (Mr. Wing) is OpenAI-compatible: choose a provider/base URL,
   paste a key, Connect → the panel auto-fetches the provider's models (via the
   admin-gated /api/models probe, or browser-direct in static mode), you pick one,
   then Save. After that, other tasks continue as normal. */

function maskSecret(v) {
  if (!v) return "";
  if (v.length <= 10) return "••••" + v.slice(-2);
  return v.slice(0, 6) + "••••" + v.slice(-4);
}

/* OpenAI-compatible provider presets (base URL + family). "Custom" lets the user
   type any OpenAI-compatible endpoint. */
const AI_PRESETS = [
  { id: "openai", label: "OpenAI", baseUrl: "https://api.openai.com/v1", kind: "openai" },
  { id: "openrouter", label: "OpenRouter", baseUrl: "https://openrouter.ai/api/v1", kind: "openai" },
  { id: "groq", label: "Groq", baseUrl: "https://api.groq.com/openai/v1", kind: "openai" },
  { id: "together", label: "Together AI", baseUrl: "https://api.together.xyz/v1", kind: "openai" },
  { id: "mistral", label: "Mistral", baseUrl: "https://api.mistral.ai/v1", kind: "openai" },
  { id: "deepseek", label: "DeepSeek", baseUrl: "https://api.deepseek.com/v1", kind: "openai" },
  { id: "anthropic", label: "Anthropic (Claude)", baseUrl: "https://api.anthropic.com", kind: "anthropic" },
  { id: "custom", label: "Custom · OpenAI-compatible", baseUrl: "", kind: "openai" },
];
function presetFor(baseUrl) {
  const u = String(baseUrl || "").replace(/\/+$/, "");
  return AI_PRESETS.find((p) => p.baseUrl && p.baseUrl === u) || AI_PRESETS.find((p) => p.id === "custom");
}

function KeyRow({ k, live, backendLive, onSave }) {
  const { t } = useLang();
  const [editing, setEditing] = React.useState(false);
  const [val, setVal] = React.useState("");
  const [show, setShow] = React.useState(false);
  const [saved, setSaved] = React.useState(false);
  const [err, setErr] = React.useState(null);
  const [busy, setBusy] = React.useState(false);
  const connected = live ? live.connected : k.status === "connected";
  const env = (live && live.env) || k.env;
  const masked = backendLive ? (connected ? (live && live.source === "env" ? "via environment variable" : "•••• stored in key vault") : "") : (connected ? k.masked : "");

  const save = async () => {
    setErr(null); if (!val.trim()) return;
    setBusy(true);
    const r = await onSave(k.id, val.trim(), { env });
    setBusy(false);
    if (r && r.ok) { setEditing(false); setVal(""); setSaved(true); setTimeout(() => setSaved(false), 2400); }
    else { setErr((r && r.error) || "save_failed"); }
  };

  const errText = {
    need_token: "Enter the admin token in the panel on the right first.",
    admin_not_configured: "Set ADMIN_TOKEN in Vercel to enable panel key entry (or use env vars).",
    kv_unconfigured: "Add a Supabase database or Vercel KV store to save keys from the panel (or use env vars).",
    vault_unconfigured: "Add a Supabase database or Vercel KV store to save keys from the panel (or use env vars).",
    unauthorized: "Admin token is incorrect.",
    save_failed: "Couldn't save the key. Try again.",
  };

  return (
    <div className="rcol" style={{ display: "grid", gridTemplateColumns: "1fr auto", gap: 18, padding: "20px 0", borderBottom: "1px solid var(--line)", alignItems: "center" }}>
      <div>
        <div style={{ display: "flex", alignItems: "center", gap: 10, flexWrap: "wrap" }}>
          <span style={{ fontWeight: 700, fontSize: 15 }}>{k.label}</span>
          <span style={{ display: "inline-flex", alignItems: "center", gap: 6, fontSize: 11.5, fontWeight: 700, color: connected ? "var(--ok)" : "var(--ink-3)", background: connected ? "var(--emerald-wash)" : "var(--paper-2)", padding: "3px 9px", borderRadius: 100 }}>
            <span className="badge-dot" style={{ background: connected ? "var(--ok)" : "var(--ink-3)" }}></span>{connected ? t("api.connected") : t("api.notConnected")}
          </span>
          <span className="chip" style={{ fontSize: 11, padding: "2px 9px", background: env === "Live" ? "var(--gold-wash)" : "var(--paper-2)", color: env === "Live" ? "var(--gold-d)" : "var(--ink-3)" }}>{env}</span>
        </div>
        <div className="muted" style={{ fontSize: 13, marginTop: 5 }}>{k.desc}</div>
        {connected && masked && !editing && <div style={{ fontFamily: "monospace", fontSize: 12.5, color: "var(--ink-3)", marginTop: 8 }}>{masked}</div>}
        {editing && (
          <div style={{ display: "flex", gap: 8, marginTop: 12, maxWidth: 480, flexWrap: "wrap" }}>
            <div style={{ position: "relative", flex: 1, minWidth: 220 }}>
              <input className="input" type={show ? "text" : "password"} value={val} onChange={e => setVal(e.target.value)} placeholder={k.placeholder} autoFocus style={{ fontFamily: "monospace", paddingInlineEnd: 64 }} />
              <button onClick={() => setShow(s => !s)} style={{ position: "absolute", insetInlineEnd: 8, top: "50%", transform: "translateY(-50%)", background: "none", border: "none", cursor: "pointer", color: "var(--ink-3)", fontSize: 12, fontWeight: 600 }}>{show ? t("common.hide") : t("common.show")}</button>
            </div>
            <button className="btn btn-primary btn-sm" onClick={save} disabled={!val.trim() || busy}>{busy ? <Spinner /> : t("common.save")}</button>
            <button className="btn btn-ghost btn-sm" onClick={() => { setEditing(false); setVal(""); setErr(null); }}>{t("common.cancel")}</button>
          </div>
        )}
        {err && <div style={{ color: "var(--danger)", fontSize: 12.5, marginTop: 8 }}>{errText[err] || err}</div>}
        {k.multi && editing && <div className="muted" style={{ fontSize: 12, marginTop: 6 }}>{k.multiHint}</div>}
      </div>
      <div style={{ display: "flex", gap: 8, alignItems: "center" }}>
        {saved && <span style={{ fontSize: 12.5, color: "var(--ok)", fontWeight: 600, display: "inline-flex", gap: 5, alignItems: "center" }}><Icon name="check" size={15} /> {t("common.save")}</span>}
        {!editing && <button className="btn btn-ghost btn-sm" onClick={() => { setEditing(true); setErr(null); }}><Icon name="key" size={15} /> {connected ? t("api.rotate") : t("api.add")}</button>}
      </div>
    </div>
  );
}

/* Mr. Wing AI provider row — OpenAI-compatible connect → fetch models → pick → save. */
function AIProviderRow({ k, live, backendLive, cfg, adminToken, onSaved }) {
  const { t } = useLang();
  const { setApiKeys } = useStore();
  const connected = live ? live.connected : (!!k.value && !!k.model);
  const curBase = (live && live.baseUrl) || k.baseUrl || "https://api.openai.com/v1";
  const curKind = (live && live.kind) || k.kind || "openai";
  const curModel = (live && live.model) || k.model || "";
  const envManaged = backendLive && live && live.source === "env";

  const [mode, setMode] = React.useState(connected ? "view" : "setup"); // view | setup
  const [presetId, setPresetId] = React.useState(() => presetFor(curBase).id);
  const [baseUrl, setBaseUrl] = React.useState(curBase);
  const [kind, setKind] = React.useState(curKind);
  const [keyVal, setKeyVal] = React.useState("");
  const [showKey, setShowKey] = React.useState(false);
  const [probing, setProbing] = React.useState(false);
  const [models, setModels] = React.useState([]);
  const [model, setModel] = React.useState(curModel);
  const [filter, setFilter] = React.useState("");
  const [saving, setSaving] = React.useState(false);
  const [savedFlash, setSavedFlash] = React.useState(false);
  const [err, setErr] = React.useState(null);

  React.useEffect(() => { setMode(connected ? "view" : "setup"); }, [connected]);

  const msg = (code, detail) => {
    const map = {
      need_token: t("api.ai.err.needToken"), admin_not_configured: t("api.ai.err.adminNeeded"),
      unauthorized: t("api.ai.err.unauthorized"), unsafe_base_url: t("api.ai.err.unsafeUrl"),
      missing_key: t("api.ai.err.needKey"), save_failed: t("api.ai.err.save"),
      no_models: t("api.ai.err.noModels"), connect: t("api.ai.err.connect"),
      kv_unconfigured: t("api.ai.err.kv"), vault_unconfigured: t("api.ai.err.kv"),
    };
    return (map[code] || t("api.ai.err.connect")) + (detail ? " (" + String(detail).slice(0, 160) + ")" : "");
  };

  const choosePreset = (id) => {
    const p = AI_PRESETS.find((x) => x.id === id) || AI_PRESETS[0];
    setPresetId(id);
    if (p.baseUrl) setBaseUrl(p.baseUrl);
    setKind(p.kind);
    setModels([]); setModel(""); setErr(null);
  };
  const onBaseUrl = (v) => { setBaseUrl(v); setKind((window.aiKindOf ? aiKindOf(v) : (/anthropic\.com/i.test(v) ? "anthropic" : "openai"))); setModels([]); };

  // browser-direct probe (static / backend unreachable) — CORS permitting
  const browserProbe = async (key) => {
    try { const list = await window.fetchAIModels({ key, baseUrl: baseUrl.trim(), kind }); return { ok: true, models: list }; }
    catch (e) { return { ok: false, error: "connect", detail: String((e && e.message) || e) }; }
  };

  const connect = async () => {
    setErr(null);
    const key = keyVal.trim();
    if (!key) { setErr(msg("missing_key")); return; }
    setProbing(true);
    let res;
    if (backendLive) {
      if (!cfg || !cfg.adminConfigured) { setProbing(false); setErr(msg("admin_not_configured")); return; }
      if (!adminToken) { setProbing(false); setErr(msg("need_token")); return; }
      res = await window.apiProbeModels({ adminToken, baseUrl: baseUrl.trim(), key, kind });
      if (res && res.__unreachable && window.fetchAIModels) res = await browserProbe(key);
    } else {
      res = window.fetchAIModels ? await browserProbe(key) : { ok: false, error: "connect" };
    }
    setProbing(false);
    if (res && res.ok) {
      const list = res.models || [];
      setModels(list);
      if (list.length) { setModel((m) => m || list[0].id); setErr(null); }
      else setErr(msg("no_models"));
      if (res.kind) setKind(res.kind);
    } else {
      setErr(msg(res && res.error === "connect" ? "connect" : (res && res.error) || "connect", res && res.detail));
    }
  };

  // re-fetch models for an already-connected provider (Change model)
  const refetch = async () => {
    setErr(null); setProbing(true);
    let res;
    if (backendLive) {
      const r = await window.apiModels(); // GET — uses the stored key
      res = r && !r.__unreachable ? (r.error ? { ok: false, error: "connect", detail: r.detail } : { ok: true, models: r.models }) : null;
      if (!res && window.fetchAIModels && k.value) res = await browserProbe(k.value);
    } else if (window.fetchAIModels && k.value) {
      const list = await window.fetchAIModels({ key: k.value, baseUrl: curBase, kind: curKind }).then((m) => ({ ok: true, models: m })).catch((e) => ({ ok: false, error: "connect", detail: String(e.message || e) }));
      res = list;
    }
    setProbing(false);
    if (res && res.ok) { setModels(res.models || []); setModel(curModel || (res.models[0] && res.models[0].id) || ""); setMode("setup"); }
    else setErr(msg("connect", res && res.detail));
  };

  const saveLocal = (key) => {
    setApiKeys((prev) => prev.map((x) => x.id === "ai" ? {
      ...x, value: key || x.value, baseUrl: baseUrl.trim(), kind, model,
      status: (key || x.value) ? "connected" : x.status, masked: key ? maskSecret(key) : x.masked,
    } : x));
    setSavedFlash(true); setMode("view"); setKeyVal(""); setTimeout(() => setSavedFlash(false), 2400);
  };

  const save = async () => {
    setErr(null);
    if (!model) { setErr(msg("no_models")); return; }
    setSaving(true);
    if (backendLive) {
      if (!cfg.adminConfigured) { setSaving(false); setErr(msg("admin_not_configured")); return; }
      if (!adminToken) { setSaving(false); setErr(msg("need_token")); return; }
      const r = await window.apiSaveKey({ id: "ai", value: keyVal.trim() || undefined, baseUrl: baseUrl.trim(), kind, model, env: k.env, adminToken });
      setSaving(false);
      if (r && r.__unreachable) { saveLocal(keyVal.trim()); return; }
      if (r && r.ok) { setSavedFlash(true); setMode("view"); setKeyVal(""); onSaved && onSaved(); setTimeout(() => setSavedFlash(false), 2400); }
      else setErr(msg((r && r.error) || "save_failed"));
    } else { setSaving(false); saveLocal(keyVal.trim()); }
  };

  const shownModels = filter ? models.filter((m) => (m.id + " " + (m.label || "")).toLowerCase().includes(filter.toLowerCase())) : models;
  const providerLabel = (AI_PRESETS.find((p) => p.id === presetFor(curBase).id) || {}).label || curBase;

  return (
    <div style={{ padding: "20px 0", borderBottom: "1px solid var(--line)" }}>
      <div style={{ display: "flex", alignItems: "center", gap: 10, flexWrap: "wrap" }}>
        <span style={{ fontWeight: 700, fontSize: 15 }}>{k.label}</span>
        <span style={{ display: "inline-flex", alignItems: "center", gap: 6, fontSize: 11.5, fontWeight: 700, color: connected ? "var(--ok)" : "var(--ink-3)", background: connected ? "var(--emerald-wash)" : "var(--paper-2)", padding: "3px 9px", borderRadius: 100 }}>
          <span className="badge-dot" style={{ background: connected ? "var(--ok)" : "var(--ink-3)" }}></span>{connected ? t("api.connected") : t("api.notConnected")}
        </span>
        {connected && <span className="chip" style={{ fontSize: 11, padding: "2px 9px", background: "var(--paper-2)", color: "var(--ink-3)" }}>{curKind === "anthropic" ? "Anthropic" : "OpenAI-compatible"}</span>}
      </div>
      <div className="muted" style={{ fontSize: 13, marginTop: 5 }}>{k.desc}</div>

      {mode === "view" && connected && (
        <div style={{ marginTop: 12 }}>
          <div className="card" style={{ background: "var(--paper)", padding: 14, display: "grid", gap: 6, maxWidth: 520 }}>
            <Field label={t("api.ai.provider")} value={providerLabel} />
            <Field label={t("api.ai.baseUrl")} value={<span style={{ fontFamily: "monospace", fontSize: 12.5 }}>{curBase}</span>} />
            <Field label={t("api.ai.model")} value={curModel ? <span style={{ fontFamily: "monospace", fontSize: 12.5 }}>{curModel}</span> : <span className="muted">{t("api.ai.selectModel")}</span>} />
            {envManaged && <div className="muted" style={{ fontSize: 12 }}>{t("api.ai.envManaged")}</div>}
          </div>
          <div style={{ display: "flex", gap: 8, marginTop: 12, flexWrap: "wrap" }}>
            <button className="btn btn-ghost btn-sm" onClick={refetch} disabled={probing}>{probing ? <Spinner color="var(--emerald)" /> : <Icon name="bolt" size={15} />} {t("api.ai.change")}</button>
            <button className="btn btn-ghost btn-sm" onClick={() => { setMode("setup"); setModels([]); setKeyVal(""); setErr(null); }}><Icon name="key" size={15} /> {t("api.ai.reconfigure")}</button>
            {savedFlash && <span style={{ fontSize: 12.5, color: "var(--ok)", fontWeight: 600, display: "inline-flex", gap: 5, alignItems: "center" }}><Icon name="check" size={15} /> {t("common.save")}</span>}
          </div>
        </div>
      )}

      {mode === "setup" && (
        <div style={{ marginTop: 14, maxWidth: 560, display: "grid", gap: 12 }}>
          <div className="field">
            <label>{t("api.ai.provider")}</label>
            <select className="select" value={presetId} onChange={(e) => choosePreset(e.target.value)}>
              {AI_PRESETS.map((p) => <option key={p.id} value={p.id}>{p.label}</option>)}
            </select>
          </div>
          <div className="field">
            <label>{t("api.ai.baseUrl")}</label>
            <input className="input" value={baseUrl} onChange={(e) => onBaseUrl(e.target.value)} placeholder="https://api.openai.com/v1" style={{ fontFamily: "monospace", fontSize: 13 }} />
          </div>
          <div className="field">
            <label>{t("api.ai.key")}</label>
            <div style={{ position: "relative" }}>
              <input className="input" type={showKey ? "text" : "password"} value={keyVal} onChange={(e) => setKeyVal(e.target.value)} placeholder={connected ? "•••• (leave blank to keep current)" : k.placeholder} style={{ fontFamily: "monospace", paddingInlineEnd: 64 }} />
              <button type="button" onClick={() => setShowKey((s) => !s)} style={{ position: "absolute", insetInlineEnd: 8, top: "50%", transform: "translateY(-50%)", background: "none", border: "none", cursor: "pointer", color: "var(--ink-3)", fontSize: 12, fontWeight: 600 }}>{showKey ? t("common.hide") : t("common.show")}</button>
            </div>
          </div>
          <div style={{ display: "flex", gap: 8, flexWrap: "wrap" }}>
            <button className="btn btn-primary btn-sm" onClick={connect} disabled={probing || (!keyVal.trim() && !connected)}>
              {probing ? <><Spinner /> {t("api.ai.connecting")}</> : <><Icon name="bolt" size={15} /> {t("api.ai.connect")}</>}
            </button>
            {connected && <button className="btn btn-ghost btn-sm" onClick={() => { setMode("view"); setErr(null); }}>{t("common.cancel")}</button>}
          </div>

          {models.length > 0 && (
            <div className="field" style={{ marginTop: 2 }}>
              <label>{t("api.ai.model")} · {t("api.ai.modelsFound", { n: models.length })}</label>
              {models.length > 8 && <input className="input" value={filter} onChange={(e) => setFilter(e.target.value)} placeholder={t("api.ai.filter")} style={{ marginBottom: 8 }} />}
              <select className="select" value={model} onChange={(e) => setModel(e.target.value)} size={Math.min(8, Math.max(3, shownModels.length))} style={{ height: "auto" }}>
                {shownModels.map((m) => <option key={m.id} value={m.id}>{m.label ? m.label + " — " + m.id : m.id}</option>)}
              </select>
              <button className="btn btn-primary btn-sm" style={{ marginTop: 10 }} onClick={save} disabled={saving || !model}>
                {saving ? <><Spinner /> {t("common.save")}</> : <><Icon name="check" size={15} /> {t("api.ai.save")}</>}
              </button>
            </div>
          )}

          <div className="muted" style={{ fontSize: 12, lineHeight: 1.5 }}>{t("api.ai.hint")}{!backendLive && " " + t("api.ai.localHint")}</div>
        </div>
      )}

      {err && <div style={{ color: "var(--danger)", fontSize: 12.5, marginTop: 10 }}>{err}</div>}
    </div>
  );
}

function Field({ label, value }) {
  return <div style={{ display: "flex", justifyContent: "space-between", gap: 16, alignItems: "baseline" }}><span className="muted" style={{ fontSize: 12.5 }}>{label}</span><span style={{ fontSize: 13.5, fontWeight: 600, textAlign: "end", wordBreak: "break-all" }}>{value}</span></div>;
}

function AdminAPI() {
  const { t } = useLang();
  const { apiKeys, setApiKeys } = useStore();
  const groups = ["Payments", "Flights", "Hotels", "AI Model"];
  const groupIcon = { Payments: "lock", Flights: "plane", Hotels: "hotel", "AI Model": "chat" };

  const [cfg, setCfg] = React.useState(null);
  const [adminToken, setAdminToken] = React.useState(() => { try { return sessionStorage.getItem("tw_admin") || ""; } catch (e) { return ""; } });
  const refresh = React.useCallback(() => { if (window.apiConfig) apiConfig(true).then(setCfg); }, []);
  React.useEffect(() => { refresh(); }, [refresh]);

  const backendLive = !!(cfg && cfg.providers && !cfg.__unreachable);
  const liveOf = (id) => backendLive ? cfg.providers[id] : null;

  const saveLocal = (id, value, meta) => {
    setApiKeys(prev => prev.map(k => k.id === id ? { ...k, status: value ? "connected" : k.status, masked: value ? maskSecret(value) : k.masked, value: value != null ? value : k.value, ...(meta || {}) } : k));
    return { ok: true, local: true };
  };

  const onSave = async (id, value, meta) => {
    if (!backendLive) return saveLocal(id, value, meta);
    if (!cfg.adminConfigured) return { error: "admin_not_configured" };
    if (!adminToken) return { error: "need_token" };
    const r = await window.apiSaveKey({ id, value, env: meta && meta.env, adminToken });
    if (r && r.__unreachable) return saveLocal(id, value, meta);
    if (r && r.ok) { refresh(); return { ok: true }; }
    return { error: (r && r.error) || "save_failed" };
  };

  const setToken = (v) => { setAdminToken(v); try { sessionStorage.setItem("tw_admin", v); } catch (e) {} };
  const aiLive = backendLive ? !!(cfg.providers.ai && cfg.providers.ai.connected) : (apiKeys || []).some(k => k.id === "ai" && k.value && k.model);

  // helper hints for the two combined-credential providers
  const enrich = (k) => k.id === "gds" ? { ...k, multi: true, multiHint: "Format: API Key : API Secret (Amadeus)" }
    : k.id === "hotelbeds" ? { ...k, multi: true, multiHint: "Format: API Key : Secret (Hotelbeds)" }
    : k;

  return (
    <div className="split" style={{ display: "grid", gridTemplateColumns: "1fr 320px", gap: 24, alignItems: "start" }}>
      <div style={{ display: "flex", flexDirection: "column", gap: 20 }}>
        {groups.map(g => (
          <div key={g} className="card card-pad">
            <div style={{ display: "flex", alignItems: "center", gap: 11, marginBottom: 4 }}>
              <div style={{ width: 38, height: 38, borderRadius: 10, background: "var(--emerald-wash)", color: "var(--emerald)", display: "grid", placeItems: "center" }}><Icon name={groupIcon[g]} size={19} /></div>
              <h3 style={{ fontFamily: "var(--serif)", fontSize: 21, fontWeight: 600 }}>{g}</h3>
            </div>
            {(apiKeys || []).filter(k => k.group === g).map(k => k.id === "ai"
              ? <AIProviderRow key={k.id} k={k} live={liveOf("ai")} backendLive={backendLive} cfg={cfg} adminToken={adminToken} onSaved={refresh} />
              : <KeyRow key={k.id} k={enrich(k)} live={liveOf(k.id)} backendLive={backendLive} onSave={onSave} />)}
          </div>
        ))}
      </div>

      <aside style={{ position: "sticky", top: 92, display: "flex", flexDirection: "column", gap: 18 }}>
        <div className="card card-pad" style={{ background: aiLive ? "var(--emerald)" : "var(--ink)", color: "#fff" }}>
          <Icon name={aiLive ? "bolt" : "chat"} size={26} color="var(--gold-l)" />
          <h3 style={{ fontFamily: "var(--serif)", fontSize: 19, fontWeight: 600, marginTop: 12 }}>{aiLive ? t("api.liveBadge") : t("api.localBadge")}</h3>
          <p style={{ color: "rgba(255,255,255,.78)", fontSize: 13, marginTop: 6, lineHeight: 1.55 }}>{t("api.plugDesc")}</p>
          <div style={{ marginTop: 10, fontSize: 12, color: "rgba(255,255,255,.6)" }}>
            {backendLive ? ((cfg.vaultEnabled || cfg.kvEnabled) ? "Backend connected · key vault ready" : "Backend connected · set keys via environment variables") : "Static mode · backend not detected"}
          </div>
        </div>

        {backendLive && cfg.adminConfigured && (
          <div className="card card-pad">
            <h4 style={{ fontSize: 15, fontWeight: 700, marginBottom: 8 }}>Admin token</h4>
            <p className="muted" style={{ fontSize: 12.5, marginBottom: 10 }}>Required to save keys to the live vault. Set as <code>ADMIN_TOKEN</code> in Vercel.</p>
            <input className="input" type="password" value={adminToken} onChange={e => setToken(e.target.value)} placeholder="Admin token" style={{ fontFamily: "monospace" }} />
          </div>
        )}

        <div className="card card-pad">
          <h4 style={{ fontSize: 15, fontWeight: 700, marginBottom: 12 }}>{t("api.security")}</h4>
          {[t("api.sec1"), t("api.sec2"), t("api.sec3"), t("api.sec4")].map(x => (
            <div key={x} style={{ display: "flex", gap: 10, alignItems: "flex-start", fontSize: 13.5, color: "var(--ink-2)", marginBottom: 10 }}><Icon name="check" size={16} color="var(--emerald)" style={{ flexShrink: 0, marginTop: 1 }} /> {x}</div>
          ))}
        </div>
      </aside>
    </div>
  );
}

Object.assign(window, { AdminAPI, KeyRow, AIProviderRow, maskSecret, AI_PRESETS });
