/* Dashboard shell — left nav rail + routed content region.
   The rail is collapsible (icon-only) and pinnable. When pinned it stays
   expanded and reflows the content (grid track grows). When unpinned it
   flies out as an overlay on hover without reflowing the page. Both states
   add `.rail-open` to the rail (JS-driven) so text fades in uniformly.
   Pin state persists in localStorage (ring.rail.pinned).

   Reuses the design tokens from tokens.css (--bg, --text, --border, …). */

:root {
  --rail-w-collapsed: 56px;
  --rail-w-expanded: 232px;
  --dock-w: 304px;
  --dock-w-closed: 46px;
}

.app-shell {
  display: grid;
  grid-template-columns: var(--rail-w-collapsed) 1fr;
  /* 100vh is the LARGE viewport on mobile — it assumes the URL bar is hidden.
     With overflow:hidden here and on .app-main, the bottom of the scroll area
     ended up under the browser chrome and the body itself couldn't scroll, so
     the list felt stuck. dvh tracks the actually-visible height; the 100vh
     line stays as a fallback for anything without dvh support. */
  height: 100vh;
  height: 100dvh;
  overflow: hidden;
}
.app-shell.rail-pinned { grid-template-columns: var(--rail-w-expanded) 1fr; }

/* ---- Rail ---------------------------------------------------------- */
.rail {
  position: relative;
  z-index: var(--z-sticky);
  grid-column: 1;
  width: var(--rail-w-collapsed);
  height: 100vh;
  height: 100dvh;
  background: var(--bg-card);
  border-right: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  overflow: visible;
  transition: width .16s ease;
}
.rail.rail-open { width: var(--rail-w-expanded); }
/* Unpinned + open = overlay flyout (doesn't push content). It must sit above
   the topbar but BELOW the modal layer: at a hardcoded 300 it beat the modal
   card (100) and backdrop (99), so hovering the left edge slid the nav rail
   over an open modal, fully undimmed (ADR 0010 F2). The ladder fixes that by
   construction — --z-flyout is defined below --z-modal. */
.app-shell:not(.rail-pinned) .rail.rail-open {
  position: absolute;
  top: 0; left: 0; bottom: 0;
  z-index: var(--z-flyout);
  box-shadow: 4px 0 28px rgba(0,0,0,.5);
}

.rail-head {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 14px 12px 10px;
  min-height: 56px;
}
.rail-mark { font-size: 20px; line-height: 1; color: var(--accent-brand); width: 28px; text-align: center; flex: 0 0 auto; }
.rail-title { font-weight: 700; font-size: 14px; white-space: nowrap; opacity: 0; transition: opacity .12s ease; }
.rail-title .kicker { font-weight: 500; font-size: 10px; text-transform: uppercase; letter-spacing: .08em; color: var(--text-muted); margin-left: 4px; }
.rail-pin {
  margin-left: auto; background: transparent; border: 0; color: var(--text-muted);
  cursor: pointer; font-size: 15px; padding: 4px 6px; border-radius: 6px;
  opacity: 0; transition: opacity .12s ease, color .12s;
}
.rail-pin:hover { color: var(--text); background: rgba(255,255,255,.06); }
.app-shell.rail-pinned .rail-pin { color: var(--accent-brand); }

.rail-nav { display: flex; flex-direction: column; gap: 2px; padding: 6px 8px; overflow-y: auto; overflow-x: hidden; flex: 1 1 auto; }
.rail-section-label { font-size: 9px; text-transform: uppercase; letter-spacing: .08em; color: var(--text-muted); padding: 12px 10px 4px; white-space: nowrap; opacity: 0; transition: opacity .12s ease; }

.rail-item {
  display: flex; align-items: center; gap: 12px; padding: 9px 10px;
  border-radius: 8px; border: 0; background: transparent; color: var(--text-muted);
  cursor: pointer; text-decoration: none; font-size: 13px; width: 100%; text-align: left; white-space: nowrap;
}
.rail-item:hover { background: rgba(255,255,255,.05); color: var(--text); }
.rail-item.active { background: var(--accent-brand-bg); color: var(--text); }
.rail-item.active .rail-ico { color: var(--accent-brand); }
.rail-ico { flex: 0 0 auto; width: 22px; text-align: center; font-size: 16px; line-height: 1; }
.rail-label { opacity: 0; transition: opacity .12s ease; }

.rail-foot { border-top: 1px solid var(--border); padding: 8px; display: flex; flex-direction: column; gap: 2px; }

/* Text fades in whenever the rail is open (pinned or hover-flyout). */
.rail.rail-open .rail-title,
.rail.rail-open .rail-pin,
.rail.rail-open .rail-section-label,
.rail.rail-open .rail-label,
.rail.rail-open .rail-machine-text,
.rail.rail-open .rail-identity { opacity: 1; }

