/* ==========================================================================
   AOS components — ported from design/claude-design/aos-primitives.jsx
   (Pill/StateDot/Card/Button/Tabs/StatTile/Kbd/Bar/SectionHeader/Empty/
   AgentAvatar), plus new (not in the source): .skeleton, .toast, .modal.

   Deviation note: the source computes hover/glow tints by string-concatenating
   an alpha hex suffix onto a css var() reference (e.g. `${stateColor(state)}22`,
   `${color}22` / `${color}44`). That only works when the JS value is a literal
   hex string; against a var() reference it produces an invalid CSS color and
   silently drops the declaration. Ported here with color-mix(in srgb, VAR X%,
   transparent) instead, which reproduces the intended tint and stays
   token-driven (2026 browser support is universal for color-mix()).
   ========================================================================== */

/* ---------- Global [hidden] guard ---------- */
/* Any component class that sets `display` (e.g. .pill's inline-flex) beats
   the UA stylesheet's [hidden] rule on specificity — the stale chip rendered
   as a permanent empty pill because of exactly this. !important restores the
   HTML contract: hidden means gone. */
[hidden] {
  display: none !important;
}

/* ---------- Motion: base interactive transitions ----------
   Measured audit (Panel B, finding 1): exactly ONE `transition` existed in
   the whole 45KB CSS surface (.sidenav's mobile-drawer transform, in
   shell.css) — every hover/active/focus state elsewhere snapped instantly.
   One base rule for the interactive-class roster instead of hand-adding
   per-component transitions. Color-only properties (no layout property
   animates — no width/height/padding/margin in this list). */
.btn,
.pill,
.row[data-clickable="true"],
.row[tabindex],
a.row,
button.row,
.sidenav-item,
.topbar-icon-btn,
.fab,
a,
select,
.tabbar-item {
  transition: background-color 120ms ease, color 120ms ease, border-color 120ms ease, opacity 120ms ease;
}

/* ---------- Screen-reader-only utilities ---------- */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* Skip-link reveal: on keyboard focus, become a normal in-flow chip. */
.sr-only-focusable:focus-visible {
  position: static;
  width: auto;
  height: auto;
  padding: 8px 12px;
  margin: 0;
  overflow: visible;
  clip-path: none;
  white-space: normal;
  display: inline-block;
  background: var(--aos-bg-surface-2);
  color: var(--aos-text-primary);
  border-radius: 6px;
  font-size: 13px;
  text-decoration: none;
  outline: 2px solid var(--aos-accent);
  outline-offset: 2px;
}

/* ---------- Pill ---------- */
.pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 3px 9px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 500;
  line-height: 1.1;
  font-family: var(--aos-font-sans);
  white-space: nowrap;
  background: var(--aos-bg-chip);
  color: var(--aos-text-secondary);
  border: 1px solid transparent;
}

.pill-sm {
  padding: 2px 8px; /* off-grid fix (4px base grid): was 2px 7px */
  font-size: 11px;
  gap: 5px;
}

.pill-mono {
  font-family: var(--aos-font-mono);
  letter-spacing: 0.02em;
}

.pill-accent {
  background: var(--aos-accent-subtle);
  color: var(--aos-accent);
  border-color: rgba(66, 232, 96, .25);   /* phosphor accent (Command Center) */
}

.pill-success {
  background: rgba(60, 191, 102, .12);     /* success #3CBF66 — quieter phosphor family */
  color: var(--aos-status-success);
  border-color: rgba(60, 191, 102, .25);
}

.pill-error {
  background: rgba(248, 113, 113, .12);
  color: var(--aos-status-error);
  border-color: rgba(248, 113, 113, .25);
}

.pill-warning {
  background: rgba(251, 191, 36, .12);
  color: var(--aos-status-warning);
  border-color: rgba(251, 191, 36, .25);
}

.pill-info {
  background: rgba(96, 165, 250, .12);
  color: var(--aos-status-info);
  border-color: rgba(96, 165, 250, .25);
}

.pill-awaith {
  background: rgba(192, 132, 252, .12);
  color: var(--aos-state-awaiting-human);
  border-color: rgba(192, 132, 252, .25);
}

.pill-quiet {
  background: transparent;
  color: var(--aos-text-tertiary);
  border-color: var(--aos-border-default);
}

