"""Chatbot UI templates: CSS, JavaScript, HTML, and theme presets."""

from __future__ import annotations

from kiss.agents.assistant.browser_ui import (
    BASE_CSS,
    EVENT_HANDLER_JS,
    HTML_HEAD,
    OUTPUT_CSS,
)

_THEME_PRESETS: dict[str, dict[str, str]] = {
    "dark": {
        "bg": "#1e1e1e", "bg2": "#252526", "fg": "#d4d4d4",
        "accent": "#3794ff", "border": "#3c3c3c", "inputBg": "#313131",
        "green": "#23d18b", "red": "#f14c4c", "purple": "#b180d7", "cyan": "#29b8db",
    },
    "light": {
        "bg": "#ffffff", "bg2": "#f3f3f3", "fg": "#333333",
        "accent": "#005fb8", "border": "#d4d4d4", "inputBg": "#ffffff",
        "green": "#388a34", "red": "#cd3131", "purple": "#7e57c2", "cyan": "#0598bc",
    },
    "hcDark": {
        "bg": "#000000", "bg2": "#0a0a0a", "fg": "#ffffff",
        "accent": "#3794ff", "border": "#6fc3df", "inputBg": "#0a0a0a",
        "green": "#23d18b", "red": "#f48771", "purple": "#b180d7", "cyan": "#29b8db",
    },
    "hcLight": {
        "bg": "#ffffff", "bg2": "#f0f0f0", "fg": "#000000",
        "accent": "#0f4a85", "border": "#0f4a85", "inputBg": "#ffffff",
        "green": "#1b7d2c", "red": "#b5200d", "purple": "#5e3a8a", "cyan": "#0f4a85",
    },
}

