/* ============================================================
   Personal Assistant Dashboard
   Catppuccin Macchiato
   ============================================================ */

*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
[hidden] { display: none !important; }

/* ── Tokens ─────────────────────────────────────────────── */
:root {
  --bg:           #24273a;
  --surface:      #1e2030;
  --surface2:     #2a2d3e;
  --border:       #494d64;
  --text:         #cad3f5;
  --text-muted:   #a5adcb;
  --text-light:   #6e738d;

  --todo:         #8aadf4;
  --todo-bg:      #1e2a3f;
  --wait:         #eed49f;
  --wait-bg:      #2e2a1e;
  --proj:         #c6a0f6;
  --proj-bg:      #261e36;
  --done:         #a6da95;
  --done-bg:      #1e2e20;
  --canc:         #6e738d;
  --canc-bg:      #2a2c3a;
  --blocked:      #ed8796;
  --blocked-bg:   #301e22;
  --peach:        #f5a97f;
  --peach-bg:     #2e2419;
  --teal:         #8bd5ca;
  --teal-bg:      #1a2e2c;

  --col-inprogress: #8aadf4;
  --col-upnext:     #c6a0f6;
  --col-backlog:    #8bd5ca;
  --col-blocked:    #ed8796;
  --col-done:       #a6da95;

  /* area colors for calendar dots */
  --area-work:       #8aadf4;
  --area-health:     #a6da95;
  --area-home:       #eed49f;
  --area-personal:   #c6a0f6;
  --area-spiritual:  #f5a97f;
  --area-finances:   #ed8796;
  --area-smallgroup: #8bd5ca;

  --radius:  8px;
  --radius-sm: 6px;
  --shadow:  0 1px 3px rgba(0,0,0,0.2);

  --header-h:      68px;
  --sidebar-left:  280px;
  --sidebar-right: 300px;
}

html, body {
  height: 100%;
  overflow: hidden;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
  font-size: 14px;
  background: var(--bg);
  color: var(--text);
  line-height: 1.5;
}

/* ── App shell ───────────────────────────────────────────── */
.app {
  display: flex;
  flex-direction: column;
  height: 100vh;
}

/* ── Header ─────────────────────────────────────────────── */
.header {
  height: var(--header-h);
  flex-shrink: 0;
  display: flex;
  align-items: center;
  padding: 0 16px;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  gap: 12px;
}
.header-left  { flex: 1; display: flex; align-items: center; }
.header-center { flex: 0 0 auto; display: flex; align-items: stretch; height: 100%; }
.header-right { flex: 1; display: flex; align-items: center; justify-content: flex-end; gap: 10px; }

/* ── View nav (in header) ──────────────────────────────── */
.view-nav {
  display: flex;
  align-items: stretch;
  gap: 0;
}
.view-nav-btn {
  background: none;
  border: none;
  border-bottom: 2px solid transparent;
  color: var(--text-light);
  font-size: 12px;
  font-weight: 600;
  padding: 0 13px;
  cursor: pointer;
  letter-spacing: 0.2px;
  transition: color 0.15s, border-color 0.15s;
  white-space: nowrap;
}
.view-nav-btn:hover  { color: var(--text); }
.view-nav-btn.active { color: var(--proj); border-bottom-color: var(--proj); }

/* ── Brand ───────────────────────────────────────────── */
.brand {
  display: flex;
  flex-direction: column;
  justify-content: center;
  line-height: 1;
  margin: 0 10px;
}
.brand-name {
  font-family: Impact, "Arial Narrow", sans-serif;
  font-size: 24px;
  letter-spacing: 2px;
  color: var(--proj);
  line-height: 1;
}
.brand-tagline {
  font-size: 9px;
  font-weight: 300;
  color: var(--text-light);
  letter-spacing: 1.4px;
  margin-top: 4px;
}

.header-date {
  font-size: 13px;
  color: var(--text-muted);
}
.header-title {
  font-size: 18px;
  font-weight: 700;
  letter-spacing: -0.3px;
  color: var(--text);
}
.header-clock {
  font-size: 13px;
  font-variant-numeric: tabular-nums;
  color: var(--text-muted);
}

/* WS status dot + label — "Agent" (Agent Chat push, dash-ws-dot) and "Voice"
   (Nova's voice/notify socket, ws-dot) are two genuinely separate connections
   to two different backends; the label disambiguates them from each other
   and from "Board" (Nova's own project board, unrelated to either socket). */
.ws-status {
  display: inline-flex;
  align-items: center;
  gap: 4px;
}
.ws-status-label {
  font-size: 11px;
  color: var(--text-muted);
}

.ws-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  display: inline-block;
  flex-shrink: 0;
  background: var(--text-light);
  transition: background 0.3s;
}
.ws-dot.connected    { background: var(--done); }
.ws-dot.connecting   { background: var(--wait); }
.ws-dot.disconnected { background: var(--text-light); }

/* Dashboard push (dynamic-dashboard, agent-chat#18) status dot — separate
   from .ws-dot above, which reflects the voice assistant's own connection. */
.dash-ws-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  display: inline-block;
  flex-shrink: 0;
  background: var(--text-light);
  transition: background 0.3s;
}
.dash-ws-dot.connected    { background: var(--done); }
.dash-ws-dot.connecting   { background: var(--wait); }
.dash-ws-dot.disconnected { background: var(--text-light); }

/* Sidebar toggle */
.sidebar-toggle {
  background: none;
  border: none;
  color: var(--text-light);
  font-size: 16px;
  cursor: pointer;
  padding: 2px 6px;
  border-radius: 4px;
  line-height: 1;
  flex-shrink: 0;
}
.sidebar-toggle:hover { color: var(--text); background: var(--surface2); }

/* Sidebar hide states — keep elements in grid flow, collapse via 0px column */
.sidebar-left.hidden  { padding: 0; border: none; }
.sidebar-right.hidden { padding: 0; border: none; }
.layout.hide-left  { grid-template-columns: 0 1fr var(--sidebar-right); }
.layout.hide-right { grid-template-columns: var(--sidebar-left) 1fr 0; }
.layout.hide-left.hide-right { grid-template-columns: 0 1fr 0; }

/* Mode select */
.mode-select {
  background: var(--surface2);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 4px 8px;
  font-size: 12px;
  cursor: pointer;
  outline: none;
}
.mode-select:focus { border-color: var(--proj); }

/* Mute button */
.mute-btn {
  background: var(--surface2);
  color: var(--text-muted);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 4px 10px;
  font-size: 12px;
  cursor: pointer;
  transition: background 0.15s, color 0.15s;
}
.mute-btn:hover  { background: var(--border); }
.mute-btn.active { background: var(--blocked-bg); color: var(--blocked); border-color: var(--blocked); }

/* ── Three-panel layout ──────────────────────────────────── */
.layout {
  flex: 1;
  min-height: 0;
  display: grid;
  grid-template-columns: var(--sidebar-left) 1fr var(--sidebar-right);
}

/* ── Left sidebar: Calendar ──────────────────────────────── */
.sidebar-left {
  border-right: 1px solid var(--border);
  background: var(--surface);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  padding: 12px;
  gap: 4px;
}

.cal-nav-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 6px;
}
.cal-month-label {
  font-size: 13px;
  font-weight: 600;
  color: var(--text);
}
.cal-nav-btn {
  background: none;
  border: none;
  color: var(--text-muted);
  font-size: 18px;
  cursor: pointer;
  padding: 0 4px;
  line-height: 1;
  border-radius: 4px;
}
.cal-nav-btn:hover { color: var(--text); background: var(--surface2); }

.cal-dow-row {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  text-align: center;
  font-size: 10px;
  font-weight: 600;
  color: var(--text-light);
  letter-spacing: 0.3px;
  margin-bottom: 4px;
}

.cal-grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 2px;
}

.cal-day {
  aspect-ratio: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-start;
  padding-top: 3px;
  border-radius: 6px;
  cursor: pointer;
  font-size: 11px;
  color: var(--text-muted);
  gap: 2px;
  transition: background 0.1s;
  position: relative;
}
.cal-day:hover          { background: var(--surface2); }
.cal-day.today          { background: var(--todo-bg); color: var(--todo); font-weight: 700; }
.cal-day.selected       { background: var(--proj-bg); color: var(--proj); }
.cal-day.today.selected { background: var(--proj-bg); color: var(--proj); }
.cal-day.other-month    { color: var(--text-light); opacity: 0.5; }

.cal-day-num { line-height: 1; }

.cal-dots {
  display: flex;
  gap: 2px;
  flex-wrap: wrap;
  justify-content: center;
}
.cal-dot {
  width: 4px;
  height: 4px;
  border-radius: 50%;
  flex-shrink: 0;
}

.cal-agenda-label {
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  color: var(--text-light);
  padding: 8px 0 4px;
  border-top: 1px solid var(--border);
  flex-shrink: 0;
}

/* ── Time grid ───────────────────────────────────────────── */
.time-grid {
  flex: 1;
  overflow-y: auto;
  position: relative;
}
.time-grid::-webkit-scrollbar { width: 4px; }
.time-grid::-webkit-scrollbar-thumb { background: var(--border); border-radius: 2px; }

.time-grid-inner {
  position: relative;
}

.tg-hour {
  position: absolute;
  left: 0;
  right: 0;
  border-top: 1px solid rgba(73,77,100,0.35);
  display: flex;
  align-items: flex-start;
}
.tg-hour-label {
  font-size: 9px;
  color: var(--text-light);
  width: 28px;
  text-align: right;
  padding-right: 5px;
  line-height: 1;
  margin-top: -5px;
  flex-shrink: 0;
  font-variant-numeric: tabular-nums;
}

.tg-slot {
  position: absolute;
  left: 32px;
  right: 3px;
  border-radius: 3px;
  padding: 2px 5px;
  overflow: hidden;
  cursor: pointer;
  border-left-width: 2px;
  border-left-style: solid;
  transition: opacity 0.1s;
  z-index: 1;
}
.tg-slot:hover { opacity: 0.8; }
.tg-slot-label {
  font-size: 10px;
  font-weight: 500;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  display: block;
  line-height: 1.35;
}