/* ---------- State dot ---------- */
.state-dot {
  display: inline-block;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--aos-state-idle);
  flex: 0 0 auto;
}

.state-dot[data-state="idle"]           { background: var(--aos-state-idle); }
.state-dot[data-state="running"]        { background: var(--aos-state-running); box-shadow: 0 0 0 2px color-mix(in srgb, var(--aos-state-running) 13%, transparent); }
.state-dot[data-state="blocked"]        { background: var(--aos-state-blocked); }
.state-dot[data-state="awaiting-human"] { background: var(--aos-state-awaiting-human); }
.state-dot[data-state="errored"]        { background: var(--aos-state-errored); }
.state-dot[data-state="complete"]       { background: var(--aos-state-complete); }

/* ---------- Card ---------- */
.card {
  background: var(--aos-bg-surface-1);
  border: 1px solid var(--aos-border-subtle);
  border-radius: 10px;
  overflow: hidden;
}

.card-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 14px 16px 0 16px;
}

.card-header-titles {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.card-kicker {
  font: 500 10px/1.3 var(--aos-font-sans);
  color: var(--aos-text-tertiary);
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

.card-title {
  /* Finding 5, same promotion as .section-header-title — consistent zone
     title weight across both card-header patterns (Settings' cardShell()
     uses this one). */
  font: 600 20px/1.25 var(--aos-font-sans);
  color: var(--aos-text-primary);
}

.card-body {
  padding: 16px;
}

/* ---------- Section header ---------- */
.section-header {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  padding: 14px 16px 12px 16px;
  gap: 16px;
  border-bottom: 1px solid var(--aos-border-subtle);
}

.section-header-titles {
  min-width: 0;
}

.section-header-kicker {
  font-size: 10px;
  font-weight: 500;
  color: var(--aos-text-tertiary);
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

.section-header-title-row {
  display: flex;
  align-items: baseline;
  gap: 8px;
  margin-top: 2px;
}

.section-header-title {
  /* Finding 5 — the DS defines .aos-h2 (20px/600) but it was never used;
     zone/card titles fell to this class's old 14px/600, reading as barely
     more than the 10px caps kicker above it. Promoted to match .aos-h2
     exactly (screenshot-tested at 20px and 16px on Insights — 20px reads
     fine on this dense dashboard, has room in the section-header padding,
     and reuses the type scale's existing step instead of adding a 7th
     ad hoc size to a scale documented as "locked at 6 sizes"). */
  font-size: 20px;
  font-weight: 600;
  color: var(--aos-text-primary);
}

.section-header-subtitle {
  font-size: 12px;
  color: var(--aos-text-tertiary);
}

/* ---------- Button ---------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 6px;
  font-weight: 500;
  font-family: var(--aos-font-sans);
  cursor: pointer;
  border: 1px solid transparent;
}

.btn:focus-visible {
  outline: none;
  box-shadow: var(--nfn-shadow-focus);
}

.btn:disabled {
  color: var(--aos-text-disabled);
  cursor: not-allowed;
  pointer-events: none;
}

/* Gated CTA (finding 2): an action the page KNOWS is blocked by auth, but
   whose honest response to a click is "open the sign-in modal" rather than a
   dead end — so this stays a real, still-clickable button (unlike
   :disabled's pointer-events:none above) with a visibly dimmed weight and an
   aria-disabled announcement. */
.btn[aria-disabled="true"] {
  opacity: .5;
  cursor: not-allowed;
}

.btn-full {
  width: 100%;
}

.btn-sm { height: 28px; padding: 0 12px; font-size: 12px; gap: 6px; } /* off-grid fix: was 0 10px */
.btn-md { height: 32px; padding: 0 12px; font-size: 13px; gap: 8px; }
.btn-lg { height: 38px; padding: 0 16px; font-size: 14px; gap: 8px; }

.btn-primary {
  background: var(--aos-accent);
  color: var(--aos-accent-on);
  border-color: transparent;
}

.btn-primary:hover {
  background: color-mix(in srgb, var(--aos-accent) 92%, white);
}

.btn-primary:active {
  background: color-mix(in srgb, var(--aos-accent) 88%, black);
}

.btn-secondary {
  background: var(--aos-bg-input);
  color: var(--aos-text-primary);
  border-color: var(--aos-border-default);
}

.btn-secondary:hover {
  background: color-mix(in srgb, var(--aos-bg-input) 94%, white);
  border-color: var(--aos-border-strong);
}

.btn-secondary:active {
  background: color-mix(in srgb, var(--aos-bg-input) 88%, black);
}

.btn-ghost {
  background: transparent;
  color: var(--aos-text-secondary);
  border-color: transparent;
}

.btn-ghost:hover {
  background: var(--nfn-bg-subtle);
  color: var(--aos-text-primary);
}

.btn-ghost:active {
  background: color-mix(in srgb, var(--aos-bg-input) 88%, black);
}

.btn-outline {
  background: transparent;
  color: var(--aos-text-primary);
  border-color: var(--aos-border-strong);
}

.btn-outline:hover {
  background: var(--nfn-bg-subtle);
}

.btn-outline:active {
  background: color-mix(in srgb, var(--aos-bg-input) 88%, black);
}

.btn-destructive {
  background: rgba(248, 113, 113, 0.10);
  color: var(--aos-status-error);
  border-color: rgba(248, 113, 113, 0.30);
}

.btn-destructive:hover {
  background: color-mix(in srgb, var(--aos-status-error) 16%, transparent);
}

.btn-destructive:active {
  background: color-mix(in srgb, var(--aos-status-error) 22%, transparent);
}

.btn-destructive:focus-visible {
  box-shadow: var(--nfn-shadow-focus-destructive);
}

/* ---------- Tabs ---------- */
.tabs {
  display: flex;
  gap: 20px;
  border-bottom: 1px solid var(--aos-border-subtle);
  margin-top: 8px;
}

.tab {
  /* Full reset first: these are <button>s, and the UA's default button
     border/appearance painted three-sided boxes over the underline rail
     (same leak class as the body-margin bug — the scoped reset only
     normalizes box-sizing). */
  appearance: none;
  border: none;
  font: inherit;
  padding: 10px 2px;
  font-size: 13px;
  font-weight: 500;
  color: var(--aos-text-tertiary);
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  cursor: pointer;
  background: transparent;
}

.tab:hover {
  color: var(--aos-text-secondary);
}

.tab:focus-visible {
  outline: none;
  box-shadow: var(--nfn-shadow-focus);
  border-radius: 6px 6px 0 0;
}

.tab.active,
.tab.active:hover {
  color: var(--aos-text-primary);
  border-bottom-color: var(--aos-accent);
}

.tab-count {
  font-size: 11px;
  color: var(--aos-text-tertiary);
  font-family: var(--aos-font-mono);
  letter-spacing: 0.02em;
}

.tab.active .tab-count {
  color: var(--aos-text-secondary);
}

.tabs.sm .tab {
  padding: 8px 12px;
}

/* ---------- Stat tile ---------- */
.stat-tile {
  background: var(--aos-bg-surface-1);
  border: 1px solid var(--aos-border-subtle);
  border-radius: 8px;
  padding: 12px 14px;
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
}

.stat-tile-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}

.stat-tile-label {
  font-size: 11px;
  font-weight: 500;
  color: var(--aos-text-tertiary);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.stat-tile-icon {
  color: var(--aos-text-tertiary);
}

.stat-tile-value-row {
  display: flex;
  align-items: baseline;
  gap: 8px;
}

.stat-tile-value {
  font-size: 26px;
  font-weight: 500;
  color: var(--aos-text-primary);
  line-height: 1;
}

.stat-tile-value.tone-accent  { color: var(--aos-accent); }
.stat-tile-value.tone-success { color: var(--aos-status-success); }
.stat-tile-value.tone-warn    { color: var(--aos-status-warning); }
.stat-tile-value.tone-error   { color: var(--aos-status-error); }

.stat-tile-delta {
  font-size: 11px;
  color: var(--aos-text-tertiary);
  font-family: var(--aos-font-mono);
  letter-spacing: 0.02em;
}

/* ---------- Kbd ---------- */
.kbd {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 18px;
  height: 18px;
  padding: 0 4px; /* off-grid fix: was 0 5px */
  border-radius: 3px;
  background: var(--aos-bg-chip);
  color: var(--aos-text-secondary);
  font-family: var(--aos-font-mono);
  font-size: 11px;
  font-weight: 500;
  border: 1px solid var(--aos-border-default);
}

/* ---------- Bar ---------- */
.bar {
  width: 100%;
  height: var(--bar-height, 4px);
  background: var(--aos-bg-input);
  border-radius: 999px;
  overflow: hidden;
}

.bar-fill {
  height: 100%;
  border-radius: 999px;
  background: var(--aos-accent);
  width: 0%;
}

.bar-fill.tone-info    { background: var(--aos-status-info); }
.bar-fill.tone-warning { background: var(--aos-status-warning); }
.bar-fill.tone-error   { background: var(--aos-status-error); }

/* ---------- Empty state ---------- */
.empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 48px 20px;
  color: var(--aos-text-tertiary);
  text-align: center;
}

.empty-icon {
  color: var(--aos-text-disabled);
  margin-bottom: 4px;
}

.empty-title {
  font-size: 14px;
  font-weight: 500;
  color: var(--aos-text-secondary);
}

.empty-body {
  font-size: 12px;
  color: var(--aos-text-tertiary);
  max-width: 320px;
}

/* ---------- Avatar tile (AgentAvatar) ---------- */
.avatar-tile {
  position: relative;
  width: var(--avatar-size, 28px);
  height: var(--avatar-size, 28px);
  border-radius: 6px;
  background: color-mix(in srgb, var(--aos-accent) 13%, transparent);
  border: 1px solid color-mix(in srgb, var(--aos-accent) 27%, transparent);
  color: var(--aos-accent);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  font-family: var(--aos-font-mono);
  font-weight: 600;
  font-size: 12px;
}

.avatar-tile-sub {
  position: absolute;
  right: -2px;
  bottom: -2px;
  width: 8px;
  height: 8px;
  border-radius: 999px;
  background: var(--aos-state-idle);
  border: 2px solid var(--aos-bg-surface-1);
}

.avatar-tile-sub[data-state="idle"]           { background: var(--aos-state-idle); }
.avatar-tile-sub[data-state="running"]        { background: var(--aos-state-running); }
.avatar-tile-sub[data-state="blocked"]        { background: var(--aos-state-blocked); }
.avatar-tile-sub[data-state="awaiting-human"] { background: var(--aos-state-awaiting-human); }
.avatar-tile-sub[data-state="errored"]        { background: var(--aos-state-errored); }
.avatar-tile-sub[data-state="complete"]       { background: var(--aos-state-complete); }

/* ==========================================================================
   New — not in the Claude Design source
   ========================================================================== */

/* ---------- Skeleton shimmer ---------- */
.skeleton {
  position: relative;
  overflow: hidden;
  background: var(--aos-bg-surface-2);
  border-radius: 4px;
}

.skeleton::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.06), transparent);
  transform: translateX(-100%);
  animation: skeleton-sweep 1.6s ease-in-out infinite;
}