CHATBOT_CSS = r"""
body{
  font-family:'Inter',system-ui,-apple-system,BlinkMacSystemFont,sans-serif;
  background:#0a0a0c;display:block;
}
header{
  background:rgba(10,10,12,0.85);backdrop-filter:blur(24px);
  -webkit-backdrop-filter:blur(24px);
  border-bottom:1px solid rgba(255,255,255,0.06);padding:14px 24px;z-index:50;
  box-shadow:0 1px 12px rgba(0,0,0,0.3);
}
.logo{font-size:12px;color:#4da6ff;font-weight:600;letter-spacing:-0.2px}
.status{font-size:12px;color:rgba(255,255,255,0.6)}
.dot{width:7px;height:7px;background:rgba(255,255,255,0.4)}
.dot.running{background:#22c55e}
#output{
  flex:1;overflow-y:auto;padding:32px 24px 24px;
  scroll-behavior:smooth;min-height:0;
}
.ev,.txt,.spinner,.empty-msg,.user-msg{max-width:820px;margin-left:auto;margin-right:auto}
.user-msg{
  background:rgba(255,255,255,0.04);border:1px solid rgba(255,255,255,0.08);
  border-radius:14px;padding:14px 20px;margin:20px auto 16px;
  font-size:14.5px;line-height:1.6;color:rgba(255,255,255,0.88);
}
.txt{
  font-size:14.5px;line-height:1.75;color:rgba(255,255,255,0.82);padding:8px 14px;
  margin:6px auto;
}
.think{
  border:1px solid rgba(168,130,255,0.12);
  background:rgba(168,130,255,0.03);border-radius:10px;margin:12px auto;
  padding:12px 16px;
}
.think .lbl{color:rgba(168,130,255,0.7)}
.think .cnt{color:rgba(255,255,255,0.4)}
.tc{
  border:1px solid rgba(88,166,255,0.15);border-radius:12px;
  margin:12px auto;background:rgba(88,166,255,0.02);
  transition:border-color 0.2s,box-shadow 0.2s;
}
.tc:hover{box-shadow:0 2px 20px rgba(88,166,255,0.08);border-color:rgba(88,166,255,0.3)}
.tc-h{
  padding:10px 16px;background:rgba(88,166,255,0.03);border-radius:12px 12px 0 0;
  border-bottom:1px solid rgba(88,166,255,0.08);
}
.tc-h:hover{background:rgba(88,166,255,0.06)}
.tn{color:rgba(88,166,255,0.9);font-size:13px}
.tp{font-size:12px;color:rgba(120,180,255,0.45)}
.td{color:rgba(255,255,255,0.3)}
.tr{
  border:1px solid rgba(34,197,94,0.15);
  background:rgba(34,197,94,0.02);border-radius:10px;
}
.tr.err{
  border-color:rgba(248,81,73,0.15);
  background:rgba(248,81,73,0.02);
}
.rc{
  border:1px solid rgba(34,197,94,0.25);border-radius:14px;
  background:rgba(34,197,94,0.02);
  box-shadow:0 0 20px rgba(34,197,94,0.04);
}
.rc-h{
  padding:16px 24px;background:rgba(34,197,94,0.05);
  border-bottom:1px solid rgba(34,197,94,0.12);
}
.usage{
  border:1px solid rgba(255,255,255,0.06);background:rgba(255,255,255,0.02);
  color:rgba(255,255,255,0.3);border-radius:8px;
}
.spinner{color:rgba(255,255,255,0.35)}
.spinner::before{border-color:rgba(255,255,255,0.08);border-top-color:rgba(88,166,255,0.7)}
#input-area{
  flex-shrink:0;padding:0 24px 24px;position:relative;
  background:linear-gradient(transparent,rgba(10,10,12,0.9) 50%);
  padding-top:24px;
}
#input-container{
  max-width:820px;margin:0 auto;position:relative;
  background:rgba(255,255,255,0.035);
  border:1px solid rgba(255,255,255,0.08);
  border-radius:16px;padding:14px 18px;
  box-shadow:0 0 0 1px rgba(255,255,255,0.02),0 8px 40px rgba(0,0,0,0.35);
  transition:border-color 0.3s,box-shadow 0.3s;
}
#input-container:focus-within{
  border-color:rgba(88,166,255,0.4);
  box-shadow:0 0 0 1px rgba(88,166,255,0.12),0 0 30px rgba(88,166,255,0.1),
    0 8px 40px rgba(0,0,0,0.35);
}
#input-wrap{display:flex;align-items:flex-start;gap:8px}
#input-text-wrap{position:relative;flex:1;min-width:0}
#task-input{
  width:100%;background:transparent;border:none;padding:0;margin:0;
  color:rgba(255,255,255,0.88);font-size:15px;font-family:inherit;
  resize:none;outline:none;line-height:1.5;
  max-height:200px;min-height:24px;
  position:relative;z-index:1;
}
#task-input::placeholder{color:rgba(255,255,255,0.28)}
#task-input:disabled{opacity:0.35;cursor:not-allowed}
#ghost-overlay{
  position:absolute;top:0;left:0;right:0;bottom:0;
  pointer-events:none;user-select:none;
  font-size:15px;font-family:inherit;line-height:1.5;
  white-space:pre-wrap;word-break:break-word;overflow:hidden;
  z-index:0;
}
.gm{visibility:hidden;white-space:pre-wrap}
.gs{color:rgba(255,255,255,0.35)}
#input-footer{
  display:flex;justify-content:space-between;align-items:center;
  margin-top:10px;padding-top:10px;
  border-top:1px solid rgba(255,255,255,0.04);
}
#model-picker{position:relative;display:flex;align-items:center;gap:4px}
#model-btn{
  background:rgba(255,255,255,0.03);color:rgba(255,255,255,0.5);
  border:1px solid rgba(255,255,255,0.08);border-radius:8px;
  padding:6px 12px;font-size:12px;font-family:inherit;
  outline:none;cursor:pointer;max-width:300px;transition:border-color 0.2s;
  display:flex;align-items:center;gap:6px;white-space:nowrap;
  overflow:hidden;text-overflow:ellipsis;
}
#model-btn:hover{border-color:rgba(255,255,255,0.16);color:rgba(255,255,255,0.65)}
#model-btn svg{flex-shrink:0;opacity:0.4}
#model-dropdown{
  position:absolute;bottom:100%;left:0;min-width:320px;max-width:420px;
  background:rgba(18,18,20,0.97);backdrop-filter:blur(20px);
  border:1px solid rgba(255,255,255,0.08);border-radius:12px;
  max-height:360px;display:none;z-index:15;
  box-shadow:0 -8px 32px rgba(0,0,0,0.5);overflow:hidden;
  flex-direction:column;
}
#model-dropdown.open{display:flex}
#model-search{
  width:100%;background:transparent;border:none;
  border-bottom:1px solid rgba(255,255,255,0.06);
  color:rgba(255,255,255,0.8);font-size:12px;font-family:inherit;
  padding:10px 14px;outline:none;
}
#model-search::placeholder{color:rgba(255,255,255,0.25)}
#model-list{overflow-y:auto;flex:1}
.model-item{
  padding:7px 14px;cursor:pointer;font-size:12px;
  display:flex;justify-content:space-between;align-items:center;
  border-bottom:1px solid rgba(255,255,255,0.02);transition:background 0.08s;
  color:rgba(255,255,255,0.6);
}
.model-item:hover,.model-item.sel{background:rgba(88,166,255,0.08)}
.model-item.active{color:rgba(88,166,255,0.9);font-weight:500}
.model-cost{font-size:10px;color:rgba(255,255,255,0.2);flex-shrink:0;margin-left:12px}
.model-group-hdr{
  padding:6px 14px 4px;font-size:10px;font-weight:600;
  text-transform:uppercase;letter-spacing:0.05em;
  color:rgba(255,255,255,0.25);
  background:rgba(18,18,20,0.97);
  border-bottom:1px solid rgba(255,255,255,0.04);
  position:sticky;top:0;z-index:1;
}
#upload-btn{
  background:none;color:rgba(255,255,255,0.3);border:none;
  width:32px;height:32px;cursor:pointer;flex-shrink:0;
  transition:color 0.15s;display:flex;align-items:center;justify-content:center;
  padding:0;border-radius:50%;
}
#upload-btn:hover{color:rgba(255,255,255,0.7);background:rgba(255,255,255,0.05)}
#upload-btn svg{width:16px;height:16px}
#upload-btn:disabled{opacity:0.2;cursor:not-allowed}
#file-chips{
  display:flex;flex-wrap:wrap;gap:6px;margin-bottom:8px;max-width:820px;margin-left:auto;margin-right:auto;
}
#file-chips:empty{display:none;margin-bottom:0}
.file-chip{
  display:inline-flex;align-items:center;gap:5px;
  background:rgba(88,166,255,0.08);border:1px solid rgba(88,166,255,0.15);
  border-radius:8px;padding:4px 10px;font-size:11px;color:rgba(88,166,255,0.8);
}
.file-chip img{width:24px;height:24px;border-radius:4px;object-fit:cover}
.file-chip .fc-icon{font-size:14px;opacity:0.6}
.file-chip .fc-rm{
  cursor:pointer;color:rgba(255,255,255,0.3);font-size:14px;margin-left:2px;
  transition:color 0.15s;
}
.file-chip .fc-rm:hover{color:rgba(248,81,73,0.8)}
#input-actions{display:flex;gap:8px;align-items:center}
#send-btn{
  background:rgba(88,166,255,0.15);color:rgba(88,166,255,0.9);border:none;
  border-radius:50%;width:36px;height:36px;cursor:pointer;
  transition:all 0.2s;display:flex;align-items:center;justify-content:center;
  flex-shrink:0;
}
#send-btn:hover{background:rgba(88,166,255,0.3);color:#fff;box-shadow:0 0 16px rgba(88,166,255,0.2)}
#send-btn:disabled{opacity:0.2;cursor:not-allowed;box-shadow:none}
#send-btn svg{width:16px;height:16px}
#stop-btn{
  background:rgba(248,81,73,0.1);color:#f85149;
  border:1px solid rgba(248,81,73,0.15);
  border-radius:50%;width:36px;height:36px;
  cursor:pointer;transition:all 0.2s;display:none;
  align-items:center;justify-content:center;flex-shrink:0;
}
#stop-btn:hover{background:rgba(248,81,73,0.2);box-shadow:0 0 16px rgba(248,81,73,0.15)}
#stop-btn svg{width:14px;height:14px}
#clear-btn{
  background:none;color:rgba(255,255,255,0.2);border:none;
  width:24px;height:24px;cursor:pointer;flex-shrink:0;
  transition:color 0.15s;display:flex;align-items:center;justify-content:center;
  padding:0;margin-top:1px;
}
#clear-btn:hover{color:rgba(255,255,255,0.6)}
#clear-btn svg{width:14px;height:14px}
@keyframes acSlideUp{
  from{opacity:0;transform:translateY(6px)}
  to{opacity:1;transform:none}
}
#autocomplete{
  position:absolute;bottom:100%;left:0;right:0;
  max-width:820px;margin:0 auto;
  background:rgba(16,16,18,0.98);backdrop-filter:blur(24px);
  -webkit-backdrop-filter:blur(24px);
  border:1px solid rgba(255,255,255,0.07);border-radius:14px;
  max-height:360px;overflow-y:auto;display:none;z-index:10;
  box-shadow:0 -12px 48px rgba(0,0,0,0.55),
    0 0 0 1px rgba(255,255,255,0.04),
    0 -2px 8px rgba(88,166,255,0.04);
  animation:acSlideUp 0.15s ease;
}
.ac-section{
  padding:7px 16px 5px;font-size:9.5px;font-weight:700;
  text-transform:uppercase;letter-spacing:0.08em;
  color:rgba(255,255,255,0.22);
  background:rgba(16,16,18,0.98);
  border-bottom:1px solid rgba(255,255,255,0.035);
  position:sticky;top:0;z-index:1;
}
.ac-item{
  padding:7px 16px;cursor:pointer;font-size:13px;
  border-bottom:1px solid rgba(255,255,255,0.02);
  display:flex;align-items:center;gap:10px;
  transition:background 0.1s,border-color 0.1s;
  border-left:2px solid transparent;
}
.ac-item:last-child{border-bottom:none}
.ac-item:hover{background:rgba(88,166,255,0.06)}
.ac-item.sel{
  background:rgba(88,166,255,0.1);
  border-left-color:rgba(88,166,255,0.7);
}
.ac-icon{
  flex-shrink:0;width:20px;height:20px;
  display:flex;align-items:center;justify-content:center;
  border-radius:5px;
  background:rgba(255,255,255,0.04);
  color:rgba(255,255,255,0.4);font-size:12px;
}
.ac-icon svg{width:13px;height:13px;stroke:currentColor;fill:none;
  stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}
.ac-item.sel .ac-icon{
  background:rgba(88,166,255,0.12);
  color:rgba(88,166,255,0.8);
}
.ac-text{
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
  color:rgba(255,255,255,0.55);flex:1;min-width:0;
  font-family:'SF Mono','Fira Code','Cascadia Code',monospace;
  font-size:12.5px;letter-spacing:-0.01em;
}
.ac-item.sel .ac-text{color:rgba(255,255,255,0.85)}
.ac-dir{color:rgba(255,255,255,0.3)}
.ac-fname{color:rgba(255,255,255,0.7)}
.ac-item.sel .ac-dir{color:rgba(255,255,255,0.45)}
.ac-item.sel .ac-fname{color:rgba(255,255,255,0.95)}
.ac-hl{color:rgba(88,166,255,0.95);font-weight:600}
.ac-hint{
  font-size:9px;color:rgba(255,255,255,0.18);
  background:rgba(255,255,255,0.04);
  border:1px solid rgba(255,255,255,0.05);
  padding:2px 7px;border-radius:4px;margin-left:auto;
  flex-shrink:0;
  font-family:'SF Mono','Fira Code',monospace;
}
.ac-item.sel .ac-hint{
  color:rgba(88,166,255,0.5);
  background:rgba(88,166,255,0.06);
  border-color:rgba(88,166,255,0.12);
}
.ac-footer{
  padding:6px 16px;font-size:10px;color:rgba(255,255,255,0.13);
  border-top:1px solid rgba(255,255,255,0.04);
  display:flex;gap:14px;
  background:rgba(16,16,18,0.98);
  position:sticky;bottom:0;
}
.ac-footer kbd{
  background:rgba(255,255,255,0.05);color:rgba(255,255,255,0.22);
  padding:1px 5px;border-radius:3px;font-size:9px;
  font-family:'SF Mono','Fira Code',monospace;
  border:1px solid rgba(255,255,255,0.04);
}
#welcome{
  display:flex;flex-direction:column;align-items:center;justify-content:center;
  min-height:100%;padding:40px 20px;text-align:center;max-width:820px;margin:0 auto;
}
#welcome h2{
  font-size:28px;font-weight:700;color:rgba(255,255,255,0.92);
  margin-bottom:8px;letter-spacing:-0.5px;
  animation:fadeUp 0.5s ease;
}
@keyframes fadeUp{from{opacity:0;transform:translateY(12px)}to{opacity:1;transform:none}}
#welcome p{color:rgba(255,255,255,0.4);font-size:14px;margin-bottom:36px;
  animation:fadeUp 0.5s ease 0.1s both}
#suggestions{animation:fadeUp 0.5s ease 0.2s both;
  display:grid;grid-template-columns:1fr 1fr;gap:12px;width:100%;max-width:760px;
}
.suggestion-chip{
  background:rgba(255,255,255,0.025);border:1px solid rgba(255,255,255,0.06);
  border-radius:12px;padding:14px 18px;cursor:pointer;text-align:left;
  font-size:13px;color:rgba(255,255,255,0.7);line-height:1.5;
  transition:all 0.2s ease;
}
.suggestion-chip:hover{
  background:rgba(255,255,255,0.055);border-color:rgba(255,255,255,0.14);
  color:rgba(255,255,255,0.9);transform:translateY(-2px);
  box-shadow:0 4px 24px rgba(0,0,0,0.35),0 0 0 1px rgba(255,255,255,0.05);
}
.suggestion-chip:active{transform:translateY(0);transition-duration:0.05s}
.chip-label{
  font-size:10px;font-weight:600;text-transform:uppercase;
  letter-spacing:0.04em;margin-bottom:5px;display:block;
}
.chip-label.recent{color:rgba(88,166,255,0.7)}
.chip-label.suggested{color:rgba(188,140,255,0.7)}
#sidebar{
  position:fixed;right:0;top:0;bottom:0;width:340px;
  background:rgba(12,12,14,0.95);backdrop-filter:blur(24px);
  border-left:1px solid rgba(255,255,255,0.06);
  transform:translateX(100%);transition:transform 0.3s cubic-bezier(0.4,0,0.2,1);
  z-index:200;overflow-y:auto;padding:24px;
}
#sidebar.open{transform:translateX(0)}
#sidebar-overlay{
  position:fixed;inset:0;background:rgba(0,0,0,0.4);
  z-index:199;opacity:0;pointer-events:none;transition:opacity 0.3s;
}
#sidebar-overlay.open{opacity:1;pointer-events:auto}
#history-btn,#proposals-btn{
  background:none;border:none;
  color:rgba(255,255,255,0.3);cursor:pointer;
  padding:4px;transition:color 0.15s;display:flex;align-items:center;
}
#history-btn:hover,#proposals-btn:hover{color:rgba(255,255,255,0.6)}
#sidebar-close{
  position:absolute;top:16px;right:16px;background:none;border:none;
  color:rgba(255,255,255,0.3);font-size:20px;cursor:pointer;
  padding:4px 8px;border-radius:6px;transition:all 0.15s;
}
#sidebar-close:hover{color:rgba(255,255,255,0.7);background:rgba(255,255,255,0.05)}
.sidebar-section{margin-bottom:28px}
.sidebar-hdr{
  font-size:11px;font-weight:600;text-transform:uppercase;
  letter-spacing:0.06em;color:rgba(255,255,255,0.25);margin-bottom:12px;
}
.sidebar-item{
  padding:10px 14px;background:rgba(255,255,255,0.02);
  border:1px solid rgba(255,255,255,0.04);border-radius:10px;
  margin-bottom:6px;cursor:pointer;font-size:13px;
  color:rgba(255,255,255,0.5);transition:all 0.15s;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
.sidebar-item:hover{
  border-color:rgba(255,255,255,0.1);background:rgba(255,255,255,0.04);
  color:rgba(255,255,255,0.8);
}
.sidebar-empty{color:rgba(255,255,255,0.2);font-size:13px;padding:8px 0}
#history-search{
  width:100%;background:rgba(255,255,255,0.04);
  border:1px solid rgba(255,255,255,0.08);border-radius:8px;
  color:rgba(255,255,255,0.8);font-size:12px;font-family:inherit;
  padding:8px 12px;outline:none;margin-bottom:12px;
  transition:border-color 0.2s;
}
#history-search:focus{border-color:rgba(88,166,255,0.4)}
#history-search::placeholder{color:rgba(255,255,255,0.25)}
.followup-bar{
  max-width:820px;margin:16px auto 8px;padding:12px 18px;
  background:rgba(188,140,255,0.04);
  border:1px solid rgba(188,140,255,0.15);border-radius:12px;
  cursor:pointer;transition:all 0.2s;display:flex;align-items:center;gap:10px;
}
.followup-bar:hover{
  background:rgba(188,140,255,0.08);
  border-color:rgba(188,140,255,0.3);
  transform:translateY(-1px);
  box-shadow:0 4px 20px rgba(188,140,255,0.08);
}
.fu-label{
  font-size:10px;font-weight:600;text-transform:uppercase;
  letter-spacing:0.04em;color:rgba(188,140,255,0.7);
  white-space:nowrap;flex-shrink:0;
}
.fu-text{
  font-size:13.5px;color:rgba(255,255,255,0.7);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
.llm-panel{
  border:1px solid rgba(88,166,255,0.15);border-radius:10px;
  margin:8px auto;max-height:350px;overflow-y:auto;
  padding:12px 16px;background:rgba(88,166,255,0.03);
  max-width:820px;
}
.llm-panel .txt{font-size:10px;line-height:1.5;color:rgba(255,255,255,0.6)}
.llm-panel .think .cnt{font-size:10px}
.bash-panel{
  max-width:820px;margin-left:auto;margin-right:auto;
  background:rgba(0,0,0,0.5);color:rgba(255,255,255,0.55);
  border-color:rgba(255,255,255,0.05);
}
#split-container{display:flex;height:100vh;width:100vw;overflow:hidden}
#editor-panel{position:relative;overflow:hidden}
#editor-panel iframe{
  width:125%;height:125%;border:none;
  transform:scale(0.8);transform-origin:0 0;
}
#editor-fallback{
  display:flex;flex-direction:column;align-items:center;justify-content:center;
  height:100%;background:#1e1e1e;color:rgba(255,255,255,0.7);
  font-size:14px;text-align:center;padding:40px;gap:4px;
}
#editor-fallback h3{color:rgba(255,255,255,0.9);margin-bottom:12px;font-size:20px}
#editor-fallback code{
  background:rgba(255,255,255,0.08);padding:8px 16px;border-radius:8px;
  display:block;margin:8px 0;font-size:13px;color:rgba(255,255,255,0.8);
}
#editor-fallback p{margin:4px 0;color:rgba(255,255,255,0.5);font-size:13px}
#merge-toolbar{
  display:none;position:absolute;bottom:12px;left:50%;transform:translateX(-50%);
  z-index:100;gap:4px;
  background:rgba(18,18,20,0.95);backdrop-filter:blur(12px);
  -webkit-backdrop-filter:blur(12px);
  border:1px solid rgba(255,255,255,0.15);border-radius:8px;
  padding:4px 8px;
  box-shadow:0 4px 24px rgba(0,0,0,0.5);
}
#merge-toolbar button{
  background:rgba(255,255,255,0.08);border:1px solid rgba(255,255,255,0.12);
  border-radius:4px;color:rgba(255,255,255,0.8);font-size:10px;
  padding:3px 8px;cursor:pointer;transition:all 0.15s;
  font-family:inherit;white-space:nowrap;
}
#merge-toolbar button:hover{
  background:rgba(88,166,255,0.15);border-color:rgba(88,166,255,0.3);color:#fff;
}
#divider{
  width:6px;flex-shrink:0;cursor:col-resize;
  background:rgba(255,255,255,0.06);position:relative;z-index:10;
  transition:background 0.15s;
}
#divider:hover,#divider.active{background:rgba(88,166,255,0.5)}
#divider::after{
  content:'';position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);
  width:2px;height:40px;background:rgba(255,255,255,0.2);border-radius:1px;
}
#assistant-panel{
  display:flex;flex-direction:column;overflow:hidden;min-width:300px;
  background:#0a0a0c;position:relative;
}
.tp[data-path]{cursor:pointer;text-decoration:underline dotted}
.tp[data-path]:hover{color:rgba(120,180,255,0.8);text-decoration:underline solid}
#assistant-panel{font-size:11px}
#assistant-panel header{padding:8px 12px}
#assistant-panel .logo{font-size:11px}
#assistant-panel .status{font-size:11px}
#assistant-panel #history-btn svg,#assistant-panel #proposals-btn svg{width:12px;height:12px}
#assistant-panel #welcome{padding:20px 14px}
#assistant-panel #welcome h2{font-size:17px;margin-bottom:3px;letter-spacing:-0.3px}
#assistant-panel #welcome p{font-size:11px;margin-bottom:14px}
#assistant-panel #suggestions{grid-template-columns:1fr;gap:5px;max-width:100%}
#assistant-panel .suggestion-chip{
  padding:7px 11px;border-radius:8px;font-size:11px;line-height:1.35;
}
#assistant-panel .chip-label{font-size:9px;margin-bottom:2px}
#assistant-panel #output{padding:14px 12px 12px}
#assistant-panel .ev,#assistant-panel .txt,#assistant-panel .spinner,
#assistant-panel .empty-msg,#assistant-panel .user-msg,
#assistant-panel .llm-panel,#assistant-panel .bash-panel,
#assistant-panel .followup-bar{max-width:none}
#assistant-panel .user-msg{
  font-size:11px;padding:10px 14px;margin:12px 0 10px;border-radius:10px;
}
#assistant-panel .txt{font-size:11px;padding:4px 10px}
#assistant-panel .tn{font-size:11px}
#assistant-panel .tp{font-size:11px}
#assistant-panel .tc{margin:8px 0;border-radius:8px}
#assistant-panel .tc-h{padding:7px 10px;border-radius:8px 8px 0 0}
#assistant-panel .tc-b{padding:6px 10px;max-height:200px;font-size:10px}
#assistant-panel .tr{padding:5px 10px;max-height:150px;font-size:10px}
#assistant-panel .think{padding:8px 12px;margin:8px 0;border-radius:8px}
#assistant-panel .think .cnt{font-size:10px}
#assistant-panel .rc{border-radius:10px}
#assistant-panel .rc-body{padding:10px 14px;max-height:250px;font-size:10px}
#assistant-panel #input-area{padding:0 12px 12px;padding-top:10px}
#assistant-panel #input-container{padding:8px 10px;border-radius:10px}
#assistant-panel #input-wrap{gap:4px}
#assistant-panel #task-input,#assistant-panel #ghost-overlay{font-size:11px}
#assistant-panel #input-footer{margin-top:5px;padding-top:5px}
#assistant-panel #model-btn{font-size:11px;padding:4px 8px;border-radius:6px}
#assistant-panel #model-search{font-size:11px;padding:7px 10px}
#assistant-panel .model-item{font-size:11px;padding:5px 10px}
#assistant-panel .model-cost{font-size:9px}
#assistant-panel .model-group-hdr{font-size:9px;padding:4px 10px 3px}
#assistant-panel #send-btn{width:28px;height:28px}
#assistant-panel #send-btn svg{width:12px;height:12px}
#assistant-panel #stop-btn{width:28px;height:28px}
#assistant-panel #stop-btn svg{width:11px;height:11px}
#assistant-panel #clear-btn{width:18px;height:18px}
#assistant-panel #clear-btn svg{width:11px;height:11px}
#assistant-panel #history-search{font-size:11px;padding:6px 10px}
#assistant-panel .sidebar-hdr{font-size:10px}
#assistant-panel .sidebar-item{font-size:11px;padding:7px 10px;border-radius:8px;margin-bottom:4px}
#assistant-panel .sidebar-empty{font-size:11px}
#assistant-panel #sidebar-close{font-size:17px}
#assistant-panel .ac-item{font-size:11px;padding:5px 12px}
#assistant-panel .ac-icon{width:17px;height:17px;border-radius:4px}
#assistant-panel .ac-icon svg{width:11px;height:11px}
#assistant-panel .ac-text{font-size:11px}
#assistant-panel .ac-section{font-size:8px;padding:5px 12px 3px}
#assistant-panel .ac-hint{font-size:8px;padding:1px 5px}
#assistant-panel .ac-footer{font-size:9px;padding:4px 12px}
#assistant-panel .ac-footer kbd{font-size:8px}
#assistant-panel .fu-label{font-size:9px}
#assistant-panel .fu-text{font-size:11px}
#assistant-panel .followup-bar{padding:8px 12px;margin:10px 0 6px;border-radius:8px}
#assistant-panel .llm-panel{padding:8px 10px;margin:6px 0;border-radius:8px}
#assistant-panel .llm-panel .txt{font-size:10px}
#assistant-panel .bash-panel{max-height:200px;font-size:10px}
#assistant-panel .prompt-h{font-size:10px;padding:6px 12px}
#assistant-panel .prompt-body{font-size:10px;padding:8px 12px}
#assistant-panel .rc-h{
  padding:10px 14px;flex-direction:column;align-items:flex-start;gap:6px;
}
#assistant-panel .rc-h h3{font-size:10px;margin-bottom:2px}
#assistant-panel .rs{
  font-size:10px;gap:0;width:100%;
  display:grid;grid-template-columns:repeat(3,1fr);
}
#assistant-panel .rs b{display:block;font-size:11px}
#assistant-panel .td{font-size:10px}
#assistant-panel .sys{font-size:11px}
#assistant-panel .spinner{font-size:11px}
#assistant-panel .empty-msg{font-size:11px}
#assistant-panel .rl{font-size:10px}
#assistant-panel .usage{font-size:11px}
"""