.tg-slot-work    { background: rgba(138,173,244,0.14); border-left-color: #8aadf4; color: #8aadf4; }
.tg-slot-break   { background: var(--surface2);        border-left-color: var(--border); color: var(--text-light); }
.tg-slot-meal    { background: rgba(166,218,149,0.14); border-left-color: #a6da95; color: #a6da95; }
.tg-slot-workout { background: rgba(245,169,127,0.14); border-left-color: #f5a97f; color: #f5a97f; }
.tg-slot-meeting { background: rgba(198,160,246,0.14); border-left-color: #c6a0f6; color: #c6a0f6; }

.tg-now {
  position: absolute;
  left: 28px;
  right: 0;
  height: 2px;
  background: var(--todo);
  z-index: 2;
  pointer-events: none;
}
.tg-now::before {
  content: '';
  position: absolute;
  width: 8px;
  height: 8px;
  background: var(--todo);
  border-radius: 50%;
  left: -4px;
  top: -3px;
}

.tg-empty {
  position: absolute;
  left: 32px;
  right: 4px;
  top: 50%;
  transform: translateY(-50%);
  font-size: 10px;
  color: var(--text-light);
  text-align: center;
  pointer-events: none;
}

.tg-popup {
  position: fixed;
  background: var(--surface2);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 10px 12px;
  z-index: 1000;
  min-width: 150px;
  max-width: 210px;
  box-shadow: 0 4px 16px rgba(0,0,0,0.5);
}
.tg-popup-title {
  font-size: 12px;
  font-weight: 600;
  color: var(--text);
  margin-bottom: 2px;
}
.tg-popup-time {
  font-size: 10px;
  color: var(--text-light);
  font-variant-numeric: tabular-nums;
  margin-bottom: 8px;
}
.tg-popup-link {
  display: block;
  width: 100%;
  background: none;
  border: none;
  color: var(--todo);
  font-size: 11px;
  cursor: pointer;
  text-align: left;
  padding: 0;
}
.tg-popup-link:hover { text-decoration: underline; }

/* ── Center: Board ───────────────────────────────────────── */
.board-area {
  overflow-y: auto;
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: 12px;
  padding: 14px;
  align-items: start;
}

/* Nova view spans all 5 grid columns */
#nova-view {
  grid-column: 1 / -1;
  padding: 2px 0;
}
/* Stretches #nova-view to fill .board-area's full height only when it's
   hosting the Agent Chat view (agent-chat#53, Task 5) — every other Nova
   view keeps its default content-sized height (.board-area's own
   align-items: start above), so this doesn't change their layout.
   Without this, .ac-chatter-footer's "sticky bottom:0" only pins it to the
   bottom of its own content once that content is already tall enough to
   scroll — on a light day with little pipeline activity, the footer just
   sits right after the content instead of anchoring to the viewport
   bottom. Stretching #nova-view to the full available height and letting
   .ac-app fill it (min-height:0 so the flex child can shrink below its
   content size, matching .layout's own flex:1/min-height:0 pattern above)
   gives .ac-chatter-footer's margin-top:auto (below) room to push it down
   to the bottom on a short day, while sticky still keeps it pinned during
   a scroll on a long one. */
#nova-view:has(> .ac-app) { align-self: stretch; display: flex; min-height: 0; }
/* min-width:0 alongside the existing min-height:0: #nova-view is a row, so
   .ac-app's *width* is its main axis here, and a flex item's automatic
   minimum main size defaults to its content's min-content contribution.
   Without this, one long unwrappable descendant (e.g. a verbose
   blockedReason in .ac-alert-cause below) forces .ac-app — and everything
   inside it, including the pipeline board's own 1fr columns further down —
   to grow to fit it instead of clipping. Confirmed live: a long
   blockedReason blew .ac-app out to ~11,700px before this fix. */
#nova-view:has(> .ac-app) > .ac-app { flex: 1; min-height: 0; min-width: 0; }

/* ── Column ─────────────────────────────────────────────── */
.column {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  overflow: hidden;
}

.column-header {
  padding: 10px 14px;
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.6px;
  border-bottom: 1px solid var(--border);
  display: flex;
  align-items: center;
  gap: 8px;
}
.column-header .count {
  font-size: 11px;
  font-weight: 600;
  background: rgba(255,255,255,0.08);
  border-radius: 10px;
  padding: 1px 7px;
  margin-left: auto;
}
.column-header .undated-count {
  font-size: 9px;
  font-weight: 500;
  color: var(--text-light);
  background: rgba(255,255,255,0.05);
  border-radius: 8px;
  padding: 1px 6px;
}

.col-inprogress .column-header { color: var(--col-inprogress); border-top: 3px solid var(--col-inprogress); }
.col-upnext     .column-header { color: var(--col-upnext);     border-top: 3px solid var(--col-upnext); }
.col-backlog    .column-header { color: var(--col-backlog);    border-top: 3px solid var(--col-backlog); }
.col-blocked    .column-header { color: var(--col-blocked);    border-top: 3px solid var(--col-blocked); }
.col-done       .column-header { color: var(--col-done);       border-top: 3px solid var(--col-done); }

/* ── Category ───────────────────────────────────────────── */
.category { border-bottom: 1px solid var(--border); }
.category:last-child { border-bottom: none; }

.category summary {
  list-style: none;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 7px 14px;
  cursor: pointer;
  user-select: none;
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  color: var(--text-light);
  transition: color 0.15s;
}
.category summary::-webkit-details-marker { display: none; }
.category summary::after {
  content: "›";
  font-size: 14px;
  font-weight: 400;
  transform: rotate(90deg);
  display: inline-block;
  transition: transform 0.2s ease;
}
.category details[open] summary::after { transform: rotate(270deg); }
.category summary:hover { color: var(--text-muted); }

.category-body { padding: 0 12px 6px; }

/* ── Card ───────────────────────────────────────────────── */
.card {
  padding: 7px 5px;
  border-radius: var(--radius-sm);
  margin-bottom: 3px;
  transition: background 0.1s;
}
.card:hover          { background: #363a4f; }
.card.overdue        { border-left: 2px solid var(--blocked); padding-left: 3px; }
.card.approaching    { border-left: 2px solid var(--peach);   padding-left: 3px; }

.card-title {
  font-size: 12px;
  font-weight: 500;
  color: var(--text);
  margin-bottom: 3px;
  line-height: 1.4;
}
.card-title.done-text {
  color: var(--text-muted);
  text-decoration: line-through;
}
.card-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  align-items: center;
  margin-top: 3px;
}
.card-note {
  font-size: 11px;
  color: var(--text-muted);
  margin-top: 3px;
  line-height: 1.4;
}

/* ── Badges + tags ──────────────────────────────────────── */
.badge {
  display: inline-block;
  font-size: 9px;
  font-weight: 700;
  padding: 1px 5px;
  border-radius: 10px;
  line-height: 1.6;
  letter-spacing: 0.3px;
}
.badge-todo    { background: var(--todo-bg);    color: var(--todo); }
.badge-wait    { background: var(--wait-bg);    color: var(--wait); }
.badge-proj    { background: var(--proj-bg);    color: var(--proj); }
.badge-done    { background: var(--done-bg);    color: var(--done); }
.badge-canc    { background: var(--canc-bg);    color: var(--canc); }
.badge-blocked { background: var(--blocked-bg); color: var(--blocked); }

.tag {
  display: inline-block;
  font-size: 10px;
  font-weight: 500;
  padding: 1px 5px;
  border-radius: 10px;
  background: #363a4f;
  color: var(--text-muted);
  border: 1px solid var(--border);
}

.date { font-size: 11px; color: var(--text-muted); }
.date.overdue { color: var(--blocked); font-weight: 600; }
.date.today   { color: var(--done);    font-weight: 600; }
.date-inline-input { font-size: 11px; background: var(--surface1); color: var(--text); border: 1px solid var(--blue); border-radius: 4px; padding: 0 4px; width: 110px; }

/* ── Checklist ──────────────────────────────────────────── */
.checklist { margin-top: 4px; padding-left: 2px; list-style: none; }
.checklist li {
  font-size: 11px;
  color: var(--text-muted);
  padding: 1px 0;
  display: flex;
  align-items: baseline;
  gap: 5px;
}
.checklist li::before { content: "○"; font-size: 9px; flex-shrink: 0; }
.checklist li.done { text-decoration: line-through; color: var(--text-light); }
.checklist li.done::before { content: "●"; color: var(--done); }

/* ── Deadline bar ───────────────────────────────────────── */
.deadline-bar {
  margin-top: 5px;
  font-size: 11px;
  display: flex;
  align-items: center;
  gap: 6px;
  color: var(--text-muted);
}
.deadline-bar .progress-track {
  flex: 1;
  height: 4px;
  background: var(--border);
  border-radius: 2px;
  overflow: hidden;
}
.deadline-bar .progress-fill {
  height: 100%;
  border-radius: 2px;
  background: var(--todo);
}

/* ── Right sidebar: Voice ────────────────────────────────── */
.sidebar-right {
  border-left: 1px solid var(--border);
  background: var(--surface);
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.voice-log {
  flex: 1;
  overflow-y: auto;
  padding: 14px 12px 8px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.voice-welcome {
  text-align: center;
  padding: 20px 8px 8px;
  color: var(--text-light);
}
.voice-welcome-title {
  font-size: 14px;
  font-weight: 600;
  color: var(--text-muted);
  margin-bottom: 4px;
}
.voice-welcome-sub { font-size: 12px; }

/* Message bubbles */
.msg {
  display: flex;
  flex-direction: column;
  max-width: 88%;
}
.msg-user   { align-self: flex-end; align-items: flex-end; }
.msg-system { align-self: flex-start; align-items: flex-start; }

.msg-bubble {
  padding: 7px 11px;
  border-radius: 14px;
  font-size: 12px;
  line-height: 1.45;
}
.msg-user   .msg-bubble { background: var(--todo-bg);    color: var(--text); border-bottom-right-radius: 4px; }
.msg-system .msg-bubble { background: var(--surface2);   color: var(--text); border-bottom-left-radius: 4px; }

/* Processing spinner bubble */
.msg-spinner .msg-bubble {
  background: var(--surface2);
  border-bottom-left-radius: 4px;
  display: flex;
  align-items: center;
  gap: 5px;
  padding: 10px 14px;
}
.spinner-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--text-muted);
  animation: spinner-bounce 1.2s ease-in-out infinite;
}
.spinner-dot:nth-child(2) { animation-delay: 0.2s; }
.spinner-dot:nth-child(3) { animation-delay: 0.4s; }
@keyframes spinner-bounce {
  0%, 80%, 100% { opacity: 0.25; transform: scale(0.8); }
  40%            { opacity: 1;    transform: scale(1);   }
}

/* Notification / reminder pill */
.msg-notify {
  align-self: stretch;
  background: var(--surface2);
  border: 1px solid var(--border);
  border-left: 3px solid var(--proj);
  border-radius: var(--radius-sm);
  padding: 6px 10px;
  font-size: 11px;
  color: var(--text-muted);
  display: flex;
  align-items: flex-start;
  gap: 7px;
}
.msg-notify-icon { color: var(--proj); flex-shrink: 0; font-size: 12px; }
.msg-notify-text { flex: 1; }
.msg-notify .msg-ts { align-self: flex-end; flex-shrink: 0; }

/* Timestamp shown beneath bubble messages and inline on notify pills */
.msg-ts {
  font-size: 9px;
  color: var(--text-muted);
  opacity: 0.6;
  margin-top: 2px;
}

/* Voice input area */
.voice-input-area {
  flex-shrink: 0;
  padding: 10px 12px 12px;
  border-top: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.voice-text-row {
  display: flex;
  gap: 6px;
}

.voice-text {
  flex: 1;
  background: var(--surface2);
  border: 1px solid var(--border);
  border-radius: 20px;
  color: var(--text);
  padding: 7px 14px;
  font-size: 13px;
  outline: none;
  transition: border-color 0.15s;
}
.voice-text::placeholder { color: var(--text-light); }
.voice-text:focus        { border-color: var(--proj); }
.voice-text:disabled     { opacity: 0.45; cursor: not-allowed; }

.voice-send {
  width: 36px;
  height: 36px;
  border-radius: 50%;
  background: var(--proj);
  color: var(--bg);
  border: none;
  font-size: 14px;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  transition: opacity 0.15s;
}
.voice-send:hover   { opacity: 0.85; }
.voice-send:disabled { opacity: 0.35; cursor: not-allowed; }

.voice-ptt {
  width: 100%;
  padding: 9px;
  background: var(--surface2);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  color: var(--text-muted);
  font-size: 13px;
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s, color 0.15s;
}
.voice-ptt:hover    { background: var(--border); }
.voice-ptt.active   { background: var(--blocked-bg); border-color: var(--blocked); color: var(--blocked); }
.voice-ptt:disabled { opacity: 0.35; cursor: not-allowed; }

/* ── Login modal ─────────────────────────────────────────── */
.modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0,0,0,0.6);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 100;
}
.modal-overlay[hidden] { display: none; }

.modal {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 28px 24px;
  width: 300px;
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.modal-title {
  font-size: 17px;
  font-weight: 700;
  color: var(--proj);
}
.modal-sub {
  font-size: 12px;
  color: var(--text-muted);
  margin-top: -8px;
}
.modal-error {
  background: var(--blocked-bg);
  border: 1px solid var(--blocked);
  color: var(--blocked);
  font-size: 12px;
  padding: 7px 10px;
  border-radius: var(--radius-sm);
}
.modal-error[hidden] { display: none; }

.modal-field {
  display: flex;
  flex-direction: column;
  gap: 5px;
}
.modal-field label {
  font-size: 11px;
  font-weight: 600;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.4px;
}
.modal-field input {
  background: var(--surface2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  color: var(--text);
  padding: 8px 12px;
  font-size: 13px;
  outline: none;
}
.modal-field input:focus { border-color: var(--proj); }

.modal-btn {
  background: var(--proj);
  color: var(--bg);
  border: none;
  border-radius: var(--radius-sm);
  padding: 9px;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  transition: opacity 0.15s;
  margin-top: 4px;
}
.modal-btn:hover    { opacity: 0.88; }
.modal-btn:disabled { opacity: 0.5; cursor: not-allowed; }

/* ── Responsive ──────────────────────────────────────────── */
@media (max-width: 900px) {
  :root {
    --sidebar-left:  0px;
    --sidebar-right: 0px;
  }
  .sidebar-left  { display: none; }
  .sidebar-right { display: none; }
  .layout { grid-template-columns: 1fr; }
  .board-area { grid-template-columns: 1fr; }
}

/* ── Nova shared ─────────────────────────────────────────── */
.nova-header {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 14px;
  flex-wrap: wrap;
}
.nova-title {
  font-size: 15px;
  font-weight: 700;
  color: var(--text);
  flex: 1;
}
.nova-btn {
  background: var(--proj);
  color: var(--bg);
  border: none;
  border-radius: var(--radius-sm);
  padding: 6px 13px;
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
  transition: opacity 0.15s;
  white-space: nowrap;
}
.nova-btn:hover    { opacity: 0.88; }
.nova-btn:disabled { opacity: 0.5; cursor: not-allowed; }
.nova-btn-sm { padding: 4px 10px; }
.nova-btn-outline {
  background: transparent;
  color: var(--text-muted);
  border: 1px solid var(--border);
}
.nova-btn-outline:hover { background: var(--surface2); opacity: 1; }

.nova-filters { display: flex; gap: 8px; }
.nova-select {
  background: var(--surface2);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 4px 8px;
  font-size: 12px;
  outline: none;
  cursor: pointer;
}
.nova-date-nav { display: flex; align-items: center; gap: 6px; }
.nova-date-input {
  background: var(--surface2);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 4px 8px;
  font-size: 12px;
  outline: none;
}

/* ── Nova table ──────────────────────────────────────────── */
.nova-table-wrap {
  overflow-y: auto;
  max-height: calc(100vh - 160px);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
}
.nova-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 13px;
}
.nova-table th {
  position: sticky;
  top: 0;
  z-index: 1;
  background: var(--surface);
  text-align: left;
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  color: var(--text-light);
  padding: 6px 10px;
  border-bottom: 1px solid var(--border);
}
.nova-table td {
  padding: 8px 10px;
  border-bottom: 1px solid rgba(73,77,100,0.25);
  vertical-align: middle;
}
.nova-row:hover td  { background: var(--surface2); }
.nova-row.archived  { opacity: 0.5; }
.nova-muted { color: var(--text-muted); font-size: 12px; }
.nova-id-col { font-family: monospace; font-size: 11px; color: var(--text-muted); white-space: nowrap; }
.nova-actions { white-space: nowrap; }

.nova-dot {
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  margin-right: 6px;
  vertical-align: middle;
}
.nova-tag {
  display: inline-block;
  font-size: 10px;
  padding: 1px 5px;
  border-radius: 8px;
  background: var(--surface2);
  color: var(--text-muted);
  border: 1px solid var(--border);
  margin-right: 3px;
}
.nova-link {
  background: none;
  border: none;
  color: var(--proj);
  font-size: 12px;
  cursor: pointer;
  padding: 2px 6px;
  border-radius: 4px;
}
.nova-link:hover  { background: var(--proj-bg); }
.nova-danger      { color: var(--blocked) !important; }
.nova-danger:hover { background: var(--blocked-bg) !important; }

.nova-badge-active { font-size: 10px; color: var(--done);  background: var(--done-bg);  padding: 2px 6px; border-radius: 8px; }
.nova-badge-arch   { font-size: 10px; color: var(--canc);  background: var(--canc-bg);  padding: 2px 6px; border-radius: 8px; }

.nova-status { font-size: 11px; }
.nova-status-not_started { color: var(--text-muted); }
.nova-status-in_progress { color: var(--todo); }
.nova-status-blocked     { color: var(--blocked); }
.nova-status-done        { color: var(--done); }
.nova-status-cancelled   { color: var(--canc); }
.nova-status-active      { color: var(--todo); }
.nova-status-on_hold     { color: var(--wait); }
.nova-status-completed   { color: var(--done); }

.nova-loading { color: var(--text-light); font-size: 13px; padding: 32px 0; text-align: center; }
.nova-empty   { color: var(--text-light); font-size: 13px; padding: 32px 0; text-align: center; }
.nova-error   { color: var(--blocked);    font-size: 13px; padding: 16px 0; }

/* ── Week schedule view ──────────────────────────────────── */
.sched-week {
  display: flex;
  flex-direction: column;
  height: calc(100vh - var(--header-h) - 30px);
  min-height: 400px;
}

.sched-week-label {
  font-size: 13px;
  font-weight: 600;
  color: var(--text);
  padding: 0 6px;
  white-space: nowrap;
}

/* Day header row */
.sched-day-headers {
  display: flex;
  border-bottom: 1px solid var(--border);
  background: var(--surface);
  flex-shrink: 0;
}
.sched-th-time { width: 48px; flex-shrink: 0; }
.sched-th-day {
  flex: 1;
  text-align: center;
  padding: 5px 2px;
  border-left: 1px solid var(--border);
  color: var(--text-muted);
}
.sched-th-today { color: var(--todo); }
.sched-th-dow {
  display: block;
  font-size: 10px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.3px;
}
.sched-th-date { font-size: 14px; font-weight: 400; }
.sched-today-badge {
  display: inline-flex; align-items: center; justify-content: center;
  width: 24px; height: 24px; border-radius: 50%;
  background: var(--todo); color: var(--bg);
  font-size: 13px; font-weight: 700;
}

/* Scrollable grid body */
.sched-grid-scroll {
  flex: 1;
  overflow-y: auto;
  overflow-x: hidden;
}
.sched-grid-scroll::-webkit-scrollbar { width: 6px; }
.sched-grid-scroll::-webkit-scrollbar-thumb { background: var(--border); border-radius: 3px; }

.sched-grid-inner { display: flex; }

/* Time label column */
.sched-time-col { width: 48px; flex-shrink: 0; position: relative; }
.sched-time-lbl {
  position: absolute;
  right: 8px;
  font-size: 9px;
  color: var(--text-light);
  transform: translateY(-50%);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  pointer-events: none;
}

/* Day columns */
.sched-day-col {
  flex: 1;
  position: relative;
  border-left: 1px solid var(--border);
  background-image: linear-gradient(to bottom, rgba(73,77,100,0.22) 1px, transparent 1px);
  background-size: 100% 64px; /* matches SCHED_PX */
  min-width: 0;
}
.sched-today-bg { background-color: rgba(138,173,244,0.04); }

/* Slot blocks */
.sched-slot {
  position: absolute;
  left: 2px;
  right: 2px;
  border-radius: 3px;
  padding: 2px 4px;
  overflow: hidden;
  cursor: pointer;
  border-left-width: 2px;
  border-left-style: solid;
  transition: opacity 0.1s;
  z-index: 1;
}
.sched-slot:hover { opacity: 0.8; }
.sched-slot-title {
  font-size: 10px;
  font-weight: 500;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.sched-slot-time { font-size: 9px; opacity: 0.75; }

.sched-slot-work    { background: rgba(138,173,244,0.14); border-left-color: #8aadf4; color: #8aadf4; }
.sched-slot-break   { background: var(--surface2);        border-left-color: var(--border); color: var(--text-light); }
.sched-slot-meal    { background: rgba(166,218,149,0.14); border-left-color: #a6da95; color: #a6da95; }
.sched-slot-workout { background: rgba(245,169,127,0.14); border-left-color: #f5a97f; color: #f5a97f; }
.sched-slot-meeting { background: rgba(198,160,246,0.14); border-left-color: #c6a0f6; color: #c6a0f6; }

/* Now line */
.sched-now-line {
  position: absolute;
  left: 0; right: 0;
  height: 2px;
  background: var(--todo);
  z-index: 2;
  pointer-events: none;
}
.sched-now-line::before {
  content: '';
  position: absolute;
  width: 8px; height: 8px;
  background: var(--todo);
  border-radius: 50%;
  left: -4px; top: -3px;
}

/* Slot popup */
.sched-popup {
  position: fixed;
  background: var(--surface2);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 10px 12px;
  z-index: 1000;
  min-width: 160px;
  max-width: 240px;
  box-shadow: 0 4px 16px rgba(0,0,0,0.5);
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.sched-popup-title { font-size: 12px; font-weight: 600; color: var(--text); }
.sched-popup-meta  { font-size: 10px; color: var(--text-light); font-variant-numeric: tabular-nums; }
.sched-popup-notes { font-size: 11px; color: var(--text-muted); }
.sched-popup .nova-link { margin-top: 4px; font-size: 11px; }

/* ── CRUD modal ──────────────────────────────────────────── */
.crud-modal {
  width: 440px;
  max-width: 95vw;
  max-height: 88vh;
  display: flex;
  flex-direction: column;
  gap: 0;
}
.crud-modal-title {
  font-size: 15px;
  font-weight: 700;
  color: var(--proj);
  padding-bottom: 12px;
  border-bottom: 1px solid var(--border);
  margin-bottom: 0;
}
.crud-modal-error {
  background: var(--blocked-bg);
  border: 1px solid var(--blocked);
  color: var(--blocked);
  font-size: 12px;
  padding: 7px 10px;
  border-radius: var(--radius-sm);
  margin-top: 8px;
}
.crud-modal-error[hidden] { display: none !important; }
.crud-modal-form { flex: 1; overflow-y: auto; }
.crud-modal-body {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 12px 0 4px;
}
.crud-modal-actions {
  display: flex;
  gap: 8px;
  justify-content: flex-end;
  padding-top: 12px;
  border-top: 1px solid var(--border);
  margin-top: 8px;
}

.nova-form-field { display: flex; flex-direction: column; gap: 5px; }
.nova-form-field label {
  font-size: 11px;
  font-weight: 600;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.4px;
}
.nova-form-field input,
.nova-form-field select {
  background: var(--surface2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  color: var(--text);
  padding: 7px 10px;
  font-size: 13px;
  outline: none;
  font-family: inherit;
}
.nova-form-field input:focus,
.nova-form-field select:focus { border-color: var(--proj); }
.nova-input-mono { font-family: monospace; font-size: 11px; color: var(--text-muted); opacity: 0.8; cursor: default; }

/* ── Inline new-task form (inside project detail) ──────────── */
.proj-inline-task-form {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-top: 8px;
  flex-wrap: wrap;
}
.proj-inline-input {
  flex: 1;
  min-width: 140px;
  background: var(--surface2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  color: var(--text);
  padding: 5px 8px;
  font-size: 13px;
  font-family: inherit;
  outline: none;
}
.proj-inline-input:focus { border-color: var(--proj); }
.proj-inline-select {
  background: var(--surface2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  color: var(--text);
  padding: 5px 8px;
  font-size: 13px;
  font-family: inherit;
  outline: none;
}
.nova-btn-ghost {
  background: transparent;
  border: 1px solid var(--border);
  color: var(--text-muted);
}
.nova-btn-ghost:hover { background: var(--surface); }

/* ── Clickable rows ────────────────────────────────────────── */
.nova-row-click { cursor: pointer; }

/* ── Show archived toggle ──────────────────────────────────── */
.nova-show-archived {
  display: flex;
  align-items: center;
  gap: 5px;
  font-size: 12px;
  color: var(--text-muted);
  cursor: pointer;
  user-select: none;
  white-space: nowrap;
}
.nova-show-archived input { accent-color: var(--proj); cursor: pointer; }

/* ── Project detail page ───────────────────────────────────── */
.proj-detail-page {
  display: flex;
  flex-direction: column;
  gap: 0;
}
.proj-detail-header {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 16px;
}
.proj-back-btn {
  font-size: 13px;
  white-space: nowrap;
  flex-shrink: 0;
}
.proj-detail-title {
  flex: 1;
  font-size: 17px;
  font-weight: 700;
  color: var(--text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.proj-fields-section {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 14px 16px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  margin-bottom: 20px;
}
.proj-fields-row {
  display: flex;
  align-items: flex-end;
  gap: 12px;
  flex-wrap: wrap;
}
.proj-field-grow { flex: 1; min-width: 180px; }
.proj-field-actions {
  display: flex;
  align-items: center;
  gap: 8px;
  padding-bottom: 1px;
  flex-shrink: 0;
}
.proj-save-msg   { font-size: 12px; }
.proj-save-ok    { color: var(--done); }
.proj-save-err   { color: var(--blocked); }

/* ── Project task list ─────────────────────────────────────── */
.proj-tasks-section { display: flex; flex-direction: column; }
.proj-tasks-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 8px;
}
.proj-tasks-label {
  font-size: 13px;
  font-weight: 700;
  color: var(--text);
}
.proj-task-list {
  display: flex;
  flex-direction: column;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  overflow: hidden;
}
.proj-task-row {
  border-bottom: 1px solid rgba(73,77,100,0.25);
}
.proj-task-row:last-child { border-bottom: none; }
.proj-task-row.proj-task-done .proj-task-title-text {
  text-decoration: line-through;
  color: var(--text-muted);
}
.proj-task-summary {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 12px;
  cursor: pointer;
  transition: background 0.1s;
}
.proj-task-summary:hover { background: var(--surface2); }
.proj-task-close {
  flex-shrink: 0;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  border: 1.5px solid var(--border);
  background: none;
  color: var(--text-muted);
  font-size: 11px;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: border-color 0.15s, color 0.15s, background 0.15s;
}
.proj-task-close:hover {
  border-color: var(--done);
  color: var(--done);
  background: var(--done-bg);
}
.proj-task-title-text { flex: 1; font-size: 13px; color: var(--text); }
.proj-task-status     { font-size: 11px; flex-shrink: 0; }
.proj-task-due        { font-size: 12px; flex-shrink: 0; min-width: 70px; text-align: right; }
.proj-task-expand {
  flex-shrink: 0;
  background: none;
  border: none;
  color: var(--text-muted);
  font-size: 11px;
  cursor: pointer;
  padding: 2px 4px;
  border-radius: 3px;
  line-height: 1;
}
.proj-task-expand:hover { background: var(--surface2); color: var(--text); }

/* ── Task inline edit form ─────────────────────────────────── */
.proj-task-form {
  padding: 12px 14px 14px;
  background: var(--surface);
  border-top: 1px solid var(--border);
}
.proj-task-form-grid {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: 10px;
  margin-bottom: 10px;
}
.proj-task-field-title { grid-column: 1 / -1; }
.proj-task-field-notes { grid-column: 1 / -1; }
.proj-task-form-actions { display: flex; gap: 8px; }

/* ── Agent Chat view ───────────────────────────────────────────
   Ported from Org/1-Projects/Productivity/agent-chat/dashboard-mockup.html
   (agent-chat#17) — component structure matches that mockup directly
   rather than a redesign. Colors/spacing reuse this file's existing
   Catppuccin Macchiato tokens (--todo/--wait/--proj/--done/--blocked/--teal
   + their *-bg soft variants) instead of a parallel palette, since this
   dashboard is single-theme (no light/dark toggle) — the mockup's own
   light/dark switching doesn't apply here. */
/* Plain emoji icons, not Nerd Font glyphs — those (mockup's original
   choice) are Supplementary Private-Use-Area codepoints that rendered as
   blank boxes in Chrome even with the right font genuinely installed
   system-wide. Emoji need no special font. */
.ac-icon {
  line-height: 1;
  display: inline-block;
}
.mono {
  font-family: ui-monospace, "SF Mono", "Cascadia Code", Menlo, Consolas, monospace;
  font-variant-numeric: tabular-nums;
}
.ac-app { display: flex; flex-direction: column; gap: 22px; }
/* Pulls the Coordinator rail up out of .ac-app's uniform 22px gap
   (agent-chat#53, Task 2) — the alert banner and this rail are two facts
   about the same "is the pipeline healthy" question and read better close
   together than at the same spacing as everything else on the page. */
.ac-health-strip-wrap { margin-top: -20px; }

/* Single line: title + on-demand info, live status right-aligned
   (agent-chat#22). The old always-visible sub-line moved behind the info
   button below — still available, just not permanently taking space for
   a sentence that's true forever and doesn't need re-reading every visit. */
.ac-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding-bottom: 14px;
  border-bottom: 1px solid var(--border); /* mirrors .ac-legend's rule below, bookending the page */
}
.ac-top-left { display: flex; align-items: center; gap: 6px; min-width: 0; }
/* .nova-title's flex:1 is meant for other views' wider single-item
   headers — pin it back to content width here so it can't grow and push
   the info button around in this narrower, two-item header. */
.ac-top-left .nova-title { flex: initial; white-space: nowrap; }

/* The Foundry — horizontal lockup (rebrand of this view, formerly a plain
   "Agent Chat" text title). Icon reuses the ingot mark's three ascending
   bars in a single accent color (--peach) rather than the chart-tribute
   colorway, matching every other single-color use of the mark. */
.ac-brand-lockup { display: flex; align-items: center; gap: 8px; }
.ac-brand-icon { width: 24px; height: 24px; flex-shrink: 0; fill: var(--peach); }
.ac-brand-wordmark { font-size: 18px; letter-spacing: 0.01em; }

.ac-info-wrap { position: relative; display: inline-flex; }
.ac-info-btn {
  background: none;
  border: none;
  padding: 2px;
  margin: 0;
  color: var(--text-light);
  font-size: 13px;
  line-height: 1;
  cursor: pointer;
  border-radius: 4px;
}
.ac-info-btn:hover, .ac-info-btn:focus-visible { color: var(--todo); }
.ac-info-btn:focus-visible { outline: 2px solid var(--todo); outline-offset: 1px; }
.ac-info-panel {
  display: none;
  position: absolute;
  top: 22px;
  left: 0;
  width: 300px;
  background: var(--surface2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 10px 12px;
  font-size: 12px;
  line-height: 1.5;
  color: var(--text-muted);
  box-shadow: 0 6px 18px rgba(0,0,0,0.4);
  z-index: 5;
}
.ac-info-wrap:hover .ac-info-panel,
.ac-info-wrap:focus-within .ac-info-panel {
  display: block;
}

/* Right side of the header (Slice 2): wall clock, machine vitals, then the
   pulse/freshness indicator, in that reading order — identity on the left,
   "is the machine alive and current" on the right. */
.ac-top-right { display: flex; align-items: center; gap: 16px; }

/* min-width reserves room for the widest realistic hour ("12:45:12 PM",
   agent-chat#53 Task 1a) so the hour digit crossing 9→10/12 can't shift
   .ac-vitals over by a character. */
.ac-clock { font-size: 13px; color: var(--text-muted); white-space: nowrap; display: inline-block; min-width: 9ch; text-align: right; }

/* Coordinator vitals (agent-chat-dashboard-revision.md R7, Decision 3) —
   grey monospace, taking color only when a value needs attention
   (.ac-vital-alarm). Deliberately not reusing .health-strip's blue: that
   strip is Coordinator's own behavior rail (a separate slice), this is
   just numbers in the header. */
.ac-vitals { display: flex; align-items: center; gap: 12px; font-size: 12px; color: var(--text-light); white-space: nowrap; }
.ac-vital b { color: var(--text-muted); font-weight: 600; display: inline-block; text-align: left; }
.ac-vital-alarm, .ac-vital-alarm b { color: var(--blocked); }
/* Reserved min-widths (agent-chat#53, Task 1a) — each field's live-updating
   value gets enough room for its own worst case, so a tick-over (e.g. "9s
   ago" -> "10s ago" -> "1m ago") can't shift the fields next to it.
   Coordinator's "Xm ago"/"Xh ago" tops out around "23h ago" (7 chars). */
.ac-vital-coordinator b { min-width: 7ch; }
.ac-vital-queue b       { min-width: 2ch; }
.ac-vital-dlq b         { min-width: 2ch; }
.ac-vital-webhook b     { min-width: 4ch; }
.ac-vital-workers b     { min-width: 5ch; }
/* tokens today (agent-chat#58) — a 6-digit comma-formatted count ("123,456")
   is a realistic worst case for a single day's session total. */
.ac-vital-tokens b      { min-width: 7ch; }

.ac-now { font-size: 11.5px; color: var(--text-light); text-align: right; white-space: nowrap; }
/* #ac-live-text itself was missed by the Task 1a reservation above — its
   "Xs ago"/"Xm ago"/"Xh ago" tick-over was still shifting .ac-now's total
   width, which .ac-top's space-between then read as the whole right-side
   group moving, dragging the clock/vitals along with it. Same 7ch cap as
   the Coordinator vital, inline-block + right-align so the reserved space
   pads on the left, not the right. */
#ac-live-text { display: inline-block; min-width: 7ch; text-align: right; }
.ac-live-dot {
  display: inline-block;
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--done);
  margin-right: 6px;
  box-shadow: 0 0 0 3px var(--done-bg);
}

/* ---------- Alert slot ---------- */
/* Fixed height and position in every state (agent-chat-dashboard-
   revision.md R1, Decision 2) — a calm and a stuck dashboard occupy the
   same footprint, so nothing on the page shifts when trouble appears.
   78px holds both the calm one-liner and the stuck state's title + cause
   + action without the calm state having to stretch to match it. */
.ac-alert-slot {
  height: 78px;
  border-radius: var(--radius);
  padding: 12px 16px;
  display: flex;
  align-items: center;
  gap: 14px;
  box-sizing: border-box;
}
.ac-alert-calm {
  background: var(--done-bg);
  border: 1px solid rgba(166,218,149,0.3);
  color: var(--done);
  font-size: 13px;
  font-weight: 500;
}
/* Second line under its own headline, not sharing the glyph's line
   (agent-chat#53, Task 1) — mirrors .ac-alert-cause sitting under
   .ac-alert-headline in the stuck state below. */
.ac-alert-calm-text { display: block; }
.ac-alert-stuck {
  background: var(--blocked-bg);
  border: 1px solid var(--blocked);
  color: var(--blocked);
}
.ac-alert-count {
  font-size: 28px;
  font-weight: 700;
  line-height: 1;
  min-width: 1.2em;
  text-align: center;
}
.ac-alert-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.ac-alert-headline { display: flex; align-items: baseline; gap: 8px; min-width: 0; }
.ac-alert-label {
  text-transform: uppercase;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.06em;
  flex-shrink: 0;
}
.ac-alert-story {
  color: var(--text);
  font-weight: 600;
  font-size: 14px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.ac-alert-cause {
  color: var(--text-muted);
  font-size: 12.5px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0; /* let the ellipsis truncation above actually engage once
                   an ancestor (see .ac-app's own min-width:0 fix) gives it
                   a bounded width to shrink into */
}
.ac-alert-action {
  flex-shrink: 0;
  background: var(--blocked);
  color: var(--bg);
  border: none;
  border-radius: var(--radius-sm);
  padding: 8px 14px;
  font-size: 12.5px;
  font-weight: 700;
  cursor: pointer;
}
.ac-alert-action:hover { filter: brightness(1.08); }

/* ---------- DLQ alert ---------- */
.ac-dlq-alert {
  display: flex;
  align-items: center;
  gap: 10px;
  background: var(--blocked-bg);
  border: 1px solid rgba(237,135,150,0.35);
  color: var(--blocked);
  border-radius: var(--radius);
  padding: 10px 14px;
  font-size: 13px;
  font-weight: 500;
}
.ac-dlq-alert .mono { color: var(--text); font-weight: 400; opacity: 0.85; }
.ac-dlq-alert.ac-stack-trigger { cursor: pointer; }
.ac-dlq-alert.ac-stack-trigger:hover { border-color: var(--blocked); }
.ac-dlq-count-badge {
  margin-left: auto;
  background: var(--blocked);
  color: var(--bg);
  font-size: 11px;
  font-weight: 700;
  border-radius: 999px;
  padding: 1px 8px;
}

/* ---------- Weekly token chart (agent-chat#59, dashboard token-usage
   rollup Slice 2) ---------- */
/* Fixed height, always visible, same "no scroll growth" rule .ac-alert-slot
   follows (agent-chat-dashboard-revision.md Decision 2) — this panel's
   footprint never changes between an empty week and a busy one. 96px holds
   the title, the tallest possible bar, and the day-label row without
   stretching. First hand-rolled chart in this codebase (no charting library
   exists here) — this file's structure (track/bar/label, one hue, a
   distinct "today" treatment) is the pattern future charts should copy. */
.ac-weekly-chart {
  height: 96px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 10px 14px 8px;
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.ac-weekly-chart-title {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-light);
}
.ac-weekly-chart-empty {
  flex: 1;
  display: flex;
  align-items: center;
  color: var(--text-light);
  font-size: 12.5px;
}
.ac-weekly-bars {
  flex: 1;
  display: flex;
  justify-content: center;
  align-items: flex-end;
  gap: 8px;
  min-height: 0;
}
/* max-width caps each column at the bar track's own width (28px) plus a
   little breathing room — without it, flex:1 stretches every column to
   fill whatever's left of the panel, so on a wide panel the 7 bars end up
   spread thin across the full width instead of reading as a compact
   cluster (agent-chat#72). flex:0 1 auto (not flex:1) is what lets the
   columns shrink to content and leave the row's justify-content: center
   above room to actually center them, instead of stretching back out to
   fill the row. */
.ac-weekly-bar-col {
  flex: 0 1 auto;
  width: 36px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  min-width: 0;
  height: 100%;
}
/* The track is the full-height flex item; the bar is an absolutely-scaled
   inner element (height:N% of the track) so a 2%-floor sliver on a
   zero-token day still renders at a visible fixed pixel size rather than
   rounding to nothing. */
.ac-weekly-bar-track {
  flex: 1;
  width: 100%;
  max-width: 28px;
  display: flex;
  align-items: flex-end;
  min-height: 0;
}
.ac-weekly-bar {
  width: 100%;
  min-height: 3px;
  background: var(--todo);
  border-radius: 3px 3px 0 0;
}
/* Today's bar (Done When: "today's partial-day total visually
   distinguishable... so it doesn't read as a misleadingly short day") —
   lighter fill AND the "so far" text label below (dataviz: identity/state
   must never be color-alone), so the distinction survives grayscale/
   color-blind viewing, not just an opacity difference. */
.ac-weekly-bar-today {
  background: color-mix(in srgb, var(--todo) 45%, transparent);
  border: 1px dashed var(--todo);
  border-bottom: none;
}
.ac-weekly-bar-label {
  font-size: 10px;
  color: var(--text-light);
  white-space: nowrap;
}
.ac-weekly-bar-sofar {
  color: var(--todo);
  font-weight: 700;
}

/* ---------- Stories-closed companion chart (agent-chat#72) ---------- */
/* Same two-panel width for both charts — no per-chart legend (Done When:
   "placed once, not per-chart, since the two charts sit next to each
   other"), so the legend row above the pair is the only place the color
   meaning is spelled out. */
.ac-weekly-charts-row {
  display: flex;
  gap: 12px;
}
.ac-weekly-charts-row > div {
  flex: 1;
  min-width: 0;
}
.ac-weekly-legend {
  display: flex;
  gap: 16px;
  font-size: 11px;
  color: var(--text-muted);
  margin-bottom: 4px;
}
.ac-weekly-legend-item {
  display: inline-flex;
  align-items: center;
  gap: 5px;
}
.ac-weekly-legend-swatch {
  width: 9px;
  height: 9px;
  border-radius: 2px;
  display: inline-block;
}
.ac-weekly-legend-swatch-tokens { background: var(--todo); }
.ac-weekly-legend-swatch-stories { background: var(--done); }
.ac-weekly-legend-swatch-bounces { background: var(--blocked); }

/* Reuses .ac-weekly-bar/.ac-weekly-bar-today's shape entirely — only the
   fill color changes, scoped under .ac-stories-chart so the token chart's
   bars (var(--todo)) and this chart's bars (var(--done)) read as distinct
   colors with real contrast rather than adjacent shades of the same hue. */
.ac-stories-chart .ac-weekly-bar {
  background: var(--done);
}

/* ---------- Review-bounces companion chart (agent-chat#73) ---------- */
/* Third chart in the same row, same legend (no per-chart legend — see the
   comment above .ac-weekly-charts-row). --blocked is the palette's existing
   red token, reused rather than inventing a new hex value — chosen by
   palette-distinctness reasoning against --todo (blue) and --done (green);
   not confirmed live at the time this was written (no browser tool in this
   environment), see the review's blockedReason for the outstanding check. */
.ac-review-bounces-chart .ac-weekly-bar {
  background: var(--blocked);
}

/* ---------- Subscriber strip ---------- */
.ac-section-label {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-light);
  margin: 0 0 10px 2px;
}
/* Shared with .ac-board's column minmax() floor below (agent-chat#23,
   board-redesign.md Requirement 7) so Subscribers and the Pipeline board
   read as one sizing system instead of two coincidentally-similar ones. */
:root { --ac-tile-w: 216px; }

/* Idle-pool rail (dashboard-phase-5-slice-3, agent-chat-dashboard-
   revision.md Decision 1/R4) — replaces the old Subscribers strip's
   Active/Dormant grouping. A worker sits here only while it holds no
   story; once assigned, it renders on that story's card instead. */
.ac-idle-pool-label {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--text-light);
  margin: 0 0 8px;
}
.ac-idle-pill {
  display: flex;
  align-items: center;
  gap: 6px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 5px 10px;
  font-size: 12px;
  white-space: nowrap;
}
.ac-idle-pill.stale { border-color: var(--blocked); color: var(--text-muted); }
/* Name truncates on its own (agent-chat#53, Task 1c) so it — not the fixed-
   width pool region — absorbs a long subscriber name; min-width:0 lets it
   shrink below content size inside the flex row. */
.ac-idle-name { overflow: hidden; text-overflow: ellipsis; min-width: 0; flex: 1; }
/* Reserved min-width (agent-chat#53, Task 1c) so the idle duration growing
   past a single digit ("9m" -> "10m") can't flex the pool's width. */
.ac-idle-age { margin-left: auto; color: var(--text-light); font-size: 11px; flex-shrink: 0; min-width: 4ch; text-align: right; }
/* Token-budget utilization/overage badge (agent-chat#57) — absent by
   default (acSubscriberOverageBadge returns null when a subscriber has
   never hit a rate limit), so most pills are unaffected. flex-shrink:0 and
   a fixed token width, same rationale as .ac-idle-age above: this must not
   be what absorbs the pool's fixed-width pressure (agent-chat#53), or it
   reintroduces the width-flex bug that fixed. */
.ac-util-badge {
  flex-shrink: 0;
  font-size: 10px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  padding: 1px 6px;
  border-radius: 999px;
  white-space: nowrap;
  background: var(--border);
  color: var(--text-light);
}
.ac-util-overage { background: var(--peach-bg); color: var(--peach); }
.ac-util-exhausted { background: var(--blocked-bg); color: var(--blocked); }

/* Coordinator's own health strip (agent-chat#24) — blue, not green: an
   agent being alive and the pipeline actively routing are different
   facts, so they get different hues. Solid border + left accent bar +
   tinted gradient, not just a faint tint, so it reads as a distinct
   object rather than blending into the Dormant row above it. */
.health-strip {
  background: linear-gradient(180deg, #16233c, #1a2b48);
  /* Toned down from solid var(--todo) (agent-chat#53, Task 1b) — a
     desaturated blend of --todo and the page's neutral --border, still
     bluer/brighter than a plain neutral border so the strip reads as its
     own distinct object, but no longer as saturated as --todo itself
     (reserved for text that needs to grab attention, not a resting rail). */
  border: 1px solid #5f76a0;
  border-left: 4px solid #5f76a0;
  border-radius: var(--radius-sm);
  padding: 10px 14px;
  display: flex;
  align-items: center;
  gap: 14px;
  font-size: 12.5px;
  flex-wrap: wrap;
  box-shadow: 0 0 0 1px rgba(138,173,244,0.08), 0 2px 10px rgba(30,58,110,0.3);
}
.health-strip .who {
  font-weight: 700;
  color: var(--todo);
  display: flex;
  align-items: center;
  gap: 6px;
  white-space: nowrap;
}
.health-strip .routing { color: var(--text-muted); flex: 1; min-width: 140px; }
.health-strip .routing .story { color: var(--text); }
.health-strip .routing .arrow { color: var(--todo); margin: 0 4px; }
.health-strip .stat { display: flex; align-items: center; gap: 5px; color: var(--text-muted); white-space: nowrap; }
.health-strip .stat .n { font-weight: 700; color: var(--text); font-variant-numeric: tabular-nums; }
/* Only the DLQ count changes color, and only when nonzero — the one state
   on this strip that actually needs attention (board-redesign.md
   Requirement 10), consistent with blocked/DLQ red used elsewhere. */
.health-strip .stat.dlq-alarm .n { color: var(--blocked); }
.health-strip .sep { color: #4d6da3; }
.ac-name { font-weight: 600; font-size: 13.5px; }
.ac-name .ac-icon { margin-right: 6px; color: var(--text-light); font-size: 13px; }
.ac-pill {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  padding: 3px 8px;
  border-radius: 999px;
  white-space: nowrap;
}
.ac-pill .ac-icon { font-size: 11px; }
.ac-pill.active { background: var(--done-bg); color: var(--done); }
.ac-pill.idle   { background: var(--wait-bg); color: var(--wait); }
.ac-pill.stale  { background: var(--blocked-bg); color: var(--blocked); }

/* ---------- Conveyor / Pipeline board (dashboard-phase-5-slice-3) -------
   Decision 1: stages become lanes, read left to right, with idle workers
   in a pool rail to the left. Decision 4: every card is one fixed height
   in every state — a card in trouble changes color and swaps its status
   text, never its size. */
.ac-conveyor-wrap { margin-top: 14px; }
.ac-conveyor { display: flex; align-items: flex-start; gap: 14px; }
.ac-idle-pool {
  flex: 0 0 180px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  border: 1px dashed var(--border);
  border-radius: var(--radius-sm);
  padding: 10px;
  align-self: stretch;
}
.ac-board-wrap { flex: 1; overflow-x: auto; padding-bottom: 4px; margin: 0 -2px; min-width: 0; }
/* Reverted from a Task 3 (agent-chat#53) attempt at
   grid-template-columns: repeat(5, minmax(var(--ac-tile-w), 1fr)) — that
   was meant to fill leftover width on a wide screen instead of leaving it
   dead to the right of the last lane, but 1fr tracks in a grid whose own
   container has no definite width (true here: .ac-board-wrap is a flex:1
   item) size against the *widest available space anywhere up the flex
   chain*, not just this row. When an unrelated ancestor briefly had no
   width bound of its own (a missing min-width:0 on .ac-app, now fixed
   separately), this blew every lane out to ~2284px. Back to the known-safe
   fixed-width pattern; the right-side-gap-on-wide-screens cosmetic issue
   is still open (agent-chat#53, Task 3) but isn't worth this failure mode
   to close. */
.ac-board { display: grid; grid-auto-flow: column; grid-auto-columns: var(--ac-tile-w); gap: 12px; min-width: min-content; padding: 2px; }

/* Coordinator behavior rail (dashboard-phase-5-slice-4, agent-chat-
   dashboard-revision.md Decision 3) — "what the Coordinator did for this
   lane," one cell per board column, sitting directly above it. Same grid
   geometry as .ac-board (explicit 5-column template, same column
   width/gap — see the Task 3 comment above) so a cell always lines up with
   the lane it describes without any per-story coordination between the two.
   Deliberately grey/blue mono only — never a card's green/amber/red state
   color, per Decision 3 ("the Coordinator's color appears nowhere else on
   the page") and this slice's Done When. */
.ac-rail-row {
  /* Reverted alongside .ac-board above — same 1fr-in-an-unbounded-flex-item
     failure mode, same fix. */
  display: grid; grid-auto-flow: column; grid-auto-columns: var(--ac-tile-w);
  gap: 12px; min-width: min-content; padding: 0 2px; margin-bottom: 6px;
}
.ac-rail-cell {
  display: flex; align-items: baseline; gap: 6px;
  font-size: 11px; padding: 3px 2px;
  border-bottom: 1px solid var(--border);
}
.ac-rail-label { color: var(--text-light); font-weight: 700; white-space: nowrap; }
/* --todo is the same blue the health strip (agent-chat#24) already reserves
   for the Coordinator's own facts, not a coincidence — Decision 3 asks for
   "grey/blue mono" specifically. It is also the Build lane's accent, but a
   lane's accent lives on that lane's border/count pill, never on this rail
   row, so the two never appear as the same-colored text in the same place. */
.ac-rail-text { color: var(--todo); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* Each lane is its own bordered, color-coded column (Done When: "each its
   own bordered lane, color-coded by state") — the accent color rides in
   via the inline --ac-lane-color custom property set by acLaneColumnHtml/
   acDoneColumnHtml, one border-top per lane rather than a class per color. */
.ac-lane {
  display: flex;
  flex-direction: column;
  gap: 10px;
  border: 1px solid var(--border);
  border-top: 3px solid var(--ac-lane-color, var(--border));
  border-radius: var(--radius-sm);
  background: var(--surface2);
  padding: 10px;
  min-height: 160px;
}
.ac-lane .ac-stage-head { display: flex; align-items: center; justify-content: space-between; padding: 0 2px; }
.ac-lane .ac-name { font-size: 12.5px; font-weight: 700; color: var(--text-muted); }
.ac-lane .ac-count {
  font-size: 11px; font-weight: 700; color: var(--text-light);
  background: var(--surface); border-radius: 999px; padding: 1px 7px;
}
.ac-stage-note { font-size: 11px; color: var(--text-light); font-style: italic; padding: 0 2px 2px; }

/* Fixed-height card (Decision 4): title / task line / worker+status row /
   issue ref, every row present in every state so the card never resizes.
   Long titles clamp to two lines instead of pushing the rows below them
   out of the fixed box. Height raised from 122px (agent-chat#53, Task 4),
   then again to 154px (post-Task-4 follow-up) when the 138px version
   turned out to only have looked fixed because of the unrelated grid
   width bug (agent-chat#53, Task 3) — once that was reverted, the
   name/status row was still one line trying to hold both the assignee
   name and the status/tag text side by side, which overlapped on the
   card's real fixed width. Rejected fix: shrinking the name with an
   ellipsis instead — the icon (AC_SUB_ICON) disambiguates impl/review/
   personal today, but not two machines running the same role (e.g. a
   future thinkpad-impl2), so status now stacks above name as its own
   line instead of competing for the same one; overflow:hidden is a hard
   backstop so any remaining overrun clips instead of bleeding into the
   next card in the lane. */
.ac-story-card {
  height: 154px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-left: 3px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 10px 11px;
  box-shadow: var(--shadow);
  cursor: pointer;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: 4px;
  overflow: hidden;
  transition: transform 0.12s ease, border-color 0.12s ease;
}
.ac-story-title-row, .ac-story-task, .ac-story-who, .ac-story-meta { flex-shrink: 0; }
.ac-story-card:hover { transform: translateY(-1px); border-color: var(--todo); }
.ac-story-card.ac-blocked { border-left-color: var(--blocked); background: var(--blocked-bg); }
.ac-story-card.ac-stuck   { border-left-color: var(--blocked); background: var(--blocked-bg); }
.ac-story-card.ac-done    { border-left-color: var(--done); opacity: 0.75; }
.ac-story-title-row { display: flex; align-items: flex-start; gap: 6px; }
/* Shape carries the domain, color is secondary (agent-chat#25,
   board-redesign.md Requirement 11) — two of these colors don't have
   enough contrast for color-vision deficiency alone. */
.domain-dot { width: 8px; height: 8px; margin-top: 4px; flex-shrink: 0; }
.domain-dot.square   { border-radius: 2px; }
.domain-dot.diamond  { border-radius: 0; transform: rotate(45deg); }
.domain-dot.circle   { border-radius: 50%; }
.ac-story-title {
  font-size: 13px; font-weight: 560; line-height: 1.35;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden;
}
.ac-story-task {
  font-size: 10.5px; color: var(--text-light); font-style: italic;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* Task position on a stuck card (agent-chat#42) — same red as the
   stuck/blocked card border and status tag, so the degraded task line
   reads as part of the same trouble signal, not a separate one. */
.ac-story-task.ac-stalled { color: var(--blocked); font-style: normal; }
/* Status stacks above name (not side-by-side) so neither ever has to
   shrink or truncate to make room for the other — see the height-history
   comment on .ac-story-card above for why side-by-side (even with an
   ellipsis on the name) wasn't the right call. */
.ac-story-who { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.ac-story-who-left { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ac-assignee { display: inline-flex; align-items: center; gap: 4px; font-size: 11px; color: var(--text-muted); }
.ac-assignee.ac-unassigned { color: var(--text-light); font-style: italic; }
.ac-assignee .ac-icon { font-size: 10px; }
/* Peach, not blocked-red — a rework isn't necessarily a failure state,
   just friction worth flagging; absent by default so a clean single-pass
   story stays exactly as quiet as it does today. */
.ac-rework-badge {
  display: inline-flex; align-items: center; gap: 3px;
  font-size: 10.5px; font-weight: 700; color: var(--peach); background: var(--peach-bg);
  border-radius: 20px; padding: 1px 7px; white-space: nowrap;
}
.ac-story-activity { font-size: 10.5px; color: var(--text-light); white-space: nowrap; }
.ac-story-meta { display: flex; align-items: center; justify-content: space-between; font-size: 11px; color: var(--text-light); }
/* Wrapper (agent-chat#57) so .ac-story-meta's space-between layout still
   sees exactly two flex children (id left, this group right) regardless of
   how many badges — rework, overage-approved — are present. */
.ac-story-meta-right { display: flex; align-items: center; gap: 5px; }
/* Overage-approved marker — a story dispatched via an explicit
   overage-spend decision must read as visibly distinct from a normal
   dispatch (agent-chat#57 Done When #2), not silently identical. Same
   peach treatment as .ac-rework-badge — flagging a notable decision, not a
   failure state. */
.ac-overage-badge {
  display: inline-flex; align-items: center;
  font-size: 10.5px; font-weight: 700; color: var(--peach); background: var(--peach-bg);
  text-transform: uppercase; letter-spacing: 0.02em;
  border-radius: 20px; padding: 1px 7px; white-space: nowrap;
}
.ac-story-id { font-size: 10.5px; color: var(--text-light); }
.ac-blocked-tag {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: 10.5px; font-weight: 700; color: var(--blocked);
  text-transform: uppercase; letter-spacing: 0.03em;
  white-space: nowrap;
}

/* ---------- Detail drawer ---------- */
.ac-drawer-backdrop {
  position: fixed; inset: 0; background: rgba(0,0,0,0.45);
  display: none; align-items: flex-end; justify-content: center; z-index: 60;
}
.ac-drawer-backdrop.open { display: flex; }
.ac-drawer {
  background: var(--surface); border: 1px solid var(--border); border-bottom: none;
  border-radius: 16px 16px 0 0; box-shadow: 0 -8px 32px rgba(0,0,0,0.4);
  overflow-y: auto; max-height: 82vh; width: 100%; max-width: 820px;
  transform: translateY(100%); transition: transform 0.22s ease;
}
.ac-drawer-backdrop.open .ac-drawer { transform: translateY(0); }
.ac-drag-handle { display: flex; justify-content: center; padding: 8px 0 2px; }
.ac-drag-handle span { width: 36px; height: 4px; border-radius: 2px; background: var(--border); }
.ac-drawer-head {
  display: flex; align-items: flex-start; justify-content: space-between; gap: 12px;
  padding: 8px 18px 16px; border-bottom: 1px solid var(--border); background: var(--surface2);
}
.ac-drawer-head h2 { margin: 0 0 4px; font-size: 16px; font-weight: 620; }
.ac-meta-line { font-size: 12px; color: var(--text-muted); display: flex; gap: 10px; flex-wrap: wrap; }
.ac-drawer-body { padding: 16px 18px 18px; display: grid; grid-template-columns: 1.3fr 1fr; gap: 20px; }
@media (max-width: 720px) { .ac-drawer-body { grid-template-columns: 1fr; } }
.ac-drawer-body h3 {
  font-size: 11.5px; font-weight: 700; letter-spacing: 0.05em; text-transform: uppercase;
  color: var(--text-light); margin: 0 0 10px;
}
.ac-blocked-banner {
  display: flex; gap: 10px; align-items: flex-start;
  background: var(--blocked-bg); border: 1px solid rgba(237,135,150,0.3);
  border-radius: var(--radius-sm); padding: 10px 12px; margin-bottom: 16px; font-size: 13px;
}
.ac-blocked-banner strong { color: var(--blocked); }
.ac-empty-note { font-size: 12.5px; color: var(--text-light); margin-bottom: 16px; }
.ac-timeline { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; }
.ac-timeline li { position: relative; padding: 0 0 16px 20px; border-left: 2px solid var(--border); font-size: 13px; }
.ac-timeline li:last-child { border-color: transparent; padding-bottom: 0; }
.ac-timeline li::before {
  content: ""; position: absolute; left: -5px; top: 2px; width: 8px; height: 8px;
  border-radius: 50%; background: var(--surface); border: 2px solid var(--text-light);
}
.ac-timeline li.ac-outcome-completed::before { border-color: var(--done); }
.ac-timeline li.ac-outcome-blocked::before { border-color: var(--blocked); }
.ac-t-stage { font-weight: 600; }
.ac-t-meta { color: var(--text-light); font-size: 11.5px; margin-top: 1px; }
.ac-refs-list { list-style: none; margin: 0 0 16px; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.ac-refs-list a, .ac-refs-list span {
  display: block; font-size: 12.5px; text-decoration: none;
  background: var(--surface2); border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 6px 9px;
}
.ac-refs-list a:hover { border-color: var(--todo); }
.ac-resume-box { border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 12px; background: var(--surface2); }
.ac-via { font-size: 11.5px; color: var(--text-light); margin-bottom: 8px; line-height: 1.5; }
.ac-via code { color: var(--todo); }
.ac-mock-input { display: flex; gap: 8px; align-items: center; }
.ac-mock-input .ac-field {
  flex: 1; font-size: 12.5px; color: var(--text);
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 8px 10px;
}
.ac-mock-input button {
  font-size: 12px; font-weight: 600; background: var(--todo); color: var(--bg);
  border: none; border-radius: var(--radius-sm); padding: 8px 12px; cursor: pointer;
}

/* ---------- Modal (blocked-stack / DLQ-stack grid) ---------- */
.ac-modal-backdrop {
  position: fixed; inset: 0; background: rgba(0,0,0,0.45);
  display: none; align-items: center; justify-content: center; padding: 24px; z-index: 50;
}
.ac-modal-backdrop.open { display: flex; }
.ac-modal {
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius);
  box-shadow: var(--shadow); max-width: 640px; width: 100%; max-height: 80vh; overflow-y: auto; padding: 18px 20px 20px;
}
.ac-modal-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 14px; }
.ac-modal-head h3 { margin: 0; font-size: 14px; font-weight: 700; color: var(--text); }
.ac-modal-close {
  background: var(--surface2); border: 1px solid var(--border); color: var(--text-muted);
  border-radius: var(--radius-sm); width: 26px; height: 26px; cursor: pointer; font-size: 14px; line-height: 1;
}
.ac-modal-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 10px; }
/* Generalized (agent-chat#23): openModal's content is no longer only a
   card grid — Dormant (and Done Today's overflow, agent-chat#26) pass
   plain block content like a table, which a forced grid would fight. */
.ac-modal-grid.ac-modal-plain { display: block; }

.ac-table { width: 100%; border-collapse: collapse; font-size: 12.5px; }
.ac-table th {
  text-align: left; font-size: 10.5px; letter-spacing: 0.04em; text-transform: uppercase;
  color: var(--text-light); font-weight: 700; padding: 0 8px 8px 0; border-bottom: 1px solid var(--border);
}
.ac-table td { padding: 8px 8px 8px 0; border-bottom: 1px solid var(--border); vertical-align: top; }
.ac-table tr:last-child td { border-bottom: none; }
.ac-table .ac-icon { margin-right: 6px; }
.ac-table-story { display: flex; align-items: flex-start; gap: 6px; max-width: 240px; }
.ac-table-story .domain-dot { margin-top: 4px; }

/* Done Today's overflow trigger (agent-chat#26) — same dashed
   glance-for-a-count affordance as Dormant's summary row, driving the
   same generalized openModal rather than a second disclosure pattern. */
.ac-more-today {
  background: none;
  border: 1px dashed var(--border);
  border-radius: var(--radius-sm);
  padding: 8px 11px;
  color: var(--text-light);
  font-size: 11.5px;
  text-align: left;
  cursor: pointer;
  font-family: inherit;
  width: 100%;
}
.ac-more-today:hover { border-color: var(--todo); color: var(--text-muted); }
.ac-more-today:focus-visible { outline: 2px solid var(--todo); outline-offset: 2px; }

.ac-legend {
  display: flex; flex-wrap: wrap; gap: 16px; font-size: 11.5px; color: var(--text-light);
  padding-top: 4px; border-top: 1px solid var(--border);
}
.ac-legend-item { display: flex; align-items: center; gap: 6px; }
.ac-swatch { width: 8px; height: 8px; border-radius: 2px; }

/* ---------- Stuck-detail strip (Dashboard Phase 5 Slice 6, agent-chat#43,
   agent-chat-dashboard-revision.md R6/Decision 4) ----------
   #ac-stuck-strip-wrap holds either this block or nothing — the element
   itself is absent from the DOM when nothing is stuck (see acStuckStripHtml
   callers in nova.js), not merely hidden, so an empty wrapper div adds no
   height and the lanes above it never move. */
.ac-stuck-strip {
  margin-top: 14px;
  border: 1px solid var(--blocked);
  background: var(--blocked-bg);
  border-radius: var(--radius);
  padding: 14px 16px 16px;
}
.ac-stuck-strip-head {
  display: flex; align-items: center; gap: 6px;
  font-size: 13px; font-weight: 700; color: var(--blocked);
  margin-bottom: 12px;
}
.ac-stuck-strip-title { color: var(--text); font-weight: 600; }
.ac-stuck-strip-grid {
  display: grid; grid-template-columns: repeat(4, 1fr); gap: 16px;
  align-items: start;
}
@media (max-width: 960px) { .ac-stuck-strip-grid { grid-template-columns: 1fr 1fr; } }
.ac-stuck-col {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius-sm); padding: 10px 12px; min-width: 0;
}
.ac-stuck-col h4 {
  font-size: 10.5px; font-weight: 700; letter-spacing: 0.05em; text-transform: uppercase;
  color: var(--text-light); margin: 0 0 8px;
}
.ac-stuck-col .ac-empty-note { margin-bottom: 0; }
.ac-event-trace { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.ac-event-trace li { font-size: 12px; display: flex; gap: 8px; align-items: baseline; }
.ac-et-time { color: var(--text-light); flex-shrink: 0; }
.ac-et-desc { color: var(--text-muted); overflow: hidden; text-overflow: ellipsis; }
.ac-diagnosis-text { font-size: 12.5px; color: var(--text-muted); line-height: 1.5; }
.ac-start-here-list, .ac-stuck-col .ac-refs-list { margin-top: 8px; }
.ac-strip-transcript-btn {
  display: block; width: 100%;
  font-size: 12px; font-weight: 600; background: var(--blocked); color: var(--bg);
  border: none; border-radius: var(--radius-sm); padding: 8px 10px; cursor: pointer; margin-bottom: 8px;
}
.ac-strip-transcript-btn:hover { filter: brightness(1.08); }
.ac-start-here-note { font-size: 11px; color: var(--text-light); line-height: 1.5; margin-bottom: 8px; }
.ac-start-here-note code { color: var(--todo); }

/* ---------- Chatter footer (Dashboard Phase 5 Slice 7, agent-chat#44) ---------- */
/* Collapsed, static line only (design doc Decision 9 / R9) — the raised
   drawer, per-agent colors, and filter chips (R10-R13) are the design
   doc's own Phase 3 (agent-chat-dashboard-revision.md's roadmap table),
   not this project's unrelated Phase 6 (per-pool queues + the `build`
   rename, see SEQUENCING.md) — no GitLab issue tracks this yet. Sticky
   to the bottom of the scrolling Agent Chat view rather than viewport-fixed,
   so it stays clear of the calendar/assistant sidebars either side of it
   (those are page furniture, not part of this feed) while still reading as
   a persistent line at the bottom of the page while this view is open. */
.ac-chatter-footer {
  position: sticky;
  bottom: 0;
  /* Pushes the footer to the bottom of .ac-app's now-stretched flex column
     (agent-chat#53, Task 5) when there's leftover vertical space — sticky
     alone only pins it once the content above is already tall enough to
     need scrolling; margin-top:auto covers the short-content case sticky
     can't. */
  margin-top: auto;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  z-index: 4;
}
.ac-chatter-footer-inner {
  display: flex;
  align-items: baseline;
  gap: 12px;
  padding: 10px 14px;
  font-size: 12.5px;
  overflow: hidden;
}
.ac-chatter-time { color: var(--text-light); flex-shrink: 0; }
.ac-chatter-agent { color: var(--todo); font-weight: 600; flex-shrink: 0; }
.ac-chatter-desc {
  color: var(--text-muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  flex: 1;
  min-width: 0;
}
.ac-chatter-rate { color: var(--text-light); flex-shrink: 0; }
.ac-chatter-empty { color: var(--text-light); font-size: 12.5px; padding: 10px 14px; }

/* Raised: the collapsed one-liner (R9, above) becomes the full-height
   drawer R10 always intended (Decision 9, agent-chat#67). Clicking the
   collapsed footer raises it; the drawer's own ✕ collapses it back — see
   nova.js's acRaiseChatter/acCollapseChatter. Not raised, .ac-chatter-footer
   carries none of this — same sticky one-liner as before, untouched. */
.ac-chatter-footer:not(.raised) { cursor: pointer; }
.ac-chatter-footer.raised {
  position: fixed;
  inset: auto 16px 16px 16px;
  top: 64px; /* leaves the page header visible above the raised drawer */
  bottom: 16px;
  display: flex;
  flex-direction: column;
  z-index: 40; /* below the detail drawer/modal (50/60) — those still layer on top if opened while raised */
  border-radius: var(--radius);
  overflow: hidden;
}
/* Resize handle (agent-chat#70) — sits on the drawer's top edge so a drag
   shrinks the fixed-bottom-anchored drawer from the top, uncovering the
   conveyor above rather than growing/shrinking from the bottom where
   there's nothing to reveal. touch-action:none stops the browser's own
   touch-scroll gesture from fighting the pointermove-driven drag on
   touchscreens. */
.ac-chatter-drawer-handle {
  height: 8px;
  flex-shrink: 0;
  cursor: ns-resize;
  touch-action: none;
  position: relative;
}
.ac-chatter-drawer-handle::after {
  content: "";
  position: absolute; top: 2px; left: 50%; transform: translateX(-50%);
  width: 36px; height: 4px; border-radius: 2px;
  background: var(--border);
}
.ac-chatter-drawer-handle:hover::after,
.ac-chatter-footer.ac-chatter-dragging .ac-chatter-drawer-handle::after {
  background: var(--todo);
}
.ac-chatter-drawer-head {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 10px 14px; border-bottom: 1px solid var(--border); background: var(--surface2); flex-shrink: 0;
}
.ac-chatter-drawer-title { font-size: 13px; font-weight: 700; color: var(--text); }

/* Filter chips + problems-only/follow toggles (Slice 4, agent-chat#68, R13).
   Same row-of-pill pattern as .ac-legend elsewhere on the page, not a new
   control style. */
.ac-chatter-drawer-filters {
  display: flex; align-items: center; flex-wrap: wrap; gap: 6px;
  padding: 8px 14px; border-bottom: 1px solid var(--border); background: var(--surface); flex-shrink: 0;
}
.ac-chatter-chip, .ac-chatter-toggle {
  font-size: 11px; font-weight: 600; padding: 3px 10px; border-radius: 999px;
  border: 1px solid var(--border); background: var(--surface2); color: var(--text-light);
  cursor: pointer;
}
.ac-chatter-chip[aria-pressed="true"], .ac-chatter-toggle[aria-pressed="true"] {
  background: var(--todo); border-color: var(--todo); color: var(--surface);
}
/* Problem marker (Slice 5, agent-chat#69): a small dot, not the row's full
   red background (.ac-chatter-row-problem stays a row-only treatment) and
   visually distinct from the aria-pressed selected-chip fill above, so the
   two signals (selected vs. has-a-problem) never get confused. */
.ac-chatter-chip { position: relative; }
.ac-chatter-chip-problem::after {
  content: ""; position: absolute; top: -2px; right: -2px;
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--blocked); border: 1px solid var(--surface2);
}
.ac-chatter-toggle { margin-left: auto; }
.ac-chatter-toggle + .ac-chatter-toggle { margin-left: 0; }
.ac-chatter-drawer-body { overflow-y: auto; flex: 1; padding: 6px 0; }
.ac-chatter-row {
  display: flex; align-items: baseline; gap: 10px;
  padding: 6px 14px; font-size: 12.5px; border-bottom: 1px solid var(--border);
}
/* agent-chat#71: fixed columns so every row's text starts at the same x
   position, instead of each column sizing to its own row's content. Widths
   are width+max-width (not min-width) — a flex item with flex-shrink:0 and
   no flex-grow still sizes to its content whenever content exceeds
   min-width, since min-width is only a floor, not a ceiling; width+max-width
   pins the box itself, so nowrap/ellipsis below actually gets a chance to
   truncate a value longer than assumed instead of the column silently
   widening. ch-unit convention matches the dashboard's existing fixed-width
   columns (e.g. .ac-vital-workers b, .ac-clock).
   - time: toLocaleTimeString(), longest current form "12:00:00 AM" = 11
     chars, rendered in the mono font so ch tracks it exactly.
   - agent: longest current subscriber name is "thinkpad-personal" (18
     chars, see AC_SUB_ICON); +2ch buffer since this column isn't mono.
   - kind: longest current kind label is "message" (7 chars); +1ch buffer
     was measured against the raw lowercase string, but this column also
     applies text-transform:uppercase + letter-spacing:0.04em, both of which
     render wider than the ch unit's lowercase-"0" basis — "MESSAGE" at 8ch
     overflowed its own box (measured scrollWidth 55px vs clientWidth 47px
     in headless Chrome). Bumped to 10ch, measured against the actual
     uppercase+letter-spaced rendering, not the raw string length.
*/
.ac-chatter-row-time {
  color: var(--text-light); flex-shrink: 0; width: 11ch; max-width: 11ch;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.ac-chatter-row-icon { flex-shrink: 0; }
.ac-chatter-row-agent {
  color: var(--todo); font-weight: 600; flex-shrink: 0; width: 20ch; max-width: 20ch;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.ac-chatter-row-kind {
  color: var(--text-light); font-size: 10.5px; text-transform: uppercase; letter-spacing: 0.04em;
  flex-shrink: 0; align-self: center; width: 10ch; max-width: 10ch;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.ac-chatter-row-text { color: var(--text-muted); flex: 1; min-width: 0; }
/* Problem row (R12): a red background, not just red text. */
.ac-chatter-row-problem {
  background: var(--blocked-bg);
}
.ac-chatter-row-problem .ac-chatter-row-text { color: var(--blocked); }

/* ── Backlog divider ───────────────────────────────────────── */
.proj-backlog-divider {
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  color: var(--text-muted);
  padding: 8px 12px 4px;
  background: var(--surface);
  border-bottom: 1px solid rgba(73,77,100,0.25);
}
