:root{
  --ink-950:#F2F5FC; --ink-800:#CDD5EA; --ink-600:#8D97B8; --ink-400:#5A6488;
  --paper-0:#0A0D13; --paper-50:#0D1119; --paper-100:#121729; --paper-200:#1A2136;
  --line:#232B44; --line-strong:#333D5C;
  --blue-500:#5B82FF; --blue-600:#84A2FF; --blue-100:#16203F;
  /* Selection has its own colour and is NOT --blue-100 (TASK-100). --blue-100 is the chip and
     badge fill, chosen to be low-contrast because it normally sits behind text. Used as the
     selection colour it measured 1.18:1 against the textarea it covers — invisible. */
  --select-bg:#3A62D8; --select-fg:#FFFFFF;
  --violet-500:#A66BFF; --violet-600:#BF92FF; --violet-100:#221A42;
  --pink-500:#FF5FA8; --pink-600:#FF8AC0; --pink-100:#3A1830;
  --focus:#84A2FF;
  --shadow: 0 1px 2px rgba(0,0,0,0.5), 0 12px 32px rgba(0,0,0,0.55);
  /* Type scale, adopted 2026-07-30. Measured off apple.com rather than guessed at:
     Display 24/1.17 at +.009em, 21/1.38 at +.011em
     Text    17/1.47 at -.022em, 15/1.42 at -.016em, 12/1.33 at +.02em for labels
     Two rules: body copy is 17px, and tracking goes POSITIVE on display sizes and
     NEGATIVE on text sizes. Nothing a person reads as language goes below 15px, and
     nothing at all goes below 12px. Mono is for timestamps and counts only.
     See `60 Reference/The interface type scale.md`. */
  --font-display: "SF Pro Display", -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, sans-serif;
  --font-ui: "SF Pro Text", -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
  --font-mono: ui-monospace, "SF Mono", "Menlo", monospace;
}