CHATBOT_THEME_CSS = r"""
body,#assistant-panel{
  --bg:#1e1e1e;--surface:#252526;--surface2:#2d2d2d;--border:#3c3c3c;
  --text:#d4d4d4;--dim:#858585;--accent:#3794ff;--green:#23d18b;
  --red:#f14c4c;--yellow:#d29922;--cyan:#29b8db;--purple:#b180d7;
  --bg-rgb:30,30,30;--bg2-rgb:37,37,38;--fg-rgb:212,212,212;
  --accent-rgb:55,148,255;--border-rgb:60,60,60;--green-rgb:35,209,139;
  --red-rgb:241,76,76;--purple-rgb:177,128,215;--cyan-rgb:41,184,219;
  --input-bg:#313131;
}
body{background:var(--bg)}
#assistant-panel{background:var(--bg)}
#assistant-panel header{
  background:rgba(var(--bg2-rgb),0.92);
  border-bottom:1px solid var(--border);
  box-shadow:0 1px 8px rgba(0,0,0,0.2);
}
#assistant-panel .logo{color:var(--accent)}
#assistant-panel .status{color:rgba(var(--fg-rgb),0.5)}
#assistant-panel .dot{background:rgba(var(--fg-rgb),0.35)}
#assistant-panel .dot.running{background:var(--green)}
#assistant-panel .user-msg{
  background:rgba(var(--fg-rgb),0.04);
  border:1px solid rgba(var(--fg-rgb),0.08);
  color:rgba(var(--fg-rgb),0.9);
}
#assistant-panel .txt{color:rgba(var(--fg-rgb),0.85)}
#assistant-panel .think{
  border:1px solid rgba(var(--purple-rgb),0.15);
  background:rgba(var(--purple-rgb),0.04);
}
#assistant-panel .think .lbl{color:rgba(var(--purple-rgb),0.8)}
#assistant-panel .think .cnt{color:rgba(var(--fg-rgb),0.4)}
#assistant-panel .tc{
  border:1px solid var(--border);
  background:rgba(var(--accent-rgb),0.02);
}
#assistant-panel .tc:hover{
  box-shadow:0 2px 16px rgba(var(--accent-rgb),0.06);
  border-color:rgba(var(--accent-rgb),0.25);
}
#assistant-panel .tc-h{
  background:rgba(var(--accent-rgb),0.04);
  border-bottom:1px solid rgba(var(--accent-rgb),0.08);
}
#assistant-panel .tc-h:hover{background:rgba(var(--accent-rgb),0.07)}
#assistant-panel .tn{color:var(--accent)}
#assistant-panel .tp{color:rgba(var(--cyan-rgb),0.7)}
#assistant-panel .td{color:rgba(var(--fg-rgb),0.35)}
#assistant-panel .tr{
  border:1px solid rgba(var(--green-rgb),0.2);
  background:rgba(var(--green-rgb),0.03);
}
#assistant-panel .tr.err{
  border-color:rgba(var(--red-rgb),0.2);
  background:rgba(var(--red-rgb),0.03);
}
#assistant-panel .rc{
  border:1px solid rgba(var(--green-rgb),0.25);
  background:rgba(var(--green-rgb),0.02);
}
#assistant-panel .rc-h{
  background:rgba(var(--green-rgb),0.06);
  border-bottom:1px solid rgba(var(--green-rgb),0.12);
}
#assistant-panel .usage{
  border:1px solid var(--border);background:rgba(var(--fg-rgb),0.02);
  color:rgba(var(--fg-rgb),0.35);
}
#assistant-panel .spinner{color:rgba(var(--fg-rgb),0.4)}
#assistant-panel .spinner::before{
  border-color:var(--border);border-top-color:rgba(var(--accent-rgb),0.7);
}
#assistant-panel #input-area{
  background:linear-gradient(transparent,rgba(var(--bg-rgb),0.95) 50%);
}
#assistant-panel #input-container{
  background:var(--input-bg);
  border:1px solid var(--border);
  box-shadow:0 0 0 1px rgba(var(--fg-rgb),0.02),0 4px 24px rgba(0,0,0,0.25);
}
#assistant-panel #input-container:focus-within{
  border-color:rgba(var(--accent-rgb),0.5);
  box-shadow:0 0 0 1px rgba(var(--accent-rgb),0.15),0 0 20px rgba(var(--accent-rgb),0.08),
    0 4px 24px rgba(0,0,0,0.25);
}
#assistant-panel #task-input{color:var(--text)}
#assistant-panel #task-input::placeholder{color:rgba(var(--fg-rgb),0.3)}
#assistant-panel .gs{color:rgba(var(--fg-rgb),0.4)}
#assistant-panel #input-footer{border-top:1px solid rgba(var(--fg-rgb),0.06)}
#assistant-panel #model-btn{
  background:rgba(var(--fg-rgb),0.04);color:rgba(var(--fg-rgb),0.5);
  border:1px solid var(--border);
}
#assistant-panel #model-btn:hover{
  border-color:rgba(var(--fg-rgb),0.2);color:rgba(var(--fg-rgb),0.7);
}
#assistant-panel #model-dropdown{
  background:rgba(var(--bg2-rgb),0.97);
  border:1px solid var(--border);box-shadow:0 -4px 24px rgba(0,0,0,0.4);
}
#assistant-panel #model-search{
  border-bottom:1px solid rgba(var(--fg-rgb),0.08);color:rgba(var(--fg-rgb),0.8);
}
#assistant-panel #model-search::placeholder{color:rgba(var(--fg-rgb),0.3)}
#assistant-panel .model-item{
  border-bottom:1px solid rgba(var(--fg-rgb),0.03);color:rgba(var(--fg-rgb),0.6);
}
#assistant-panel .model-item:hover,#assistant-panel .model-item.sel{
  background:rgba(var(--accent-rgb),0.1);
}
#assistant-panel .model-item.active{color:var(--accent)}
#assistant-panel .model-cost{color:rgba(var(--fg-rgb),0.25)}
#assistant-panel .model-group-hdr{
  color:rgba(var(--fg-rgb),0.3);background:rgba(var(--bg2-rgb),0.97);
  border-bottom:1px solid rgba(var(--fg-rgb),0.05);
}
#assistant-panel #send-btn{
  background:rgba(var(--accent-rgb),0.18);color:var(--accent);
}
#assistant-panel #send-btn:hover{
  background:rgba(var(--accent-rgb),0.35);color:#fff;
  box-shadow:0 0 12px rgba(var(--accent-rgb),0.2);
}
#assistant-panel #stop-btn{
  background:rgba(var(--red-rgb),0.12);color:var(--red);
  border:1px solid rgba(var(--red-rgb),0.2);
}
#assistant-panel #stop-btn:hover{
  background:rgba(var(--red-rgb),0.25);
  box-shadow:0 0 12px rgba(var(--red-rgb),0.15);
}
#assistant-panel #clear-btn{color:rgba(var(--fg-rgb),0.25)}
#assistant-panel #clear-btn:hover{color:rgba(var(--fg-rgb),0.6)}
#assistant-panel #autocomplete{
  background:rgba(var(--bg2-rgb),0.97);border:1px solid var(--border);
  box-shadow:0 -4px 24px rgba(0,0,0,0.4);
}
#assistant-panel .ac-section{
  color:rgba(var(--fg-rgb),0.25);background:rgba(var(--bg2-rgb),0.97);
  border-bottom:1px solid rgba(var(--fg-rgb),0.04);
}
#assistant-panel .ac-item{
  border-bottom:1px solid rgba(var(--fg-rgb),0.03);
  border-left:2px solid transparent;
}
#assistant-panel .ac-item:hover{
  background:rgba(var(--accent-rgb),0.06);
}
#assistant-panel .ac-item.sel{
  background:rgba(var(--accent-rgb),0.1);
  border-left-color:var(--accent);
}
#assistant-panel .ac-icon{
  background:rgba(var(--fg-rgb),0.05);
  color:rgba(var(--fg-rgb),0.4);
}
#assistant-panel .ac-item.sel .ac-icon{
  background:rgba(var(--accent-rgb),0.12);
  color:var(--accent);
}
#assistant-panel .ac-text{color:rgba(var(--fg-rgb),0.55)}
#assistant-panel .ac-item.sel .ac-text{
  color:rgba(var(--fg-rgb),0.9);
}
#assistant-panel .ac-dir{color:rgba(var(--fg-rgb),0.3)}
#assistant-panel .ac-fname{color:rgba(var(--fg-rgb),0.7)}
#assistant-panel .ac-item.sel .ac-dir{
  color:rgba(var(--fg-rgb),0.45);
}
#assistant-panel .ac-item.sel .ac-fname{
  color:rgba(var(--fg-rgb),0.95);
}
#assistant-panel .ac-hl{color:var(--accent)}
#assistant-panel .ac-hint{
  color:rgba(var(--fg-rgb),0.2);
  background:rgba(var(--fg-rgb),0.04);
  border-color:rgba(var(--fg-rgb),0.06);
}
#assistant-panel .ac-item.sel .ac-hint{
  color:rgba(var(--accent-rgb),0.5);
  background:rgba(var(--accent-rgb),0.06);
  border-color:rgba(var(--accent-rgb),0.12);
}
#assistant-panel .ac-footer{
  color:rgba(var(--fg-rgb),0.15);
  border-top:1px solid rgba(var(--fg-rgb),0.05);
  background:rgba(var(--bg2-rgb),0.98);
}
#assistant-panel .ac-footer kbd{
  background:rgba(var(--fg-rgb),0.06);
  color:rgba(var(--fg-rgb),0.25);
  border:1px solid rgba(var(--fg-rgb),0.04);
}
#assistant-panel #welcome h2{color:var(--text)}
#assistant-panel #welcome p{color:rgba(var(--fg-rgb),0.45)}
#assistant-panel .suggestion-chip{
  background:rgba(var(--fg-rgb),0.03);
  border:1px solid rgba(var(--fg-rgb),0.07);color:rgba(var(--fg-rgb),0.7);
}
#assistant-panel .suggestion-chip:hover{
  background:rgba(var(--fg-rgb),0.07);
  border-color:rgba(var(--fg-rgb),0.15);color:rgba(var(--fg-rgb),0.9);
  box-shadow:0 4px 20px rgba(0,0,0,0.25);
}
#assistant-panel .chip-label.recent{color:rgba(var(--accent-rgb),0.75)}
#assistant-panel .chip-label.suggested{color:rgba(var(--purple-rgb),0.75)}
#assistant-panel #sidebar{
  background:rgba(var(--bg2-rgb),0.97);border-left:1px solid var(--border);
}
#assistant-panel #sidebar-overlay{background:rgba(0,0,0,0.35)}
#assistant-panel #history-btn,#assistant-panel #proposals-btn{
  color:rgba(var(--fg-rgb),0.35);
}
#assistant-panel #history-btn:hover,#assistant-panel #proposals-btn:hover{
  color:rgba(var(--fg-rgb),0.6);
}
#assistant-panel #sidebar-close{color:rgba(var(--fg-rgb),0.35)}
#assistant-panel #sidebar-close:hover{
  color:rgba(var(--fg-rgb),0.7);background:rgba(var(--fg-rgb),0.06);
}
#assistant-panel .sidebar-hdr{color:rgba(var(--fg-rgb),0.3)}
#assistant-panel .sidebar-item{
  background:rgba(var(--fg-rgb),0.02);border:1px solid rgba(var(--fg-rgb),0.05);
  color:rgba(var(--fg-rgb),0.5);
}
#assistant-panel .sidebar-item:hover{
  border-color:rgba(var(--fg-rgb),0.12);background:rgba(var(--fg-rgb),0.05);
  color:rgba(var(--fg-rgb),0.8);
}
#assistant-panel .sidebar-empty{color:rgba(var(--fg-rgb),0.25)}
#assistant-panel #history-search{
  background:rgba(var(--fg-rgb),0.04);border:1px solid var(--border);
  color:rgba(var(--fg-rgb),0.8);
}
#assistant-panel #history-search:focus{border-color:rgba(var(--accent-rgb),0.5)}
#assistant-panel #history-search::placeholder{color:rgba(var(--fg-rgb),0.3)}
#assistant-panel .followup-bar{
  background:rgba(var(--purple-rgb),0.05);
  border:1px solid rgba(var(--purple-rgb),0.18);
}
#assistant-panel .followup-bar:hover{
  background:rgba(var(--purple-rgb),0.1);
  border-color:rgba(var(--purple-rgb),0.3);
  box-shadow:0 4px 16px rgba(var(--purple-rgb),0.08);
}
#assistant-panel .fu-label{color:rgba(var(--purple-rgb),0.75)}
#assistant-panel .fu-text{color:rgba(var(--fg-rgb),0.7)}
#assistant-panel .llm-panel{
  border:1px solid rgba(var(--accent-rgb),0.15);
  background:rgba(var(--accent-rgb),0.03);
}
#assistant-panel .llm-panel .txt{color:rgba(var(--fg-rgb),0.6)}
#assistant-panel .bash-panel{
  background:rgba(0,0,0,0.35);color:rgba(var(--fg-rgb),0.6);
  border-color:var(--border);
}
#divider{background:var(--border)}
#divider:hover,#divider.active{background:var(--accent)}
#editor-fallback{background:var(--bg);color:rgba(var(--fg-rgb),0.7)}
#merge-toolbar{
  background:rgba(var(--bg2-rgb),0.95);border:1px solid var(--border);
  box-shadow:0 4px 24px rgba(0,0,0,0.4);
}
#merge-toolbar button{
  background:rgba(var(--fg-rgb),0.08);border:1px solid rgba(var(--fg-rgb),0.12);
  color:rgba(var(--fg-rgb),0.8);
}
#merge-toolbar button:hover{
  background:rgba(var(--accent-rgb),0.15);
  border-color:rgba(var(--accent-rgb),0.3);color:#fff;
}
#assistant-panel .prompt-h{
  background:rgba(var(--cyan-rgb),0.08);color:var(--cyan);
}
"""