@keyframes skeleton-sweep {
  100% { transform: translateX(100%); }
}

@media (prefers-reduced-motion: reduce) {
  .skeleton::after {
    animation: none;
  }

  .btn,
  .pill,
  .row[data-clickable="true"],
  .row[tabindex],
  a.row,
  button.row,
  .sidenav-item,
  .topbar-icon-btn,
  .fab,
  a,
  select,
  .tabbar-item {
    transition: none;
  }
}

/* ---------- Toast ---------- */
.toast {
  position: fixed;
  left: 50%;
  bottom: 20px;
  transform: translateX(-50%);
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 14px;
  background: var(--aos-bg-surface-2);
  border: 1px solid var(--aos-border-default);
  border-radius: 8px;
  box-shadow: var(--nfn-shadow-md);
  color: var(--aos-text-primary);
  font-size: 13px;
  z-index: 80;
  max-width: min(420px, calc(100vw - 40px));
}

/* ---------- Modal ---------- */
.modal-scrim {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.6);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 90;
}

.modal {
  background: var(--aos-bg-surface-1);
  border: 1px solid var(--aos-border-default);
  border-radius: 12px;
  box-shadow: var(--nfn-shadow-lg);
  width: 100%;
  max-width: min(560px, calc(100vw - 40px));
  max-height: calc(100vh - 80px);
  overflow: auto;
}

.modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16px 20px;
  border-bottom: 1px solid var(--aos-border-subtle);
}

.modal-title {
  font-size: 16px;
  font-weight: 600;
  color: var(--aos-text-primary);
}

.modal-body {
  padding: 20px;
}

.modal-footer {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 8px;
  padding: 16px 20px;
  border-top: 1px solid var(--aos-border-subtle);
}

/* --- In-content links -------------------------------------------------------
   Sign-in hints and empty states build bare <a> elements (automation,
   insights, projects, commands). The DS ships --nfn-link but no bare-anchor
   rule, so those fell to UA default blue (#0000EE) — 1.96:1 on the dark
   canvas (caught by the E3 ship-verify matrix). Scoped to unclassed anchors
   so component link styles (.sidenav-item etc.) are untouched. */
.aos-root main a:not([class]) {
  color: var(--nfn-link);
  text-decoration: underline;
  text-underline-offset: 2px;
}
.aos-root main a:not([class]):hover { color: var(--nfn-blue-300); }

/* --- Page-level column grids ------------------------------------------------
   Pages build side-by-side columns via the cols() wrapper (home.js), which
   sets --page-cols inline. Collapse to a single column at the same 767px
   breakpoint the shell uses — a hardcoded inline template can't respond. */
.page-cols { display: grid; grid-template-columns: var(--page-cols, 1fr); }
@media (max-width: 767px) {
  .page-cols { grid-template-columns: 1fr; }
}