*{box-sizing:border-box;}
html,body{height:100%;}
body{ margin:0; font-family:var(--font-ui); font-size:17px; line-height:1.47; letter-spacing:-0.022em; color:var(--ink-950); background:#000; -webkit-font-smoothing:antialiased; }
/* TASK-100 — Gabriel could not see his own text selection in the output fields, so he stopped
   making partial edits entirely: "I'm just like Command A. And then when I paste it over, it
   just overrides it." That has a second cost. `edits` (TASK-007) exists so TASK-022 can learn
   what he changes; select-all-and-replace stores a whole-document rewrite, which carries no
   usable signal. The invisible highlight and the stalled learning loop were the same bug.
   Set BOTH background and colour: background alone leaves the text at its original colour,
   which is what made the old rule read as "nothing happened". */
::selection{ background:var(--select-bg); color:var(--select-fg); }
::-moz-selection{ background:var(--select-bg); color:var(--select-fg); }
/* Form fields are named explicitly. Some engines give textarea/input their own UA highlight
   that a bare ::selection does not reliably reach — and the output fields are the exact place
   this has to work. */
textarea::selection, input::selection{ background:var(--select-bg); color:var(--select-fg); }
textarea::-moz-selection, input::-moz-selection{ background:var(--select-bg); color:var(--select-fg); }
button{ font-family:inherit; }
:focus-visible{ outline:2px solid var(--focus); outline-offset:2px; }
.hidden{ display:none !important; }
.linklike{ background:none; border:none; color:var(--ink-400); text-decoration:underline; cursor:pointer; font-size:13px; margin-left:auto; padding:0; }
.linklike:hover{ color:var(--blue-600); }

#app{ height:100vh; }

/* ---------- auth ---------- */
.auth-wrap{ height:100%; display:flex; align-items:center; justify-content:center; }
.auth-card{ width:320px; display:flex; flex-direction:column; gap:10px; background:var(--paper-100); border:1px solid var(--line); border-radius:12px; padding:26px; box-shadow:var(--shadow); }
.auth-card input{ border:1px solid var(--line); border-radius:8px; padding:11px 13px; font-size:17px; font-family:inherit; background:var(--paper-50); color:var(--ink-950); }
.auth-card input:focus{ outline:none; border-color:var(--blue-500); }
.auth-msg{ font-size:15px; color:var(--pink-500); min-height:14px; text-align:center; }
.auth-title{ font-family:var(--font-display); font-size:20px; font-weight:600; letter-spacing:-.02em; text-align:center; margin-bottom:2px; }
.auth-links{ display:flex; justify-content:space-between; gap:12px; font-size:13px; margin-top:4px; }
.auth-links a{ color:var(--ink-400); text-decoration:none; } .auth-links a:hover{ color:var(--ink-950); }

/* ---------- shell ---------- */
/* Column widths come from variables so the panes can be dragged (TASK-091) WITHOUT inline
   styles on .app — an inline grid-template-columns would outrank every media query below and
   break the icon rail and the mobile single-column layout. Each breakpoint keeps control by
   supplying its own fallback, and the ≤900px rail and ≤640px mobile rules deliberately ignore
   the variables entirely: a 400px "icon rail" is not a layout anyone wants. */
.app{ display:grid; grid-template-columns:var(--w-sidebar, 208px) var(--w-list, 280px) minmax(0,1fr);
  height:100vh; min-height:640px; background:var(--paper-0); position:relative; }
@media (max-width:1100px){ .app{ grid-template-columns:var(--w-sidebar, 176px) var(--w-list, 240px) minmax(0,1fr); } }
/* UI CLEANUP 2026-08-05 — the 641-900px band used to keep a 56px "icon rail" whose nav items
   were `display:none`. There are no icons in this app, so the rail showed a logo above a blank
   strip and the ENTIRE navigation (Insights, Suggestions, the account menu's pages) had
   zero-size hit targets: unreachable, silently, at exactly a half-screen laptop window. The
   rail is gone; this band now uses the same slide-over the phone uses, driven by the same
   markup — one nav idiom below 900px instead of two, one of which was broken. */
@media (max-width:900px){
  .app{ grid-template-columns:240px minmax(0,1fr); }
  /* Below 900px the columns are fixed, so there is nothing to drag — hide the handles rather
     than let them move a width nothing reads. */
  .resizer{ display:none; }
  .sb-toggle{ display:none; }
  .sb-close{ display:block; }
  body.sb-collapsed .sidebar{ opacity:1; pointer-events:auto; border-width:1px;
    padding:16px 12px; margin:0; }
  .sidebar{
    position:fixed; top:0; bottom:0; left:0; width:250px; z-index:60; align-items:stretch;
    transform:translateX(-100%); transition:transform .22s ease; padding:16px 12px;
    margin:0; border-radius:0 14px 14px 0; border-width:0 1px 0 0;
  }
  .sidebar.open{ transform:translateX(0); box-shadow:0 0 40px rgba(0,0,0,.6); }
  @media (prefers-reduced-motion: reduce){ .sidebar{ transition:none; } }
  /* The call-list header grows a menu button in this band (see .list-nav-btn). */
  .list-header .list-nav-btn{ display:inline-flex; }
  /* The scrim belongs to the slide-over, and the slide-over now lives at ≤900, not ≤640.
     Without it, tapping beside the panel did nothing and the content behind stayed live. */
  .nav-scrim{ display:none; position:fixed; inset:0; background:rgba(0,0,0,.5); z-index:55; }
  .nav-scrim.show{ display:block; }
}

/* ---------- sidebar ----------
   Inset rounded panel rather than a full-bleed column with a hairline — the macOS pattern
   from Tahoe onward. Deliberately NOT glassy: no backdrop-filter, no translucency. A blur
   layer costs a compositor pass on every scroll, and this app is read on a laptop at 1am. */
.sidebar{ background:var(--paper-100); border:1px solid var(--line); border-radius:12px;
  margin:8px 0 8px 8px; padding:14px 10px 10px; display:flex; flex-direction:column;
  min-height:0; overflow-y:auto; }
.brand-row{ display:flex; align-items:center; gap:4px; padding-bottom:16px; }
.brand{ display:flex; align-items:center; gap:8px; padding:4px 8px; flex:1; min-width:0;
  background:none; border:none; color:inherit; font:inherit; text-align:left; cursor:pointer;
  border-radius:8px; }
button.brand:hover{ background:var(--paper-200); }
.brand-mark{ width:22px; height:22px; border-radius:6px; background:linear-gradient(155deg, var(--blue-500), var(--violet-500)); flex-shrink:0; }
.brand-name{ font-family:var(--font-display); font-size:17px; font-weight:600; letter-spacing:-0.022em; }
/* Explicit dismiss for the mobile slide-over; desktop has the sidebar toggle instead. */
.sb-close{ display:none; background:none; border:none; color:var(--ink-400); font-size:24px;
  line-height:1; cursor:pointer; padding:2px 8px; border-radius:8px; }
.sb-close:hover{ background:var(--paper-200); color:var(--ink-950); }

/* ---------- sidebar collapse (desktop) ---------- */
.sb-toggle{ width:26px; height:26px; flex-shrink:0; background:none; border:none; cursor:pointer;
  border-radius:6px; padding:0; position:relative; }
.sb-toggle:hover{ background:var(--paper-200); }
/* Drawn in CSS so there is no icon font or SVG asset to keep in sync: a rounded rectangle
   with a filled leading column — the standard sidebar glyph. */
.sb-toggle::before{ content:""; position:absolute; inset:6px 4px; border:1.5px solid var(--ink-400);
  border-radius:3px; }
.sb-toggle::after{ content:""; position:absolute; top:6px; bottom:6px; left:4px; width:5px;
  background:var(--ink-400); border-radius:3px 0 0 3px; }
.sb-toggle:hover::before, .sb-toggle:hover::after{ border-color:var(--ink-800); background-color:var(--ink-800); }
body.sb-collapsed .sb-toggle::after{ background:none; }

body.sb-collapsed .app{ grid-template-columns:0 var(--w-list, 280px) minmax(0,1fr); }
body.sb-collapsed .sidebar{ opacity:0; margin-left:0; padding-left:0; padding-right:0;
  border-width:0; pointer-events:none; overflow:hidden; }
@media (prefers-reduced-motion: no-preference){
  .app{ transition:grid-template-columns .18s ease; }
  .sidebar{ transition:opacity .14s ease; }
}
/* ---------- draggable pane dividers (TASK-091) ----------
   Apple Mail behaviour: grab the boundary, drag, double-click to reset. The handles are
   absolutely positioned OVER the boundary rather than being grid items, so the three-column
   grid is untouched and nothing reflows when they appear. They are wider than they look
   (9px hit area, 1px visual) because a 1px target is a dexterity test, not an affordance. */
.resizer{ position:absolute; top:0; bottom:0; width:9px; margin-left:-4px; z-index:45;
  cursor:col-resize; background:transparent; border:none; padding:0; touch-action:none; }
.resizer::after{ content:""; position:absolute; inset:0 4px; background:transparent; transition:background .12s ease; }
.resizer:hover::after, .resizer.dragging::after{ background:var(--blue-500); }
.resizer:focus-visible{ outline:none; }
.resizer:focus-visible::after{ background:var(--focus); }

/* The debrief / outputs divider is a real flex item in the detail column, so the two sections
   genuinely share the height rather than overlapping. */

/* While dragging: kill the collapse transition (it would rubber-band the drag), stop text
   selection, and keep the resize cursor even when the pointer outruns the 9px handle. */
body.resizing{ user-select:none; -webkit-user-select:none; }
/* ...and the same during a keyboard nudge: each arrow press would otherwise restart the .18s
   grid transition, leaving the pane permanently lagging a held-down arrow key. */
body.resizing .app, body.pane-nudge .app{ transition:none; }
body.resizing.resizing-x, body.resizing.resizing-x *{ cursor:col-resize !important; }
body.resizing.resizing-y, body.resizing.resizing-y *{ cursor:row-resize !important; }
/* Nothing to grab when the sidebar is collapsed to zero. */
body.sb-collapsed .resizer[data-resize="sidebar"]{ display:none; }

.nav-group{ margin-bottom:16px; }
.nav-label{ font-size:12px; font-weight:600; text-transform:uppercase; letter-spacing:0.02em; color:var(--ink-400); padding:0 8px 6px; }
.nav-item{ display:flex; align-items:center; gap:9px; padding:6px 8px; border-radius:6px; font-size:15px; letter-spacing:-0.016em; color:var(--ink-800); cursor:pointer; user-select:none; }
.nav-item .count{ margin-left:auto; font-family:var(--font-mono); font-variant-numeric:tabular-nums; font-size:12px; color:var(--ink-400); }
/* "Arrived since you last looked". Violet because blue means active/selected and pink means
   primary action — this needed a colour that wasn't already saying something else. Hides
   itself when empty, so there is no visibility class that can drift out of sync with content. */
.nav-item .new-badge{ margin-left:auto; background:var(--violet-500); color:#fff; font-size:12px;
  font-weight:700; font-variant-numeric:tabular-nums; line-height:1; padding:3px 6px;
  border-radius:999px; }
.nav-item .new-badge:empty{ display:none; }
.nav-item .new-badge + .count{ margin-left:6px; }
.nav-item:hover{ background:var(--paper-200); }
.nav-item.active{ background:var(--blue-100); color:var(--blue-600); font-weight:600; }
.nav-item.active .count{ color:var(--blue-600); }
.sidebar-foot{ margin-top:auto; padding:10px 8px; border-top:1px solid var(--line); font-size:13px; color:var(--ink-400); display:flex; align-items:center; gap:8px; }
.avatar{ width:20px; height:20px; border-radius:50%; background:var(--ink-800); color:var(--paper-0); display:flex; align-items:center; justify-content:center; font-size:12px; font-weight:600; flex-shrink:0; }

/* ---------- call list ---------- */
.call-list{ border-right:1px solid var(--line); display:flex; flex-direction:column; min-height:0; background:var(--paper-0); }
.list-header{ padding:12px 14px 10px; border-bottom:1px solid var(--line); display:flex; align-items:center; justify-content:space-between; gap:8px; }
/* margin-right:auto keeps the toggle+title paired on the left and pushes + New to the right;
   space-between alone would strand the title in the middle once the toggle was added. */
.list-title{ font-family:var(--font-display); font-size:21px; font-weight:600; letter-spacing:0.011em; margin-right:auto; }
.search-row{ padding:8px 14px 10px; border-bottom:1px solid var(--line); }
.search-box{ display:flex; align-items:center; background:var(--paper-100); border:1px solid var(--line); border-radius:7px; padding:6px 9px; }
.search-box:focus-within{ border-color:var(--blue-500); }
.search-box input{ border:none; background:transparent; outline:none; flex:1; min-width:0; font-family:inherit; font-size:15px; color:var(--ink-950); }
.search-box input::placeholder{ color:var(--ink-400); }
.call-scroll{ overflow-y:auto; flex:1; min-height:0; }
.call-item{ padding:11px 14px; border-bottom:1px solid var(--paper-100); cursor:pointer; display:flex; flex-direction:column; gap:4px; }
.call-item:hover{ background:var(--paper-50); }
.call-item.active{ background:var(--blue-100); }
.call-row1{ display:flex; align-items:baseline; justify-content:space-between; gap:8px; }
.call-name{ font-size:15px; font-weight:600; letter-spacing:-0.016em; }
.call-time{ font-family:var(--font-mono); font-variant-numeric:tabular-nums; font-size:12px; color:var(--ink-400); flex-shrink:0; }
.call-meta{ display:flex; align-items:center; gap:6px; margin-top:2px; flex-wrap:wrap; }
.pill{ font-size:12px; font-weight:600; letter-spacing:0.02em; text-transform:uppercase; padding:2px 7px; border-radius:100px; white-space:nowrap; }
.pill-closed{ background:var(--blue-100); color:var(--blue-600); }
.pill-followup{ background:var(--violet-100); color:var(--violet-600); }
.pill-new{ background:var(--paper-200); color:var(--ink-600); }
/* A failed run must not read as a neutral status chip. */
.pill-failed{ background:var(--pink-100); color:var(--pink-500); }
.offer-tag{ font-size:13px; color:var(--ink-400); }
/* The external attendee, shown beside the meeting title rather than instead of it. */
.attendee-tag{ font-size:13px; color:var(--ink-600); }
.attendee-tag::before{ content:"· "; color:var(--ink-400); }
.sent-flags{ font-size:12px; color:var(--blue-600); font-weight:600; }

/* Traffic-light status dots (TASK-037).
   Rules — grey hollow = New (nothing started), violet pulsing = Working,
   blue = Ready, pink = Failed. Grey stays neutral so pink keeps meaning "wrong". */
[class^="dot-"]{
  display:inline-block; width:8px; height:8px; border-radius:50%;
  margin-right:7px; flex-shrink:0; vertical-align:middle;
}
.dot-new{ background:transparent; border:1.5px solid var(--ink-400); }
.dot-processing{ background:var(--violet-500); box-shadow:0 0 0 0 var(--violet-500); animation:pulse 1.6s ease-out infinite; }
.dot-processed{ background:var(--blue-500); }
.dot-failed{ background:var(--pink-500); }
@keyframes pulse{
  0%   { box-shadow:0 0 0 0 rgba(166,107,255,0.55); }
  70%  { box-shadow:0 0 0 6px rgba(166,107,255,0); }
  100% { box-shadow:0 0 0 0 rgba(166,107,255,0); }
}
@media (prefers-reduced-motion: reduce){ .dot-processing{ animation:none; } }

/* Rename-on-double-click */
.renameable{ border-radius:5px; padding:1px 4px; margin-left:-4px; cursor:text; }
.renameable:hover{ background:var(--paper-200); }
.renameable.editing{ background:var(--paper-0); outline:2px solid var(--blue-500); cursor:text; }

.fail-banner{
  border:1px solid var(--pink-500); border-left:3px solid var(--pink-500);
  background:var(--pink-100); border-radius:8px; padding:10px 13px;
  font-size:15px; line-height:1.5; color:var(--ink-800);
}
.fail-banner b{ color:var(--pink-500); }

/* ---------- detail ---------- */
.detail{ display:flex; flex-direction:column; min-height:0; background:var(--paper-0); overflow-y:auto; padding-bottom:84px; }
.detail-header{ padding:14px 22px; border-bottom:1px solid var(--line); display:flex; flex-direction:column; gap:12px; flex-shrink:0; }
.dh-top{ display:flex; align-items:flex-start; justify-content:space-between; gap:16px; }
.dh-name{ font-family:var(--font-display); font-size:24px; font-weight:600; letter-spacing:0.009em; }
.dh-meta{ font-size:15px; color:var(--ink-600); display:flex; align-items:center; gap:6px; flex-wrap:wrap; }
.dh-meta .sep{ color:var(--line-strong); }
.fathom-badge{ display:inline-flex; align-items:center; gap:4px; font-size:12px; font-weight:600; color:var(--blue-600); background:var(--blue-100); padding:2px 8px; border-radius:100px; }
.dh-actions{ display:flex; align-items:center; gap:8px; flex-shrink:0; }
.regen-btn{ display:flex; align-items:center; gap:6px; background:var(--paper-0); border:1px solid var(--line-strong); border-radius:7px; padding:7px 13px; font-size:15px; font-weight:600; letter-spacing:-0.016em; color:var(--ink-800); cursor:pointer; }
.regen-btn:hover{ border-color:var(--blue-500); color:var(--blue-600); }

.tone-row{ display:flex; align-items:center; gap:14px; flex-wrap:wrap; }
.tone-label{ font-size:13px; font-weight:600; color:var(--ink-600); }
.tone-seg{ display:inline-flex; background:var(--paper-100); border:1px solid var(--line); border-radius:8px; padding:2px; }
.tone-opt{ padding:6px 13px; font-size:15px; font-weight:600; color:var(--ink-600); border-radius:6px; cursor:pointer; background:transparent; border:none; }
.tone-opt.selected{ background:var(--paper-0); color:var(--ink-950); box-shadow:var(--shadow); }
.tone-suggested{ display:flex; align-items:center; gap:6px; font-size:13px; color:var(--violet-600); background:var(--violet-100); padding:4px 10px; border-radius:100px; }
.applies-to{ font-size:13px; color:var(--ink-400); }
.brief-toggle{ background:transparent; border:1px solid var(--violet-500); color:var(--violet-600); border-radius:6px; padding:4px 10px; font-size:12px; font-weight:600; cursor:pointer; margin-left:auto; }
.brief-body{ font-size:15px; line-height:1.5; border-top:1px solid var(--line); padding-top:8px; }

/* NEW LAYOUT: debrief full-width on top, then three output columns */
/* The unified section (2026-08-05): debrief pages and outputs share one chip row and one
   full-height body. Exactly one panel is in flow at a time and it gets every vertical pixel —
   Gabriel's screen-real-estate ask, finished. */
.unified-section{ flex:1; min-height:0; display:flex; flex-direction:column; }
.unified-body{ flex:1; min-height:0; overflow-y:auto; padding:6px 22px 22px;
  font-size:17px; line-height:1.47; letter-spacing:-0.022em; color:var(--ink-800);
  display:flex; flex-direction:column; }
/* An active OUTPUT panel stretches, so the textarea can take the full height for editing. */
.unified-body .opane.active{ display:flex; flex-direction:column; flex:1; min-height:0; }
.unified-body .opane .panel, .unified-body .opane .panel-body{ display:flex; flex-direction:column; flex:1; min-height:0; }
.unified-body .opane textarea.msg-edit{ flex:1; min-height:180px; }
/* The transcript page (2026-08-12) stretches exactly like an output pane so it gets the full
   height Gabriel asked for, but it is source material rather than a draft: read-only, no resize
   handle, and no Copy/Mark-sent in the chip row (see `noCopy` in DEBRIEF_PAGES). */
.unified-body .dpage.dpage-transcript.active{ display:flex; flex-direction:column; flex:1; min-height:0; }
.transcript-view{ flex:1; min-height:180px; width:100%; resize:none; border:1px solid var(--line);
  border-radius:9px; background:var(--paper-50); padding:14px; color:var(--ink-800);
  font-family:var(--font-mono); font-size:13px; line-height:1.6; white-space:pre-wrap; }
.transcript-view:focus{ outline:none; border-color:var(--blue-500); }
.subnav-split{ width:1px; align-self:stretch; margin:4px 6px; background:var(--line-strong); }
.subnav-actions{ margin-left:auto; display:flex; align-items:center; gap:6px; }
/* Wraps rather than scrolls (2026-08-05): nine debrief pages clipped mid-word at the right
   edge with no affordance — macOS overlay scrollbars are invisible until touched, which is the
   TASK-092 dialog lesson again on a different element. A second line of pills costs 30px and
   hides nothing. */
.panel-subnav{ display:flex; align-items:center; gap:5px; padding:9px 22px; flex-wrap:wrap; }
/* The outputs tab strip carries its own actions on the SAME line (TASK-093). Copy and Mark
   sent used to sit in a header strip below the chips, which read as a rendering mistake and
   cost a full row of vertical height on every call. Only the active tab's set is shown. */
.oacts{ display:none; gap:6px; margin-left:auto; flex:none; }
.oacts.active{ display:flex; }
.chip{ font-size:12px; font-weight:600; color:var(--ink-600); background:var(--paper-100); border:1px solid var(--line); border-radius:100px; padding:3.5px 9px; white-space:nowrap; cursor:pointer; }
.chip:hover{ background:var(--paper-200); }
/* FIXED height (TASK-055), not max-height: the pane must be the same size on every pill page,
   so short pages show whitespace rather than the box jumping between tabs. Long pages scroll. */

.unified-body h4{ font-size:12px; text-transform:uppercase; letter-spacing:0.02em; font-weight:700; color:var(--ink-400); margin:20px 0 8px; }
.unified-body h4:first-of-type{ margin-top:2px; }
.unified-body ul{ margin:0 0 10px; padding-left:16px; }
.unified-body li{ margin-bottom:5px; }

.highlights{ border:1px solid var(--line); border-radius:9px; background:var(--paper-100); padding:11px 13px; margin-bottom:14px; display:flex; flex-direction:column; gap:6px; }
.hl-title{ font-size:12px; font-weight:600; text-transform:uppercase; letter-spacing:0.02em; color:var(--ink-400); }
.hl-row{ display:flex; gap:8px; font-size:15px; align-items:baseline; }
.hl-tag{ font-size:12px; font-weight:600; padding:1px 7px; border-radius:100px; flex-shrink:0; }
.hl-best{ background:var(--blue-100); color:var(--blue-600); }
.hl-worst{ background:var(--pink-100); color:var(--pink-600); }
.hl-lesson{ background:var(--violet-100); color:var(--violet-600); }
.hl-overall{ background:var(--paper-200); color:var(--ink-800); }

/* Executive diagnosis (TASK-089): the opinionated top-of-report read. Sits above the TL;DR. */
.diagnosis{ border:1px solid var(--line-strong); border-left:3px solid var(--violet-500);
  border-radius:9px; background:var(--paper-50); padding:12px 14px; margin-bottom:14px; }
.diag-eyebrow{ font-size:12px; font-weight:600; text-transform:uppercase; letter-spacing:0.02em; color:var(--violet-600); margin-bottom:5px; }
.diag-text{ margin:0; font-size:17px; line-height:1.47; letter-spacing:-0.022em; color:var(--ink-950); }
.diag-outcome{ margin:8px 0 0; font-size:15px; line-height:1.45; color:var(--ink-600); }

/* Did-well / hurt-sale / missed-openings: each item is a titled finding, and (for hurt-sale and
   missed openings) carries the exact better wording — the coaching, not just the critique. */
.rich-list{ list-style:none; margin:0; padding:0; display:flex; flex-direction:column; gap:11px; }
.rich-list > li{ border-left:2px solid var(--line-strong); padding-left:11px; }
.ri-main{ font-size:17px; font-weight:600; letter-spacing:-0.022em; color:var(--ink-950); line-height:1.5; }
.ri-why{ font-size:15px; color:var(--ink-600); margin-top:3px; line-height:1.5; }
.ri-fix{ font-size:15px; color:var(--ink-950); margin-top:6px; line-height:1.5;
  background:var(--blue-100); border-radius:7px; padding:7px 10px; }
.ri-fix-tag{ display:inline-block; font-size:12px; font-weight:600; text-transform:uppercase;
  letter-spacing:0.02em; color:var(--blue-600); margin-right:7px; }

/* Structured client profile (TASK-089). */
.prof-lines{ display:flex; flex-wrap:wrap; gap:6px 18px; margin-bottom:6px; }
.prof-line{ display:flex; gap:7px; font-size:15px; align-items:baseline; }
.prof-k{ font-size:12px; font-weight:600; text-transform:uppercase; letter-spacing:0.02em; color:var(--ink-400); }
.ranked{ margin:0; padding-left:20px; font-size:15px; line-height:1.7; }
.prof-wound{ margin:0; font-size:15px; font-style:italic; color:var(--ink-800); line-height:1.55;
  border-left:2px solid var(--pink-500); padding-left:10px; }

.sc-note{ grid-column:1/-1; font-size:13px; color:var(--ink-400); line-height:1.45; margin-top:-1px; }

/* Flows into as many columns as the pane is wide. The old 1fr/auto grid stacked all 10
   dimensions vertically, which is what forced the scorecard to scroll. */
.scorecard{ display:grid; grid-template-columns:repeat(auto-fit, minmax(195px, 1fr)); gap:10px 22px; margin-bottom:6px; }
.sc-item{ display:flex; flex-direction:column; gap:4px; }
.sc-top{ display:flex; align-items:baseline; justify-content:space-between; gap:10px; }
.sc-k{ color:var(--ink-600); }
.sc-v{ font-family:var(--font-mono); font-variant-numeric:tabular-nums; font-weight:700; }
.scorecard .bar{ grid-column:1/-1; height:4px; background:var(--paper-200); border-radius:2px; overflow:hidden; margin-bottom:5px; }
.scorecard .bar > i{ display:block; height:100%; }

.objection{ border:1px solid var(--line); border-radius:8px; padding:10px 11px; margin-bottom:10px; background:var(--paper-50); }
.objection .said{ font-style:italic; color:var(--ink-950); margin-bottom:6px; }
.objection dl{ margin:0; display:grid; grid-template-columns:auto 1fr; gap:4px 9px; font-size:15px; }
.objection dt{ color:var(--ink-400); font-weight:600; }
.objection dd{ margin:0; }

/* One output at a time (TASK-088): the section holds a segmented subnav over a single visible
   pane, instead of three columns side by side. */

.outputs{ flex:1; min-height:0; display:block; }
.opane{ display:none; height:100%; }
.opane.active{ display:flex; flex-direction:column; min-height:0; height:100%; }
.panel{ display:flex; flex-direction:column; flex:1; min-height:0; }
.copy-btn, .sent-btn{ display:flex; align-items:center; gap:5px; border-radius:6px; padding:6px 11px; font-size:13px; font-weight:600; cursor:pointer; }
.copy-btn{ background:var(--paper-0); border:1px solid var(--line-strong); color:var(--ink-800); }
.copy-btn:hover{ border-color:var(--blue-500); color:var(--blue-600); }
.copy-btn.copied{ background:var(--blue-100); border-color:var(--blue-500); color:var(--blue-600); }
.sent-btn{ background:transparent; border:1px solid var(--line); color:var(--ink-600); }
.sent-btn:hover{ border-color:var(--blue-500); color:var(--blue-600); }
.sent-btn.is-sent{ background:var(--blue-100); border-color:var(--blue-500); color:var(--blue-600); }
.panel-body{ flex:1; min-height:0; overflow-y:auto; padding:14px 16px 20px; display:flex; flex-direction:column; gap:10px; }
.edit-note{ font-size:13px; color:var(--ink-400); }
.subject-input{ border:1px solid var(--line); border-radius:8px; background:var(--paper-50); padding:10px 13px; font-size:17px; font-weight:600; letter-spacing:-0.022em; font-family:inherit; color:var(--ink-950); }
.subject-input:focus{ outline:none; border-color:var(--blue-500); }
.msg-edit{ flex:1; min-height:140px; resize:vertical; border:1px solid var(--line); border-radius:10px; background:var(--paper-50); padding:14px 15px; font-size:17px; line-height:1.55; letter-spacing:-0.022em; font-family:inherit; color:var(--ink-950); white-space:pre-wrap; }
.msg-edit:focus{ outline:none; border-color:var(--blue-500); background:var(--paper-0); }
.msg-edit.dirty{ border-color:var(--violet-500); }

/* compose + generic views */
.compose-body, .view-body{ flex:1; padding:20px 26px 34px; display:flex; flex-direction:column; gap:12px; min-height:0; overflow-y:auto; }
.view-body{ display:block; font-size:17px; line-height:1.5; letter-spacing:-0.022em; color:var(--ink-800); max-width:820px; }
.view-body h4{ font-size:12px; text-transform:uppercase; letter-spacing:0.02em; font-weight:700; color:var(--ink-400); margin:22px 0 8px; }
.view-body h4:first-child{ margin-top:0; }
.view-body textarea{ width:100%; min-height:260px; resize:vertical; border:1px solid var(--line); border-radius:9px; background:var(--paper-50); padding:14px; font-family:var(--font-mono); font-size:13px; line-height:1.6; color:var(--ink-950); }
.view-body textarea:focus{ outline:none; border-color:var(--blue-500); }
.compose-body label{ font-size:12px; font-weight:600; color:var(--ink-600); text-transform:uppercase; letter-spacing:0.02em; }
.compose-body input, .compose-body select{ border:1px solid var(--line); border-radius:8px; padding:8px 11px; font-size:13px; font-family:inherit; background:var(--paper-50); color:var(--ink-950); }
.compose-body input:focus, .compose-body select:focus{ outline:none; border-color:var(--blue-500); }
.compose-body textarea{ flex:1; resize:none; border:1px solid var(--line); border-radius:9px; padding:14px; font-family:inherit; font-size:13px; line-height:1.55; color:var(--ink-950); background:var(--paper-50); min-height:180px; }
.compose-body textarea:focus{ outline:none; border-color:var(--blue-500); }
.primary-btn{ background:var(--pink-500); color:#0A0D13; border:none; border-radius:8px; padding:11px 19px; font-size:15px; font-weight:600; letter-spacing:-0.016em; cursor:pointer; align-self:flex-start; display:flex; align-items:center; gap:8px; }
.primary-btn:hover{ background:var(--pink-600); }
.primary-btn:disabled{ opacity:.5; cursor:default; }

.integration-row{ display:flex; align-items:center; justify-content:space-between; gap:12px; border:1px solid var(--line); border-radius:9px; background:var(--paper-50); padding:13px 15px; margin-bottom:10px; }
.integration-name{ font-size:13px; font-weight:700; }
.integration-sub{ font-size:13px; color:var(--ink-600); }
.status-chip{ font-size:12px; font-weight:700; padding:3px 9px; border-radius:100px; }
.status-on{ background:var(--blue-100); color:var(--blue-600); }
.status-off{ background:var(--paper-200); color:var(--ink-600); }

/* API key entry (TASK-032) */
  flex:1; min-width:200px; border:1px solid var(--line); border-radius:7px; padding:8px 11px;
  font-family:var(--font-mono); font-size:12px; background:var(--paper-0); color:var(--ink-950);
}
  background:transparent; border:1px solid var(--line); border-radius:6px; color:var(--ink-600);
  font-size:12px; font-weight:600; padding:7px 9px; cursor:pointer;
}