CHATBOT_JS = r"""
var O=document.getElementById('output');
var D=document.getElementById('dot');
var ST=document.getElementById('stxt');
var inp=document.getElementById('task-input');
var btn=document.getElementById('send-btn');
var stopBtn=document.getElementById('stop-btn');
var clearBtn=document.getElementById('clear-btn');
var ac=document.getElementById('autocomplete');var rl=document.getElementById('recent-list');
var pl=document.getElementById('proposed-list');
var histSearch=document.getElementById('history-search');
var allTasks=[];
var modelLabel=document.getElementById('model-label');
var modelDD=document.getElementById('model-dropdown');
var modelSearch=document.getElementById('model-search');
var modelList=document.getElementById('model-list');
var allModels=[],selectedModel='',modelDDIdx=-1;
var sidebar=document.getElementById('sidebar');
var sidebarOverlay=document.getElementById('sidebar-overlay');
var suggestionsEl=document.getElementById('suggestions');
var running=false,_scrollLock=false;
var scrollRaf=0,state=mkS();
var acIdx=-1,t0=null,timerIv=null,evtSrc=null;
var acTimer=null,histIdx=-1,histCache=[];
var lastToolName='',llmPanel=null,pendingPanel=false;
var llmPanelState=mkS();
var ghostEl=document.getElementById('ghost-overlay');
var ghostSuggest='',ghostTimer2=null,ghostAbort=null;
var ghostCache={q:'',s:''};
var fileInput=document.getElementById('file-input');
var uploadBtn=document.getElementById('upload-btn');
var fileChips=document.getElementById('file-chips');
var pendingFiles=[];
uploadBtn.addEventListener('click',function(){if(!running)fileInput.click()});
fileInput.addEventListener('change',function(){
  Array.from(this.files||[]).forEach(function(f){
    var reader=new FileReader();
    reader.onload=function(){
      var b64=reader.result.split(',')[1];
      pendingFiles.push({name:f.name,mime_type:f.type,data:b64,url:reader.result});
      renderFileChips();
    };
    reader.readAsDataURL(f);
  });
  this.value='';
});
function renderFileChips(){
  fileChips.innerHTML='';
  pendingFiles.forEach(function(f,i){
    var chip=document.createElement('span');chip.className='file-chip';
    if(f.mime_type.startsWith('image/')){
      var img=document.createElement('img');img.src=f.url;chip.appendChild(img);
    }else{
      var icon=document.createElement('span');
      icon.className='fc-icon';icon.textContent='\ud83d\udcc4';
      chip.appendChild(icon);
    }
    var label=document.createElement('span');label.textContent=f.name;chip.appendChild(label);
    var rm=document.createElement('span');rm.className='fc-rm';rm.textContent='\u00d7';
    rm.onclick=function(){pendingFiles.splice(i,1);renderFileChips()};
    chip.appendChild(rm);
    fileChips.appendChild(chip);
  });
}
function recordFileUsage(path){
  fetch('/record-file-usage',{
    method:'POST',
    headers:{'Content-Type':'application/json'},
    body:JSON.stringify({path:path})
  }).catch(function(){});
}
function mkS(){return{thinkEl:null,txtEl:null,bashPanel:null}}
inp.addEventListener('input',function(){
  this.style.height='auto';
  this.style.height=Math.min(this.scrollHeight,200)+'px';
  histIdx=-1;
  clearGhost();
  if(getAtCtx()){
    if(acTimer)clearTimeout(acTimer);
    acTimer=setTimeout(fetchAC,150);
  } else {
    hideAC();
    if(ghostTimer2)clearTimeout(ghostTimer2);
    ghostTimer2=setTimeout(fetchGhost,200);
  }
});
var sidebarHistSec=document.getElementById('sidebar-history-sec');
var sidebarPropSec=document.getElementById('sidebar-proposals-sec');
function toggleSidebar(mode){
  if(mode){
    sidebarHistSec.style.display=mode==='proposals'?'none':'';
    sidebarPropSec.style.display=mode==='history'?'none':'';
    if(sidebar.classList.contains('open'))return;
  }
  sidebar.classList.toggle('open');
  sidebarOverlay.classList.toggle('open');
}
O.addEventListener('wheel',function(e){
  if(running&&e.deltaY<0)_scrollLock=true;
});
O.addEventListener('scroll',function(){
  if(_scrollLock){
    var atBottom=O.scrollTop+O.clientHeight>=O.scrollHeight-150;
    if(atBottom)_scrollLock=false;
  }
});
function sb(){
  if(!_scrollLock&&!scrollRaf){scrollRaf=requestAnimationFrame(function(){
    O.scrollTo({top:O.scrollHeight,behavior:'instant'});scrollRaf=0;
  });}
}
new MutationObserver(function(){sb()}).observe(O,{childList:true,subtree:true,characterData:true});
function startTimer(){
  t0=Date.now();
  if(timerIv)clearInterval(timerIv);
  timerIv=setInterval(function(){
    var s=Math.floor((Date.now()-t0)/1000);
    var m=Math.floor(s/60);
    ST.textContent='Running '+(m>0?m+'m ':'')+s%60+'s';
  },1000);
}
function stopTimer(){if(timerIv){clearInterval(timerIv);timerIv=null;}}
var _spinnerTimer=null;
function removeSpinner(){
  if(_spinnerTimer){clearTimeout(_spinnerTimer);_spinnerTimer=null;}
  var sp=document.getElementById('wait-spinner');
  if(sp)sp.remove();
}
function showSpinner(msg){
  removeSpinner();
  _spinnerTimer=setTimeout(function(){
    _spinnerTimer=null;
    var sp=mkEl('div','spinner');
    sp.id='wait-spinner';
    sp.textContent=msg||'Waiting ...';
    O.appendChild(sp);sb();
  },250);
}
function setReady(label){
  running=false;D.classList.remove('running');
  stopTimer();removeSpinner();
  ST.textContent=label||'Ready';
  inp.disabled=false;
  btn.style.display='';
  stopBtn.style.display='none';
  inp.focus();
}
function connectSSE(){
  if(evtSrc)evtSrc.close();
  evtSrc=new EventSource('/events');
  evtSrc.onopen=function(){};
  evtSrc.onmessage=function(e){
    var ev;try{ev=JSON.parse(e.data);}catch(x){return;}
    try{handleEvent(ev);}catch(err){console.error('Event error:',err,ev);}
  };
  evtSrc.onerror=function(){};
}
function handleEvent(ev){
  var t=ev.type;
  if(t==='thinking_start'||t==='thinking_delta'||t==='text_delta'
    ||t==='tool_call'||t==='tool_result'||t==='system_output'
    ||t==='task_done'||t==='task_error'||t==='task_stopped'
    ||t==='prompt')removeSpinner();
  switch(t){
  case'tasks_updated':loadTasks();loadWelcome();break;
  case'proposed_updated':loadProposed();loadWelcome();break;
  case'theme_changed':applyTheme(ev);break;
  case'merge_started':document.getElementById('merge-toolbar').style.display='flex';break;
  case'merge_ended':document.getElementById('merge-toolbar').style.display='none';inp.focus();break;
  case'clear':
    O.innerHTML='';state=mkS();
    llmPanel=null;llmPanelState=mkS();lastToolName='';pendingPanel=false;
    _scrollLock=false;showSpinner();break;
  case'task_done':{
    var el=t0?Math.floor((Date.now()-t0)/1000):0;
    var em=Math.floor(el/60);
    setReady('Done ('+(em>0?em+'m ':'')+el%60+'s)');
    loadTasks();break}
  case'followup_suggestion':{
    var fu=mkEl('div','followup-bar');
    fu.title=ev.text;
    fu.innerHTML='<span class="fu-label">Suggested next</span>'
      +'<span class="fu-text">'+esc(ev.text)+'</span>';
    fu.addEventListener('click',function(){
      inp.value=ev.text;inp.focus();
    });
    O.appendChild(fu);sb();break}
  case'task_error':{
    var err=mkEl('div','ev tr err');
    err.innerHTML='<div class="rl fail">ERROR</div>'+esc(ev.text||'Unknown error');
    O.appendChild(err);
    setReady('Error');loadTasks();loadProposed();break}
  case'task_stopped':{
    var stEl=mkEl('div','ev tr err');
    stEl.innerHTML='<div class="rl fail">STOPPED</div>Agent execution stopped by user';
    O.appendChild(stEl);
    setReady('Stopped');loadTasks();loadProposed();break}
  default:{
    if(t==='tool_call'){
      lastToolName=ev.name||'';
      llmPanel=null;llmPanelState=mkS();pendingPanel=false;
    }
    if(t==='tool_result'&&lastToolName!=='finish'){pendingPanel=true;}
    if(pendingPanel&&(t==='thinking_start'||t==='text_delta')){
      llmPanel=mkEl('div','llm-panel');
      O.appendChild(llmPanel);
      llmPanelState=mkS();pendingPanel=false;
    }
    var target=O,tState=state;
    if(llmPanel&&(t==='thinking_start'||t==='thinking_delta'||t==='thinking_end'
      ||t==='text_delta'||t==='text_end')){
      target=llmPanel;tState=llmPanelState;
    }
    handleOutputEvent(ev,target,tState);
    if(target===llmPanel)llmPanel.scrollTop=llmPanel.scrollHeight;
    if(running)showSpinner();
  }}
  sb();
}
function loadModels(){
  fetch('/models').then(function(r){return r.json();})
  .then(function(d){
    allModels=d.models;
    selectedModel=d.selected;
    modelLabel.textContent=selectedModel;
    renderModelList('');
  }).catch(function(){});
}
function modelVendor(name){
  if(name.startsWith('claude-'))return'Anthropic';
  if(/^(gpt|o[134]|codex|computer-use)/.test(name)&&!name.startsWith('openai/'))return'OpenAI';
  if(name.startsWith('gemini-'))return'Gemini';
  if(name.startsWith('minimax-'))return'MiniMax';
  if(name.startsWith('openrouter/'))return'OpenRouter';
  return'Together AI';
}
function renderModelItem(m){
  var d=mkEl('div','model-item'+(m.name===selectedModel?' active':''));
  var price='$'+m.inp.toFixed(2)+' / $'+m.out.toFixed(2);
  d.innerHTML='<span>'+esc(m.name)+'</span><span class="model-cost">'+price+'</span>';
  d.addEventListener('click',function(){selectModel(m.name)});
  return d;
}
function renderModelList(q){
  modelList.innerHTML='';modelDDIdx=-1;
  var ql=q.toLowerCase();
  var used=[],rest=[];
  allModels.forEach(function(m){
    if(ql&&m.name.toLowerCase().indexOf(ql)<0)return;
    if(m.uses>0)used.push(m);else rest.push(m);
  });
  used.sort(function(a,b){return b.uses-a.uses});
  if(used.length){
    var hdr=mkEl('div','model-group-hdr');
    hdr.textContent='Recently Used';
    modelList.appendChild(hdr);
    used.forEach(function(m){modelList.appendChild(renderModelItem(m))});
  }
  var lastVendor='';
  rest.forEach(function(m){
    var v=modelVendor(m.name);
    if(v!==lastVendor){
      var hdr=mkEl('div','model-group-hdr');
      hdr.textContent=v;
      modelList.appendChild(hdr);
      lastVendor=v;
    }
    modelList.appendChild(renderModelItem(m));
  });
}
function selectModel(name){
  selectedModel=name;
  modelLabel.textContent=name;
  closeModelDD();
  renderModelList('');
}
function toggleModelDD(){
  if(modelDD.classList.contains('open')){closeModelDD();return}
  modelDD.classList.add('open');
  modelSearch.value='';
  renderModelList('');
  modelSearch.focus();
}
function closeModelDD(){
  modelDD.classList.remove('open');
  modelSearch.value='';
  modelDDIdx=-1;
}
modelSearch.addEventListener('input',function(){renderModelList(this.value)});
modelSearch.addEventListener('keydown',function(e){
  var items=modelList.querySelectorAll('.model-item');
  if(e.key==='ArrowDown'){e.preventDefault();modelDDIdx=Math.min(modelDDIdx+1,items.length-1);updateModelSel(items);return}
  if(e.key==='ArrowUp'){e.preventDefault();modelDDIdx=Math.max(modelDDIdx-1,-1);updateModelSel(items);return}
  if(e.key==='Enter'){e.preventDefault();var ti=modelDDIdx>=0?modelDDIdx:0;
  if(items[ti])items[ti].click();return}
  if(e.key==='Escape'){e.preventDefault();closeModelDD();return}
});
function updateModelSel(items){
  items.forEach(function(it,i){it.classList.toggle('sel',i===modelDDIdx)});
  if(modelDDIdx>=0)items[modelDDIdx].scrollIntoView({block:'nearest'});
}
document.addEventListener('click',function(e){
  if(!document.getElementById('model-picker').contains(e.target))closeModelDD();
  if(!ac.contains(e.target)&&e.target!==inp)hideAC();
});
function submitTask(){
  var task=inp.value.trim();
  if(!task||running)return;
  var fileMatch=task.match(/^@(\S+)$/);
  if(fileMatch){openInEditor(fileMatch[1]);inp.value='';return}
  running=true;inp.disabled=true;
  btn.style.display='none';
  stopBtn.style.display='inline-flex';
  D.classList.add('running');hideAC();startTimer();
  inp.style.height='auto';
  var payload={task:task,model:selectedModel};
  if(pendingFiles.length>0){
    payload.attachments=pendingFiles.map(function(f){return{mime_type:f.mime_type,data:f.data}});
  }
  fetch('/run',{
    method:'POST',
    headers:{'Content-Type':'application/json'},
    body:JSON.stringify(payload)
  }).then(function(r){
    if(!r.ok){r.json().then(function(d){setReady('Error');alert(d.error||'Failed')});return;}
    inp.value='';pendingFiles=[];renderFileChips();loadModels();
  }).catch(function(){setReady('Error');alert('Network error')});
}
btn.addEventListener('click',submitTask);
stopBtn.addEventListener('click',function(){fetch('/stop',{method:'POST'}).catch(function(){})});
clearBtn.addEventListener('click',function(){
  if(running)return;
  O.innerHTML='<div id="welcome"><h2>What can I help you with?</h2>'
    +'<p>Describe a task and the agent will work on it</p>'
    +'<div id="suggestions"></div></div>';
  suggestionsEl=document.getElementById('suggestions');
  state=mkS();
  llmPanel=null;llmPanelState=mkS();
  lastToolName='';pendingPanel=false;_scrollLock=false;
  pendingFiles=[];renderFileChips();
  loadWelcome();inp.value='';inp.focus();
});
var inputContainer=document.getElementById('input-container');
['dragenter','dragover'].forEach(function(ev){inputContainer.addEventListener(ev,function(e){
  e.preventDefault();e.stopPropagation();inputContainer.style.borderColor='rgba(88,166,255,0.5)';
})});
['dragleave','drop'].forEach(function(ev){inputContainer.addEventListener(ev,function(e){
  e.preventDefault();e.stopPropagation();inputContainer.style.borderColor='';
})});
inputContainer.addEventListener('drop',function(e){
  if(running)return;
  var files=e.dataTransfer&&e.dataTransfer.files;
  if(!files)return;
  Array.from(files).forEach(function(f){
    var ok=['image/jpeg','image/png','image/gif','image/webp','application/pdf'];
    if(ok.indexOf(f.type)<0)return;
    var reader=new FileReader();
    reader.onload=function(){
      var b64=reader.result.split(',')[1];
      pendingFiles.push({name:f.name,mime_type:f.type,data:b64,url:reader.result});
      renderFileChips();
    };
    reader.readAsDataURL(f);
  });
});
inputContainer.addEventListener('paste',function(e){
  if(running)return;
  var items=e.clipboardData&&e.clipboardData.items;
  if(!items)return;
  var dominated=false;
  var ok=[
    'image/jpeg','image/png','image/gif','image/webp',
    'application/pdf'
  ];
  Array.from(items).forEach(function(item){
    if(ok.indexOf(item.type)<0)return;
    var file=item.getAsFile();if(!file)return;
    dominated=true;
    var reader=new FileReader();
    reader.onload=function(){
      var b64=reader.result.split(',')[1];
      var name=file.name||('pasted.'+item.type.split('/')[1]);
      pendingFiles.push({
        name:name,mime_type:item.type,data:b64,
        url:reader.result
      });
      renderFileChips();
    };
    reader.readAsDataURL(file);
  });
  if(dominated)e.preventDefault();
});
inp.addEventListener('keydown',function(e){
  if(ac.style.display==='block'){
    var items=ac.querySelectorAll('.ac-item');
    if(e.key==='ArrowDown'){e.preventDefault();acIdx=Math.min(acIdx+1,items.length-1);updateACSel(items);return}
    if(e.key==='ArrowUp'){e.preventDefault();acIdx=Math.max(acIdx-1,-1);updateACSel(items);return}
    if(e.key==='Tab'){e.preventDefault();var ti=acIdx>=0?acIdx:0;
      if(items[ti])items[ti].click();return}
    if(e.key==='Enter'&&acIdx>=0){e.preventDefault();items[acIdx].click();return}
    if(e.key==='Escape'){hideAC();return}
  }
  if(ghostSuggest){
    if(e.key==='Tab'){e.preventDefault();acceptGhost();return}
    if(e.key==='ArrowRight'&&inp.selectionStart===inp.value.length){e.preventDefault();acceptGhost();return}
    if(e.key==='Escape'){clearGhost();return}
  }
  if(e.key==='ArrowUp'&&ac.style.display!=='block'&&(!inp.value.trim()||histIdx>=0)){
    e.preventDefault();cycleHistory(1);return;
  }
  if(e.key==='ArrowDown'&&histIdx>=0&&ac.style.display!=='block'){
    e.preventDefault();cycleHistory(-1);return;
  }
  if(e.key==='Enter'&&!e.shiftKey){e.preventDefault();submitTask()}
});
function getAtCtx(){
  var val=inp.value,pos=inp.selectionStart||0;
  var before=val.substring(0,pos);
  var m=before.match(/@([^\s]*)$/);
  return m?{start:before.length-m[0].length,query:m[1]}:null;
}
function fetchAC(){
  var atCtx=getAtCtx();
  if(!atCtx){hideAC();return}
  fetch('/suggestions?mode=files&q='+encodeURIComponent(atCtx.query))
    .then(function(r){return r.json()}).then(renderAC).catch(function(){hideAC()});
}
function hlMatch(text,query){
  if(!query)return esc(text);
  var idx=text.toLowerCase().indexOf(query.toLowerCase());
  if(idx<0)return esc(text);
  return esc(text.substring(0,idx))
    +'<strong class="ac-hl">'+esc(text.substring(idx,idx+query.length))+'</strong>'
    +esc(text.substring(idx+query.length));
}
var _acSvg={
  dir:'<svg viewBox="0 0 24 24"><path d="M22 19a2 2 0 01-2 2H4a2'
    +' 2 0 01-2-2V5a2 2 0 012-2h5l2 3h9a2 2 0 012 2z"/></svg>',
  file:'<svg viewBox="0 0 24 24"><path d="M14 2H6a2 2 0 00-2'
    +' 2v16a2 2 0 002 2h12a2 2 0 002-2V8z"/>'
    +'<polyline points="14 2 14 8 20 8"/></svg>',
  star:'<svg viewBox="0 0 24 24"><path d="M12 2l3.09 6.26L22'
    +' 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7'
    +' 14.14 2 9.27l6.91-1.01L12 2z"/></svg>'
};
function _acIcon(type){
  if(type.startsWith('frequent_'))return _acSvg.star;
  return _acSvg[type]||_acSvg.file;
}
function _acPathHtml(text,query){
  var last=text.lastIndexOf('/');
  if(last<0||last===text.length-1)return hlMatch(text,query);
  var dir=text.substring(0,last+1);
  var fname=text.substring(last+1);
  return '<span class="ac-dir">'+esc(dir)+'</span>'
    +'<span class="ac-fname">'+esc(fname)+'</span>';
}
function renderAC(data){
  if(!data.length){hideAC();return}
  ac.innerHTML='';acIdx=-1;
  var atCtx=getAtCtx();
  var searchQ=atCtx?atCtx.query:'';
  var order=[
    'frequent_dir','frequent_file','dir','file'
  ];
  var labels={
    frequent_dir:'Frequent',frequent_file:'Frequent',
    dir:'Directories',file:'Files'
  };
  var groups={};
  data.forEach(function(item){
    var t=item.type;
    if(!groups[t])groups[t]=[];
    groups[t].push(item);
  });
  var isFirst=true;
  var shownFrequent=false;
  order.forEach(function(type){
    var g=groups[type];if(!g)return;
    var lbl=labels[type]||type;
    if(type.startsWith('frequent_')){
      if(shownFrequent)lbl=null;
      shownFrequent=true;
    }
    if(lbl){
      var hdr=mkEl('div','ac-section');
      hdr.textContent=lbl;ac.appendChild(hdr);
    }
    g.forEach(function(item){
      var baseType=item.type.replace('frequent_','');
      var d=mkEl('div','ac-item');
      var useSearch=searchQ&&searchQ.length>0;
      var textHtml=useSearch
        ?hlMatch(item.text,searchQ)
        :_acPathHtml(item.text,searchQ);
      d.innerHTML='<span class="ac-icon">'
        +_acIcon(item.type)+'</span>'
        +'<span class="ac-text">'+textHtml+'</span>';
      if(isFirst){
        d.innerHTML+='<span class="ac-hint">tab</span>';
        isFirst=false;
      }
      d.addEventListener('click',function(){
        selectAC({type:baseType,text:item.text});
      });
      ac.appendChild(d);
    });
  });
  var footer=mkEl('div','ac-footer');
  footer.innerHTML='<span><kbd>\u2191\u2193</kbd> navigate</span>'
    +'<span><kbd>Tab</kbd> accept</span>'
    +'<span><kbd>Esc</kbd> dismiss</span>';
  ac.appendChild(footer);
  ac.style.display='block';
  acIdx=0;
  var allItems=ac.querySelectorAll('.ac-item');
  updateACSel(allItems);
}
function selectAC(item){
  var atCtx=getAtCtx();
  if(atCtx){
    var before=inp.value.substring(0,atCtx.start);
    var after=inp.value.substring(
      inp.selectionStart||inp.value.length
    );
    var sep=(!after||/^\s/.test(after))?'':' ';
    inp.value=before+'@'+item.text+sep+after;
    var np=before.length+1+item.text.length+sep.length;
    inp.setSelectionRange(np,np);
    recordFileUsage(item.text);
  }
  hideAC();inp.focus();
}
function hideAC(){ac.style.display='none';acIdx=-1}
function updateACSel(items){
  items.forEach(function(it,i){it.classList.toggle('sel',i===acIdx)});
  if(acIdx>=0)items[acIdx].scrollIntoView({block:'nearest'});
}
function clearGhost(){ghostSuggest='';ghostEl.innerHTML=''}
function updateGhost(){
  if(!ghostSuggest){ghostEl.innerHTML='';return}
  ghostEl.innerHTML='<span class="gm">'+esc(inp.value)+'</span>'
    +'<span class="gs">'+esc(ghostSuggest)+'</span>';
}
function acceptGhost(){
  inp.value+=ghostSuggest;  clearGhost();inp.focus();
}
function fetchGhost(){
  var q=inp.value;  if(!q.trim()||q.trim().length<2){clearGhost();return}
  if(ghostCache.q&&q.startsWith(ghostCache.q)&&ghostCache.s){
    var extra=q.substring(ghostCache.q.length);
    if(ghostCache.s.startsWith(extra)){
      ghostSuggest=ghostCache.s.substring(extra.length);
      if(ghostSuggest){updateGhost();return}
    }
  }
  if(ghostAbort)ghostAbort.abort();
  ghostAbort=new AbortController();
  fetch('/complete?q='+encodeURIComponent(q),{signal:ghostAbort.signal})
    .then(function(r){return r.json()})
    .then(function(d){
      if(d.suggestion&&inp.value===q){
        ghostSuggest=d.suggestion;
        ghostCache={q:q,s:d.suggestion};
        updateGhost();
      }
    }).catch(function(){});
}
function cycleHistory(dir){
  if(!histCache.length){
    fetch('/tasks').then(function(r){return r.json()}).then(function(tasks){
      histCache=tasks.map(function(t){return typeof t==='string'?t:(t.task||'')});
      doHistCycle(dir);
    });return;
  }
  doHistCycle(dir);
}
function doHistCycle(dir){
  histIdx+=dir;
  if(histIdx<0){histIdx=-1;inp.value='';return}
  if(histIdx>=histCache.length){histIdx=histCache.length-1;return}
  inp.value=histCache[histIdx];
}
function loadTasks(){
  fetch('/tasks').then(function(r){return r.json()}).then(function(tasks){
    allTasks=tasks;renderTasks('');histSearch.value='';
  }).catch(function(){});
}
function renderTasks(q){
  rl.innerHTML='';
  var ql=q.toLowerCase(),filtered=[];
  allTasks.forEach(function(t){
    var txt=typeof t==='string'?t:(t.task||'');
    if(!ql||txt.toLowerCase().indexOf(ql)>=0)filtered.push(txt);
  });
  if(!filtered.length){rl.innerHTML='<div class="sidebar-empty">'
    +(ql?'No matches':'No recent tasks')+'</div>';return}
  filtered.forEach(function(taskText){
    var d=mkEl('div','sidebar-item');
    d.textContent=taskText;d.title=taskText;
    d.addEventListener('click',function(){inp.value=taskText;inp.focus();toggleSidebar()});
    rl.appendChild(d);
  });
}
histSearch.addEventListener('input',function(){renderTasks(this.value)});
function loadProposed(){
  fetch('/proposed_tasks').then(function(r){return r.json()}).then(function(tasks){
    pl.innerHTML='';
    if(!tasks.length){pl.innerHTML='<div class="sidebar-empty">No suggestions yet</div>';return}
    tasks.forEach(function(t){
      var d=mkEl('div','sidebar-item');
      d.textContent=t;d.title=t;
      d.addEventListener('click',function(){inp.value=t;inp.focus();toggleSidebar()});
      pl.appendChild(d);
    });
  }).catch(function(){});
}
function loadWelcome(){
  if(!suggestionsEl)return;
  Promise.all([
    fetch('/tasks').then(function(r){return r.json()}).catch(function(){return []}),
    fetch('/proposed_tasks').then(function(r){return r.json()}).catch(function(){return []})
  ]).then(function(res){
    var tasks=res[0],proposed=res[1];
    suggestionsEl.innerHTML='';
    var items=[];
    proposed.slice(0,5).forEach(function(t){items.push({text:t,type:'suggested'})});
    tasks.slice(0,5).forEach(function(t){
      items.push({text:typeof t==='string'?t:(t.task||''),type:'recent'});
    });
    items.slice(0,10).forEach(function(item){
      var chip=mkEl('div','suggestion-chip');
      chip.title=item.text;
      chip.innerHTML='<span class="chip-label '+item.type+'">'
        +(item.type==='recent'?'Recent':'Suggested')+'</span>'
        +esc(item.text);
      chip.addEventListener('click',function(){inp.value=item.text;inp.focus()});
      suggestionsEl.appendChild(chip);
    });
  });
}
var divider=document.getElementById('divider');
var editorPanel=document.getElementById('editor-panel');
var assistantPanel=document.getElementById('assistant-panel');
var splitContainer=document.getElementById('split-container');
var isDragging=false;
if(divider){
  divider.addEventListener('mousedown',function(e){
    isDragging=true;divider.classList.add('active');
    document.body.style.cursor='col-resize';
    document.body.style.userSelect='none';
    var frame=document.getElementById('code-server-frame');
    if(frame)frame.style.pointerEvents='none';
    e.preventDefault();
  });
  document.addEventListener('mousemove',function(e){
    if(!isDragging)return;
    var rect=splitContainer.getBoundingClientRect();
    var x=e.clientX-rect.left;
    var pct=Math.max(15,Math.min(85,(x/rect.width)*100));
    editorPanel.style.width=pct+'%';
    editorPanel.style.flex='none';
    assistantPanel.style.flex='1';
  });
  document.addEventListener('mouseup',function(){
    if(!isDragging)return;
    isDragging=false;divider.classList.remove('active');
    document.body.style.cursor='';
    document.body.style.userSelect='';
    var frame=document.getElementById('code-server-frame');
    if(frame)frame.style.pointerEvents='';
  });
}
function openInEditor(path){
  fetch('/open-file',{method:'POST',headers:{'Content-Type':'application/json'},
    body:JSON.stringify({path:path})}).catch(function(){});
}
document.addEventListener('click',function(e){
  var el=e.target.closest('[data-path]');
  if(el&&el.dataset.path){openInEditor(el.dataset.path);}
});
function mergeAction(action){
  fetch('/merge-action',{method:'POST',headers:{'Content-Type':'application/json'},
    body:JSON.stringify({action:action})}).then(function(r){return r.json()}).then(function(d){
    if(action==='accept-all'||action==='reject-all'){
      document.getElementById('merge-toolbar').style.display='none';
    }
  }).catch(function(){});
}
function mergeCommit(){
  var btn=document.getElementById('commit-btn');
  btn.textContent='Committing...';btn.disabled=true;
  fetch('/commit',{method:'POST',headers:{'Content-Type':'application/json'},
    body:JSON.stringify({})}).then(function(r){return r.json()}).then(function(d){
    if(d.error)alert('Commit failed: '+d.error);
    else{alert('Committed: '+d.message);
      document.getElementById('merge-toolbar').style.display='none';}
    btn.textContent='\uD83D\uDCE6 Commit';btn.disabled=false;
  }).catch(function(e){alert('Error: '+e);
    btn.textContent='\uD83D\uDCE6 Commit';btn.disabled=false;});
}
function hexToRgb(h){
  var r=parseInt(h.slice(1,3),16),g=parseInt(h.slice(3,5),16),b=parseInt(h.slice(5,7),16);
  return r+','+g+','+b;
}
function applyTheme(t){
  var p=document.getElementById('assistant-panel')||document.body;
  var map={
    '--bg':t.bg,'--surface':t.bg2,'--surface2':t.bg2,
    '--text':t.fg,'--accent':t.accent,'--border':t.border,
    '--green':t.green,'--red':t.red,'--purple':t.purple,'--cyan':t.cyan,
    '--input-bg':t.inputBg
  };
  for(var k in map){
    if(!map[k])continue;
    p.style.setProperty(k,map[k]);
  }
  var rgbMap={
    '--bg-rgb':t.bg,'--bg2-rgb':t.bg2,'--fg-rgb':t.fg,
    '--accent-rgb':t.accent,'--border-rgb':t.border,
    '--green-rgb':t.green,'--red-rgb':t.red,
    '--purple-rgb':t.purple,'--cyan-rgb':t.cyan
  };
  for(var k in rgbMap){
    if(!rgbMap[k])continue;
    p.style.setProperty(k,hexToRgb(rgbMap[k]));
  }
  document.body.style.setProperty('--bg',t.bg);
  document.body.style.setProperty('background',t.bg);
}
function loadTheme(){
  fetch('/theme').then(function(r){return r.json()}).then(applyTheme).catch(function(){});
}
loadTheme();setInterval(loadTheme,3000);
connectSSE();loadModels();loadTasks();loadProposed();loadWelcome();inp.focus();
"""