/* Current-machine block. */
.rail-machine { position: relative; margin: 4px 2px 6px; }
.rail-machine-btn {
  display: flex; align-items: center; gap: 10px; width: 100%; padding: 8px;
  border-radius: 8px; border: 1px solid var(--border); background: transparent;
  color: var(--text); cursor: pointer; font-size: 12px; text-align: left;
}
.rail-machine-btn:hover { background: rgba(255,255,255,.05); }
.rail-machine-text { overflow: hidden; opacity: 0; transition: opacity .12s; min-width: 0; }
.rail-machine-name { font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.rail-machine-sub { font-size: 10px; color: var(--text-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.rail-caret { margin-left: auto; opacity: .5; font-size: 10px; flex: 0 0 auto; }

.rail-machine-menu {
  position: absolute; bottom: calc(100% + 6px); left: 0; right: 0;
  max-height: 340px; overflow-y: auto; background: var(--bg-card);
  border: 1px solid var(--border); border-radius: 8px;
  box-shadow: 0 8px 28px rgba(0,0,0,.4); padding: 4px; z-index: var(--z-dock); min-width: 220px;
}
.rail-machine-item {
  display: flex; align-items: center; justify-content: space-between; gap: 8px; width: 100%;
  padding: 8px 10px; border: 0; background: transparent; cursor: pointer;
  color: var(--text); font-size: 12px; text-align: left; border-radius: 6px;
}
.rail-machine-item:hover { background: rgba(255,255,255,.06); }
.rail-machine-item.current { color: var(--accent-brand); }
.rail-machine-item .role { font-size: 10px; color: var(--text-muted); }

.rail-identity { font-size: 11px; color: var(--text-muted); padding: 6px 10px; white-space: nowrap; overflow: hidden; opacity: 0; transition: opacity .12s; }
.rail-identity a { color: var(--accent-brand); }

/* ---- Main region --------------------------------------------------- */
.app-main {
  grid-column: 2; display: flex; flex-direction: column; min-width: 0;
  height: 100vh; height: 100dvh; overflow: hidden;
}
.app-topbar {
  display: flex; align-items: center; gap: 12px; padding: 5px 16px;
  background: var(--bg); position: relative; z-index: var(--z-sticky);
  border-bottom: 1px solid var(--border); min-height: 36px; flex: 0 0 auto;
}
.topbar-title { font-weight: 600; font-size: 14px; }
.topbar-right { margin-left: auto; display: flex; align-items: center; gap: 10px; }

/* ---- Status strip additions (ADR 0010 D1) -------------------------- */
.kbd-open {
  display: flex; align-items: center; gap: 7px;
  padding: 3px 9px 3px 7px; margin-left: 8px;
  border: 1px solid var(--border-strong); border-radius: 6px;
  background: transparent; color: var(--text-subtle); font: inherit; font-size: 12px;
  cursor: pointer; transition: border-color .12s, color .12s;
}
.kbd-open:hover { border-color: var(--accent-brand); color: var(--text-muted); }
kbd {
  font-family: var(--font-mono); font-size: 10px;
  padding: 1px 4px; border-radius: 3px;
  background: var(--bg-subtle); border: 1px solid var(--border-strong); color: var(--text-muted);
}
.keys-btn {
  width: 22px; height: 22px; border-radius: 5px; flex: none;
  border: 1px solid var(--border-strong); background: transparent; color: var(--text-subtle);
  font-family: var(--font-mono); font-size: 11px; line-height: 1; cursor: pointer;
}
.keys-btn:hover { color: var(--accent-brand); border-color: var(--accent-brand); }

.strip-counts { display: flex; align-items: center; gap: 4px; }
.count {
  display: flex; align-items: center; gap: 6px;
  padding: 2px 9px; border-radius: 999px;
  border: 1px solid var(--border); color: var(--text-muted);
  font-family: var(--font-mono); font-size: 11px; white-space: nowrap;
}
.count b { font-weight: 600; color: var(--text); }
.count-hot {
  border-color: var(--sig-bad); background: var(--sig-bad-bg); color: var(--sig-bad);
  box-shadow: 0 0 16px -3px var(--sig-bad-glow);
}
.count-hot b { color: var(--sig-bad); }

/* ---- Body: viewport + dock ----------------------------------------- */
/* The frame is permanent; only .route-outlet swaps. It is also the ONLY
   scroll container — the previous shape had three nested scroll/sticky
   contexts and produced a class of overlap bug twice (ADR 0010 F3). */
.app-body {
  flex: 1 1 auto; min-height: 0;
  display: grid; grid-template-columns: 1fr var(--dock-w);
}
.app-body.dock-closed { grid-template-columns: 1fr var(--dock-w-closed); }

.route-outlet { min-height: 0; min-width: 0; overflow: auto; position: relative; }
section[data-route] { display: none; height: 100%; }
section[data-route].route-active { display: block; }
/* min-height, not height. At height:100% the section was pinned to exactly one
   viewport while its content overflowed, which made it the containing block for
   the sticky .tab-bar — so the tab bar stopped sticking after one screen of
   scrolling. Growing with content lets it stick for the whole list.
   The generic height:100% above is left alone on purpose: the admin route's
   iframe uses height:100%, which needs a definite parent height to resolve. */
section[data-route="home"].route-active {
  display: flex;
  flex-direction: column;
  height: auto;
  min-height: 100%;
}
/* Every route gets a gutter; exceptions opt OUT by name.
 *
 * This was the other way round — an allowlist naming exactly two routes,
 * `command-center` and `services`. `command-center` was dissolved in ADR 0010
 * D8 and no longer exists, and every route added since (actions, briefs,
 * plans, deployments, drive) was never added to the list, so five modules ran
 * flush against the nav rail.
 *
 * Inverted so the failure mode flips: a new route is spaced by default, and
 * going without a gutter has to be a decision someone wrote down. Same
 * property the deploy-lease work needed — a rule nobody has to remember beats
 * one that five people in a row forgot.
 *
 * box-sizing is border-box globally (styles.css:7), so this does not break the
 * height:100% above. */
section[data-route] { padding: 20px 24px; }

/* The three that manage their own space, and why:
 *   home     — the projects grid pads inside .workspace; this would double it
 *   theatre  — stage and dock split a full-height flex column, and padding on
 *              the section shifts the scroll container rather than the content
 *   admin    — an iframe, which should meet its own edges */
section[data-route="home"],
section[data-route="theatre"],
section[data-route="admin"] { padding: 0; }

.route-embed { width: 100%; height: 100%; border: 0; display: block; }

@media (max-width: 640px) {
  .app-shell, .app-shell.rail-pinned { grid-template-columns: var(--rail-w-collapsed) 1fr; }
  .app-shell.rail-pinned .rail { position: absolute; }
  .kbd-open span { display: none; }
}

/* ---- Routed views: shared head + toolbar --------------------------- */
.view-head { margin-bottom: 16px; }
.view-head .subtitle { color: var(--text-muted); margin-bottom: 12px; }
.view-head .toolbar { display: flex; align-items: center; gap: 12px; }
.view-head .toolbar button {
  padding: 6px 12px; background: transparent; border: 1px solid var(--border);
  border-radius: var(--radius); cursor: pointer; font-size: 12px; color: var(--text-muted);
}
.view-head .toolbar button:hover { background: var(--bg-subtle); color: var(--text); }
.view-head .toolbar .status { font-size: 11px; color: var(--text-muted); }
.view-head .toolbar .legend { margin-left: auto; display: flex; gap: 12px; font-size: 11px; color: var(--text-muted); }

/* ---- Services grid ------------------------------------------------- */
.svc-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(420px, 1fr)); gap: 16px; }
.svc-card h2 { margin: 0 0 4px; font-size: 14px; }
.svc-card .root { font-family: var(--font-mono); font-size: 10px; color: var(--text-muted); margin-bottom: 10px; word-break: break-all; }
.svc-empty { color: var(--text-muted); font-size: 12px; font-style: italic; padding: 6px 0; }
.svc { padding: 8px 0; border-bottom: 1px solid var(--border); }
.svc:last-child { border-bottom: 0; }
.svc-head { display: flex; align-items: center; gap: 8px; margin-bottom: 4px; }
.svc-label { font-size: 13px; font-weight: 600; }
.svc-kind { font-size: 9px; text-transform: uppercase; letter-spacing: .04em; padding: 1px 5px; border-radius: 4px; background: var(--bg-subtle); color: var(--text-muted); }
.env { display: flex; align-items: center; gap: 8px; font-size: 12px; padding: 3px 0 3px 4px; }
.env .name { min-width: 92px; font-family: var(--font-mono); font-size: 11px; }
.env .ro { font-size: 9px; text-transform: uppercase; letter-spacing: .04em; color: var(--text-muted); border: 1px solid var(--border); border-radius: 4px; padding: 0 3px; }
.env a.url { color: var(--text); text-decoration: none; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.env a.url:hover { text-decoration: underline; }
.env .detail { margin-left: auto; font-size: 10px; color: var(--text-muted); font-family: var(--font-mono); white-space: nowrap; }
.env .msg { color: var(--sig-warn); }

/* ---- Plans grid (ADR 0010 D8) --------------------------------------- */
.plan-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(360px, 1fr)); gap: 16px; }
.plan-card h2 { margin: 0 0 10px; font-size: 13px; text-transform: uppercase; letter-spacing: .04em; color: var(--text-muted); }
.plan-card .meta { font-size: 11px; color: var(--text-muted); margin-left: 6px; }
.plan-row { padding: 8px 0; border-bottom: 1px solid var(--border); font-size: 12px; }
.plan-row:last-child { border-bottom: 0; }
.plan-prompt { font-style: italic; color: var(--text); margin-top: 3px; }
.plan-time { font-family: var(--font-mono); font-size: 10px; color: var(--text-muted); }
.plan-badge { display: inline-block; padding: 1px 6px; background: var(--bg-subtle); border-radius: 999px; font-size: 10px; margin-right: 4px; }
.plan-badge.unmapped { color: var(--text-muted); font-style: italic; }
.plan-empty { color: var(--text-muted); font-size: 12px; font-style: italic; padding: 8px 0; }
.plan-adr { display: flex; gap: 6px; font-size: 11px; padding: 2px 0; }
.plan-adr .id { font-family: var(--font-mono); color: var(--text-muted); min-width: 36px; }
.plan-adr .status {
  padding: 0 4px; border-radius: 4px; font-size: 9px;
  /* nowrap + flex:none — the status is one word and a fixed-width column.
     Without it the chip wrapped mid-word ("propos / ed") once the header
     gained a count and squeezed the row. */
  white-space: nowrap; flex: none; align-self: start;
}
.plan-adr .id { flex: none; }
.plan-adr .status.accepted { background: var(--sig-ok-bg); color: var(--sig-ok); }
.plan-adr .status.proposed { background: var(--sig-warn-bg); color: var(--sig-warn); }
.plan-adr .status.superseded { background: var(--bg-subtle); color: var(--text-muted); }
.plan-adr .status.rejected { background: var(--sig-bad-bg); color: var(--sig-bad); }
.plan-phase-bar { display: flex; height: 8px; background: var(--bg-subtle); border-radius: 999px; overflow: hidden; margin: 6px 0; }
.plan-phase-seg.completed { background: var(--sig-ok); }
.plan-phase-seg.current { background: var(--sig-warn); }
.plan-phase-seg.pending { background: transparent; }
.plan-phase-name { font-size: 11px; }
.plan-phase-name.completed { color: var(--text-muted); text-decoration: line-through; }
.plan-phase-name.current { color: var(--sig-warn); font-weight: 600; }
.plan-phase-name.pending { color: var(--text); }
.plan-phase-now { font-size: 11px; color: var(--sig-warn); margin-top: 2px; }
.plan-badge { text-decoration: none; }
a.plan-badge:hover { background: var(--accent-brand-bg); color: var(--accent-brand); }