.insight-grid{ display:grid; grid-template-columns:1fr auto; gap:5px 10px; margin-bottom:16px; }
.insight-grid .bar{ grid-column:1/-1; height:4px; background:var(--paper-200); border-radius:2px; overflow:hidden; margin-bottom:5px; }
.insight-grid .bar > i{ display:block; height:100%; }
.insight-note{ font-size:12px; color:var(--ink-600); margin-bottom:14px; }

.loading-state{ flex:1; display:flex; flex-direction:column; align-items:center; justify-content:center; gap:14px; color:var(--ink-600); font-size:13px; min-height:200px; }
.spinner{ width:26px; height:26px; border-radius:50%; border:3px solid var(--paper-200); border-top-color:var(--blue-500); animation:spin .8s linear infinite; }
@media (prefers-reduced-motion: reduce){ .spinner{ animation-duration:2s; } }
@keyframes spin{ to{ transform:rotate(360deg); } }

.toast{ position:fixed; bottom:20px; left:50%; transform:translateX(-50%) translateY(12px); background:var(--ink-950); color:var(--paper-50); font-size:15px; font-weight:600; padding:9px 16px; border-radius:100px; box-shadow:var(--shadow); opacity:0; pointer-events:none; transition:opacity .18s ease, transform .18s ease; z-index:50; }
.toast.show{ opacity:1; transform:translateX(-50%) translateY(0); }

/* Activity log (TASK-040) */
.ev-summary{ display:flex; gap:10px; flex-wrap:wrap; margin-bottom:14px; }
.ev-summary > div{ flex:1; min-width:104px; background:var(--paper-50); border:1px solid var(--line); border-radius:9px; padding:11px 13px; }
.ev-summary b{ display:block; font-family:var(--font-display); font-size:24px; font-weight:600; letter-spacing:0.009em; color:var(--ink-950); font-variant-numeric:tabular-nums; }
.ev-summary span{ font-size:12px; color:var(--ink-400); text-transform:uppercase; letter-spacing:0.02em; }
.ev-summary .bad b{ color:var(--pink-500); }
.ev-filters{ display:flex; gap:6px; margin-bottom:12px; flex-wrap:wrap; }
.ev-table{ width:100%; border-collapse:collapse; font-size:12px; table-layout:fixed; }
/* Time and kind are fixed-width; the detail column takes everything else. Without this the
   table's auto layout gave the meta column whatever it asked for and long error text wrapped
   into eight-line towers in a squeezed detail cell. */
.ev-table td:nth-child(1){ width:150px; }
.ev-table td:nth-child(2){ width:170px; }
.ev-table td:nth-child(4){ width:130px; }
.ev-table td{ overflow-wrap:break-word; }
.ev-table td{ padding:7px 10px; border-bottom:1px solid var(--paper-100); vertical-align:top; }
.ev-at{ font-family:var(--font-mono); font-size:12px; color:var(--ink-400); white-space:nowrap; }
.ev-kind{ font-family:var(--font-mono); font-size:12px; padding:2px 6px; border-radius:4px; background:var(--paper-200); color:var(--ink-600); white-space:nowrap; }
.ev-meta{ font-family:var(--font-mono); font-size:12px; color:var(--ink-400); white-space:nowrap; }
.ev-error .ev-kind{ background:var(--pink-100); color:var(--pink-500); }
.ev-error td{ color:var(--ink-800); }
.ev-warn .ev-kind{ background:var(--violet-100); color:var(--violet-600); }
.work-elapsed{ font-variant-numeric:tabular-nums; }
/* TASK-104. Replaces the tone segmented control on single-voice calls. Reads as a quiet note
   from the app, not a control — there is nothing to pick, and styling it like a chip would
   invite Gabriel to click it. */

/* Hidden except in the 641-900px band, where it is the only door to navigation. */
.list-nav-btn{ display:none; background:var(--paper-200); color:var(--ink-950);
  border:1px solid var(--line); border-radius:8px; padding:5px 10px; font-size:15px; cursor:pointer; }

