/* --- Base typography -------------------------------------------------- */

* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
html { font-size: 17px; }   /* one notch above the 16px default — easier on the eyes */
body {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
  background: #f6f7f8;
  color: #1f2328;
  line-height: 1.55;
}

h1, h2, h3 { font-weight: 600; line-height: 1.25; }
h1 { font-size: 1.6rem; margin: 0 0 .5rem; }
h2 { font-size: 1.15rem; margin: 0 0 .5rem; }
.muted { color: #6b7280; }


/* --- Header ----------------------------------------------------------- */

header {
  background: #1f2937;
  color: #fff;
  padding: .85rem 1.5rem;
  display: flex;
  justify-content: space-between;
  align-items: center;
}
.brand {
  font-weight: 600; font-size: 1.05rem; letter-spacing: .2px;
  color: inherit; text-decoration: none;
}
.brand:hover { opacity: .85; }
nav { display: inline-flex; align-items: center; gap: 1.1rem; }
nav .user { opacity: .85; font-size: .95rem; }
nav .nav-link {
  color: inherit; text-decoration: none;
  font-size: .95rem; opacity: .9;
}
nav .nav-link:hover { opacity: 1; text-decoration: underline; }
.link {
  background: none; border: 0; color: inherit; cursor: pointer;
  text-decoration: underline; font: inherit; padding: 0;
}
.link:hover { opacity: .8; }


/* --- Layout ----------------------------------------------------------- */

/* Two layout modes:
   - layout-narrow: cases-list, login, etc. — bounded reading column.
   - layout-wide:   case-view — full viewport for the two-pane case page. */
main.layout-narrow {
  max-width: 1200px;
  margin: 1.75rem auto;
  padding: 0 1.5rem;
}
main.layout-wide {
  max-width: none;
  margin: .35rem 0 0;
  padding: 0 1.25rem;
}

/* Case-view page locks the viewport so the chat / activity panes each
   scroll internally and the topbar + attachments strip stay pinned at
   the top. Without this, a tall attachments strip or a long chat
   history makes the WHOLE page scroll, which loses the topbar /
   activity sidebar from view as the user scrolls down. */
body.case-view-page {
  height: 100vh;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}
/* Case-view-only: tighten the global header so the chat gets every
   pixel back. Other pages keep the roomier default. */
body.case-view-page > header {
  padding: .5rem 1.5rem;
}
body.case-view-page main.layout-wide {
  flex: 1 1 auto;
  min-height: 0;        /* allow children to shrink below content size */
  display: flex;
  flex-direction: column;
  margin-bottom: .35rem;
}
body.case-view-page .case-page {
  flex: 1 1 auto;
  min-height: 0;
  height: auto;          /* override the calc()-based height — flex sizes it */
}


/* --- Login ------------------------------------------------------------ */

.login-box {
  max-width: 460px;
  margin: 5rem auto;
  background: #fff;
  padding: 2.25rem 2rem;
  border: 1px solid #e5e7eb;
  border-radius: 8px;
  box-shadow: 0 4px 18px rgba(0,0,0,.04);
}
.login-box h1 { margin-bottom: 1rem; }
.login-box label { display: block; margin: 1.1rem 0 .35rem; font-size: .95rem; color: #374151; }
.login-box input {
  width: 100%; padding: .65rem .85rem;
  border: 1px solid #d1d5db; border-radius: 4px;
  font-size: 1rem; line-height: 1.4;
}
.login-box input:focus { outline: 2px solid #2563eb; outline-offset: 1px; }


/* --- Buttons ---------------------------------------------------------- */

button.primary {
  margin-top: 1.4rem;
  background: #2563eb; color: #fff;
  border: 0; padding: .65rem 1.4rem;
  border-radius: 4px; cursor: pointer;
  font-size: 1rem; font-weight: 500;
}
button.primary:hover:not(:disabled) { background: #1d4ed8; }
button.primary:active { background: #1e40af; }
button.primary:disabled { background: #9ca3af; cursor: default; }

button.small {
  background: transparent; color: #2563eb;
  border: 1px solid #d1d5db; border-radius: 4px;
  padding: .35rem .8rem; font-size: .88rem;
  cursor: pointer;
}
button.small:hover:not(:disabled) { background: #eff6ff; border-color: #93c5fd; }
button.small:disabled { color: #6b7280; cursor: default; opacity: .8; }
button.small.saved { background: #dcfce7; color: #166534; border-color: #86efac; }


/* --- Errors ----------------------------------------------------------- */

.error {
  background: #fee2e2; color: #991b1b;
  padding: .65rem .9rem; border-radius: 4px;
  margin-bottom: 1.25rem; font-size: .95rem;
}


/* --- Home page (claude.ai-style sidebar + composer) ------------------ */

/* Locked viewport: sidebar + main composer fill the screen, neither
   scrolls the page itself. The sidebar's case list scrolls
   internally; the main composer is centered with breathing room. */
body.home-page-body {
  height: 100vh;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}
body.home-page-body main.layout-wide {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
  margin: 0;
  padding: 0;
}

.home-page {
  display: grid;
  grid-template-columns: 280px 1fr;
  flex: 1 1 auto;
  min-height: 0;
  background: #fff;
}

.cases-sidebar {
  background: #fafaf9;
  border-right: 1px solid #e7e5e4;
  display: flex; flex-direction: column;
  min-height: 0;
}
.sidebar-header {
  padding: .85rem .9rem .65rem;
  border-bottom: 1px solid #e7e5e4;
}
.case-search {
  width: 100%;
  padding: .5rem .75rem;
  border: 1px solid #d6d3d1; border-radius: 6px;
  background: #fff; font-size: .92rem;
}
.case-search:focus { outline: 2px solid #2563eb; outline-offset: 1px; }

.cases-list {
  list-style: none; padding: .5rem 0; margin: 0;
  overflow-y: auto;
  flex: 1 1 auto;
  min-height: 0;
}
.cases-list .empty,
.cases-list .search-empty {
  padding: .75rem 1rem; color: #78716c; font-size: .9rem;
}
.cases-list .case-item { padding: 0; margin: 0; }
.cases-list .case-item a {
  display: block;
  padding: .65rem .9rem;
  text-decoration: none; color: #1c1917;
  transition: background .1s ease;
}
.cases-list .case-item a:hover { background: #f5f5f4; }
.cases-list .case-item-name {
  display: block;
  font-weight: 500; font-size: .94rem;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.cases-list .case-item-meta {
  display: block;
  font-size: .76rem; color: #78716c;
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  margin-top: 1px;
}

/* Main composer area */
.home-main {
  display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  padding: 2rem 2.5rem;
  overflow-y: auto;
  min-height: 0;
}
.home-greeting {
  text-align: center;
  margin-bottom: 1.75rem;
  max-width: 640px;
}
.home-greeting h1 {
  font-size: 1.85rem; font-weight: 600;
  letter-spacing: -.5px; margin-bottom: .35rem;
}
.home-greeting p { color: #6b7280; font-size: .98rem; margin: 0; }

.composer {
  width: 100%; max-width: 720px;
  background: #fff;
  border: 1px solid #d6d3d1; border-radius: 12px;
  padding: 1rem 1rem .85rem;
  box-shadow: 0 2px 8px rgba(0, 0, 0, .03);
}
.composer textarea {
  width: 100%;
  border: 0; outline: 0; resize: none;
  font: inherit; font-size: 1rem; line-height: 1.55;
  padding: .35rem .25rem;
  background: transparent;
  color: #1c1917;
}
.composer textarea::placeholder { color: #a8a29e; }

/* Single-line name input — replaces the textarea on the home composer.
   The home page is now strictly for NAMING the investigation; the
   issue description happens in the case screen as the first chat
   message. Sized close to the textarea's resting height for visual
   continuity with the rest of the composer chrome. */
.composer .composer-name {
  width: 100%;
  border: 0; outline: 0;
  font: inherit; font-size: 1.05rem; line-height: 1.6;
  padding: .55rem .35rem;
  background: transparent;
  color: #1c1917;
}
.composer .composer-name::placeholder { color: #a8a29e; }

.composer-attachments {
  margin: .65rem 0 .35rem;
  padding-top: .65rem;
  border-top: 1px solid #f5f5f4;
}
.composer-attachments .att-label {
  font-size: .78rem; color: #78716c;
  display: block; margin-bottom: .35rem;
}
#composer-file-list {
  list-style: none; padding: 0; margin: 0;
  display: flex; flex-wrap: wrap; gap: .35rem;
}
.composer-file {
  display: inline-flex; align-items: center; gap: .4rem;
  padding: .25rem .55rem;
  background: #f5f5f4; border: 1px solid #e7e5e4;
  border-radius: 4px;
  font-size: .82rem;
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
}
.composer-file-tag {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
  font-size: .68rem; font-weight: 500;
  text-transform: uppercase; letter-spacing: .35px;
  padding: 1px 5px; border-radius: 3px;
  background: #ede9fe; color: #6d28d9;
}
.composer-file-size { color: #78716c; font-size: .78rem; }

.composer-actions {
  display: flex; align-items: center; gap: .5rem;
  margin-top: .85rem;
  padding-top: .85rem;
  border-top: 1px solid #f5f5f4;
}
.composer-spacer { flex: 1; }
.composer button.primary {
  margin: 0; padding: .55rem 1.4rem;
  font-size: .95rem;
  border-radius: 6px;
}

.ghost-btn {
  display: inline-flex; align-items: center; gap: .35rem;
  padding: .45rem .75rem;
  background: transparent; color: #44403c;
  border: 1px solid #d6d3d1; border-radius: 6px;
  cursor: pointer; font: inherit; font-size: .88rem;
  transition: background .1s ease, border-color .1s ease;
}
.ghost-btn:hover { background: #f5f5f4; border-color: #a8a29e; }

.zendesk-disclosure {
  width: 100%; max-width: 720px;
  margin-top: 1rem;
  background: #f0f9ff;
  border: 1px solid #bfdbfe; border-radius: 8px;
  padding: .85rem 1rem;
}
.zendesk-form {
  display: flex; align-items: center; gap: .65rem;
}
.zendesk-form label {
  font-size: .85rem; color: #1e3a8a; font-weight: 500;
  flex: 0 0 auto;
}
.zendesk-form input {
  flex: 1;
  padding: .5rem .75rem;
  border: 1px solid #d6d3d1; border-radius: 6px;
  font-size: .95rem;
}
.zendesk-form input:focus { outline: 2px solid #2563eb; outline-offset: 1px; }
.zendesk-form button.primary { margin: 0; padding: .5rem 1.1rem; }

/* "or" divider between the topic composer and the Zendesk import card —
   horizontal hairline with the word "or" centered on it. */
.or-divider {
  width: 100%; max-width: 720px;
  display: flex; align-items: center; gap: .85rem;
  margin: 1.4rem 0 1rem;
  color: #a8a29e;
  font-size: .82rem;
  letter-spacing: .8px;
  text-transform: uppercase;
}
.or-divider::before,
.or-divider::after {
  content: ""; flex: 1;
  border-top: 1px solid #e7e5e4;
}

/* Zendesk import as its own card — paired with the topic composer above
   it. Same visual weight, lighter background tint to signal "alternate
   path" without competing with the primary composer. */
.zendesk-form-card {
  width: 100%; max-width: 720px;
  background: #f0f9ff;
  border: 1px solid #bfdbfe; border-radius: 12px;
  padding: 1rem 1.15rem 1.05rem;
}
.zendesk-form-card label {
  display: block;
  font-size: .9rem; color: #1e3a8a; font-weight: 600;
  margin-bottom: .55rem;
}
.zendesk-row {
  display: flex; gap: .5rem;
}
.zendesk-row input[type="text"] {
  flex: 1;
  padding: .55rem .8rem;
  border: 1px solid #bfdbfe; border-radius: 6px;
  background: #fff;
  font-size: .95rem;
}
.zendesk-row input[type="text"]:focus { outline: 2px solid #2563eb; outline-offset: 1px; }
.zendesk-row button { margin: 0; padding: .55rem 1.15rem; flex: 0 0 auto; }
.zendesk-form-card .hint {
  margin: .55rem 0 0;
  font-size: .82rem; color: #64748b;
  line-height: 1.45;
}


/* --- Case page: topbar + attachments strip + 2-pane chat -------------- */

.case-topbar {
  display: flex; align-items: center; justify-content: space-between;
  gap: 1rem; padding: .35rem 0 .25rem;
}
.topbar-left { display: flex; align-items: baseline; gap: 1rem; flex-wrap: wrap; }
.back-link { color: #2563eb; text-decoration: none; font-size: .9rem; flex: 0 0 auto; }
.back-link:hover { text-decoration: underline; }
.case-topbar .case-title {
  margin: 0; font-size: 1.15rem; font-weight: 600; line-height: 1.3;
}
.case-topbar .case-meta {
  margin: 0; color: #6b7280; font-size: .85rem;
}
.case-topbar .case-meta .case-slug {
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
}

.topbar-right { display: flex; align-items: center; gap: .5rem; flex-shrink: 0; }
.freshness-tag {
  background: #f0f9ff; color: #1e3a8a;
  border: 1px solid #dbeafe; border-radius: 4px;
  padding: .2rem .55rem;
  font-size: .76rem; font-weight: 500;
  text-transform: lowercase; letter-spacing: .2px;
}
.freshness-tag.error { background: #fef3c7; color: #92400e; border-color: #fde68a; }

/* "Pull latest" — re-fetch Zendesk + queue new comments for next turn. */
.refresh-zd-form { display: inline-flex; }
.refresh-zd-btn {
  background: #eef2ff; color: #4338ca;
  border: 1px solid #c7d2fe; border-radius: 4px;
  padding: .2rem .55rem;
  font-size: .76rem; font-weight: 500;
  cursor: pointer;
  transition: background .1s ease, border-color .1s ease;
}
.refresh-zd-btn:hover { background: #e0e7ff; border-color: #818cf8; }

/* Horizontal attachments strip — every file from Zendesk + user uploads. */
.attachments-strip {
  display: flex; align-items: center;
  gap: .65rem;
  background: #fff;
  border: 1px solid #e5e7eb; border-radius: 6px;
  padding: .3rem .85rem;
  margin-bottom: .4rem;
}
.attachments-strip .strip-label {
  font-size: .82rem; color: #6b7280;
  flex: 0 0 auto; font-weight: 500;
}
.attachments-list {
  list-style: none; padding: 0; margin: 0;
  display: flex; flex-wrap: wrap; gap: .35rem;
  /* Cap height at ~1 row so the strip stays compact. Operator can
     scroll vertically within the strip to see more chips on heavy
     cases. With few chips the natural height stays under the cap. */
  max-height: 2.4rem;
  overflow-y: auto;
  flex: 1 1 auto;
  align-content: flex-start;
}
.attachments-list::-webkit-scrollbar { width: 6px; }
.attachments-list::-webkit-scrollbar-thumb { background: #d1d5db; border-radius: 3px; }
.attachments-list::-webkit-scrollbar-thumb:hover { background: #9ca3af; }
.attachment {
  display: inline-flex; align-items: center; gap: .4rem;
  padding: .25rem .55rem;
  background: #f9fafb; border: 1px solid #e5e7eb;
  border-radius: 4px;
  font-size: .82rem;
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
}
.attachment .att-name { color: #1f2937; max-width: 22rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.attachment .att-source {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
  font-size: .68rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: .35px;
  padding: 1px 5px;
  border-radius: 3px;
}
.attachment.src-zendesk .att-source { background: #dbeafe; color: #1d4ed8; }
.attachment.src-user .att-source { background: #ede9fe; color: #6d28d9; }
.attachment .att-state, .attachment .att-meta {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
  font-size: .72rem;
  color: #6b7280;
}
.attachment .att-state.ready { color: #047857; }
.attachment .att-state.indexing { color: #d97706; font-style: italic; }
.attachment .att-state.failed {
  color: #b91c1c; font-weight: 600;
  background: #fee2e2; border-radius: 3px; padding: 1px 5px;
}
/* In-flight chips get a pulsing border so the eye catches them. */
.attachment.state-indexing { border-color: #fcd34d; }
.attachment.state-failed   { border-color: #fca5a5; }


/* --- Upload error banner -------------------------------------------- */

.upload-error-banner {
  background: #fee2e2; color: #7f1d1d;
  border: 1px solid #fca5a5; border-radius: 6px;
  padding: .45rem .7rem;
  margin-bottom: .6rem;
  font-size: .85rem;
}
.upload-error-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: .65rem;
}
.upload-error-dismiss-all-form { margin: 0; }
.upload-error-dismiss-all {
  background: #fff; color: #991b1b;
  border: 1px solid #fca5a5; border-radius: 4px;
  padding: .12rem .55rem;
  font-size: .75rem; font-weight: 500;
  cursor: pointer;
}
.upload-error-dismiss-all:hover { background: #fee2e2; }

.upload-error-list {
  list-style: none;
  margin: .35rem 0 0;
  padding: 0;
}
.upload-error-list li {
  display: flex; align-items: center; gap: .5rem;
  padding: .1rem 0;
  font-size: .82rem;
}
.upload-error-msg {
  flex: 1;
  /* The error text from a sidecar can be long (full Python tracebacks
     etc.) — clip with ellipsis instead of letting it wrap to many
     rows. Hover to read in full via the native title attr. */
  white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis;
}
.upload-error-dismiss-form { margin: 0; }
.upload-error-dismiss {
  background: transparent; color: #7f1d1d;
  border: none;
  padding: 0 .25rem;
  font-size: .9rem; font-weight: 700;
  cursor: pointer; line-height: 1;
}
.upload-error-dismiss:hover { color: #b91c1c; }

.upload-error-banner code {
  background: #fff;
  padding: 1px 4px; border-radius: 3px;
  font-size: .88em;
}
.upload-error-hint {
  margin: .35rem 0 0;
  font-size: .76rem; color: #991b1b;
}
.upload-error-hint summary { cursor: pointer; }

.sync-form { margin-left: auto; }
.sync-btn {
  background: #fef3c7; color: #92400e;
  border: 1px solid #fcd34d; border-radius: 4px;
  padding: .35rem .8rem;
  font-size: .82rem; font-weight: 500;
  cursor: pointer;
}
.sync-btn:hover { background: #fde68a; border-color: #f59e0b; }

/* Upload area docked just above the chat input. Two stacked .upload-row
   forms — one for techdumps (.gz family), one for free-form artifacts.
   Each row carries its own trigger label, file input (visually hidden),
   Upload button, and pending-filename span. The pending chip + Upload
   button only become prominent when files are selected. */
.upload-stack {
  display: flex; flex-direction: column;
  border-top: 1px solid #f3f4f6;
  background: #fafafa;
}
.upload-row {
  display: flex; align-items: center; gap: .5rem;
  padding: .2rem .85rem;
  font-size: .85rem;
}
.upload-row + .upload-row {
  border-top: 1px solid #f3f4f6;
}
.upload-row input[type="file"] { display: none; }
.upload-trigger {
  background: transparent; color: #44403c;
  border: 1px dashed #a8a29e; border-radius: 4px;
  padding: .3rem .7rem;
  font-size: .82rem; font-weight: 500;
  cursor: pointer;
  transition: background .1s ease, border-color .1s ease;
  flex: 0 0 9rem;        /* stable width so both forms align under each other */
}
.upload-trigger:hover { background: #f5f5f4; border-color: #57534e; }
/* Techdumps get an indigo accent so the user's eye separates the two
   options at a glance — the techdump path is destructive (extracts +
   indexes a multi-MB tarball into the case dir) and worth a chrome
   distinction from the lightweight artifact path. */
.upload-trigger-dump {
  border-color: #818cf8;
  color: #4338ca;
}
.upload-trigger-dump:hover {
  background: #eef2ff;
  border-color: #4f46e5;
}
.upload-pending {
  flex: 1;
  font-size: .8rem; color: #4338ca;
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.upload-submit {
  background: #4338ca; color: #fff;
  border: 0; border-radius: 4px;
  padding: .3rem .9rem;
  font-size: .82rem; font-weight: 500;
  cursor: pointer;
  flex: 0 0 auto;
}
/* When no files are selected, the Upload CTA hides entirely so the row
   is just the small "📎 Attach files" affordance. */
.upload-submit:disabled {
  visibility: hidden;   /* keep layout space stable; toggle on file select */
  pointer-events: none;
}
.upload-submit:hover:not(:disabled) { background: #3730a3; }

/* "RCA" button — sits next to Send. Distinct accent color so users
   notice it as the one-click first-pass RCA shortcut. */
.rca-btn {
  background: #fef3c7; color: #92400e;
  border: 1px solid #fcd34d; border-radius: 4px;
  padding: 0 1rem;
  font-size: .92rem; font-weight: 500;
  cursor: pointer;
  white-space: nowrap;
}
.rca-btn:hover:not(:disabled) { background: #fde68a; border-color: #f59e0b; }
.rca-btn:disabled { background: #f3f4f6; color: #9ca3af; border-color: #e5e7eb; cursor: default; }

/* 🚀 Deep mode toggle — sits next to RCA in the chat input row. Off
   state is muted so the default Send is still visually dominant; on
   state pops indigo to remind the user every turn is going to the
   boost-tier model (cost discipline). */
.deep-btn {
  background: #f5f5f4; color: #44403c;
  border: 1px solid #d6d3d1; border-radius: 4px;
  padding: 0 .9rem;
  font-size: .92rem; font-weight: 500;
  cursor: pointer;
  white-space: nowrap;
  transition: background .1s ease, border-color .1s ease, color .1s ease;
}
.deep-btn:hover:not(:disabled) { background: #e7e5e4; border-color: #a8a29e; }
.deep-btn.deep-on {
  background: #4338ca; color: #fff; border-color: #3730a3;
}
.deep-btn.deep-on:hover { background: #3730a3; border-color: #312e81; }
.deep-btn:disabled { background: #f3f4f6; color: #9ca3af; border-color: #e5e7eb; cursor: default; }
/* Subtle indigo hairline at the top of the input row when Deep is on. */
.chat-input-row.deep-mode-on { border-top-color: #818cf8; }


/* --- Save-as-KB modal ------------------------------------------------- */

.modal-backdrop {
  position: fixed; inset: 0;
  background: rgba(15, 23, 42, .55);
  display: flex; align-items: center; justify-content: center;
  z-index: 1000;
}
.modal-card {
  background: #fff; border-radius: 10px;
  width: min(640px, 92vw);
  max-height: 90vh;
  overflow-y: auto;
  box-shadow: 0 12px 40px rgba(0, 0, 0, .25);
}
.modal-card header {
  background: #fff; color: #111827;
  padding: 1rem 1.25rem .85rem;
  border-bottom: 1px solid #e5e7eb;
  display: flex; align-items: center; justify-content: space-between;
}
.modal-card header h2 { margin: 0; font-size: 1.05rem; }
.modal-close {
  background: transparent; border: 0; color: #6b7280;
  font-size: 1.5rem; line-height: 1; cursor: pointer;
  padding: 0 .35rem;
}
.modal-close:hover { color: #111827; }
.modal-body {
  padding: 1rem 1.25rem;
  font-size: .95rem;
}
.modal-body label {
  display: block;
  font-weight: 600; font-size: .88rem;
  margin: .85rem 0 .35rem;
  color: #374151;
}
.modal-body label:first-child { margin-top: 0; }
.modal-body textarea {
  width: 100%;
  padding: .6rem .75rem;
  border: 1px solid #d1d5db; border-radius: 6px;
  font: inherit; font-size: .95rem; line-height: 1.5;
  resize: vertical;
}
.modal-body textarea:focus { outline: 2px solid #2563eb; outline-offset: 1px; }
.modal-hint {
  font-size: .82rem; color: #6b7280;
  margin: 0 0 .25rem;
}
.modal-actions {
  display: flex; justify-content: flex-end; gap: .5rem;
  padding: .85rem 1.25rem 1.1rem;
  border-top: 1px solid #f3f4f6;
}
.modal-actions button { margin: 0; }
.modal-actions .ghost-btn { padding: .5rem 1rem; }
.modal-actions .primary { padding: .5rem 1.2rem; }

.sync-banner {
  background: #f0f9ff; color: #1e3a8a;
  border: 1px solid #bfdbfe; border-radius: 6px;
  padding: .65rem .9rem; margin-bottom: .85rem;
  font-size: .92rem;
  display: flex; align-items: center; gap: .65rem;
}
.sync-banner .sync-spinner {
  display: inline-block;
  animation: spin 2s linear infinite;
  font-size: 1.1rem;
}
@keyframes spin {
  from { transform: rotate(0deg); }
  to   { transform: rotate(360deg); }
}

/* Two-pane area below: chat + activity */
.case-page {
  display: grid;
  grid-template-columns: 1fr 360px;
  gap: 1rem;
  height: calc(100vh - 11rem);   /* viewport minus header + topbar + strip */
  min-height: 480px;
  position: relative;            /* anchor for the floating "Show Activity" pill */
}

/* Activity-pane collapsed state — JS toggles `activity-collapsed` on
   .case-page based on a per-case localStorage flag. When set, the
   chat takes the full grid width and the activity pane is hidden;
   the floating "Show Activity" pill appears bottom-right of the
   chat as the way to bring the pane back. Lots more reading room
   when collapsed; sub-second toggle preserved across reloads. */
.case-page.activity-collapsed {
  grid-template-columns: 1fr;
}
.case-page.activity-collapsed .activity-pane {
  display: none;
}

/* Header row inside the activity pane — title on the left, collapse
   button on the right. */
.activity-pane .activity-header {
  display: flex; align-items: center; justify-content: space-between;
  margin-bottom: .35rem;
}
.activity-pane .activity-header h2 { margin: 0; }
.activity-collapse-btn {
  background: transparent;
  border: 1px solid #d1d5db;
  border-radius: 4px;
  padding: .15rem .55rem;
  font-size: .75rem;
  color: #4b5563;
  cursor: pointer;
}
.activity-collapse-btn:hover {
  background: #f3f4f6;
  color: #1f2937;
}

/* Floating "Show Activity" pill — bottom-right of the case-page when
   the activity pane is hidden. Hidden by default; revealed when
   .case-page has the .activity-collapsed class. */
.activity-show-btn {
  display: none;
  position: absolute;
  bottom: .75rem;
  right: .75rem;
  background: #1d4ed8;
  color: #fff;
  border: 1px solid #1e3a8a;
  border-radius: 999px;
  padding: .35rem .85rem;
  font-size: .8rem;
  cursor: pointer;
  box-shadow: 0 2px 8px rgba(0, 0, 0, .15);
  z-index: 10;
}
.activity-show-btn:hover { background: #1e3a8a; }
.case-page.activity-collapsed .activity-show-btn {
  display: inline-block;
}

/* The chat column is just a wrapper that lets chat-pane fill its grid
   cell; no extra chrome. min-width:0 + min-height:0 are the
   "let-flex-shrink" pair — without min-height:0 the chat-history
   inside .chat-pane can't actually scroll (default min-height: auto
   keeps it at content-size, ignoring overflow:auto). */
.chat-column {
  display: flex; flex-direction: column;
  min-width: 0;
  min-height: 0;
}


/* In-chat context blocks (synopsis, prior findings) — collapsible cards
   that live AT THE TOP of the chat history scroll, before any turns. */
.chat-context {
  margin: 0 0 1rem;
  border: 1px solid #dbeafe;
  background: #f0f9ff;
  border-radius: 8px;
  overflow: hidden;
}
.chat-context > summary {
  cursor: pointer;
  padding: .65rem .9rem;
  font-weight: 600;
  font-size: .9rem;
  color: #1e3a8a;
  list-style: none;
  user-select: none;
  display: flex; align-items: center; gap: .35rem;
}
.chat-context > summary::-webkit-details-marker { display: none; }
.chat-context > summary::after {
  content: "▾";
  margin-left: auto;
  color: #6b7280;
  font-size: .8rem;
  transition: transform .15s ease;
}
.chat-context:not([open]) > summary::after { transform: rotate(-90deg); }
.chat-context > summary:hover { background: rgba(255,255,255,.5); }
.chat-context .context-body {
  border-top: 1px solid #dbeafe;
  background: #fff;
  border-radius: 0 0 8px 8px;
  padding: .85rem 1.1rem;
  max-height: 28rem;
  overflow-y: auto;
}

.prior-divider {
  border-top: 1px dashed #d1d5db;
  padding-top: .85rem !important;
  margin-top: .25rem;
}


/* --- Context blocks (synopsis, prior findings) ----------------------- */

.context-block {
  background: #fff; border: 1px solid #e5e7eb; border-radius: 6px;
  padding: 0; margin-bottom: 1rem;
}
.context-block > summary {
  cursor: pointer;
  padding: .8rem 1rem;
  font-weight: 600; font-size: .95rem;
  color: #1f2937;
  list-style: none;
  user-select: none;
  border-radius: 6px;
}
.context-block > summary::-webkit-details-marker { display: none; }
.context-block > summary::before {
  content: "▸"; display: inline-block;
  margin-right: .5rem; color: #6b7280;
  transition: transform .15s ease;
}
.context-block[open] > summary::before { transform: rotate(90deg); }
.context-block > summary:hover { background: #f9fafb; }

.context-body {
  margin: 0; padding: 1rem 1.25rem 1.15rem;
  border-top: 1px solid #f3f4f6;
  background: #fff;
  color: #1f2937;
  font-size: 1rem; line-height: 1.6;
  max-height: 28rem;
  overflow-y: auto;
  border-bottom-left-radius: 6px;
  border-bottom-right-radius: 6px;
}

/* Server-rendered markdown body. Used by both the inline context
   blocks (synopsis, prior findings) AND chat msg-body for assistant
   replies (live + prior). Tuned for readable but information-dense
   text — bumped sizes from earlier iteration after user feedback that
   the synopsis looked cramped. */
.context-html { font-size: 1rem; line-height: 1.6; }
.context-html h1,
.context-html h2,
.context-html h3 {
  margin: 1rem 0 .5rem; line-height: 1.3;
}
.context-html h1:first-child,
.context-html h2:first-child,
.context-html h3:first-child { margin-top: 0; }
.context-html h1 { font-size: 1.3rem; font-weight: 600; }
.context-html h2 {
  font-size: 1.15rem; font-weight: 600;
  border-bottom: 1px solid #e5e7eb; padding-bottom: .25rem;
}
.context-html h3 { font-size: 1.02rem; font-weight: 600; }
.context-html p { margin: .55rem 0; }
.context-html ul, .context-html ol { margin: .55rem 0; padding-left: 1.5rem; }
.context-html li { margin: .35rem 0; }
.context-html strong { color: #111827; font-weight: 600; }
.context-html em { color: #374151; }
.context-html code {
  background: #f1f5f9; color: #be185d;
  padding: 1px 5px; border-radius: 3px;
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  font-size: .92em;
}
.context-html pre {
  background: #f9fafb; border: 1px solid #e5e7eb;
  border-radius: 4px; padding: .75rem .9rem;
  margin: .75rem 0;
  overflow-x: auto;
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  font-size: .92rem; line-height: 1.5;
}
.context-html pre code {
  background: none; color: inherit; padding: 0;
  font-size: 1em;   /* parent <pre> already sized; don't double-shrink */
}
.context-html hr {
  border: 0; border-top: 1px solid #e5e7eb;
  margin: 1rem 0;
}
.context-html blockquote {
  border-left: 3px solid #cbd5e1;
  margin: .75rem 0; padding: .25rem 1rem;
  color: #475569;
}
.context-html a { color: #2563eb; text-decoration: none; }
.context-html a:hover { text-decoration: underline; }

/* When .context-html is on a chat .msg-body, override pre-wrap so the
   markdown structure renders cleanly. */
.msg-body.context-html { white-space: normal; }


/* --- Chat layout ------------------------------------------------------ */

.chat-pane {
  display: flex; flex-direction: column;
  background: #fff; border: 1px solid #e5e7eb; border-radius: 6px;
  overflow: hidden;
  min-width: 0;
  min-height: 0;     /* let chat-history's overflow:auto actually scroll */
  flex: 1 1 auto;    /* fills the chat-column wrapper height */
}
.chat-history {
  flex: 1 1 auto; overflow-y: auto;
  padding: 1.15rem 1.25rem; line-height: 1.6;
}

.msg {
  margin-bottom: 1.1rem; padding: .85rem 1rem;
  border-radius: 8px; max-width: 95%;
  font-size: 1rem;
}
.msg.muted { background: transparent; padding: .35rem 0; color: #6b7280; }
.msg-label {
  font-size: .78rem; text-transform: uppercase;
  letter-spacing: .6px; color: #6b7280;
  margin-bottom: .4rem; font-weight: 600;
}
.msg-user { background: #eff6ff; border: 1px solid #dbeafe; }
.msg-user .msg-label { color: #1d4ed8; }
.msg-assistant { background: #f8fafc; border: 1px solid #e5e7eb; }
.msg-assistant .msg-label { color: #047857; }
.msg-body { white-space: pre-wrap; word-wrap: break-word; }
.msg-error { background: #fee2e2; color: #991b1b; }

.msg-actions { margin-top: .65rem; display: flex; gap: .5rem; }

/* "Agent is thinking" placeholder — shown immediately after Send,
   updated with the current tool name as events stream in, removed
   when the assistant_message frame lands. */
.msg-thinking {
  background: #f8fafc; border: 1px solid #e5e7eb;
}
.msg-thinking .msg-label { color: #047857; }
.msg-thinking .thinking-body {
  display: flex; align-items: center; gap: .5rem;
  font-style: italic; color: #6b7280;
}
.thinking-dots { display: inline-flex; gap: 3px; align-items: center; }
.thinking-dots > span {
  display: inline-block;
  width: 7px; height: 7px;
  background: #6b7280; border-radius: 50%;
  animation: dot-bounce 1.3s ease-in-out infinite both;
}
.thinking-dots > span:nth-child(1) { animation-delay: -0.32s; }
.thinking-dots > span:nth-child(2) { animation-delay: -0.16s; }
@keyframes dot-bounce {
  0%, 80%, 100% { transform: scale(0.6); opacity: .4; }
  40%           { transform: scale(1);   opacity: 1; }
}

/* "Prior" tag on server-rendered turns from earlier sessions, so the
   user can see at a glance what's history vs what they're producing
   right now. */
.msg-prior { opacity: .92; }
.prior-tag {
  display: inline-block;
  margin-left: .5rem;
  padding: 1px 6px;
  border-radius: 3px;
  background: #e5e7eb;
  color: #6b7280;
  font-weight: 500;
  font-size: .65rem;
  letter-spacing: .4px;
  text-transform: lowercase;
}


/* --- Chat input ------------------------------------------------------- */

.chat-input-row {
  display: flex; gap: .65rem;
  padding: .85rem;
  border-top: 1px solid #e5e7eb;
  background: #f9fafb;
}
.chat-input-row textarea {
  flex: 1; resize: none;
  padding: .65rem .85rem;
  border: 1px solid #d1d5db; border-radius: 4px;
  font-family: inherit; font-size: 1rem; line-height: 1.5;
}
.chat-input-row textarea:focus { outline: 2px solid #2563eb; outline-offset: 1px; }
.chat-input-row button.primary { margin: 0; padding: 0 1.4rem; }
/* Send button morphs to Stop while a turn is in flight. Red accent
   so the destructive action reads at a glance; matches the chat-app
   convention of using muted red for "stop / cancel". */
.chat-input-row button.primary.stop-mode {
  background: #b91c1c;
}
.chat-input-row button.primary.stop-mode:hover:not(:disabled) {
  background: #991b1b;
}
.chat-input-row button.primary.stop-mode:disabled {
  background: #7f1d1d; opacity: .7;
}


/* --- Activity pane (right sidebar) ----------------------------------- */

.activity-pane {
  background: #fff; border: 1px solid #e5e7eb; border-radius: 6px;
  display: flex; flex-direction: column;
  overflow: hidden;
  min-width: 0;
  min-height: 0;     /* let activity-log's overflow:auto actually scroll */
  /* In the case-page grid, this is just one of three columns; height
     is governed by the .case-page grid row. */
}
.activity-pane h2 {
  margin: 0; padding: .85rem 1rem;
  font-size: 1rem; font-weight: 600;
  border-bottom: 1px solid #e5e7eb; background: #f9fafb;
}
.activity-log {
  flex: 1; overflow-y: auto;
  padding: .65rem .9rem;
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  font-size: .9rem;
}
.activity-row {
  padding: .35rem 0; border-bottom: 1px dotted #e5e7eb;
  display: grid;
  grid-template-columns: auto 1fr auto;
  gap: .55rem;
  align-items: center;
}
.activity-row .ts { color: #6b7280; font-size: .82rem; }
.activity-row .tool { color: #1f2937; font-weight: 500; }
.activity-row .param {
  color: #6b7280; font-size: .82rem;
  grid-column: 1 / -1; padding-left: 5rem;
}
.activity-row .status { color: #047857; font-weight: 600; }
.activity-row.err .status { color: #b91c1c; }
.activity-row .activity-error {
  grid-column: 1 / -1; padding-left: 5rem;
  color: #b91c1c; font-size: .82rem;
}

/* Turn divider in the activity pane — drops a strip whenever the user
   sends a question, so subsequent tool-call rows visually belong to
   that question. Past dividers persist (history is preserved). */
.activity-turn-divider {
  margin: .85rem -.9rem .25rem;   /* breach the panel padding for full width */
  padding: .4rem .9rem;
  background: #eff6ff;
  border-top: 1px solid #dbeafe;
  border-bottom: 1px solid #dbeafe;
  color: #1e3a8a;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
  font-size: .82rem;
  font-weight: 500;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.activity-turn-divider:first-child { margin-top: 0; }

/* Reasoning-trace blocks in the activity pane — appears only when the
   active turn is on a reasoning model (REASONING_MODEL_MODE / Deep
   analysis with GLM). Collapsed by default; click summary to expand. */
.activity-reasoning {
  margin: .3rem 0;
  padding: .25rem .5rem;
  background: #fffbeb;
  border-left: 3px solid #f59e0b;
  border-radius: 4px;
  font-size: .82rem;
}
.activity-reasoning summary {
  display: grid;
  grid-template-columns: 4.5rem 5.5rem 1fr;
  align-items: baseline;
  gap: .4rem;
  cursor: pointer;
  list-style: none;
  color: #78350f;
}
.activity-reasoning summary::-webkit-details-marker { display: none; }
.activity-reasoning summary .ts { color: #92400e; font-size: .78rem; }
.activity-reasoning summary .rlabel { color: #b45309; font-weight: 500; }
.activity-reasoning summary .rpreview {
  color: #57534e;
  font-style: italic;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: .78rem;
}
.activity-reasoning[open] summary .rpreview { white-space: normal; }
.activity-reasoning-body {
  margin: .4rem 0 .1rem;
  padding: .5rem .65rem;
  background: #fff;
  border: 1px solid #fde68a;
  border-radius: 3px;
  font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace;
  font-size: .78rem;
  line-height: 1.45;
  white-space: pre-wrap;
  word-break: break-word;
  max-height: 24rem;
  overflow-y: auto;
  color: #1f2937;
}

/* Summary-checkpoint blocks — high-signal mid-investigation updates
   the agent emits via submit_summary. Always-expanded (no <details>);
   teal/green so they're visually distinct from amber thinking blocks
   and standard tool-call rows. Appears only when the active turn is
   on a reasoning model (REASONING_MODEL_MODE / Deep analysis). */
.activity-checkpoint {
  margin: .5rem 0;
  padding: .5rem .65rem;
  background: #ecfeff;
  border-left: 3px solid #0891b2;
  border-radius: 4px;
}
.activity-checkpoint-head {
  display: grid;
  grid-template-columns: 4.5rem 7rem 1fr;
  align-items: baseline;
  gap: .4rem;
  font-size: .82rem;
  margin-bottom: .35rem;
}
.activity-checkpoint-head .ts { color: #155e75; font-size: .78rem; }
.activity-checkpoint-head .clabel { color: #0e7490; font-weight: 600; }
.activity-checkpoint-head .ccount {
  color: #475569;
  font-size: .76rem;
  font-style: italic;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.activity-checkpoint .ckp-section { margin: .35rem 0; }
.activity-checkpoint .ckp-title {
  font-size: .72rem;
  font-weight: 600;
  letter-spacing: .04em;
  color: #0e7490;
  margin-bottom: .15rem;
}
.activity-checkpoint .ckp-list {
  margin: 0 0 0 1.1rem;
  padding: 0;
  font-size: .82rem;
  line-height: 1.4;
  color: #1f2937;
}
.activity-checkpoint .ckp-list li { margin: .1rem 0; }
.activity-checkpoint .ckp-next {
  padding: .35rem .5rem;
  background: #fff;
  border: 1px solid #cffafe;
  border-radius: 3px;
  font-size: .82rem;
  line-height: 1.4;
  color: #1f2937;
}


/* --- Responsive breakpoints ------------------------------------------ */

/* Narrow desktops / large tablets: shrink activity column. */
@media (max-width: 1200px) {
  .case-page { grid-template-columns: 1fr 320px; }
}

/* Tablets: stack chat above activity, and let the page scroll naturally —
   cramming everything into the viewport stops being useful at this size. */
@media (max-width: 900px) {
  main.layout-wide { padding: 0 .85rem; }
  .case-page {
    grid-template-columns: 1fr;
    grid-template-rows: 1fr auto;
    height: auto;
  }
  .chat-pane { height: 60vh; min-height: 360px; }
  .activity-pane { height: 28vh; min-height: 200px; }
  .attachments-strip { flex-wrap: wrap; }
  /* Drop the viewport-lock so the page can scroll the topbar away if
     the user prefers. */
  body.case-view-page { height: auto; overflow: visible; }
  body.case-view-page main.layout-wide { flex: 0 0 auto; }
  body.case-view-page .case-page { flex: 0 0 auto; }
}

/* Home page: smaller laptops — sidebar stays at 240px, composer
   gets a bit less padding. */
@media (max-width: 1100px) {
  .home-page { grid-template-columns: 240px 1fr; }
  .home-main { padding: 1.5rem 1.25rem; }
}

/* Home page: tablets and below — drop the sidebar, stack list above
   composer (and let the page scroll naturally). */
@media (max-width: 800px) {
  body.home-page-body { height: auto; overflow: visible; }
  .home-page {
    grid-template-columns: 1fr;
  }
  .cases-sidebar {
    border-right: 0; border-bottom: 1px solid #e7e5e4;
    max-height: 30vh;
  }
  .home-main { padding: 1.5rem 1rem; }
}

/* Phones / very narrow windows: shrink chrome. */
@media (max-width: 640px) {
  html { font-size: 16px; }
  main.layout-narrow { margin: 1rem auto; padding: 0 .85rem; }
  header { padding: .65rem 1rem; flex-wrap: wrap; gap: .5rem; }
  .brand { font-size: 1rem; }
  nav .user { font-size: .85rem; }

  .login-box { margin: 1.5rem 0; padding: 1.5rem; }

  .chat-input-row { padding: .65rem; }
  .chat-input-row textarea { font-size: 16px; /* avoid iOS auto-zoom */ }

  .context-body { font-size: .82rem; padding: .75rem .9rem; }

  .home-greeting h1 { font-size: 1.4rem; }
  .composer-actions { flex-wrap: wrap; }
}


/* --- KB browser ------------------------------------------------------ */

.kb-page { padding: 1rem 0 2rem; }
.kb-header { margin-bottom: 1.25rem; }
.kb-header h1 { font-size: 1.45rem; margin: 0 0 .25rem; }
.kb-header .muted { font-size: .92rem; }

.kb-empty {
  background: #fff; border: 1px solid #e5e7eb; border-radius: 6px;
  padding: 1rem 1.25rem; font-size: .95rem;
}
.kb-empty code {
  background: #f1f5f9; padding: 1px 5px; border-radius: 3px;
  font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: .9em;
}

.kb-table {
  width: 100%; border-collapse: collapse;
  background: #fff; border: 1px solid #e5e7eb; border-radius: 6px;
  overflow: hidden;
}
.kb-table thead {
  background: #f9fafb;
  border-bottom: 1px solid #e5e7eb;
}
.kb-table th, .kb-table td {
  padding: .65rem .85rem;
  text-align: left;
  vertical-align: top;
  font-size: .92rem;
  border-bottom: 1px solid #f3f4f6;
}
.kb-table th {
  font-weight: 600; color: #374151;
  font-size: .82rem; letter-spacing: .3px; text-transform: uppercase;
}
.kb-table tbody tr:hover { background: #fafafa; }
.kb-title-cell a {
  color: #1d4ed8; text-decoration: none; font-weight: 500;
}
.kb-title-cell a:hover { text-decoration: underline; }
.kb-case-slug, .kb-ticket {
  font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: .88rem;
  color: #4b5563;
}
.kb-date {
  font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: .82rem;
  color: #6b7280; white-space: nowrap;
}
.kb-tag {
  display: inline-block;
  background: #ede9fe; color: #5b21b6;
  font-size: .72rem; font-weight: 500;
  padding: 1px 7px; border-radius: 3px;
  margin-right: .25rem;
}

/* --- KB detail page -------------------------------------------------- */

.kb-detail { padding: 1rem 0 2rem; }
.kb-detail .back-link {
  display: inline-block;
  color: #2563eb; text-decoration: none; font-size: .9rem;
  margin-bottom: .85rem;
}
.kb-detail .back-link:hover { text-decoration: underline; }

.kb-meta-strip {
  display: flex; flex-wrap: wrap; gap: .35rem;
  margin-bottom: 1.25rem;
  padding: .65rem .85rem;
  background: #f9fafb; border: 1px solid #e5e7eb; border-radius: 6px;
  font-size: .85rem;
}
.kb-meta-chip {
  background: #fff;
  border: 1px solid #e5e7eb; border-radius: 4px;
  padding: 2px 8px; color: #4b5563;
}
.kb-meta-chip code {
  background: transparent; padding: 0;
  font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: .9em;
  color: inherit;
}

.kb-body {
  background: #fff; border: 1px solid #e5e7eb; border-radius: 8px;
  padding: 1.25rem 1.5rem;
}

/* ============================================================== */
/* Engineering feedback — case-page <details> + aggregator page.    */
/* Gates on ENG_FEEDBACK_ENABLED; styles only render when wrapping  */
/* templates do.                                                    */
/* ============================================================== */

.ef-section {
  margin: 1.5rem 0; padding: .5rem 1rem;
  border: 1px solid #e5e7eb; border-radius: 6px;
  background: #f9fafb;
}
.ef-section > summary {
  cursor: pointer; font-weight: 600; padding: .25rem 0;
}
.ef-pending-count {
  display: inline-block; margin-left: .5rem;
  background: #f59e0b; color: #fff; padding: .1rem .4rem;
  border-radius: 3px; font-size: .75rem; font-weight: 600;
}
.ef-subsection { margin: .75rem 0 1rem; }
.ef-subsection h4 { margin: 0 0 .4rem; font-size: .9rem; color: #374151; }
.ef-empty { font-size: .85rem; }

.ef-add-form { display: flex; flex-direction: column; gap: .4rem; max-width: 600px; }
.ef-add-form select, .ef-add-form textarea {
  padding: .35rem .5rem; font-size: .85rem;
  border: 1px solid #d1d5db; border-radius: 4px; font-family: inherit;
}
.ef-add-form textarea { resize: vertical; }
.ef-submit-btn, .ef-filter-btn {
  background: #1d4ed8; color: #fff; border: none; padding: .35rem .75rem;
  border-radius: 4px; cursor: pointer; font-size: .85rem; align-self: flex-start;
}
.ef-submit-btn:hover, .ef-filter-btn:hover { background: #1e3a8a; }

.ef-pending-list, .ef-entry-list, .ef-member-list { list-style: none; padding: 0; margin: 0; }
.ef-pending-row, .ef-entry-row, .ef-cluster-row {
  border: 1px solid #e5e7eb; border-radius: 4px;
  padding: .5rem .75rem; margin: .4rem 0;
  background: #fff;
}
.ef-pending-row { background: #fffbeb; border-color: #fcd34d; }
.ef-row-meta { font-size: .8rem; margin-bottom: .25rem; }
.ef-row-text { font-size: .9rem; line-height: 1.4; white-space: pre-wrap; }
.ef-row-actions { margin-top: .4rem; display: flex; gap: .4rem; align-items: center; }

.ef-cat-badge {
  display: inline-block; padding: .1rem .4rem; border-radius: 3px;
  font-size: .7rem; font-weight: 600;
  background: #dbeafe; color: #1e3a8a; margin-right: .3rem;
}
.ef-case-link { color: #1d4ed8; text-decoration: none; }
.ef-case-link:hover { text-decoration: underline; }

.ef-approve-btn, .ef-reject-btn, .ef-triage-btn, .ef-issue-btn {
  font-size: .75rem; padding: .25rem .55rem; border-radius: 3px;
  cursor: pointer; border: 1px solid; text-decoration: none; display: inline-block;
}
.ef-approve-btn { background: #16a34a; color: #fff; border-color: #15803d; }
.ef-approve-btn:hover { background: #15803d; }
.ef-reject-btn { background: transparent; color: #b91c1c; border-color: #fca5a5; }
.ef-reject-btn:hover { background: #fee2e2; }
.ef-triage-btn { background: #6b7280; color: #fff; border-color: #4b5563; }
.ef-triage-btn:hover { background: #4b5563; }
.ef-issue-btn { background: transparent; color: #1d4ed8; border-color: #93c5fd; }
.ef-issue-btn:hover { background: #eff6ff; }

/* Aggregator page surfaces. */
.eng-feedback-page .ef-page-header { margin-bottom: 1rem; }
.ef-orientation {
  display: flex; gap: 1rem; flex-wrap: wrap;
  margin: 1rem 0; padding: .75rem;
  background: #f3f4f6; border-radius: 6px;
}
.ef-stat { display: flex; flex-direction: column; min-width: 120px; }
.ef-stat-value { font-size: 1.5rem; font-weight: 700; color: #1f2937; }
.ef-stat-label { font-size: .75rem; color: #6b7280; }

.ef-cat-bar { display: flex; gap: .25rem; flex-wrap: wrap; margin: .75rem 0; }
.ef-cat-pill {
  display: inline-block; padding: .2rem .6rem; border-radius: 3px;
  background: #e5e7eb; color: #374151; font-size: .75rem;
  text-decoration: none;
}
.ef-cat-pill:hover { background: #d1d5db; }
.ef-cat-pill-active { background: #1d4ed8; color: #fff; }
.ef-cat-pill-active:hover { background: #1e3a8a; }
.ef-cat-count { opacity: .7; margin-left: .25rem; }

.ef-filters { margin: 1rem 0; }
.ef-filter-form { display: flex; gap: .5rem; align-items: center; flex-wrap: wrap; font-size: .85rem; }
.ef-search { padding: .3rem .5rem; border: 1px solid #d1d5db; border-radius: 4px; min-width: 200px; }
.ef-filter-form select { padding: .3rem .4rem; border: 1px solid #d1d5db; border-radius: 4px; }

.ef-cluster-row { padding: .75rem 1rem; }
.ef-cluster-details { margin-top: .4rem; font-size: .8rem; }
.ef-cluster-details summary { cursor: pointer; color: #6b7280; }
.ef-member-list li { padding: .25rem 0; border-top: 1px dashed #e5e7eb; }
.ef-member-text { color: #4b5563; margin-top: .15rem; padding-left: .5rem; border-left: 2px solid #e5e7eb; }
.ef-cluster-triaged { opacity: .55; }
.ef-reemerged {
  display: inline-block; background: #fef3c7; color: #92400e;
  padding: 0 .35rem; border-radius: 3px; font-size: .7rem; font-weight: 600;
  margin-left: .4rem;
}

/* Topbar nav badge for pending count. */
.nav-badge {
  display: inline-block; background: #f59e0b; color: #fff;
  padding: 0 .35rem; border-radius: 3px; font-size: .7rem; font-weight: 600;
}

/* Creator email shown next to a case slug — slightly muted so the
   case name + slug stay primary. Used on both the cases list and
   the case-view topbar. */
.case-creator {
  color: #4b5563;
  font-style: italic;
}

/* Per-attachment Remove button (× glyph) on each chip in the
   attachments strip. Subtle by default; reddens on hover so misclicks
   stand out. The form wrapper is inline to keep the chip on one line. */
.att-delete-form {
  display: inline;
  margin: 0; padding: 0;
}
.att-delete {
  background: none; border: none;
  color: #999; font-size: 1rem; line-height: 1;
  padding: 0 .25rem; margin-left: .25rem;
  cursor: pointer; border-radius: 3px;
}
.att-delete:hover {
  color: #b91c1c; background: #fee2e2;
}

/* Admin-only "Delete case" button at the bottom of a case page.
   Compact: just a small red text-button, right-aligned, with all
   warning copy delivered via the confirm dialog rather than a
   permanent banner. The button still reads as destructive (red),
   but takes minimal real estate. */
.danger-form-compact {
  margin: 1.5rem 0 .5rem; text-align: right;
}
.danger-btn-compact {
  background: transparent; color: #b91c1c; border: 1px solid #fca5a5;
  padding: .25rem .6rem; border-radius: 4px;
  font-size: .8rem; cursor: pointer;
  opacity: .75;
  transition: opacity .15s, background-color .15s, color .15s;
}
.danger-btn-compact:hover {
  opacity: 1;
  background: #dc2626; color: #fff; border-color: #991b1b;
}

/* Clickable provenance tags inside agent replies — only emitted for
   query_logs / read_logs_in_time_window. Subtle so they don't
   visually compete with the prose, but obviously interactive. */
.cite-link {
  color: #1d4ed8;
  text-decoration: none;
  border-bottom: 1px dashed #93c5fd;
  cursor: pointer;
}
.cite-link:hover {
  color: #1e3a8a;
  border-bottom-color: #1d4ed8;
  background: #eff6ff;
}


/* ============================================================================
   Topology — button (topbar) + native <dialog> modal + Mermaid container
   ============================================================================ */

/* Mirrors .refresh-zd-btn's shape so the topbar reads as one cluster. */
.topology-btn {
  background: #f0fdf4; color: #14532d;
  border: 1px solid #bbf7d0; border-radius: 4px;
  padding: .2rem .55rem;
  font-size: .76rem; font-weight: 500;
  cursor: pointer;
  position: relative;
  transition: background .1s ease, border-color .1s ease;
}
.topology-btn:hover { background: #dcfce7; border-color: #4ade80; }
.topology-btn:disabled { opacity: .55; cursor: progress; }
.topology-btn.is-stale { border-color: #fb923c; }
.topology-dot {
  color: #ea580c;
  font-weight: 700;
  margin-left: .15rem;
}

/* Native <dialog>. ESC + backdrop click are free.
   Layout: modal-inner is a flex column where the chrome (header,
   progress, narrative, source, actions) is fixed-height and the
   diagram is the only flexible child. The diagram dominates the
   modal as the actual content — not as an afterthought beneath
   the chrome it used to be. */
.topology-modal {
  width: min(96vw, 1200px);
  height: 92vh;
  max-width: 96vw; max-height: 92vh;
  border: 1px solid #d1d5db;
  border-radius: 8px;
  padding: 0;
  box-shadow: 0 24px 60px rgba(0,0,0,.25);
  background: #fff;
}
.topology-modal::backdrop { background: rgba(15,23,42,.55); }

/* Maximize toggle — operator-driven full-screen. Native <dialog>
   carries UA defaults that center it (`margin: auto`) AND cap its
   max-height to `calc(100vh - 2em - 6px)` on Chromium. Both have to
   be explicitly overridden or "100vh" silently clips. Use !important
   to win against any future global dialog rules without surgery. */
.topology-modal.is-maximized {
  width: 100vw !important;
  max-width: 100vw !important;
  height: 100vh !important;
  max-height: 100vh !important;
  top: 0 !important;
  left: 0 !important;
  right: 0 !important;
  bottom: 0 !important;
  margin: 0 !important;
  inset: 0 !important;
  border-radius: 0;
  border: none;
}

.topology-modal-inner {
  display: flex; flex-direction: column;
  height: 100%;
  padding: .6rem .85rem .65rem .85rem;
  gap: .45rem;
}

.topology-modal-head {
  flex: 0 0 auto;
  display: flex; align-items: center; justify-content: space-between;
  gap: 1rem;
  border-bottom: 1px solid #e5e7eb;
  padding-bottom: .35rem;
}
.topology-modal-head h2 {
  margin: 0; font-size: 1rem; color: #111827;
  display: inline-flex; align-items: center; gap: .55rem;
}
.topology-caveat-inline {
  /* Compact one-glance warning. Full text on hover via the title attr. */
  background: #fef3c7; color: #78350f;
  border: 1px solid #fcd34d; border-radius: 999px;
  padding: .08rem .55rem;
  font-size: .68rem; font-weight: 500;
  text-transform: uppercase; letter-spacing: .3px;
  cursor: help;
}
.topology-meta {
  margin: .1rem 0 0 0;
  font-size: .74rem; color: #6b7280;
}
.topology-head-actions {
  display: flex; align-items: center; gap: .15rem;
}
.topology-close, .topology-maximize {
  background: transparent;
  color: #6b7280;
  border: none; padding: 0 .3rem;
  font-size: 1.05rem; cursor: pointer;
}
.topology-close:hover, .topology-maximize:hover { color: #111827; }

/* Pre-existing caveat-banner rule kept for back-compat if anything
   still references the class; new template uses the inline pill above. */
.topology-caveat-banner {
  flex: 0 0 auto;
  margin: 0;
  background: #fef3c7; color: #78350f;
  border: 1px solid #fcd34d; border-radius: 6px;
  padding: .55rem .75rem;
  font-size: .8rem;
  line-height: 1.4;
}

/* Live progress lines while the mini-agent runs. */
.topology-progress {
  background: #f9fafb;
  border: 1px solid #e5e7eb; border-radius: 6px;
  padding: .4rem .65rem;
  flex: 0 0 auto;
  max-height: 7rem; overflow-y: auto;
  font-family: ui-monospace, SFMono-Regular, monospace;
  font-size: .72rem; color: #374151;
}
.topology-progress-line { padding: .08rem 0; }
.topology-progress-line.is-info { color: #1e40af; }
.topology-progress-line.is-error { color: #b91c1c; }

/* Narrative line(s) the LLM put above the ```mermaid fence. */
.topology-narrative {
  flex: 0 0 auto;
  background: #f0f9ff; color: #0c4a6e;
  border: 1px solid #bae6fd; border-radius: 6px;
  padding: .4rem .65rem;
  font-size: .78rem; line-height: 1.4;
  max-height: 5.5rem; overflow: auto;
}
.topology-narrative p { margin: 0 0 .25rem 0; }
.topology-narrative p:last-child { margin-bottom: 0; }

/* Mermaid renders its SVG inside .topology-stage. The diagram pane
   is the ONLY flexible child of modal-inner so it absorbs all
   leftover vertical space. .topology-stage holds the SVG and gets
   transform: scale(N) for in-diagram zoom — Cmd+ on the browser
   no longer fights with the chrome for vertical space. */
.topology-diagram {
  position: relative;
  flex: 1 1 auto;
  min-height: 0;
  background: #fff;
  border: 1px solid #e5e7eb; border-radius: 6px;
  padding: .5rem;
  overflow: auto;
}
.topology-stage {
  /* origin top-left so scaled diagrams grow DOWN+RIGHT into the
     parent's scrollable area. setZoom() sets transform. */
  transform-origin: 0 0;
  display: inline-block;
  min-width: 100%;
}
.topology-stage svg {
  display: block;
  max-width: 100%;
  height: auto;
}

/* Zoom controls — floating in the top-right of the diagram pane.
   Independent of browser zoom: Cmd+ inflates these too (they're
   chrome) but they stay usable; the SVG zoom they drive is
   independent. */
.topology-zoom-controls {
  position: absolute;
  top: .55rem; right: .55rem;
  display: inline-flex;
  gap: .15rem;
  background: rgba(255,255,255,.92);
  border: 1px solid #e5e7eb; border-radius: 4px;
  padding: .1rem;
  z-index: 5;
  box-shadow: 0 1px 3px rgba(0,0,0,.08);
}
.topology-zoom-controls button {
  background: transparent;
  color: #374151;
  border: none;
  padding: .15rem .55rem;
  font-size: .82rem; font-weight: 600;
  font-family: ui-monospace, SFMono-Regular, monospace;
  cursor: pointer;
  min-width: 1.8rem;
}
.topology-zoom-controls button:hover { background: #f3f4f6; }
.topology-error { color: #b91c1c; font-size: .9rem; padding: 1rem; }
.topology-error a { color: #1d4ed8; text-decoration: underline; }

/* Source viewer — collapsed by default. */
.topology-source { flex: 0 0 auto; font-size: .8rem; }
.topology-source summary {
  cursor: pointer; color: #4338ca;
  padding: .2rem 0;
}
.topology-source pre {
  background: #f3f4f6;
  border: 1px solid #e5e7eb; border-radius: 4px;
  padding: .45rem .6rem;
  max-height: 10rem; overflow: auto;
  font-size: .72rem;
  white-space: pre-wrap; word-break: break-word;
}

.topology-actions {
  flex: 0 0 auto;
  display: flex; align-items: center; gap: .65rem;
  padding-top: .2rem;
}
.topology-action-link {
  display: none;
  background: #eef2ff; color: #4338ca;
  border: 1px solid #c7d2fe; border-radius: 4px;
  padding: .25rem .65rem;
  font-size: .8rem; text-decoration: none;
}
.topology-action-link:hover { background: #e0e7ff; border-color: #818cf8; }
.topology-action-btn {
  background: #f0fdf4; color: #14532d;
  border: 1px solid #bbf7d0; border-radius: 4px;
  padding: .25rem .65rem;
  font-size: .8rem; cursor: pointer;
}
.topology-action-btn:hover { background: #dcfce7; border-color: #4ade80; }


/* --- Admin metrics page (/admin/metrics) ----------------------------- */
.metrics-page-header { margin-bottom: 1.25rem; }
.metrics-page-header h1 { margin: 0 0 .25rem; }
.metrics-window-picker {
  margin-top: .5rem;
  font-size: .9rem;
  color: #475569;
}
.metrics-window-picker a {
  display: inline-block;
  padding: .15rem .55rem;
  margin: 0 .15rem;
  border-radius: 3px;
  border: 1px solid #cbd5e1;
  text-decoration: none;
  color: #334155;
  background: #fff;
}
.metrics-window-picker a:hover { background: #f1f5f9; }
.metrics-window-picker a.active {
  background: #0e7490;
  border-color: #0e7490;
  color: #fff;
  font-weight: 600;
}
.metrics-empty {
  padding: 1.5rem;
  background: #f8fafc;
  border: 1px dashed #cbd5e1;
  border-radius: 6px;
  color: #475569;
}
.metrics-overview {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr));
  gap: .65rem;
  margin: 1rem 0 1.75rem;
}
.metric-card {
  padding: .75rem .85rem;
  background: #ecfeff;
  border-left: 3px solid #0891b2;
  border-radius: 4px;
}
.metric-card .metric-value {
  font-size: 1.55rem;
  font-weight: 600;
  color: #0e7490;
  line-height: 1.1;
}
.metric-card .metric-label {
  font-size: .78rem;
  color: #475569;
  margin-top: .15rem;
}
.metrics-block { margin: 1.5rem 0; }
.metrics-block h2 {
  font-size: 1.05rem;
  margin: 0 0 .4rem;
  color: #1e293b;
}
.metrics-table {
  width: 100%;
  border-collapse: collapse;
  font-size: .85rem;
}
.metrics-table th, .metrics-table td {
  padding: .35rem .55rem;
  border-bottom: 1px solid #e5e7eb;
  text-align: left;
  vertical-align: top;
}
.metrics-table th {
  background: #f1f5f9;
  font-weight: 600;
  color: #334155;
  font-size: .78rem;
  text-transform: uppercase;
  letter-spacing: .03em;
}
.metrics-table th.r, .metrics-table td.r { text-align: right; }
.metrics-table tbody tr:hover { background: #fafafa; }
.metrics-table td code {
  background: #f1f5f9;
  padding: .05rem .35rem;
  border-radius: 3px;
  font-size: .82rem;
}
.metrics-table .err { color: #b91c1c; font-weight: 600; }

/* --- Connection-state banner (Phase 1 WebSocket UX) ------------------ */
/* Shown at the top of the chat column when the WebSocket dropped,
   is being reconnected, has stalled (no heartbeat in 45s while a
   turn is in flight), or when a resumed connection tells us a turn
   is already running for this case in the background. */
.conn-banner {
  margin: 0 0 .65rem 0;
  padding: .55rem .85rem;
  border-radius: 4px;
  font-size: .88rem;
  line-height: 1.4;
  border: 1px solid;
  border-left-width: 3px;
}
.conn-banner-info {
  background: #ecfeff;
  color: #155e75;
  border-color: #0891b2;
}
.conn-banner-warn {
  background: #fef3c7;
  color: #78350f;
  border-color: #d97706;
}
