/* ---------------------------------------------------------------------
   Design tokens
   Palette: deep charcoal control-room base with a single jade accent —
   chosen to read as an internal ops/IT tool, not a marketing surface.
--------------------------------------------------------------------- */
:root {
  --bg: #0f1216;
  --panel: #161b21;
  --surface: #1e252c;
  --surface-hover: #242c34;
  --border: #2a323b;
  --border-soft: #20272e;

  --text: #edeff2;
  --text-secondary: #99a3ad;
  --text-tertiary: #6b7480;

  --accent: #2f8f7e;
  --accent-strong: #3ba98f;
  --accent-soft: rgba(47, 143, 126, 0.14);

  --ok: #3fa66d;
  --ok-soft: rgba(63, 166, 109, 0.14);
  --bad: #d96c6c;
  --bad-soft: rgba(217, 108, 108, 0.14);
  --warn: #d9a441;
  --warn-soft: rgba(217, 164, 65, 0.14);

  --radius-sm: 6px;
  --radius-md: 10px;
  --sidebar-w: 320px;
  --font: -apple-system, BlinkMacSystemFont, "Segoe UI", "Inter", Roboto,
    Helvetica, Arial, sans-serif;
  --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
}

* {
  box-sizing: border-box;
}

html,
body {
  height: 100%;
}

body {
  margin: 0;
  font-family: var(--font);
  background: var(--bg);
  color: var(--text);
  -webkit-font-smoothing: antialiased;
}

button {
  font-family: inherit;
}

::selection {
  background: var(--accent-soft);
}

a {
  color: var(--accent-strong);
}

/* ---------------------------------------------------------------------
   App shell
--------------------------------------------------------------------- */
#app {
  display: block;
  height: 100vh;
}

/* ---------------------------------------------------------------------
   Brand mark (topbar)
--------------------------------------------------------------------- */
.brand-mark {
  width: 26px;
  height: 26px;
  border-radius: 7px;
  background: linear-gradient(155deg, var(--accent-strong), #1d5b50);
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 700;
  font-size: 11px;
  letter-spacing: 0.02em;
  color: #eafff9;
  flex-shrink: 0;
}

.job-status {
  margin-top: 8px;
  font-size: 12px;
  color: var(--text-secondary);
  background: var(--surface);
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-sm);
  padding: 8px 9px;
  line-height: 1.5;
  display: flex;
  gap: 7px;
  align-items: flex-start;
}

.job-status.error {
  color: var(--bad);
  border-color: rgba(217, 108, 108, 0.35);
}

.job-status.done {
  color: var(--ok);
  border-color: rgba(63, 166, 109, 0.35);
}

.spin {
  width: 12px;
  height: 12px;
  border-radius: 50%;
  border: 2px solid var(--border);
  border-top-color: var(--accent-strong);
  animation: spin 0.7s linear infinite;
  flex-shrink: 0;
  margin-top: 2px;
}

@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}

/* ---------------------------------------------------------------------
   Main / chat column
--------------------------------------------------------------------- */
#main {
  display: flex;
  flex-direction: column;
  min-width: 0;
  height: 100vh;
}

#topbar {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px 22px;
  border-bottom: 1px solid var(--border-soft);
  flex-shrink: 0;
}

#topbar h1 {
  font-size: 15px;
  font-weight: 600;
  margin: 0;
  letter-spacing: -0.01em;
}

#topbar .status-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--ok);
  display: inline-block;
  margin-right: 6px;
}

.topbar-spacer {
  flex: 1;
}

.debug-toggle {
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: 12.5px;
  color: var(--text-secondary);
  cursor: pointer;
  user-select: none;
}

.debug-toggle input {
  accent-color: var(--accent);
}

#chat-log {
  flex: 1;
  overflow-y: auto;
  padding: 24px 0 12px;
}

.chat-inner {
  max-width: 720px;
  margin: 0 auto;
  padding: 0 24px;
  display: flex;
  flex-direction: column;
  gap: 22px;
}