/* UI CLEANUP 2026-08-05 — the collapsed header settings (call type + tone editors live inside;
   the summary line is all that shows until clicked). */
.dh-settings .dh-controls{ display:none; }
.dh-settings.open .dh-controls{ display:block; padding-top:2px; }
.dh-summary{ display:flex; align-items:center; gap:7px; width:100%; text-align:left; flex-wrap:nowrap; overflow:hidden; }
.dh-summary > span{ white-space:nowrap; }
.dh-summary{
  background:none; border:none; padding:4px 0 2px; cursor:pointer;
  font-family:inherit; font-size:13px; color:var(--ink-600); min-width:0; }
.dh-summary:hover .dh-sum-type{ color:var(--blue-600); }
.dh-sum-type{ font-weight:600; color:var(--ink-800); white-space:nowrap; }
.dh-sum-note{ font-style:italic; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; min-width:0; flex:0 1 auto; }
.dh-sum-chev{ color:var(--ink-400); font-size:11px; }

/* TASK-105 — the per-call chat. Below the outputs, like ChatGPT and Claude, so anything it
   rewrites appears ABOVE the box where the change is visible. */
.chat-section{ display:flex; flex-direction:column; gap:8px; border-top:1px solid var(--line);
  padding:12px 16px 14px; background:var(--paper-50); }
.chat-log{ display:flex; flex-direction:column; gap:8px; max-height:260px; overflow-y:auto; }
.chat-msg{ font-size:14px; line-height:1.55; padding:9px 12px; border-radius:12px;
  max-width:82%; white-space:pre-wrap; word-break:break-word; }
.chat-u{ align-self:flex-end; background:var(--blue-100); color:var(--ink-950); border-bottom-right-radius:4px; }
.chat-a{ align-self:flex-start; background:var(--paper-100); border:1px solid var(--line);
  color:var(--ink-950); border-bottom-left-radius:4px; }
.chat-pending{ color:var(--ink-400); font-style:italic; }
.chat-err{ border-color:var(--pink-500); color:var(--pink-500); }
.chat-updated{ margin-top:6px; font-size:12px; color:var(--blue-600); font-weight:600; }
.chat-input{ display:flex; gap:8px; align-items:flex-end; }
.chat-input textarea{ flex:1; resize:none; overflow-y:auto; min-height:38px; max-height:140px;
  border:1px solid var(--line); border-radius:10px; padding:9px 12px; background:var(--paper-0);
  color:var(--ink-950); font-family:inherit; font-size:14px; line-height:1.45; }
.chat-input textarea:focus{ outline:none; border-color:var(--blue-500); }
.chat-input .primary-btn{ flex:0 0 auto; }
@media (max-width:640px){ .chat-log{ max-height:180px; } .chat-msg{ max-width:92%; } }
/* The live debrief tail (TASK-101). Fixed height on purpose — it grows for three minutes, and
   a panel that reflows the page under Gabriel every 1.5 seconds is worse than no panel. It
   scrolls itself to the bottom instead. Muted and monospaced because it is machine output in
   progress, not a result: it should read as evidence of work, never as something to act on. */