/* Group = one project's (or one session's) block inside a card. */
.plan-group { padding: 8px 0; border-bottom: 1px solid var(--border); }
.plan-group:last-child { border-bottom: 0; }
.plan-group-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 4px; font-size: 12px; }
.plan-todo { font-size: 12px; padding: 2px 0; display: flex; gap: 6px; align-items: baseline; }
.plan-todo.current { font-weight: 600; }
.plan-todo-dot { color: var(--text-muted); font-size: 10px; }

/* ---- Deployments pane (ADR 0008 P4) ------------------------------------- */
/* Uses the existing token palette; --accent (green) reads as "free/safe to
   deploy" and --warning as "claimed", which matches how a signal reads rather
   than inventing a second colour language for this pane. */

.dep-subhead {
  font-size: 12px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--text-subtle);
  margin: 22px 0 10px;
}
.dep-subhead:first-of-type { margin-top: 6px; }

.dep-env-grid {
  display: grid;
  gap: 12px;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
}

/* Geometry from the shared card rule; only the status stripe + stacking
   are local to this component. */
.dep-env {
  border-left: 3px solid var(--border-strong);
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.dep-env-free { border-left-color: var(--accent); }
.dep-env-held { border-left-color: var(--warning); background: var(--warning-bg); }

.dep-env-head { display: flex; align-items: center; gap: 8px; }
.dep-env-name {
  font-family: var(--font-mono);
  font-size: 13px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.dep-env-project { color: var(--text-muted); font-size: 13px; margin-left: auto; }

.dep-holder { font-size: 13px; display: flex; flex-direction: column; gap: 2px; }
.dep-holder-free { color: var(--accent-hover); font-weight: 600; }
/* An environment mid-deploy without a lease. Reads as occupied, because it is
   — the lease only ever told you whether someone remembered to claim it. */
.dep-holder-deploying { color: var(--warn, #d9a441); font-weight: 600; }
.dep-holder-who { font-family: var(--font-mono); font-weight: 600; }
.dep-holder-label { color: var(--text); }
.dep-holder-cwd {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--text-muted);
  word-break: break-all;
}
.dep-holder-expiry { font-size: 11px; color: var(--text-subtle); }

.dep-last { font-size: 12px; color: var(--text-muted); }
.dep-last code { font-family: var(--font-mono); font-size: 11px; }
.dep-last-none { color: var(--text-subtle); font-style: italic; }

.dep-runs { display: flex; flex-direction: column; gap: 8px; }

.dep-run {
  border-left: 3px solid var(--border-strong);
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.dep-run-succeeded { border-left-color: var(--accent); }
.dep-run-failed { border-left-color: var(--danger); background: var(--danger-bg); }
.dep-run-running { border-left-color: var(--warning); }

.dep-run-main { display: flex; flex-wrap: wrap; align-items: baseline; gap: 10px; font-size: 13px; }
.dep-run-status {
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.07em;
}
.dep-run-succeeded .dep-run-status { color: var(--accent-hover); }
.dep-run-failed .dep-run-status { color: var(--danger); }
.dep-run-running .dep-run-status { color: var(--warning); }
.dep-run-project { font-weight: 600; }
.dep-run-env { font-family: var(--font-mono); font-size: 11px; color: var(--text-muted); text-transform: uppercase; }
.dep-run-sha { font-family: var(--font-mono); font-size: 11px; color: var(--text-muted); }
.dep-run-modality {
  margin-left: auto;
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--text-subtle);
}

/* Stage chips carry the shape of a run, so a failure shows WHERE it broke
   without opening anything. */
.dep-run-stages { display: flex; flex-wrap: wrap; gap: 4px; }
.dep-stage {
  font-family: var(--font-mono);
  font-size: 10px;
  padding: 2px 7px;
  border-radius: 999px;
  border: 1px solid var(--border-strong);
  color: var(--text-muted);
  cursor: default;
}
.dep-stage-succeeded { border-color: var(--accent); color: var(--accent-hover); background: var(--success-bg); }
.dep-stage-failed { border-color: var(--danger); color: var(--danger); background: var(--danger-bg); }
.dep-stage-running { border-color: var(--warning); color: var(--warning); background: var(--warning-bg); }

.dep-run-detail {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--danger-hover);
  word-break: break-word;
}
.dep-run-when { font-size: 11px; color: var(--text-subtle); }

/* ==================================================================== */
/* Signal dock (ADR 0010 D2/D3)                                         */
/* ==================================================================== */
/* Outside the router by construction, so it keeps reporting on every
   route. Glow is a state channel, not decoration: a row glows exactly
   while it is unattended, and the glow goes OUT on acknowledgement. */

.dock {
  background: var(--bg-card);
  border-left: 1px solid var(--border);
  display: flex; flex-direction: column;
  min-height: 0; min-width: 0;
  position: relative; z-index: var(--z-dock);
}
.dock-head {
  display: flex; align-items: center; gap: 8px;
  padding: 8px 11px; border-bottom: 1px solid var(--border); flex: none;
}
.dock-head .lbl { color: var(--text-muted); }
.lbl {
  font-family: var(--font-mono); font-size: 10px;
  letter-spacing: .11em; text-transform: uppercase; color: var(--text-subtle);
}
.dock-toggle {
  margin-left: auto; background: transparent; border: 0; cursor: pointer;
  color: var(--text-subtle); font-size: 13px; padding: 2px 5px; border-radius: 4px;
}
.dock-toggle:hover { color: var(--text); background: var(--bg-subtle); }

/* Mark-all-read. `margin-left: auto` moves to this one so the pair sits
   together on the right rather than splitting across the header. */
.dock-toggle { margin-left: 0; }
.dock-ackall {
  margin-left: auto; background: transparent; border: 0; cursor: pointer;
  color: var(--text-subtle); font-size: 12px; padding: 2px 5px; border-radius: 4px;
}
.dock-ackall:hover { color: var(--accent-brand); background: var(--bg-subtle); }

.dock-list { flex: 1; min-height: 0; overflow-y: auto; padding: 8px; display: flex; flex-direction: column; gap: 6px; }
.dock-empty { color: var(--text-subtle); font-size: 12px; font-style: italic; padding: 10px 4px; }

.tier-head { display: flex; align-items: center; gap: 7px; margin: 6px 2px 1px; }
.tier-head:first-child { margin-top: 0; }
.tier-head .rule { flex: 1; height: 1px; background: var(--border); }

.sig {
  display: grid; grid-template-columns: 7px 1fr; gap: 9px; align-items: start;
  width: 100%; padding: 8px 9px; text-align: left;
  border: 1px solid var(--border); border-radius: 7px;
  background: var(--bg-subtle); color: inherit; cursor: pointer; font: inherit;
  transition: background .12s, border-color .12s;
}
.sig:hover { background: var(--bg-inset); border-color: var(--border-strong); }
.sig-dot { width: 7px; height: 7px; border-radius: 50%; margin-top: 4px; background: var(--sig-idle); }
.sig-title { font-size: 12px; font-weight: 600; color: var(--text); display: block; }
.sig-detail { font-size: 11px; color: var(--text-subtle); margin-top: 1px; line-height: 1.4; display: block; }
.sig-meta { display: flex; align-items: center; gap: 6px; margin-top: 5px; }
.sig-when { font-family: var(--font-mono); font-size: 10px; color: var(--text-subtle); margin-left: auto; }

.sig[data-tier="ambient"] { border-style: dashed; background: transparent; }
.sig[data-tier="ambient"] .sig-title { font-weight: 500; color: var(--text-muted); }
.sig[data-tier="ambient"] .sig-dot { background: var(--sig-busy); }
.sig[data-tier="nudge"] .sig-dot { background: var(--sig-warn); }
.sig[data-tier="interrupt"] .sig-dot { background: var(--sig-bad); }

/* THE PULSE RULE (D3): fires exactly twice on arrival, then .lit holds a
   steady state. It never pulses again — repetition is precisely what
   teaches you to ignore a channel. Steady-lit is not weaker than flashing;
   it is more durable, because it is still there in ten minutes. */
@keyframes sig-arrive {
  0%   { box-shadow: 0 0 0 0 var(--pulse-c), 0 0 30px -2px var(--pulse-c); }
  60%  { box-shadow: 0 0 0 7px transparent, 0 0 10px -2px var(--pulse-c); }
  100% { box-shadow: 0 0 0 0 transparent,   0 0 22px -3px var(--pulse-c); }
}
.sig.pulsing { animation: sig-arrive .6s ease-out 2; }
.sig[data-tier="nudge"]     { --pulse-c: var(--sig-warn-glow); }
.sig[data-tier="interrupt"] { --pulse-c: var(--sig-bad-glow); }

.sig.lit[data-tier="nudge"] {
  background: var(--sig-warn-bg); border-color: rgba(255,179,64,.4);
  box-shadow: inset 2px 0 0 var(--sig-warn), 0 0 18px -4px var(--sig-warn-glow);
}
.sig.lit[data-tier="interrupt"] {
  background: var(--sig-bad-bg); border-color: rgba(232,96,122,.45);
  box-shadow: inset 2px 0 0 var(--sig-bad), 0 0 22px -3px var(--sig-bad-glow);
}
/* Acknowledged: the glow goes out. That extinguishing IS the feedback. */
.sig.acked { opacity: .42; box-shadow: none; }
.sig.acked .sig-title { font-weight: 500; }
.sig.acked .sig-dot { box-shadow: none; animation: none; }

/* RESOLUTIONS (ADR 0011 D1). "api down" sitting there after it came back was
   the complaint; this is the row that replaces it. Green, quiet, arrives with
   a duration, and ages out on its own — it never joins the jump queue, so it
   costs nothing to leave unread. */
.sig.resolved { border-color: rgba(87,201,138,.32); background: var(--sig-ok-bg); opacity: 1; }
.sig.resolved .sig-dot { background: var(--sig-ok); }
.sig.resolved .sig-title { font-weight: 500; color: var(--text-muted); }
.sig.resolved { --pulse-c: var(--sig-ok-glow); }

/* Flap damping (D5) and parent rollup (D3) annotate the row rather than
   spawning more of them — the count is shown because hiding information is
   not the goal, ranking it is. */
.chip--flap { background: var(--warning-bg); color: var(--sig-warn); border-color: rgba(255,179,64,.35); }
.chip--roll { background: var(--bg-inset); color: var(--text-muted); }

/* These four modifiers were referenced by the dock, the tier heads and the
   status strip but never defined, so every one of those dots rendered
   colourless. */
.dot--ok   { background: var(--sig-ok); }
.dot--busy { background: var(--sig-busy); }
.dot--warn { background: var(--sig-warn); }
.dot--bad  { background: var(--sig-bad); }
.dot--idle { background: var(--sig-idle); }

.dock-elsewhere {
  margin-top: 4px; padding: 7px 9px;
  border: 1px dashed var(--border); border-radius: 7px;
  color: var(--text-subtle); font-size: 11px;
  display: flex; align-items: center; gap: 7px;
}

.dock-foot { flex: none; border-top: 1px solid var(--border); padding: 8px; }
.jump {
  width: 100%; display: flex; align-items: center; justify-content: center; gap: 8px;
  padding: 8px; border-radius: 7px; cursor: pointer;
  border: 1px solid var(--border-strong); background: transparent;
  color: var(--text-muted); font: inherit; font-size: 12px;
  transition: border-color .12s, color .12s, background .12s;
}
.jump:not(:disabled) {
  border-color: rgba(232,96,122,.4); color: var(--sig-bad);
  box-shadow: 0 0 18px -6px var(--sig-bad-glow);
}
.jump:hover:not(:disabled) { border-color: var(--sig-bad); background: var(--sig-bad-bg); }
.jump:disabled { opacity: .35; cursor: default; box-shadow: none; }

/* Collapsed: a strip of dots. Heads-down work without going blind. */
.dock-rail { display: none; flex-direction: column; align-items: center; gap: 9px; padding: 12px 0; }
.dock-rail .dot { width: 9px; height: 9px; }
.dock-closed .dock-head .lbl,
.dock-closed .dock-list,
.dock-closed .dock-foot { display: none; }
.dock-closed .dock-rail { display: flex; }
.dock-closed .dock-toggle { margin: 0 auto; }

/* ==================================================================== */
/* Command palette + shortcuts sheet (ADR 0010 D4)                      */
/* ==================================================================== */
.scrim {
  position: fixed; inset: 0; z-index: var(--z-palette);
  background: rgba(6,8,12,.68);
  display: grid; place-items: start center; padding-top: 13vh;
}
.scrim[hidden] { display: none; }

.palette, .keys-sheet {
  width: min(560px, 92vw);
  background: var(--bg-subtle);
  border: 1px solid var(--border-strong);
  border-radius: 11px;
  box-shadow: var(--shadow-lg);
  overflow: hidden;
}
.palette-input {
  width: 100%; padding: 14px 16px;
  background: transparent; border: 0; border-bottom: 1px solid var(--border);
  color: var(--text); font: inherit; font-size: 15px;
}
.palette-input::placeholder { color: var(--text-subtle); }
.palette-input:focus { outline: none; }
.palette-list { max-height: 46vh; overflow-y: auto; padding: 6px; }
.pal-row {
  display: flex; align-items: center; gap: 10px; width: 100%;
  padding: 8px 10px; border-radius: 7px; border: 0; background: transparent;
  color: inherit; font: inherit; font-size: 13px; text-align: left; cursor: pointer;
}
.pal-row[aria-selected="true"] { background: var(--accent-brand-bg); }
.pal-row[aria-selected="true"] .pal-name { color: var(--accent-brand); }
.pal-ico { width: 16px; text-align: center; color: var(--text-subtle); font-size: 12px; flex: none; }
.pal-name { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pal-kind { font-family: var(--font-mono); font-size: 10px; color: var(--text-subtle); flex: none; }
.pal-empty { padding: 18px 16px; color: var(--text-subtle); font-size: 13px; text-align: center; }

.keys-head { padding: 13px 16px; border-bottom: 1px solid var(--border); display: flex; align-items: center; gap: 10px; }
.keys-head h2 { margin: 0; font-size: 14px; font-weight: 600; }
.keys-body { padding: 6px 8px 12px; }
.keys-group { padding: 10px 10px 3px; }
.keys-row { display: flex; align-items: center; gap: 12px; padding: 6px 10px; border-radius: 6px; font-size: 13px; }
.keys-row .k { flex: 0 0 108px; display: flex; gap: 4px; }
.keys-row .d { color: var(--text-muted); }
.keys-row .d b { color: var(--text); font-weight: 600; }

@media (prefers-reduced-motion: reduce) {
  /* Glow is retained — colour and luminance carry the same information
     without movement. Only the motion stops. */
  .sig.pulsing { animation: none; }
}


/* ==================================================================== */
/* Scrollbars                                                           */
/* ==================================================================== */
/* There was no scrollbar styling at all, so every scroll container drew
   the OS default — bright chrome on a near-black ground, and the most
   visually loud thing on screen after going dark in P1.

   Grey, thin, and transparent-tracked: present when you need it, absent
   otherwise. `scrollbar-color` covers Firefox; the ::-webkit rules cover
   Chromium, which is what this actually runs in. */

* {
  scrollbar-width: thin;
  scrollbar-color: var(--border-strong) transparent;
}

::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb {
  background: var(--border-strong);
  border-radius: 6px;
  /* Transparent border + background-clip insets the thumb, so it reads as a
     floating grey bar rather than a filled gutter. */
  border: 3px solid transparent;
  background-clip: content-box;
}
::-webkit-scrollbar-thumb:hover { background: var(--text-subtle); background-clip: content-box; }
::-webkit-scrollbar-corner { background: transparent; }

/* ---- No horizontal scrollbars ------------------------------------- */
/* A horizontal scrollbar in this app is always a layout bug — nothing here
   is wider than its column on purpose. Turning overflow-x off would only
   hide the symptom, so each container that had one also gets the min-width
   or wrapping fix that removes the cause. */

.route-outlet { overflow-x: hidden; }
.dock-list { overflow-x: hidden; }

/* The dock's rows are `grid-template-columns: 7px 1fr`. A grid item's
   default `min-width: auto` refuses to shrink below its content, so a long
   unbroken title ("Turns Hospitality Software/Turns.Dashboard.Web · prod")
   pushed the row wider than the dock and produced the horizontal bar under
   the signal list. min-width:0 lets it shrink; overflow-wrap lets it break. */
.sig > * { min-width: 0; }
.sig-title,
.sig-detail { overflow-wrap: anywhere; }

/* Same class of fix for the other places long unbroken strings land: paths,
   URLs and shas have no spaces to break at. */
.plan-todo,
.plan-adr,
.pal-name,
.dock-elsewhere { overflow-wrap: anywhere; }

/* Wide content that genuinely cannot shrink — tables, pre blocks — scrolls
   inside ITS OWN container rather than making the page scroll sideways. */
.pane pre,
.plan-card pre,
.card pre { overflow-x: auto; max-width: 100%; }

/* ==================================================================== */
/* Responsive — LAST on purpose                                         */
/* ==================================================================== */
/* This lived above the dock rules and lost the cascade: `.dock { display:
   flex }` is the same specificity and came later, so `display: none` never
   applied and the dock stayed on a 900px viewport. Media queries carry no
   specificity bonus — only source order decides. Keep this block last. */
@media (max-width: 1100px) {
  /* The dock earns its width only when there is width to spare. Below this
     it folds away and the status strip's counts carry the same information. */
  .app-body, .app-body.dock-closed { grid-template-columns: 1fr; }
  .dock { display: none; }
}

/* ---- Working-context chip (ADR 0010 D5) ---------------------------- */
.ctx-chip {
  display: flex; align-items: baseline; gap: 7px;
  padding: 3px 9px; border-radius: 6px; cursor: pointer;
  background: var(--accent-brand-bg); border: 1px solid var(--accent-brand-dim, var(--border-strong));
  font: inherit;
}
.ctx-chip:hover:not(:disabled) { border-color: var(--accent-brand); box-shadow: 0 0 14px -4px var(--accent-brand-glow); }
.ctx-chip:disabled { cursor: default; opacity: .85; }
.ctx-slot { font-family: var(--font-mono); font-size: 10px; color: var(--accent-brand); }
.ctx-name { font-size: 12px; font-weight: 600; color: var(--text); }
.dock-elsewhere { width: 100%; cursor: pointer; font: inherit; }
.dock-elsewhere:hover { border-color: var(--border-strong); color: var(--text-muted); }

/* Settled ADRs are context, not work — dimmed so the proposed ones lead. */
.plan-adr-settled { opacity: .55; }

/* ---- Module matrix (ADR 0013) --------------------------------------
   The rail renders a module for every project; a card links into the same
   module scoped to one. `.scope-of` is the "…for this project" marker that
   tells the two apart at a glance. */
.scope-of {
  font-family: var(--font-mono); font-size: 11px; font-weight: 500;
  color: var(--accent-brand); background: var(--accent-brand-bg);
  border-radius: 5px; padding: 2px 7px; margin-left: 8px; vertical-align: middle;
}

/* Per-project module nav, above whichever module is mounted. */
.proj-modnav {
  display: flex; align-items: center; flex-wrap: wrap; gap: 4px;
  padding: 0 0 10px; margin-bottom: 14px; border-bottom: 1px solid var(--border);
}
.proj-modnav-home {
  text-decoration: none; color: var(--text-subtle); font-size: 15px;
  padding: 3px 8px; border-radius: 6px; line-height: 1;
}
.proj-modnav-home:hover { color: var(--text); background: var(--bg-subtle); }
.proj-modnav-name {
  font-family: var(--font-mono); font-size: 11px; color: var(--text-muted);
  margin-right: 10px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 320px;
}
.proj-modtab {
  text-decoration: none; color: var(--text-muted); font-size: 12px;
  padding: 5px 10px; border-radius: 6px; border: 1px solid transparent;
}
.proj-modtab:hover { color: var(--text); background: var(--bg-subtle); }
.proj-modtab.active {
  color: var(--text); background: var(--accent-brand-bg);
  border-color: var(--accent-brand-dim, var(--border-strong));
}

/* ---- Card module rows (ADR 0013 D2) --------------------------------
   The card IS the summary. Each row is a status plus a link into that
   module for THIS project — the card's count and its destination finally
   agree, which is the defect that prompted the ADR. */
.pc-mods { display: flex; flex-direction: column; gap: 1px; margin: 10px 0 2px; }
.pc-mod {
  display: grid; grid-template-columns: 88px 1fr 16px; align-items: center; gap: 8px;
  padding: 5px 7px; border-radius: 6px; text-decoration: none; color: inherit;
  border: 1px solid transparent;
}
.pc-mod:hover { background: var(--bg-inset); border-color: var(--border); }
.pc-mod-label {
  font-family: var(--font-mono); font-size: 9px; letter-spacing: .1em;
  text-transform: uppercase; color: var(--text-subtle);
}
.pc-mod-value {
  font-size: 12px; color: var(--text-muted);
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* Pending reads as waiting, not as a value. */
.pc-mod-value[data-pending] { color: var(--text-subtle); opacity: .6; }
.pc-mod-go { justify-self: end; color: var(--text-subtle); font-size: 13px; opacity: 0; transition: opacity .12s; }
.pc-mod:hover .pc-mod-go { opacity: 1; color: var(--accent); }

/* ---- Drive portfolio table (ADR 0013 D3) --------------------------- */
.drv-table { display: flex; flex-direction: column; gap: 3px; margin-top: 12px; }
.drv-row {
  display: grid; grid-template-columns: 1fr 160px 190px 16px; align-items: center; gap: 12px;
  padding: 9px 11px; border: 1px solid var(--border); border-radius: 7px;
  background: var(--bg-subtle); text-decoration: none; color: inherit; font-size: 12px;
}
.drv-row:hover { border-color: var(--border-strong); background: var(--bg-inset); }
.drv-name { font-weight: 600; color: var(--text); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.drv-slug, .drv-last { font-family: var(--font-mono); font-size: 10px; color: var(--text-subtle); }
.drv-stale { color: var(--sig-warn); }
.drv-go { justify-self: end; color: var(--text-subtle); }

/* A terminal opened from inside Sessions (ADR 0013 D4). */
.th-terminal { margin: 12px 0 18px; }
.th-start-alt { background: transparent; color: var(--text-muted); }

@media (max-width: 640px) {
  .pc-mod { grid-template-columns: 1fr 16px; row-gap: 1px; }
  .pc-mod-label { grid-column: 1 / -1; }
  .drv-row { grid-template-columns: 1fr 16px; row-gap: 3px; }
  .drv-slug, .drv-last { grid-column: 1 / -1; }
}


/* The button only exists on mobile; above the breakpoint the hover flyout and
   the pin are the interaction, and a second affordance for the same nav is
   clutter. Declared BEFORE the media query on purpose: same specificity, so
   whichever comes last wins, and with this at the bottom of the file it beat
   the query and the button stayed hidden on a phone. */
.nav-toggle { display: none; }

/* ==== Mobile: the rail becomes a drawer ==============================
   Everything above assumes a pointer that can hover. `.rail` expands on
   mouseenter and collapses on mouseleave, which on a touch screen means it
   never expands at all: eleven unlabelled glyphs in a 56px gutter, taking
   14% of a 390px phone to say nothing.

   Below the breakpoint the rail leaves the grid entirely and becomes an
   off-canvas drawer behind the ☰ button. The desktop behaviour is not
   touched — every rule here is inside the query. */
@media (max-width: 720px) {
  /* One column. The 56px gutter is the single biggest win on a phone. */
  .app-shell,
  .app-shell.rail-pinned { grid-template-columns: 1fr; }

  .rail {
    position: fixed;
    top: 0; bottom: 0; left: 0;
    width: min(82vw, 300px);
    /* Off-canvas rather than display:none so it animates, and so the nav
       stays in the accessibility tree in a predictable place. */
    transform: translateX(-100%);
    transition: transform .18s ease;
    z-index: var(--z-modal);
    box-shadow: 4px 0 28px rgba(0,0,0,.5);
  }
  .app-shell.nav-open .rail { transform: translateX(0); }

  /* Hover can't reach it, so the width transition must not fight the
     transform — and a stale `rail-open` from a desktop session must not
     leave the drawer half-expanded. */
  .rail, .rail.rail-open { width: min(82vw, 300px); }

  /* Labels are the entire point of opening it; never fade them out here. */
  .rail-label,
  .rail-title,
  .rail-section-label { opacity: 1 !important; }

  /* Pinning is a desktop idea — it trades content width for labels, and on a
     phone there is no width to trade. */
  .rail-pin { display: none; }

  .nav-scrim {
    position: fixed;
    inset: 0;
    background: rgba(0,0,0,.5);
    z-index: calc(var(--z-modal) - 1);
  }

  .nav-toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    /* 44px is the Apple/Android minimum touch target. The topbar's other
       controls are smaller because a mouse is precise; this one is thumbed. */
    width: 44px; height: 44px;
    margin-left: -6px;
    flex: 0 0 auto;
    background: none;
    border: 0;
    color: var(--text);
    font-size: 20px;
    line-height: 1;
    cursor: pointer;
    border-radius: var(--radius-sm, 6px);
  }
  .nav-toggle:active { background: rgba(255,255,255,.08); }

  /* The topbar carries four controls designed for a 1600px window. On a
     phone the title plus the menu button is the honest subset — the palette
     has a keyboard shortcut nobody can press here, and the context chip is
     reachable from inside the drawer's own controls. */
  .app-topbar { gap: 8px; padding-left: 8px; padding-right: 8px; }
  .kbd-open { display: none; }
  .topbar-title { font-size: 15px; }
}