def _build_html(title: str, code_server_url: str = "", work_dir: str = "") -> str:
    font_import = "@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap');\n"
    css = font_import + BASE_CSS + OUTPUT_CSS + CHATBOT_CSS + CHATBOT_THEME_CSS

    if code_server_url:
        import urllib.parse
        wd_enc = urllib.parse.quote(work_dir, safe="")
        editor_content = (
            f'<iframe id="code-server-frame"'
            f' src="{code_server_url}/?folder={wd_enc}"'
            f' data-base-url="{code_server_url}"'
            f' data-work-dir="{work_dir}"></iframe>'
        )
    else:
        editor_content = (
            '<div id="editor-fallback">'
            '<h3>VS Code Editor</h3>'
            '<p>code-server is not installed. Install it to enable the embedded editor:</p>'
            '<code>curl -fsSL https://code-server.dev/install.sh | sh</code>'
            '<p>Or via Homebrew:</p>'
            '<code>brew install code-server</code>'
            '<p style="margin-top:16px;font-size:12px;opacity:0.5">'
            'Restart the assistant after installation.</p>'
            '</div>'
        )

    return HTML_HEAD.format(title=title, css=css) + f"""<body>
<div id="split-container">
  <div id="editor-panel" style="width:80%;flex-shrink:0">
    {editor_content}
    <div id="merge-toolbar">
      <button onclick="mergeAction('next')">&#9654; Next</button>
      <button onclick="mergeAction('accept-all')">&#10004; Accept All</button>
      <button onclick="mergeAction('reject-all')">&#10008; Reject All</button>
      <button id="commit-btn" onclick="mergeCommit()">&#128230; Commit</button>
    </div>
  </div>
  <div id="divider"></div>
  <div id="assistant-panel">
    <div id="sidebar-overlay" onclick="toggleSidebar()"></div>
    <div id="sidebar">
      <button id="sidebar-close" onclick="toggleSidebar()">&times;</button>
      <div class="sidebar-section" id="sidebar-history-sec">
        <div class="sidebar-hdr">Recent Tasks</div>
        <input type="text" id="history-search" placeholder="Search history\u2026"
          autocomplete="off"/>
        <div id="recent-list"></div>
      </div>
      <div class="sidebar-section" id="sidebar-proposals-sec">
        <div class="sidebar-hdr">Suggested Tasks</div>
        <div id="proposed-list"></div>
      </div>
    </div>
    <header>
      <div class="logo">KISS Sorcar</div>
      <div style="display:flex;align-items:center;gap:10px;flex-shrink:0">
        <div class="status"><div class="dot" id="dot"></div><span id="stxt">Ready</span></div>
      </div>
    </header>
    <div id="output">
      <div id="welcome">
        <h2>What can I help you with?</h2>
        <p>Describe a task and the agent will work on it</p>
        <div id="suggestions"></div>
      </div>
    </div>
    <div id="input-area">
      <div id="autocomplete"></div>
      <div id="input-container">
        <div id="file-chips"></div>
        <div id="input-wrap">
          <div id="input-text-wrap">
            <div id="ghost-overlay"></div>
            <textarea id="task-input" placeholder="Ask anything\u2026 (@ for files)" rows="1"
              autocomplete="off"></textarea>
          </div>
          <input type="file" id="file-input" multiple
            accept="image/jpeg,image/png,image/gif,image/webp,application/pdf"
            style="display:none"/>
          <button id="upload-btn" title="Attach files">
            <svg viewBox="0 0 24 24" fill="none"
            stroke="currentColor" stroke-width="2"
            stroke-linecap="round" stroke-linejoin="round"
            ><path d="M21.44 11.05l-9.19 9.19a6 6 0 01-8.49
            -8.49l9.19-9.19a4 4 0 015.66 5.66l-9.2 9.19a2
            2 0 01-2.83-2.83l8.49-8.48"/></svg></button>
          <button id="clear-btn" title="Clear chat"><svg viewBox="0 0 24 24" fill="none"
            stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
            ><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6"
              x2="18" y2="18"/></svg></button>
        </div>
        <div id="input-footer">
          <div id="model-picker">
            <button type="button" id="model-btn" onclick="toggleModelDD()">
              <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor"
                stroke-width="2"><path d="M12 2l3 7h7l-5.5 4 2 7L12 16l-6.5 4 2-7L2 9h7z"/></svg>
              <span id="model-label">Loading\u2026</span>
            </button>
            <button id="history-btn" onclick="toggleSidebar('history')" title="Task history">
              <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor"
                stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                <circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/>
              </svg>
            </button>
            <button id="proposals-btn" onclick="toggleSidebar('proposals')" title="Suggested tasks">
              <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor"
                stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                <path d="M12 2L2 7l10 5 10-5-10-5z"/><path d="M2 17l10 5 10-5"/>
                <path d="M2 12l10 5 10-5"/>
              </svg>
            </button>
            <div id="model-dropdown">
              <input type="text" id="model-search"
                placeholder="Search models\u2026" autocomplete="off"/>
              <div id="model-list"></div>
            </div>
          </div>
          <div id="input-actions">
            <button id="send-btn"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor"
              stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
              ><line x1="22" y1="2" x2="11" y2="13"/><polygon points="22 2 15 22 11 13 2 9 22 2"
              /></svg></button>
            <button id="stop-btn"><svg viewBox="0 0 24 24" fill="currentColor"
              ><rect x="6" y="6" width="12" height="12" rx="2"/></svg></button>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>
<script>
{EVENT_HANDLER_JS}
{CHATBOT_JS}
</script>
</body>
</html>"""