.work-preview{
  max-width:min(640px, 100%); height:88px; overflow:hidden;
  margin:2px auto 0; padding:10px 12px;
  background:var(--paper-100); border:1px solid var(--line); border-radius:9px;
  font-family:var(--font-mono); font-size:12px; line-height:1.5; color:var(--ink-600);
  text-align:left; white-space:pre-wrap; word-break:break-word;
  /* Fades into the top edge so it reads as a window onto something longer, not a truncated box. */
  -webkit-mask-image:linear-gradient(180deg, transparent 0, #000 22px);
          mask-image:linear-gradient(180deg, transparent 0, #000 22px);
}

/* Generation progress (TASK-044). Driven by real streamed bytes from the server — the fill
   cannot move unless the model actually produced output. The indeterminate state is used
   only before the first byte arrives, and is deliberately the ONLY animated-without-data
   case. */
.progress-wrap{ width:100%; max-width:420px; display:flex; flex-direction:column; gap:7px; }
.progress-track{ height:6px; border-radius:99px; background:var(--paper-200); overflow:hidden; }
.progress-fill{
  height:100%; border-radius:99px;
  background:linear-gradient(90deg, var(--blue-500), var(--violet-500));
  transition:width .45s ease;
}
.progress-fill.indeterminate{
  background:linear-gradient(90deg, var(--paper-200) 0%, var(--blue-500) 50%, var(--paper-200) 100%);
  background-size:200% 100%; animation:progress-sweep 1.3s linear infinite;
}
@keyframes progress-sweep{ from{ background-position:200% 0; } to{ background-position:-200% 0; } }
.progress-row{ display:flex; justify-content:space-between; align-items:baseline; font-size:13px; }
.progress-step{ color:var(--ink-800); }
.progress-pct{ color:var(--violet-600); font-variant-numeric:tabular-nums; }
@media (prefers-reduced-motion: reduce){
  .progress-fill{ transition:none; }
  .progress-fill.indeterminate{ animation:none; background:var(--blue-500); }
}

/* Debrief pagination (pills act as tabs). Exactly one page is in flow at a time — the point is
   that you never scroll past one section to reach another. */
.dpage{ display:none; }
.dpage.active{ display:block; }
.dpage-empty{ color:var(--ink-400); font-style:italic; padding:8px 0; }
.chip.active{ background:linear-gradient(90deg, var(--blue-500), var(--violet-500)); border-color:transparent; color:#fff; }
.chip.active:hover{ opacity:.92; background:linear-gradient(90deg, var(--blue-500), var(--violet-500)); }

/* Settings menu behind the profile row. */
.sidebar-foot{ position:relative; }
.user-btn{ display:flex; align-items:center; gap:8px; width:100%; padding:4px 4px; background:none; border:none; cursor:pointer; color:var(--ink-400); font-size:12px; font-family:inherit; text-align:left; border-radius:6px; }
.user-btn:hover{ background:var(--paper-100); color:var(--ink-800); }
.user-btn #userEmail{ overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.user-caret{ margin-left:auto; font-size:12px; opacity:.7; }
/* position:fixed, not absolute — the menu is no longer inside .sidebar-foot (collapsing the
   sidebar used to take the whole menu with it). JS anchors it to whichever button opened it. */
.settings-menu{ position:fixed; z-index:90; width:190px;
  background:var(--paper-100); border:1px solid var(--line); border-radius:9px; padding:5px;
  display:flex; flex-direction:column; gap:1px; box-shadow:0 10px 30px rgba(0,0,0,.55); }

/* Compact account button in the list header. Only exists while the sidebar is hidden, which is
   exactly when the sidebar's own profile button is unreachable. */
.user-btn-mini{ display:none; background:none; border:none; cursor:pointer; padding:2px;
  border-radius:999px; margin-right:2px; }
.user-btn-mini:hover{ background:var(--paper-200); }
body.sb-collapsed .user-btn-mini{ display:inline-flex; align-items:center; }
/* An action inside the menu, deliberately styled as a button so it doesn't read as another
   navigation row. */
.settings-action{ text-align:center; background:var(--pink-500); color:#0A0D13; border:none;
  border-radius:7px; padding:8px 10px; font-size:13px; font-weight:700; font-family:inherit;
  cursor:pointer; margin:1px 0 2px; }
.settings-action:hover{ background:var(--pink-600); }
.settings-item{ text-align:left; background:none; border:none; cursor:pointer; font-family:inherit;
  font-size:13px; color:var(--ink-800); padding:7px 9px; border-radius:6px; }
.settings-item:hover{ background:var(--paper-200); color:var(--ink-950); }
.settings-item.danger{ color:var(--ink-400); }
.settings-item.danger:hover{ color:var(--pink-500); background:var(--pink-100); }
.settings-sep{ height:1px; background:var(--line); margin:4px 2px; }

/* Rename-in-place. The title is its own span so editing cannot touch the status pill. */
.call-title{ cursor:text; border-radius:4px; padding:0 3px; margin:0 -3px; }
.call-title:hover{ background:var(--paper-100); }
.call-title.editing{ background:var(--paper-200); outline:1.5px solid var(--blue-500); cursor:text; }

/* Delete is the only irreversible control in the app — it should not look like the others. */
.danger-btn{ color:var(--pink-500); border-color:var(--pink-100); }
.danger-btn:hover{ background:var(--pink-100); color:var(--pink-600); }

/* ============================================================================
   iPhone / phone layout (TASK-056). Single column; list OR detail shown one at
   a time; sidebar becomes a slide-over. Desktop (>640px) is untouched.
   ============================================================================ */
.mobile-bar{ display:none; }             /* hidden on desktop; grid ignores display:none */
.nav-scrim{ display:none; }

@media (max-width:640px){
  .app{
    grid-template-columns:1fr;
    grid-template-rows:auto minmax(0,1fr);
    min-height:0; height:100vh; height:100dvh;   /* dvh: account for iOS Safari's toolbar */
  }

  /* top bar */
  .mobile-bar{
    display:flex; align-items:center; gap:10px; grid-row:1;
    padding:10px 14px; background:var(--paper-100); border-bottom:1px solid var(--line);
  }
  .mobile-title{ font-weight:600; font-size:17px; letter-spacing:-0.022em; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  /* Back button only when a call/detail is showing; menu only when on the list. */
  #mBackBtn{ display:none; }
  body.m-detail #mNavBtn{ display:none; }
  body.m-detail #mBackBtn{ display:inline-flex; align-items:center; }

  /* The desktop sidebar toggle is meaningless here — the ☰ slide-over is the mobile idiom. */
  .sb-toggle{ display:none; }
  .sb-close{ display:block; }
  /* The collapse class is desktop-only state; it must not follow you onto a phone and leave
     the slide-over invisible and unclickable. */
  body.sb-collapsed .sidebar{ opacity:1; pointer-events:auto; border-width:1px;
    padding:16px 12px; margin:0; }

  /* sidebar as a slide-over, full width & labels (override the 900px icon-rail rule) */
  .sidebar{
    position:fixed; top:0; bottom:0; left:0; width:250px; z-index:60; align-items:stretch;
    transform:translateX(-100%); transition:transform .22s ease; padding:16px 12px;
    margin:0; border-radius:0 14px 14px 0; border-width:0 1px 0 0;
  }
  /* translateX(0), not `none`: some engines won't animate a transition TO `none`, which
     left the slide-over stuck off-screen. Same-type interpolation is reliable. */
  .sidebar.open{ transform:translateX(0); box-shadow:0 0 40px rgba(0,0,0,.6); }
  @media (prefers-reduced-motion: reduce){ .sidebar{ transition:none; } }
  .sidebar .brand-name, .sidebar .nav-label,
  .sidebar-foot span, .sidebar-foot .linklike{ display:revert; }
  /* nav-item is restored to flex, NOT `revert`. `revert` undoes the 900px icon-rail
     display:none, but it also throws away the base rule's display:flex — which kills the
     count's margin-left:auto and leaves "Needs Follow-up6" run together. Harmless while the
     counts were never populated; visible the moment they were. */
  .sidebar .nav-item{ display:flex; }
  /* cursor:pointer is load-bearing, not decoration. iOS Safari does not reliably dispatch
     `click` on a non-interactive element without it, so tap-to-dismiss silently did nothing
     on an iPhone and the slide-over could only be escaped by reloading the page. */
  .nav-scrim{ display:none; position:fixed; inset:0; background:rgba(0,0,0,.5); z-index:55;
    cursor:pointer; -webkit-tap-highlight-color:transparent; }
  .nav-scrim.show{ display:block; }

  /* one pane at a time in the content row */
  .call-list, .detail{ grid-row:2; grid-column:1; }
  body:not(.m-detail) .detail{ display:none; }
  body.m-detail .call-list{ display:none; }
  .call-list{ border-right:none; }

  /* Outputs are one-at-a-time now (TASK-088), so on mobile the active pane just sizes to its
     own content and flows with the page rather than fighting for a fixed-height inner box. */
  .unified-section{ flex:1 1 auto; min-height:260px; }
  .outputs{ display:block; flex:0 0 auto; }
  .opane.active{ height:auto; }
  .panel{ min-width:0; flex:0 0 auto; }
  .msg-edit{ min-height:120px; }

  /* debrief flows with the page rather than a fixed inner scroll box */
  .unified-body{ height:auto; max-height:none; padding-left:16px; padding-right:16px; }
  .detail-header{ padding:14px 16px; }

  /* finger-sized targets */
  .nav-item{ min-height:40px; }
  .tone-opt, .chip, .regen-btn, .copy-btn, .primary-btn{ min-height:38px; }
  .call-item{ padding-top:12px; padding-bottom:12px; }
}

/* Fathom token inbox label (TASK-054 follow-up) */

/* "New version available" reload banner (TASK-046) */
.update-banner{
  position:fixed; left:50%; bottom:18px; transform:translateX(-50%); z-index:200;
  background:linear-gradient(90deg, var(--blue-500), var(--violet-500)); color:#fff;
  padding:10px 14px; border-radius:10px; font-size:15px; box-shadow:0 10px 30px rgba(0,0,0,.5);
  display:flex; align-items:center; gap:12px; max-width:calc(100vw - 32px);
}
.update-banner button{ background:rgba(255,255,255,.18); color:#fff; border:1px solid rgba(255,255,255,.4);
  border-radius:7px; padding:5px 12px; font-size:12px; font-weight:700; cursor:pointer; }
.update-banner button:hover{ background:rgba(255,255,255,.3); }

/* ---------- release notes (TASK-077) ---------- */
.release-dlg{
  border:1px solid var(--line-strong); border-radius:14px; padding:0; width:min(520px, calc(100vw - 32px));
  background:var(--paper-0); color:var(--ink-800); box-shadow:0 24px 60px rgba(0,0,0,.55);
}
.release-dlg::backdrop{ background:rgba(0,0,0,.55); backdrop-filter:blur(2px); }
.release-head{ display:flex; align-items:flex-start; justify-content:space-between; gap:12px;
  padding:18px 20px 12px; border-bottom:1px solid var(--line); }
.release-eyebrow{ font-size:12px; text-transform:uppercase; letter-spacing:.02em; color:var(--ink-400); }
.release-title{ font-size:17px; font-weight:700; margin-top:3px;
  background:linear-gradient(90deg,var(--blue-500),var(--violet-500)); -webkit-background-clip:text;
  background-clip:text; color:transparent; }
.release-x{ background:none; border:none; color:var(--ink-400); font-size:22px; line-height:1;
  cursor:pointer; padding:0 2px; }
.release-x:hover{ color:var(--ink-800); }
/* Overflow has to announce itself (TASK-092). Now that a whole day aggregates into one entry,
   these lists got long enough to scroll — and macOS overlay scrollbars stay invisible until you
   touch them, so the note just looked like it stopped mid-sentence. Gabriel reads six of eight
   items and closes it, which is precisely the "he never sees the full scope" problem the
   aggregation exists to solve, reintroduced at the presentation layer.
   CSS-only scroll shadows: the `local` layers scroll with the content and cover the `scroll`
   layers at each extreme, so the hint shows up only when there really is more to read. */
.release-body{
  padding:14px 20px 4px; max-height:min(68vh, 560px); overflow-y:auto;
  background:
    linear-gradient(var(--paper-0) 30%, rgba(0,0,0,0))        top    / 100% 20px no-repeat local,
    linear-gradient(rgba(0,0,0,0), var(--paper-0) 70%)        bottom / 100% 20px no-repeat local,
    radial-gradient(farthest-side at 50% 0,    rgba(0,0,0,.3), rgba(0,0,0,0)) top    / 100% 9px no-repeat scroll,
    radial-gradient(farthest-side at 50% 100%, rgba(0,0,0,.3), rgba(0,0,0,0)) bottom / 100% 9px no-repeat scroll;
}
.release-block + .release-block{ margin-top:14px; padding-top:14px; border-top:1px solid var(--line); }
.release-v{ font-size:12px; text-transform:uppercase; letter-spacing:.02em; color:var(--ink-400); margin-bottom:6px; }
.release-body ul{ margin:0; padding-left:18px; }
.release-body li{ font-size:13px; line-height:1.55; margin-bottom:7px; }
.release-foot{ padding:8px 20px 18px; display:flex; justify-content:flex-end; }
.release-foot .primary-btn{ align-self:auto; }

/* ============================================================================
   Light theme (TASK-066). Dark is the default; this re-maps the same tokens so
   every component follows without per-component work.
   ============================================================================ */
:root[data-theme="light"]{
  --ink-950:#0F1422; --ink-800:#2C3450; --ink-600:#5A6488; --ink-400:#7E88A8;
  --paper-0:#FFFFFF; --paper-50:#F7F8FC; --paper-100:#F0F2F9; --paper-200:#E4E8F3;
  --line:#DCE1EE; --line-strong:#C3CADD;
  --blue-500:#3B62E8; --blue-600:#2A4AC4; --blue-100:#E5EBFF;
  /* 2.01:1 against paper — deliberately stronger than the native macOS highlight (~1.42:1),
     because Gabriel edits these fields under real light and could not see his own selection. */
  --select-bg:#8FB0FF; --select-fg:#0F1422;
  --violet-500:#8B45E0; --violet-600:#6F2FBF; --violet-100:#F1E7FF;
  --pink-500:#D6246F; --pink-600:#B01356; --pink-100:#FFE6F0;
  --shadow: 0 1px 2px rgba(16,22,40,.08), 0 12px 32px rgba(16,22,40,.10);
}
:root[data-theme="light"] body{ background:var(--paper-50); }
:root[data-theme="light"] .avatar{ background:var(--ink-800); color:#fff; }
:root[data-theme="light"] .update-banner{ color:#fff; }

/* ---------- "What's in Fathom?" preview panel (TASK-082) ---------- */
.peek-panel{ margin-top:10px; border:1px solid var(--line); border-radius:9px; background:var(--paper-50); padding:10px 12px; }
.peek-loading{ font-size:12px; color:var(--ink-400); padding:4px 0; }
.peek-head{ font-size:12px; color:var(--ink-600); margin-bottom:8px; line-height:1.6; }
.peek-foot{ font-size:12px; color:var(--ink-400); margin-top:8px; line-height:1.6; }
.peek-table{ width:100%; border-collapse:collapse; font-size:13px; }
.peek-table td{ padding:5px 8px 5px 0; border-bottom:1px solid var(--line); vertical-align:top; }
.peek-table tr:last-child td{ border-bottom:none; }
.peek-skip td{ color:var(--ink-400); }
.peek-yes{ color:var(--blue-600); font-weight:700; white-space:nowrap; }
.peek-no{ color:var(--ink-400); font-weight:700; white-space:nowrap; }
.peek-when{ font-family:var(--font-mono); font-variant-numeric:tabular-nums; white-space:nowrap; color:var(--ink-400); }
.peek-by{ color:var(--ink-400); }
.peek-act{ text-align:right; white-space:nowrap; }
.peek-import, .peek-open{ background:var(--paper-200); color:var(--ink-800); border:1px solid var(--line);
  border-radius:6px; padding:3px 10px; font-size:12px; font-weight:600; font-family:inherit; cursor:pointer; }
.peek-import:hover, .peek-open:hover{ background:var(--blue-100); color:var(--blue-600); border-color:var(--blue-500); }
.peek-import:disabled{ opacity:.6; cursor:default; }

/* ---------- Prompt Library (call types) ---------- */
.ct-list{ display:flex; flex-direction:column; gap:8px; }
.ct-row{ display:flex; align-items:center; gap:14px; padding:13px 15px; border:1px solid var(--line);
  border-radius:10px; background:var(--paper-50); }
.ct-row:hover{ border-color:var(--line-strong); }
.ct-main{ flex:1; min-width:0; }
.ct-name{ font-size:15px; font-weight:700; display:flex; align-items:center; gap:8px; }
.ct-badge{ font-size:12px; font-weight:700; text-transform:uppercase; letter-spacing:.02em;
  background:var(--blue-100); color:var(--blue-600); padding:2px 6px; border-radius:100px; }
.ct-desc{ font-size:12px; color:var(--ink-400); margin-top:3px; }
.ct-meta{ font-size:12px; color:var(--ink-600); white-space:nowrap; }

.ct-editor{ border:1px solid var(--blue-500); border-radius:12px; background:var(--paper-50); padding:16px; margin-top:6px; }
.ct-editor-head{ font-family:var(--font-display); font-size:21px; font-weight:600; letter-spacing:0.011em; margin-bottom:12px; }
.ct-editor-grid{ display:grid; grid-template-columns:minmax(220px,1fr) minmax(0,1.6fr); gap:18px; }
.ct-editor-side label, .ct-editor-main label{ display:block; font-size:12px; font-weight:600;
  text-transform:uppercase; letter-spacing:.02em; color:var(--ink-400); margin:10px 0 5px; }
.ct-editor-side input, .ct-editor-side textarea, .ct-editor-main textarea{
  width:100%; background:var(--paper-0); border:1px solid var(--line); border-radius:8px;
  padding:9px 11px; font-size:15px; font-family:inherit; color:var(--ink-950); }
.ct-editor-main textarea{ min-height:320px; line-height:1.55; resize:vertical; }
.ct-editor-side textarea{ resize:vertical; font-family:var(--font-mono); font-size:13px; }
.ct-editor-side input:focus, .ct-editor-side textarea:focus, .ct-editor-main textarea:focus{
  outline:none; border-color:var(--blue-500); }
.ct-hint{ font-size:12px; color:var(--ink-400); margin-top:6px; line-height:1.45; }
.ct-check{ display:flex !important; align-items:center; gap:8px; text-transform:none !important;
  letter-spacing:0 !important; font-size:12px !important; color:var(--ink-800) !important; margin-top:12px !important; }
.ct-editor-foot{ display:flex; align-items:center; gap:8px; margin-top:16px; padding-top:14px; border-top:1px solid var(--line); }
@media (max-width:820px){ .ct-editor-grid{ grid-template-columns:1fr; } .ct-editor-main textarea{ min-height:220px; } }

/* ---------- call-type picker on a call ---------- */
.ct-picker{ display:flex; flex-wrap:wrap; gap:7px; }
.ct-chip{ font-size:12px; font-weight:600; color:var(--ink-800); background:var(--paper-100);
  border:1px solid var(--line); border-radius:100px; padding:7px 13px; cursor:pointer; }
.ct-chip:hover{ background:var(--paper-200); }
.ct-chip.active{ background:linear-gradient(90deg, var(--blue-500), var(--violet-500)); color:#fff; border-color:transparent; }

/* ---------- duplicate flags (TASK-064) ---------- */
.dup-tag{ font-size:12px; font-weight:700; text-transform:uppercase; background:var(--violet-100);
  color:var(--violet-600); padding:2px 6px; border-radius:100px; }
.dup-banner{ border:1px solid var(--violet-500); border-left:3px solid var(--violet-500);
  background:var(--violet-100); border-radius:8px; padding:10px 13px; font-size:15px;
  line-height:1.5; color:var(--ink-800); margin-bottom:4px; }
/* keep the checkbox rows on one clean left-aligned line */
.ct-check{ text-align:left; line-height:1.35; }
.ct-check input{ flex:0 0 auto; margin:0; width:15px; height:15px; }

/* ---------- call-type tag: right-justified, bold, one word ---------- */
.type-tag{ margin-left:auto; font-size:12px; font-weight:800; letter-spacing:.02em;
  color:var(--ink-800); white-space:nowrap; }
.call-item.active .type-tag{ color:var(--blue-600); }

/* Unread marker. A ::before bar rather than .picked's inset box-shadow, so a call can be both
   new and selected without the two fighting over the same left edge. */
.call-item.is-new::before{ content:""; position:absolute; left:0; top:0; bottom:0; width:3px;
  background:var(--violet-500); }
.call-item.is-new .call-name{ color:var(--violet-500); }
.call-item.is-new.active .call-name{ color:var(--blue-600); }   /* open beats unread */

/* ---------- multi-select + bulk bar ---------- */
.call-item{ position:relative; }
.call-pick{ position:absolute; top:12px; right:12px; width:15px; height:15px; cursor:pointer;
  opacity:0; transition:opacity .12s; accent-color:var(--blue-500); }
.call-item:hover .call-pick, .call-pick:checked, .call-item.picked .call-pick{ opacity:1; }
.call-item.picked{ background:var(--blue-100); box-shadow:inset 3px 0 0 var(--blue-500); }
.bulk-bar{ position:fixed; left:50%; bottom:20px; transform:translateX(-50%); z-index:150;
  display:flex; align-items:center; gap:9px; padding:10px 14px; border-radius:11px;
  background:var(--paper-100); border:1px solid var(--line-strong); box-shadow:0 12px 34px rgba(0,0,0,.5); }
.bulk-count{ font-size:12px; font-weight:700; color:var(--ink-950); }
.bulk-bar select{ background:var(--paper-50); color:var(--ink-950); border:1px solid var(--line);
  border-radius:7px; padding:6px 9px; font-size:12px; font-family:inherit; }
.load-more{ width:calc(100% - 28px); margin:10px 14px 16px; padding:9px; background:var(--paper-100);
  color:var(--ink-800); border:1px solid var(--line); border-radius:8px; font-size:12px; cursor:pointer; }
.load-more:hover{ background:var(--paper-200); }

/* ---------- spend cards ---------- */
.spend-row{ display:grid; grid-template-columns:repeat(auto-fit,minmax(150px,1fr)); gap:10px; margin-bottom:10px; }
.spend-card{ border:1px solid var(--line); border-radius:10px; padding:12px 14px; background:var(--paper-50); }
.spend-k{ font-size:12px; text-transform:uppercase; letter-spacing:.02em; color:var(--ink-400); }
.spend-v{ font-family:var(--font-display); font-size:24px; font-weight:600; letter-spacing:0.009em; font-variant-numeric:tabular-nums; margin-top:4px;
  background:linear-gradient(90deg,var(--blue-500),var(--violet-500)); -webkit-background-clip:text;
  background-clip:text; color:transparent; }
.spend-sub{ font-size:12px; color:var(--ink-400); margin-top:2px; }
.insight-n{ font-size:12px; color:var(--ink-400); font-weight:400; }

/* ---------- model picker (TASK-098) ----------
   Lives in the Prompt Library because choosing a model IS a prompt-level decision: the same
   prompt behaves differently on each. Price is shown on the card so the cost of a choice is
   visible at the moment it's made, not in a doc nobody opens. */
.model-pick{ border:1px solid var(--line); border-radius:12px; background:var(--paper-50); padding:16px 18px; margin-bottom:22px; }
.mp-head{ display:flex; align-items:baseline; gap:10px; flex-wrap:wrap; margin-bottom:12px; }
.mp-title{ font-size:13px; font-weight:700; }
.mp-note{ font-size:13px; color:var(--ink-400); }
.mp-grid{ display:grid; grid-template-columns:repeat(auto-fit,minmax(190px,1fr)); gap:8px; }
.mp-card{ display:flex; flex-direction:column; gap:4px; text-align:left; cursor:pointer;
  background:var(--paper-0); border:1px solid var(--line); border-radius:10px; padding:12px 13px; color:inherit; }
.mp-card:hover{ border-color:var(--line-strong); }
.mp-card.on{ border-color:var(--blue-500); background:var(--blue-100); }
.mp-card[disabled]{ opacity:.6; cursor:default; }
.mp-name{ font-size:13px; font-weight:700; display:flex; align-items:center; gap:6px; }
.mp-tier{ font-size:12px; font-weight:600; letter-spacing:.02em; text-transform:uppercase; color:var(--ink-400); }
.mp-price{ font-size:12px; font-weight:600; color:var(--blue-600); margin-top:2px; }
.mp-per{ font-weight:400; color:var(--ink-400); }
.mp-desc{ font-size:13px; color:var(--ink-600); line-height:1.45; }
.mp-cmp{ font-size:13px; color:var(--ink-400); margin-top:12px; }
/* Reasoning depth sits under the model cards because the two together decide cost — and the
   note line spells out when a level forces thinking on, rather than letting a bigger bill be
   the way Ivan finds out. */
.mp-effort{ display:flex; align-items:center; gap:10px; flex-wrap:wrap; margin-top:14px; padding-top:13px; border-top:1px solid var(--line); }
.mp-elabel{ font-size:13px; font-weight:700; }
.mp-eseg{ display:flex; gap:2px; background:var(--paper-100); border:1px solid var(--line); border-radius:8px; padding:2px; }
.mp-eopt{ background:none; border:none; border-radius:6px; padding:5px 11px; font-size:13px; font-weight:600; color:var(--ink-600); cursor:pointer; }
.mp-eopt:hover{ color:var(--ink-950); }
.mp-eopt.on{ background:var(--paper-0); color:var(--ink-950); box-shadow:0 1px 2px rgba(0,0,0,.4); }
.mp-enote{ font-size:13px; color:var(--ink-400); flex:1; min-width:180px; }

/* ---- Spend (TASK-110) ------------------------------------------------------------------
   A stacked bar chart in plain CSS. No library, because a strict CSP blocks external
   scripts and because the entire chart is a grid of divs with percentage heights. */
.sp-legend{ display:flex; flex-wrap:wrap; gap:14px; margin:2px 0 10px; font-size:12px; color:var(--ink-600); }
.sp-leg{ display:inline-flex; align-items:center; gap:6px; }
.sp-leg i{ width:9px; height:9px; border-radius:2px; display:inline-block; }
.sp-leg b{ color:var(--ink-950); font-variant-numeric:tabular-nums; }
.sp-unpriced{ font-style:normal; color:#D08A32; font-weight:600; }
/* .spend-v.warn and .bad have been emitted by the Activity health card since it shipped and
   were never defined, so a failing health score rendered in the same brand gradient as a
   healthy one. Defined here because Spend uses .warn too. The gradient is painted via
   background-clip:text, so an explicit color simply paints over it. */
.spend-v.warn{ color:#D08A32; }
.spend-v.bad{ color:#E5484D; }

.sp-chart{ display:flex; align-items:flex-end; gap:3px; height:190px; padding:10px 2px 0;
           border:1px solid var(--line); border-radius:10px; background:var(--paper-50);
           margin-bottom:16px; overflow-x:auto; }
.sp-col{ flex:1 1 0; min-width:16px; display:flex; flex-direction:column; height:100%; }
/* The wrapper is the full-height track; the bar sits at its bottom. Without it a short bar
   would float, because flex-end on the column applies to the whole stack including the label. */
.sp-bar-wrap{ flex:1; min-height:0; display:flex; align-items:flex-end; padding:0 2px; }
.sp-bar{ width:100%; border-radius:3px 3px 0 0; overflow:hidden; display:flex; flex-direction:column-reverse; }
.sp-seg{ width:100%; }
.sp-col:hover .sp-bar{ filter:brightness(1.18); }
.sp-x{ font-size:12px; color:var(--ink-400); text-align:center; padding:6px 0 8px;
       white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.sp-empty{ margin:auto; color:var(--ink-400); font-size:13px; padding:20px; }

.sp-table th{ font-size:12px; text-transform:uppercase; letter-spacing:.02em; color:var(--ink-400);
              font-weight:700; text-align:left; padding:7px 10px; border-bottom:1px solid var(--line); }
.sp-table td:nth-child(1), .sp-table th:nth-child(1){ width:auto; }
.sp-table td:nth-child(n+2), .sp-table th:nth-child(n+2){ width:88px; }
.sp-num{ text-align:right; font-variant-numeric:tabular-nums; }
.sp-dot{ width:9px; height:9px; border-radius:2px; display:inline-block; margin-right:7px; }
.sp-id{ color:var(--ink-400); font-family:var(--font-mono); font-size:12px; margin-left:7px; }
/* Marks a figure inferred from our own log rather than billed by Anthropic. The whole page
   depends on those two never being mistaken for each other. */
.spend-v.est{ color:var(--ink-600); }
.spend-v.est::after{ content:"≈"; font-size:14px; vertical-align:super; margin-left:3px; color:var(--ink-400); }

.sp-import{ border:1px solid var(--line); border-radius:10px; padding:14px 16px; background:var(--paper-50); margin-top:14px; }
.sp-import textarea{ width:100%; min-height:110px; margin:10px 0; resize:vertical;
                     border:1px solid var(--line); border-radius:8px; background:var(--paper-0);
                     padding:10px; font-family:var(--font-mono); font-size:12px; color:var(--ink-950); }
.sp-import textarea:focus{ outline:none; border-color:var(--blue-500); }
.sp-msg{ font-size:12px; color:var(--ink-600); margin-left:8px; }

/* Account & Access (TASK-112) */
.acc-form{ display:flex; flex-wrap:wrap; align-items:center; gap:8px; margin-bottom:18px; }
.acc-form input{ flex:1 1 200px; min-width:160px; border:1px solid var(--line); border-radius:8px;
  background:var(--paper-0); padding:9px 11px; font-size:15px; color:var(--ink-950); }
.acc-form input:focus{ outline:none; border-color:var(--blue-500); }
.acc-select{ border:1px solid var(--line); border-radius:8px; padding:9px 11px; font-size:15px;
  background:var(--select-bg, var(--paper-0)); color:var(--select-fg, var(--ink-950)); }

/* ---- People (TASK-118) --------------------------------------------------------------------
   Every class below is used by renderPeople/renderPerson in app.js. The Spend page once shipped
   `.spend-v.warn` for weeks with no rule behind it, so: if you delete a rule here, grep app.js
   first, and if you add a class there, add it here in the same commit.

   Deliberately monochrome. Scores are NOT colour-coded — no green for high, no red for low —
   because the page reports numbers and does not render verdicts. See the note in app.js. */
.pp-row, .pp-callrow { cursor:pointer; }
.pp-row:hover, .pp-callrow:hover { background:var(--paper-100); }
.pp-name { font-weight:600; }

/* Column widths. `.ev-table` is table-layout:fixed and `.sp-table` sets every column after the
   first to 88px. Seven columns of that leaves the name ~430px short in a normal window, and
   because .ev-table also sets overflow-wrap:break-word the result was "gabriel@exa / mple.com"
   split mid-word. Caught by looking at the page; no assertion would have found it.
   Numbers here are 1-3 digits, so they do not need 88px. */
/* min-width, so the table OVERFLOWS its `overflow-x:auto` wrapper instead of collapsing.
   `.ev-table` is table-layout:fixed at width:100%, which means a container narrower than the
   sum of the fixed columns steals the space from column 1 rather than scrolling. At tablet
   width the Person column shrank to a single character and the "PERSON" and "CALLS" headers
   printed on top of each other. Found by resizing the window, not by any assertion. */
.pp-table { min-width:640px; }
.pp-calls { min-width:520px; }
.pp-dims  { min-width:470px; }
.pp-table td:nth-child(n+2), .pp-table th:nth-child(n+2) { width:62px; }
.pp-table td:nth-child(1), .pp-table th:nth-child(1) { width:190px; }
.pp-table td:nth-child(6), .pp-table th:nth-child(6) { width:92px; }
.pp-table td:nth-child(7), .pp-table th:nth-child(7) { width:120px; text-align:left; }
/* An email is one token. Truncate it rather than hyphenating it into nonsense; the full value
   stays available on hover via the title attribute. */
.pp-table td:nth-child(1) { overflow-wrap:normal; white-space:nowrap;
                            overflow:hidden; text-overflow:ellipsis; }
.pp-calls td:nth-child(2), .pp-calls th:nth-child(2) { width:120px; }
.pp-calls td:nth-child(3), .pp-calls th:nth-child(3) { width:92px; }
.pp-calls td:nth-child(1) { overflow-wrap:normal; white-space:nowrap;
                            overflow:hidden; text-overflow:ellipsis; }
/* The unowned marker sits beside the name on one line, not stacked under it. */
.pp-noowner { color:var(--ink-400); font-size:11px; margin-left:6px; white-space:nowrap; }
.pp-mix { color:var(--ink-400); font-size:12px; }
.pp-h { font-size:12px; text-transform:uppercase; letter-spacing:.02em; color:var(--ink-400);
        margin:22px 0 8px; font-weight:600; }

/* The dimension bar. One neutral fill: length carries the number, colour carries nothing. */
.pp-dims td:nth-child(2), .pp-dims th:nth-child(2) { width:120px; }
.pp-barcell { vertical-align:middle; }
.pp-bar { display:block; height:6px; border-radius:3px; background:var(--line); overflow:hidden; }
.pp-bar-fill { display:block; height:100%; border-radius:3px;
               background:linear-gradient(90deg, var(--blue-500), var(--violet-500)); }

/* Trend columns, reusing .sp-chart/.sp-col/.sp-bar-wrap from Spend so the two pages agree. */
/* Cap the column width. `.sp-col` is flex:1, which is right for thirty days of spend and wrong
   for two weeks of calls: two bars grew to 350px each and read as blocks of colour rather than
   as a chart. Caught by looking at it. */
.pp-chart .sp-col { flex:0 1 90px; }
.pp-tbar { width:100%; border-radius:3px 3px 0 0; min-height:2px;
           background:linear-gradient(180deg, var(--violet-500), var(--blue-500)); }
.pp-tlabel { font-size:10px; color:var(--ink-400); text-align:center; padding-top:4px;
             white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }

/* ---- Billing (TASK-122) -------------------------------------------------------------------
   Three unlabelled inputs sat in a row and the third truncated to "Days before the licen".
   A placeholder is not a label: once you type in the field the only explanation of what it
   means disappears. Caught by looking at the page. */
.bl-fields { display:flex; flex-wrap:wrap; gap:10px; margin:10px 0; }
.bl-f { display:flex; flex-direction:column; gap:4px; flex:1 1 220px; }
.bl-f.bl-narrow { flex:0 0 140px; }
.bl-f > span { font-size:11px; text-transform:uppercase; letter-spacing:.02em; color:var(--ink-400); font-weight:600; }
.bl-f > input { width:100%; }
/* A disabled action that looks identical to an enabled one reads as a broken button. */
.chip[disabled] { opacity:.45; cursor:not-allowed; }
.chip[disabled]:hover { background:var(--paper-100); }

/* ---- Key moments (TASK-123) ---------------------------------------------------------------
   A linked timestamp and an unlinked one must not look the same. The linked version is the
   accent colour and underlines on hover; the unlinked one is muted and carries a title saying
   why. A trainer clicking a dead-looking link in front of their team is the failure to avoid. */
.km-list { display:flex; flex-direction:column; gap:10px; margin:8px 0 18px; }
.km { display:flex; gap:12px; align-items:flex-start; padding:10px 12px;
      border:1px solid var(--line); border-radius:10px; background:var(--paper-50); }
.km-at { font-family:var(--font-mono); font-size:12px; font-weight:600; white-space:nowrap;
         padding-top:1px; color:var(--blue-500); text-decoration:none; }
a.km-at:hover { text-decoration:underline; }
.km-at.km-plain { color:var(--ink-400); cursor:help; }
.km-body { flex:1; min-width:0; }
.km-label { font-weight:600; font-size:13px; }
.km-what { font-size:13px; color:var(--ink-800); margin-top:3px; }
.km-why { font-size:12px; color:var(--ink-400); margin-top:3px; }

/* ---- Integrations, rebuilt 2026-09-11 ------------------------------------------------------
   A quiet list, after Linear and MagicPath. A COLLAPSED row shows state; an EXPANDED row shows
   controls. That single rule is what stopped this page being a wall of always-open forms with
   four save buttons visible at once. */
.ig-group { margin-bottom:26px; }
.ig-group-t { font-size:11px; text-transform:uppercase; letter-spacing:.14em; color:var(--ink-400);
              font-weight:700; margin-bottom:8px; }

.ig-row { border:1px solid var(--line); border-radius:12px; margin-bottom:8px;
          background:var(--paper-50); overflow:hidden; }
.ig-row.is-open { border-color:var(--blue-500); }

/* The whole header is the toggle: a 44px-tall target rather than a chevron you have to hit. */
.ig-head { display:flex; align-items:center; gap:12px; width:100%; padding:13px 14px;
           background:none; border:0; text-align:left; cursor:pointer; color:inherit; font:inherit;
           flex-wrap:wrap; row-gap:6px; }
.ig-head:hover { background:var(--paper-100); }
/* Size and tint come from the markup so one renderer serves both the rows and the picker tiles,
   and so a real logo SVG dropped into INTEGRATION_META.icon lands in both at once. */
.ig-mark { flex:0 0 auto; border-radius:8px; display:grid; place-items:center;
           font-weight:700; font-size:13px; color:#fff; overflow:hidden; }
.ig-mark svg { width:62%; height:62%; }
/* A real brand mark brings its own colours, so it gets a neutral surface rather than a tint.
   The faint border keeps a white-ish logo from vanishing into a light theme. */
.ig-mark-logo { background:var(--paper-100); border:1px solid var(--line); }
.ig-mark-logo svg { width:66%; height:66%; }
/* flex-basis 180px with wrap: on a wide pane the state sits on the right, and on a narrow one it
   drops to its own line instead of colliding with the description. The detail pane is genuinely
   narrow when the call list is open, and the first version overlapped the badge with the text. */
.ig-main { flex:1 1 180px; min-width:0; display:flex; flex-direction:column; gap:2px; }
.ig-name { font-weight:600; font-size:14px; }
/* One line. A description that wraps to four lines turns a list back into a wall. */
.ig-blurb { font-size:12px; color:var(--ink-400);
            white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.ig-tag { font-size:11px; font-weight:600; color:var(--ink-400); background:var(--paper-200);
          border-radius:5px; padding:1px 6px; margin-left:6px; }
.ig-right { display:flex; align-items:center; gap:10px; flex:0 0 auto; margin-left:auto;
            max-width:100%; min-width:0; }
.ig-chev { color:var(--ink-400); font-size:11px; }

/* State, collapsed. "Connected as WHAT" is the thing people actually come here to check. */
.ig-state { font-size:12px; font-weight:600; }
.ig-state.ig-on { color:var(--blue-500); }
.ig-state.ig-off { color:var(--ink-400); }
/* Amber, not green and not red: a credential is saved and has simply not been proven to work.
   Colouring it green is a lie; colouring it red implies a failure that may never have happened. */
.ig-state.ig-unver { color:#D08A32; cursor:help; }
.ig-as { font-size:11px; color:var(--ink-400); margin-left:8px;
         display:inline-block; max-width:min(320px, 42vw); overflow:hidden;
         text-overflow:ellipsis; white-space:nowrap; vertical-align:bottom; }
.ig-as code { font-family:var(--font-mono); font-size:11px; }
.ig-warn { color:var(--pink-500); font-weight:600; }

.ig-panel { padding:4px 14px 14px; border-top:1px solid var(--line); }

/* "Where do I find this?" — Bolt.new's move. The instructions live at the point of use rather
   than in a prose block at the bottom of the page, which is where they went stale for 8 weeks. */
.ig-where { background:var(--paper-100); border-radius:9px; padding:11px 13px; margin:12px 0 14px; }
.ig-where-t { font-size:11px; text-transform:uppercase; letter-spacing:.1em; font-weight:700;
              color:var(--ink-400); margin-bottom:6px; }
.ig-where ol { margin:0; padding-left:18px; font-size:12.5px; line-height:1.65; color:var(--ink-800); }

.ig-field { display:flex; flex-direction:column; gap:5px; margin-bottom:12px; }
.ig-field > span:first-child { font-size:11px; text-transform:uppercase; letter-spacing:.02em;
                               color:var(--ink-400); font-weight:600; }
.ig-field input { width:100%; }
.ig-help { font-size:12px; color:var(--ink-400); line-height:1.55; }
.ig-keyrow { display:flex; gap:8px; }
.ig-keyrow input { flex:1; }

.ig-actions { display:flex; flex-wrap:wrap; gap:8px; margin-top:14px; }
.ig-danger { color:var(--pink-500); }

/* The test result lands here, in the panel, and stays — n8n's pattern. A toast that vanishes is
   the wrong home for the one sentence telling you why a connection failed. */
.ig-result { font-size:12.5px; line-height:1.55; margin-top:10px; min-height:1em; color:var(--ink-400); }
.ig-result.is-ok { color:var(--blue-500); font-weight:600; }
.ig-result.is-bad { color:var(--pink-500); font-weight:600; }

/* ---- Workspace mode (2026-09-11) -----------------------------------------------------------
   Settings pages take the whole window. The call list is 280px of unrelated conversation while
   you are pasting an API key, and hiding it is the difference between a settings page and a
   settings column. Matches how Devin, Pipedrive and Google Drive treat settings.

   Declared AFTER the shell rules so it wins, and repeated inside the ≤900px band because that
   band re-declares grid-template-columns and would otherwise put the list back. */
body.workspace .call-list { display:none; }
body.workspace .app { grid-template-columns:var(--w-sidebar, 208px) minmax(0,1fr); }
body.workspace.sb-collapsed .app { grid-template-columns:0 minmax(0,1fr); }
/* Both handles sit on column boundaries that no longer exist here. */
body.workspace .resizer { display:none; }
@media (max-width:1100px){ body.workspace .app { grid-template-columns:var(--w-sidebar, 176px) minmax(0,1fr); } }
/* ONE column below 900px, not two.
   In this band the sidebar stops being a grid column and becomes a fixed slide-over, so the two
   columns are the call list and the detail. Hiding the list therefore leaves the detail sitting
   in a 240px slot with the rest of the window empty — which is exactly what shipped for an hour:
   the Integrations page rendered 240px wide against a black void, and its rows overflowed their
   own column. Found by measuring element positions, not by checking for overflow, which was
   clean the whole time. Same band as the icon-rail bug of 2026-08-05. */
@media (max-width:900px){ body.workspace .app { grid-template-columns:minmax(0,1fr); } }

/* Full width is not full bleed. A form stretched across 1900px is harder to read than one at
   280px, and readability is the whole point of the change — so the content is capped and
   centred while the PANE is full width. Tables and charts opt out with .view-wide. */
body.workspace .view-body { max-width:1120px; margin-inline:auto; }
body.workspace .detail-header > .dh-top { max-width:1120px; margin-inline:auto; width:100%; }

/* ---- Add-integration picker (2026-09-11) ---------------------------------------------------
   Frame's compact tile grid rather than a searchable catalogue: there are four integration
   types, and a search field over four items is decoration pretending to be a feature. */
.ig-top { display:flex; justify-content:flex-end; margin-bottom:14px; }

.ig-modal { position:fixed; inset:0; background:rgba(0,0,0,.55); z-index:60;
            display:none; align-items:center; justify-content:center; padding:24px; }
.ig-modal.show { display:flex; }
.ig-modal-card { width:min(680px, 100%); max-height:82vh; overflow:auto;
                 background:var(--paper-0); border:1px solid var(--line); border-radius:16px;
                 box-shadow:0 24px 64px rgba(0,0,0,.45); padding:20px; }
.ig-modal-head { display:flex; align-items:flex-start; justify-content:space-between; gap:16px;
                 margin-bottom:16px; }
.ig-modal-t { font-family:var(--font-display); font-size:19px; font-weight:600; }
.ig-modal-s { font-size:12.5px; color:var(--ink-400); margin-top:3px; }
.ig-modal-x { background:none; border:0; color:var(--ink-400); font-size:22px; line-height:1;
              cursor:pointer; padding:0 4px; }
.ig-modal-x:hover { color:var(--ink-800); }

/* align-items:stretch plus margin-top:auto on the badge, so tiles with a "more than one" note
   and tiles without one still end at the same line. Without it the grid bottoms out ragged. */
.ig-tiles { display:grid; grid-template-columns:repeat(auto-fit, minmax(180px, 1fr)); gap:10px;
            align-items:stretch; }
.ig-tile { display:flex; flex-direction:column; align-items:flex-start; gap:6px; text-align:left;
           padding:14px; border:1px solid var(--line); border-radius:12px; cursor:pointer;
           background:var(--paper-50); color:inherit; font:inherit; height:100%; }
.ig-tile:hover { border-color:var(--blue-500); background:var(--paper-100); }
.ig-tile:disabled { opacity:.5; cursor:wait; }
.ig-tile-name { font-weight:600; font-size:14px; margin-top:2px; }
.ig-tile-blurb { font-size:12px; color:var(--ink-400); line-height:1.45; }
.ig-tile-note { font-size:11px; color:var(--ink-400); background:var(--paper-200);
                border-radius:5px; padding:1px 6px; margin-top:auto; }

/* ---- Conversation bubbles. Born with the Ask page (TASK-126); the page is gone and Vera's panel
   (TASK-128/129) renders the same .ask-msg / .ask-who / .ask-body. One rule family, one feature. */
.ask-log { min-height:180px; max-height:52vh; overflow-y:auto; display:flex; flex-direction:column;
           gap:14px; padding:4px 2px 12px; }
.ask-msg { display:flex; flex-direction:column; gap:4px; }
.ask-who { font-size:10px; text-transform:uppercase; letter-spacing:.14em; color:var(--ink-400);
           font-weight:700; }
.ask-body { font-size:14.5px; line-height:1.65; }
.ask-user .ask-body { background:var(--paper-100); border-radius:10px; padding:10px 12px; }
.ask-compose { display:flex; gap:8px; align-items:flex-end; }
.ask-compose textarea { flex:1; resize:vertical; min-height:44px; }

/* ---------------------------------------------------------------- Vera (TASK-128)
   The assistant got a name and a voice, so the panel had to stop looking like a query box with
   a log under it. Three changes carry it: her opening line renders as a message rather than
   empty-state furniture, the waiting state says what is actually happening instead of showing a
   spinner, and the scope disclosure moved BELOW the composer -- it is a footnote about billing
   and access, not the first thing to read on a page that now opens with a sentence from her. */
.ask-log{ display:flex; flex-direction:column; gap:14px; }
.ask-msg{ display:flex; flex-direction:column; gap:3px; }
.ask-who{ font-size:12px; letter-spacing:0.02em; color:var(--ink-400); text-transform:uppercase; }
.ask-assistant .ask-who{ color:var(--violet-600); }
.ask-assistant .ask-body{ font-size:17px; line-height:1.5; }
/* A raw API error is one long unbroken token. Without this it does not wrap, the column grows to
   fit it, and the composer and the send button leave the screen -- which is precisely the moment
   the reader most needs the composer, because something just failed. Found by looking at a 401. */
.ask-body{ overflow-wrap:anywhere; min-width:0; }
.ask-msg{ min-width:0; }
.ask-user .ask-body{ color:var(--ink-800); }

/* "Vera is reading" beats a spinner because it is true: in that second something is going
   through up to sixty calls. A spinner says the app is busy; this says who is doing what. */
.ask-pending{ color:var(--ink-600); font-style:italic; }
.ask-dots{ display:inline-flex; gap:3px; margin-left:5px; vertical-align:baseline; }
.ask-dots i{ width:3px; height:3px; border-radius:50%; background:var(--violet-600);
  animation:ask-blink 1.25s infinite ease-in-out; }
.ask-dots i:nth-child(2){ animation-delay:0.18s; }
.ask-dots i:nth-child(3){ animation-delay:0.36s; }
@keyframes ask-blink{ 0%,80%,100%{ opacity:0.22; } 40%{ opacity:1; } }
/* Respect the setting. An idling animation is exactly the kind that triggers vestibular
   symptoms, and it carries no information a static state cannot. */
@media (prefers-reduced-motion: reduce){
  .ask-dots i{ animation:none; opacity:0.55; }
}

.ask-starter{ cursor:pointer; text-align:left; }

/* ---------------------------------------------------------------- Vera, floating (TASK-129/130)
   Ivan: "I would rather her be in the lower right corner, like a chatbot, always available and
   easy to reach, an icon inspired by the latest Siri but in our colors... Make her a little
   smaller until clicked. Animate the movement... Think of how Jony Ive and Dieter Rams might
   have designed this."

   The Rams half: as little as possible. A 40px ring at rest, no glow, one colour system, one
   easing, nothing that moves unless it is telling you something. The Ive half: it is ONE object.
   The ring in the corner is the same ring that sits in the panel's header -- on open it travels
   there (a FLIP morph in app.js), and on close it travels back. The panel does not "appear";
   she moves. Speed and glow are reserved for the one honest state: reading. */
:root{ --vera-idle:40px; --vera-hover:44px; --vera-ease:cubic-bezier(.3,0,.16,1); }
.vera-fab{
  position:fixed; right:22px; bottom:22px; z-index:100;
  width:var(--vera-idle); height:var(--vera-idle); padding:0; border:0; border-radius:50%;
  cursor:pointer; background:transparent; -webkit-tap-highlight-color:transparent;
  transition:width .22s var(--vera-ease), height .22s var(--vera-ease), opacity .18s var(--vera-ease), transform .18s var(--vera-ease);
}
.vera-fab:hover, .vera-fab:focus-visible{ width:var(--vera-hover); height:var(--vera-hover); }
.vera-fab:active{ transform:scale(.96); }
.vera-fab:focus-visible{ outline:2px solid var(--focus); outline-offset:5px; }
/* While she is in the panel, the corner is empty. The ghost handles the travel. */
.vera-fab[aria-expanded="true"]{ opacity:0; pointer-events:none; }

.vera-orb{ position:relative; display:block; width:100%; height:100%; border-radius:50%; }
.vera-orb-glow, .vera-orb-core, .vera-orb-center{ position:absolute; inset:0; border-radius:50%; }
/* The ring: one conic gradient in the app's three accents, and the LAYER rotates -- a plain
   transform, not an animated @property. Two reasons. Older Safari has no @property, so the ring
   simply did not turn there. And on the phone viewport an animated registered property in a
   subtree stalled every animation on its ancestors: the travelling ring never arrived and the
   panel froze at its first keyframe. A rotating circle is visually identical and boring, which is
   the point. Idle turn is 14s: alive, not busy. */
.vera-orb-core{
  background:conic-gradient(from 0deg, var(--blue-500), var(--violet-500), var(--pink-500), var(--blue-600), var(--blue-500));
  animation:vera-turn 14s linear infinite;
}
/* The centre is a SIBLING, not a child of the ring, so it does not rotate with it: the little
   highlight stays at ten o'clock like light on a real object. inset is the ring's thickness --
   10% of the diameter is a fine line at 40px and the same line at 24px. */
.vera-orb-center{
  inset:10%;
  background:radial-gradient(circle at 38% 34%, rgba(255,255,255,.10), transparent 58%), var(--paper-50);
}
[data-theme="light"] .vera-orb-center{ background:radial-gradient(circle at 38% 34%, rgba(255,255,255,.95), transparent 58%), #fff; }
/* The glow exists but is OFF at rest. Rams would not have it at all; it earns its place only
   when she is doing something -- hover (you are about to), open (she is here), reading. */
.vera-orb-glow{
  background:conic-gradient(from 0deg, var(--blue-500), var(--violet-500), var(--pink-500), var(--blue-600), var(--blue-500));
  filter:blur(8px); opacity:0; scale:1.05;
  animation:vera-turn 14s linear infinite;
  transition:opacity .22s var(--vera-ease), scale .22s var(--vera-ease);
}
.vera-fab:hover .vera-orb-glow, .vera-fab:focus-visible .vera-orb-glow{ opacity:.35; }
.vera-head .vera-orb-glow{ opacity:.28; filter:blur(5px); }
/* Reading: the only fast state. */
.vera-fab.busy .vera-orb-core, .vera-fab.busy .vera-orb-glow,
.vera-panel.busy .vera-orb-core, .vera-panel.busy .vera-orb-glow{ animation-duration:1.4s; }
.vera-fab.busy .vera-orb-glow, .vera-panel.busy .vera-orb-glow{ opacity:.6; scale:1.18; }
@keyframes vera-turn{ to{ transform:rotate(360deg); } }
@media (prefers-reduced-motion: reduce){
  .vera-orb-glow, .vera-orb-core{ animation:none !important; }
  .vera-fab.busy .vera-orb-glow, .vera-panel.busy .vera-orb-glow{ opacity:.7; scale:1; }
}
/* The travelling ring. Created by app.js for the duration of an open or close, then removed. */
.vera-ghost{ position:fixed; z-index:120; pointer-events:none; will-change:transform; }
.vera-ghost .vera-orb-glow{ opacity:.3; }

/* The panel opens from the corner she left. Non-modal: the page behind stays live. */
.vera-panel{
  position:fixed; right:22px; bottom:22px; z-index:110;
  width:min(420px, calc(100vw - 44px)); height:min(640px, calc(100vh - 44px));
  display:flex; flex-direction:column; min-height:0;
  background:var(--paper-100); border:1px solid var(--line-strong); border-radius:18px;
  box-shadow:var(--shadow); overflow:hidden;
  /* No CSS entrance here on purpose: it is driven from app.js (fadePanel) so it can be raced and
     cancelled like the ring's travel. A fill:both keyframe left the panel invisible when the
     document timeline stalled. The origin is the corner she left. */
  transform-origin:calc(100% - 20px) calc(100% - 20px);
}
.vera-head{ display:flex; align-items:center; gap:10px; padding:12px 12px 12px 14px; border-bottom:1px solid var(--line); }
.vera-head .vera-orb{ width:24px; height:24px; flex:none; }
.vera-title{ font-family:var(--font-display); font-size:17px; font-weight:600; letter-spacing:-0.022em; line-height:1.2; }
.vera-sub{ font-size:12px; line-height:16px; color:var(--ink-400); letter-spacing:.02em; display:flex; align-items:baseline; gap:4px; flex-wrap:wrap; }
/* The window control is text until you touch it. It reads as part of the sentence: same size,
   same line, same weight; only a dotted underline and a hairline chevron say it can change. */
.vera-window{ appearance:none; -webkit-appearance:none; background:transparent; border:0; margin:0; padding:0 11px 0 0;
  font-family:inherit; font-size:12px; line-height:16px; font-weight:400; letter-spacing:.02em; color:var(--ink-600);
  cursor:pointer; border-bottom:1px dotted var(--line-strong); border-radius:0; vertical-align:baseline; height:16px;
  background-image:linear-gradient(45deg, transparent 50%, var(--ink-400) 50%), linear-gradient(135deg, var(--ink-400) 50%, transparent 50%);
  background-position:calc(100% - 5px) 7px, calc(100% - 2px) 7px; background-size:3px 3px, 3px 3px; background-repeat:no-repeat; }
.vera-window option{ color:var(--ink-950); background:var(--paper-100); }
.vera-window:hover{ color:var(--ink-950); }
.vera-window:focus-visible{ outline:2px solid var(--focus); outline-offset:2px; border-radius:2px; }
.vera-close{ margin-left:auto; width:32px; height:32px; border-radius:8px; border:1px solid transparent; background:transparent; color:var(--ink-600); font-size:18px; line-height:1; cursor:pointer; transition:background .15s var(--vera-ease), color .15s var(--vera-ease); }
.vera-close:hover{ background:var(--paper-200); color:var(--ink-950); }
.vera-close:focus-visible{ outline:2px solid var(--focus); }
.vera-body{ flex:1 1 auto; min-height:0; overflow-y:auto; padding:14px; }
.vera-body .ask-log{ gap:12px; }
.vera-foot{ flex:none; border-top:1px solid var(--line); padding:10px 12px 12px; display:flex; flex-direction:column; gap:8px; }
.vera-chips{ display:flex; gap:6px; overflow-x:auto; scrollbar-width:none; padding-bottom:2px; }
.vera-chips::-webkit-scrollbar{ display:none; }
.vera-chips .chip{ flex:none; white-space:nowrap; cursor:pointer; }
.vera-panel .ask-compose{ display:flex; gap:8px; align-items:flex-end; }
.vera-panel .ask-compose textarea{ flex:1 1 auto; min-width:0; resize:none; }
.vera-scope{ font-size:12px; color:var(--ink-400); letter-spacing:.02em; }

/* Phone: the panel is the screen, and the orb stays clear of the thumb-side edge. */
@media (max-width:640px){
  :root{ --vera-idle:44px; --vera-hover:44px; }   /* thumbs, not pointers */
  .vera-fab{ right:16px; bottom:16px; }
  .vera-panel{ inset:0; width:auto; height:auto; border-radius:0; border:0; transform-origin:calc(100% - 38px) calc(100% - 38px); }
  .detail{ padding-bottom:78px; }
}


/* ---- Onboarding intake, on Account & Access (TASK-131) ---- */
.in-count{ font-family:var(--font-mono); font-size:12px; color:var(--blue-600); background:var(--blue-100); border-radius:100px; padding:2px 8px; margin-left:6px; vertical-align:middle; }
.in-empty{ font-size:15px; color:var(--ink-400); padding:10px 0 4px; }
.in-row{ border:1px solid var(--line); border-radius:10px; background:var(--paper-50); margin:8px 0; }
.in-row summary{ list-style:none; cursor:pointer; display:flex; flex-wrap:wrap; align-items:baseline; gap:10px; padding:10px 12px; font-size:15px; }
.in-row summary::-webkit-details-marker{ display:none; }
.in-when{ font-family:var(--font-mono); font-size:12px; color:var(--ink-400); }
.in-contact{ color:var(--ink-600); }
.in-n{ margin-left:auto; font-size:12px; color:var(--ink-400); }
.in-body{ border-top:1px solid var(--line); padding:6px 12px 10px; display:grid; gap:6px; }
.in-kv{ display:grid; grid-template-columns:150px 1fr; gap:10px; font-size:14px; }
.in-k{ color:var(--ink-400); text-transform:capitalize; }
.in-v{ color:var(--ink-800); white-space:pre-wrap; overflow-wrap:anywhere; }
@media (max-width:640px){ .in-kv{ grid-template-columns:1fr; gap:2px; } }
.in-actions{ display:flex; justify-content:flex-end; padding-top:4px; }