/* Base display for home.js's stack()-built column wrappers — kept in the
   stylesheet (not inline) specifically so the MUST-FIX B override below can
   beat it at <=767px; an inline style would out-specificity any external
   rule regardless of selector weight. */
.home-col { display: grid; }

/* MUST-FIX B (blind critique, 2026-07-07; taste-log 2026-07-06 — "an
   ambient signal you scroll to isn't ambient"). Home's two .page-cols
   children are each a .home-col stack (left: needs-you+today, right:
   fleet+quick — home.js's stack()). Below
   767px the columns collapse to one, but the stacks themselves still
   render as two boxes, so Fleet (in the right stack) can never appear
   before Today (in the left stack) — an empty Today still buries the
   fleet-health signal below the fold. Flatten both .home-col boxes to
   `display: contents` at this width ONLY: their [data-zone] children
   become direct .page-cols grid items and `order` can move Fleet ahead of
   an empty Today. Desktop's 2fr/1fr layout (the .home-col boxes intact,
   independently stacked per column) is untouched. */
@media (max-width: 767px) {
  .page-cols > .home-col { display: contents; }
  .page-cols > .home-col > [data-zone="needs"]  { order: 1; }
  .page-cols > .home-col > [data-zone="today"]  { order: 2; }
  .page-cols > .home-col > [data-zone="fleet"]  { order: 3; }
  .page-cols > .home-col > [data-zone="quick"]  { order: 5; }
  .page-cols > .home-col > [data-zone="today"][data-empty="true"] { order: 4; }
}

/* --- Command palette ---------------------------------------------------
   Drainer-down honesty line (fix wave W3G finding 5) — same warning color
   formula as .pill-warning, but a full-width banner rather than a chip. */
.palette-drainer-warning {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 8px 10px;
  border-radius: 6px;
  background: rgba(251, 191, 36, .12);
  border: 1px solid rgba(251, 191, 36, .25);
  color: var(--aos-status-warning);
  font-size: 12px;
}

/* ============================================================================
   L2 wave (2026-07-06/07) — APPENDED BLOCK, do not merge new rules above
   this marker. Owned by home.js (Needs-you row weight, finding 3). A
   parallel agent (L1) owns this file's other rules broadly this wave —
   keeping additions in one block at the end avoids merge pain. The stale
   chip (finding 1) and fleet dots (finding 2) needed no new CSS: the chip
   reuses its existing static .pill-warning class (web/index.html), and the
   fleet dots reuse the existing .state-dot[data-state] vocabulary already
   defined above (idle/blocked/errored/complete = gray/amber/red/green).
   ============================================================================ */

/* Finding 3 — error-severity Needs-you rows get a heavier title and a
   stronger state stripe than every other severity, so a $38K past-due row
   doesn't read at the same visual weight as a lint-untriaged digest.
   Weight differentiation only: no font-size change, no layout shift. Scoped
   to .row-severity-error (set only on Needs-you alert rows with
   severity:"error" in home.js's buildAlertRow) — NOT a blanket
   .row[data-state="errored"] rule, which would also reshape Today's
   past_due task rows and Fleet's red dots. */
.row-severity-error .row-primary {
  font-weight: 600;
}
.row-severity-error .row-stripe {
  width: 4px;
}