.empty-state {
  margin-top: 14vh;
  text-align: center;
  color: var(--text-tertiary);
}

.empty-state .empty-title {
  font-size: 18px;
  font-weight: 600;
  color: var(--text-secondary);
  margin-bottom: 6px;
}

.empty-state .empty-sub {
  font-size: 13.5px;
  max-width: 380px;
  margin: 0 auto;
  line-height: 1.6;
}

.msg {
  display: flex;
  flex-direction: column;
  max-width: 92%;
}

.msg.user {
  align-self: flex-end;
  align-items: flex-end;
}

.msg.assistant {
  align-self: flex-start;
  align-items: flex-start;
}

.msg .bubble {
  border-radius: var(--radius-md);
  padding: 11px 14px;
  font-size: 14.5px;
  line-height: 1.65;
  white-space: pre-wrap;
  word-break: break-word;
}

.msg.user .bubble {
  background: var(--accent);
  color: #ecfffb;
  border-bottom-right-radius: 3px;
}

.msg.assistant .bubble {
  background: var(--surface);
  border: 1px solid var(--border-soft);
  border-bottom-left-radius: 3px;
}

.msg.assistant .bubble ul,
.msg.assistant .bubble ol {
  margin: 6px 0;
  padding-left: 20px;
}

.msg .bubble p {
  margin: 0 0 8px;
}
.msg .bubble p:last-child {
  margin-bottom: 0;
}

/* Shown in place of an assistant reply when the user stops a response
   mid-flight (see script.js's appendStoppedNotice()) — visually distinct
   (italic, muted) from a real answer bubble so it reads as a UI status
   note, not as content the assistant actually said. */
.msg.assistant .bubble.stopped-notice {
  font-style: italic;
  color: var(--text-tertiary);
  background: transparent;
  border-style: dashed;
}

.compliance-badge {
  margin-top: 8px;
  border-radius: var(--radius-sm);
  padding: 9px 12px;
  font-size: 13px;
  line-height: 1.55;
  border: 1px solid transparent;
  max-width: 100%;
}

.compliance-badge .verdict-line {
  font-weight: 600;
  margin-bottom: 3px;
}

.compliance-badge.compliant {
  background: var(--ok-soft);
  color: var(--ok);
  border-color: rgba(63, 166, 109, 0.3);
}

.compliance-badge.non_compliant {
  background: var(--bad-soft);
  color: var(--bad);
  border-color: rgba(217, 108, 108, 0.3);
}

.compliance-badge.partially_compliant {
  background: var(--warn-soft);
  color: var(--warn);
  border-color: rgba(217, 164, 65, 0.3);
}

.compliance-badge .basis {
  color: var(--text);
  opacity: 0.88;
  font-weight: 400;
}

.policy-quote {
  margin-top: 7px;
  padding-top: 7px;
  border-top: 1px solid rgba(255, 255, 255, 0.08);
  font-size: 12px;
  line-height: 1.5;
  color: var(--text);
  opacity: 0.8;
  font-style: italic;
}

.policy-quote:first-of-type {
  margin-top: 8px;
}

.sources-panel-label {
  padding: 9px 12px;
  font-size: 12.5px;
  color: var(--text-tertiary);
  display: flex;
  align-items: center;
  gap: 6px;
}

.sources-panel {
  margin-top: 9px;
  width: 100%;
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-md);
  background: var(--panel);
  overflow: hidden;
}

.sources-panel summary {
  cursor: pointer;
  padding: 9px 12px;
  font-size: 12.5px;
  color: var(--text-secondary);
  list-style: none;
  display: flex;
  align-items: center;
  gap: 6px;
}

.sources-panel summary::-webkit-details-marker {
  display: none;
}

.source-item {
  padding: 10px 12px;
  border-top: 1px solid var(--border-soft);
}

.source-item .source-meta {
  font-size: 12px;
  color: var(--text-secondary);
  margin-bottom: 7px;
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}

.source-item .source-meta .score {
  color: var(--text-tertiary);
}

/* .video-frame is a fixed-aspect-ratio box so the <video> inside it has
   an actual box to fill — without it, "height: 100%" on the video would
   resolve against an auto-height parent and do nothing. The video is
   then stretched/cropped (object-fit: cover) to fill that box
   completely, edge-to-edge, instead of rendering at its native size
   with letterboxing. Swap "cover" for "contain" below if you'd rather
   see the whole frame with bars than crop it. */
.source-item .video-frame {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 9;
  border-radius: var(--radius-sm);
  background: #000;
  overflow: hidden;
}

.source-item .video-frame video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  display: block;
}

.source-item audio {
  width: 100%;
  max-width: 420px;
  border-radius: var(--radius-sm);
  display: block;
}

.debug-panel {
  display: none;
  margin-top: 9px;
  width: 100%;
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-md);
  background: #0c0f13;
}

body.debug-mode .debug-panel {
  display: block;
}

.debug-panel summary {
  cursor: pointer;
  padding: 8px 12px;
  font-size: 12px;
  color: var(--text-tertiary);
  list-style: none;
}

.debug-panel summary::-webkit-details-marker {
  display: none;
}

.debug-panel pre {
  margin: 0;
  padding: 10px 12px;
  border-top: 1px solid var(--border-soft);
  font-family: var(--mono);
  font-size: 11.5px;
  color: var(--text-secondary);
  white-space: pre-wrap;
  word-break: break-word;
  max-height: 320px;
  overflow-y: auto;
}

.thinking {
  display: flex;
  gap: 4px;
  align-items: center;
  padding: 4px 2px;
}

.thinking span {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--text-tertiary);
  animation: pulse 1.1s ease-in-out infinite;
}

.thinking span:nth-child(2) {
  animation-delay: 0.15s;
}
.thinking span:nth-child(3) {
  animation-delay: 0.3s;
}

@keyframes pulse {
  0%,
  80%,
  100% {
    opacity: 0.25;
    transform: scale(0.85);
  }
  40% {
    opacity: 1;
    transform: scale(1);
  }
}

/* ---------------------------------------------------------------------
   Composer
--------------------------------------------------------------------- */
#composer-wrap {
  border-top: 1px solid var(--border-soft);
  padding: 14px 24px 18px;
  flex-shrink: 0;
}

.composer-inner {
  max-width: 720px;
  margin: 0 auto;
}

#compliance-job-status {
  max-width: 720px;
  margin: 0 auto 8px;
}

#composer {
  display: flex;
  align-items: flex-end;
  gap: 8px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 8px 8px 8px 12px;
}

#composer:focus-within {
  border-color: var(--accent);
}

#composer textarea {
  flex: 1;
  resize: none;
  border: none;
  outline: none;
  background: transparent;
  color: var(--text);
  font-family: inherit;
  font-size: 14.5px;
  line-height: 1.5;
  max-height: 160px;
  padding: 6px 0;
}

#composer textarea::placeholder {
  color: var(--text-tertiary);
}

.composer-btn {
  width: 34px;
  height: 34px;
  border-radius: 10px;
  border: 1px solid var(--border);
  background: transparent;
  color: var(--text-secondary);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  flex-shrink: 0;
}

.composer-btn:hover {
  background: var(--surface-hover);
  color: var(--text);
}

.composer-btn.send {
  background: var(--accent);
  border-color: var(--accent);
  color: #ecfffb;
}

.composer-btn.send:hover {
  background: var(--accent-strong);
}

.composer-btn.send:disabled {
  opacity: 0.45;
  cursor: default;
}

/* Stop state: the same button element as .send, with a .stop class
   toggled on top while a response is in flight (see script.js's
   setSendingState()) — swapped to a warning color so it visually reads
   as a different action ("stop this"), not just a disabled send. */
.composer-btn.send.stop {
  background: var(--bad);
  border-color: var(--bad);
  color: #fff;
}

.composer-btn.send.stop:hover {
  background: #c65a5a;
}

.composer-btn svg {
  width: 16px;
  height: 16px;
}

.composer-hint {
  text-align: center;
  font-size: 11px;
  color: var(--text-tertiary);
  margin-top: 8px;
}

/* ---------------------------------------------------------------------
   Knowledge-base sidebar — a slide-out drawer toggled by
   #kb-sidebar-toggle, listing dynamic (uploaded) and static files. Each
   file gets a 🔍 compliance-check button (POST /api/compliance/{name})
   and a 🗑 delete button (DELETE /api/files/{name}) — both static and
   dynamic files are deletable the same way; see main.py's delete_file()
   for how a static file's on-disk removal is handled so KBWatcher
   doesn't silently re-index it back on its next poll. Uses the same
   design tokens as the rest of the app rather than a separate look.
--------------------------------------------------------------------- */
/* Now an INLINE topbar button, not a floating fixed one — see
   index.html's comment. The earlier fixed-position version overlapped
   whatever else sat in the same top-left screen corner (first the
   drawer's own "Knowledge base" title, then the back-to-systems
   button); putting it in the topbar's normal flex flow, next to those
   other controls, removes that whole class of overlap bug rather than
   patching coordinates again. It's also now naturally scoped to only
   appear while inside a system's chat (a child of #main), instead of
   floating visibly even on the launcher screen where there's no
   "current system" for it to show a KB for. */
.kb-sidebar-toggle {
  width: 28px;
  height: 28px;
  border-radius: 8px;
  border: 1px solid var(--border);
  background: transparent;
  color: var(--text-secondary);
  font-size: 14px;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

.kb-sidebar-toggle:hover {
  background: var(--surface-hover);
  color: var(--text);
}

.kb-sidebar-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.45);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.25s ease;
  z-index: 999;
}

.kb-sidebar-backdrop.open {
  opacity: 1;
  pointer-events: auto;
}

.kb-sidebar {
  position: fixed;
  top: 0;
  left: 0;
  height: 100vh;
  width: var(--sidebar-w);
  max-width: 85vw;
  background: var(--panel);
  border-right: 1px solid var(--border-soft);
  z-index: 1000;
  box-shadow: 4px 0 24px rgba(0, 0, 0, 0.35);
  transform: translateX(-100%);
  transition: transform 0.28s ease;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.kb-sidebar.open {
  transform: translateX(0);
}

.kb-sidebar-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16px 18px;
  border-bottom: 1px solid var(--border-soft);
  flex-shrink: 0;
}

.kb-sidebar-header h3 {
  margin: 0;
  font-size: 14.5px;
  font-weight: 600;
  color: var(--text);
}

.kb-sidebar-close {
  border: none;
  background: transparent;
  font-size: 16px;
  cursor: pointer;
  color: var(--text-tertiary);
  line-height: 1;
}

.kb-sidebar-close:hover {
  color: var(--text);
}

.kb-sidebar-body {
  flex: 1;
  overflow-y: auto;
  padding: 14px 16px;
}

.kb-add-file-btn {
  width: 100%;
  padding: 10px;
  margin-bottom: 12px;
  border: 1px dashed var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--text-secondary);
  cursor: pointer;
  font-size: 13px;
}

.kb-add-file-btn:hover {
  background: var(--surface-hover);
  color: var(--text);
}

.kb-upload-status {
  font-size: 12px;
  color: var(--text-tertiary);
  min-height: 16px;
  margin-bottom: 4px;
}

.kb-section-label {
  font-size: 11.5px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-tertiary);
  margin: 16px 2px 8px;
}

.kb-file-list {
  list-style: none;
  margin: 0;
  padding: 0;
}

.kb-file-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 6px;
  padding: 8px 10px;
  border-radius: var(--radius-sm);
  font-size: 12.5px;
  color: var(--text-secondary);
  background: var(--surface);
  border: 1px solid var(--border-soft);
  margin-bottom: 6px;
}

.kb-file-item .name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  flex: 1;
  min-width: 0;
}

.kb-file-item .kb-actions {
  display: flex;
  align-items: center;
  gap: 2px;
  flex-shrink: 0;
}

.kb-file-item button {
  border: none;
  background: transparent;
  cursor: pointer;
  font-size: 13px;
  flex-shrink: 0;
  width: 22px;
  height: 22px;
  border-radius: var(--radius-sm);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--text-tertiary);
}

.kb-file-item button:hover {
  background: var(--surface-hover);
  color: var(--text);
}

.kb-file-item button.kb-check-btn:hover {
  color: var(--accent-strong);
}

.kb-file-item button.kb-delete-btn:hover {
  color: var(--bad);
}

.kb-file-item button.kb-check-btn.checking {
  opacity: 0.5;
  cursor: default;
}

.kb-empty-note {
  color: var(--text-tertiary);
  font-size: 12.5px;
  padding: 4px 2px 8px;
}

/* ---------------------------------------------------------------------
   Utility
--------------------------------------------------------------------- */
.hidden {
  display: none !important;
}

/* ---------------------------------------------------------------------
   System launcher — shown first (see script.js's loadLauncher()/
   enterSystem()). Populated dynamically from GET /api/systems; not
   hardcoded to any particular set of systems.
--------------------------------------------------------------------- */
#launcher-view {
  height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
}

.launcher-inner {
  max-width: 640px;
  width: 100%;
  text-align: center;
}

.launcher-title {
  font-size: 24px;
  font-weight: 700;
  color: var(--text);
  margin-bottom: 6px;
}

.launcher-sub {
  font-size: 14px;
  color: var(--text-secondary);
  margin-bottom: 28px;
}

.launcher-error {
  color: var(--bad);
  font-size: 13px;
  margin-bottom: 12px;
  min-height: 18px;
}

.launcher-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
  gap: 14px;
  margin-bottom: 18px;
}

.system-tile {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 20px 10px;
  border-radius: var(--radius-md);
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text);
  cursor: pointer;
  transition: background 0.15s ease, border-color 0.15s ease, transform 0.1s ease;
}

.system-tile:hover {
  background: var(--surface-hover);
  border-color: var(--accent);
  transform: translateY(-2px);
}

.system-tile-icon {
  font-size: 30px;
  line-height: 1;
}

.system-tile-name {
  font-size: 13px;
  font-weight: 600;
  text-align: center;
  word-break: break-word;
}

.add-system-tile {
  width: 100%;
  max-width: 220px;
  margin: 0 auto;
  border-style: dashed;
  color: var(--text-secondary);
}

.add-system-form {
  max-width: 320px;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  gap: 8px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 14px;
}

.add-system-form input {
  background: var(--panel);
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-sm);
  color: var(--text);
  padding: 8px 10px;
  font-size: 13.5px;
  font-family: inherit;
}

.add-system-form input::placeholder {
  color: var(--text-tertiary);
}

.add-system-actions {
  display: flex;
  gap: 8px;
  justify-content: flex-end;
}

.add-system-btn {
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 7px 14px;
  font-size: 13px;
  cursor: pointer;
  background: transparent;
  color: var(--text-secondary);
}

.add-system-btn.submit {
  background: var(--accent);
  border-color: var(--accent);
  color: #ecfffb;
}

.add-system-btn.submit:hover {
  background: var(--accent-strong);
}

.add-system-btn.cancel:hover {
  background: var(--surface-hover);
  color: var(--text);
}

/* Back-to-systems control in the topbar, next to the brand mark */
.back-to-systems-btn {
  width: 28px;
  height: 28px;
  border-radius: 8px;
  border: 1px solid var(--border);
  background: transparent;
  color: var(--text-secondary);
  cursor: pointer;
  font-size: 14px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

.back-to-systems-btn:hover {
  background: var(--surface-hover);
  color: var(--text);
}