/* UI v2 — every rule scoped under .ui-v2, which the layout sets only when the
   signed ui_version cookie says "v2". Without the cookie NOTHING here matches,
   so shipping this file is provably inert for anyone still on v1. That is what
   makes merging v2 work safe while the rest of the app is untouched.

   Imported last-but-one in application.css (before responsive.css) so it wins
   over components.css but mobile refinements still win over it. */

/* ── Nav ──────────────────────────────────────────────────────────────────
   Eight items instead of twelve, so the sections can breathe instead of
   scrolling. v1's nav-section is a tight all-caps label repeated three times;
   with two groups of one and two mid-sized groups it reads better with more
   air above than below. */
.ui-v2 .nav-section {
  margin-top: var(--space-5);
  margin-bottom: var(--space-1);
}
.ui-v2 .sidebar-nav > .nav-item:first-of-type {
  /* DECIDE sits above the first section label — give it the same top offset a
     labelled group gets, so it doesn't crowd the brand mark. */
  margin-top: var(--space-2);
}

/* The one item that is the point of the app. Kept quiet until it has something
   to say — step 2 adds the live count, and only then does it earn emphasis. */
.ui-v2 .sidebar-nav > .nav-item:first-of-type.is-active {
  background: var(--accent-soft);
  color: var(--accent);
}


/* ── Topbar ───────────────────────────────────────────────────────────────
   The locale button is gone from the v2 topbar (Settings owns it), which is
   45px back — the exact overflow that squashed the hamburger below 375px.
   Guarantee the hamburger keeps its tap target regardless of what else lands
   in the row later. */
.ui-v2 .topbar-hamburger {
  flex-shrink: 0;
}

/* ── DECIDE (the landing page) ────────────────────────────────────────────
   The attention list is the spine, so it gets the full column instead of a
   360px rail that stacked below the whole projects table under 1000px. */
.ui-v2 .v2-dash-header {
  margin-bottom: var(--space-4);
}
.ui-v2 .needs-you {
  margin-bottom: var(--space-5);
}

/* Context, not headline: one quiet strip instead of five cards competing with
   the decisions above them. Wraps rather than scrolls on a phone. */
.ui-v2 .v2-metrics {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin-bottom: var(--space-5);
}
.ui-v2 .v2-metric {
  display: flex;
  align-items: baseline;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--text-secondary);
  text-decoration: none;
}
.ui-v2 a.v2-metric:hover {
  border-color: var(--border-strong);
  background: var(--surface-hover);
}
.ui-v2 .v2-metric-label {
  font-size: var(--text-xs);
  color: var(--text-muted);
}
.ui-v2 .v2-metric-value {
  font-size: var(--text-xl);
  color: var(--text);
}
.ui-v2 .v2-timers {
  margin-bottom: var(--space-5);
}

/* ── Rows that can be resolved in place ───────────────────────────────────
   An escalation row is two-part now: the acting link, then the lane's actual
   question with its answer box. Give it enough separation that the form does
   not read as part of the row above it. */
.ui-v2 .needs-you-row--escalation {
  display: block;
  border-left: 2px solid var(--danger-border);
}
.ui-v2 .needs-you-escalation-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
}
.ui-v2 .needs-you-escalation-head .dash-feed-main {
  text-decoration: none;
}
.ui-v2 .needs-you-row--escalation .lane-prompt {
  margin-top: var(--space-3);
}

/* Ship is the most consequential button on the page — it merges a PR and
   deploys. Styled as a deliberate act, and it carries a turbo_confirm. */
.ui-v2 .v2-ship-form {
  display: inline;
}
.ui-v2 .v2-ship-btn {
  padding: 3px 10px;
  border: 1px solid var(--success-border);
  border-radius: var(--radius-sm);
  background: var(--success-tint);
  color: var(--success-chip);
  font-size: var(--text-xs);
  font-weight: 500;
  cursor: pointer;
  white-space: nowrap;
}
.ui-v2 .v2-ship-btn:hover {
  border-color: var(--success);
  color: var(--success);
}

/* ── THE closed state vocabulary (§3.2) ───────────────────────────────────
   .state is the ONLY class allowed to colour a task state. Its variants are
   enumerated from Task::BOARD_STATES, so adding a state means adding a case to
   one method and one rule here — not inventing another badge family.

   Three orthogonal families survive alongside it because they are genuinely
   different axes: .label-chip (Ali's own labels), .metric-chip (measurements),
   and the CI chips (third-party GitHub truth). Priority is the card border. */
.ui-v2 .state {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 2px 8px;
  border-radius: 999px;
  font-size: var(--text-2xs);
  font-weight: 500;
  letter-spacing: var(--tracking-tight);
  white-space: nowrap;
}
.ui-v2 .state--needs-you { background: var(--danger-tint);  color: var(--danger-chip); }
.ui-v2 .state--working   { background: var(--accent-tint);  color: var(--accent); }
.ui-v2 .state--waiting   { background: var(--info-tint);    color: var(--info-chip); }
.ui-v2 .state--held      { background: var(--violet-tint);  color: var(--violet-chip); }
.ui-v2 .state--done      { background: var(--success-tint); color: var(--success-chip); }

/* Measurements, not states — quiet by default, loud only when overdue. */
.ui-v2 .metric-chip {
  display: inline-flex;
  align-items: center;
  padding: 1px 6px;
  border-radius: var(--radius-xs);
  background: var(--surface-chip);
  color: var(--text-muted);
  font-size: var(--text-2xs);
}
.ui-v2 .metric-chip--overdue {
  background: var(--danger-tint);
  color: var(--danger-chip);
}

/* ── Board card ───────────────────────────────────────────────────────────
   Priority stops being a chip competing with state and becomes the card's left
   edge — always present, never in the way, readable at a glance down a column. */
.ui-v2 .v2-card {
  border-left: 2px solid var(--border-strong);
}
.ui-v2 .v2-card--low    { border-left-color: var(--text-ghost); }
.ui-v2 .v2-card--medium { border-left-color: var(--info); }
.ui-v2 .v2-card--high   { border-left-color: var(--warning); }
.ui-v2 .v2-card--urgent { border-left-color: var(--danger); }

.ui-v2 .v2-card-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  min-height: 20px;
}
.ui-v2 .v2-card-metrics {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1);
  margin-top: var(--space-2);
}

/* ── Task detail ──────────────────────────────────────────────────────────
   v1's aside was 16 blocks, 8 unconditional, with things you can DO sitting in
   the same visual weight as things you can only READ — so Release-a-tripped-
   circuit was below the project deadline. v2 pins the actions above the fold
   and folds every fact into one disclosure. */
.ui-v2 .v2-task {
  max-width: 900px;
}
/* The action strip (Ali, 2026-07-31). It used to lay every cell out as
   label-beside-control on one centred line, which had three problems: the
   micro-labels floated at mid-height where they were hard to scan and
   ambiguous about what they labelled; a cell with two controls (a pill AND a
   button) silently doubled a cell's width and pushed its neighbours onto a new
   row; and the invoice cell — a v1 sidebar block with its own <h3> — read as a
   section header among fields.

   Now every cell is label-over-control: the label takes a full flex line
   (flex-basis 100%), so the controls always start beneath it. That gives one
   scan line of labels and one of controls, keeps a two-control cell from
   disturbing the row, and needs no markup change to the existing cells. */
.ui-v2 .v2-actions {
  /* A grid, not flex-wrap: with flex the second row's cells line up under the
     first only by coincidence of content width, so one longer button label
     makes the whole strip go ragged. auto-fit columns keep the alignment
     intentional, collapse to fewer columns as the viewport narrows, and reach
     one column on a phone with no media query. */
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  align-items: start;
  gap: var(--space-4) var(--space-5);
  padding: var(--space-4);
  margin-bottom: var(--space-5);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--surface);
}
/* The alarm spans the full width — a tripped circuit is not one field among
   several, and it carries two buttons of its own. */
.ui-v2 .v2-actions .v2-action--urgent { grid-column: 1 / -1; }
.ui-v2 .v2-action {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
}
.ui-v2 .v2-action-label {
  flex: 0 0 100%;          /* forces the controls onto their own line */
  font-size: var(--text-2xs);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-muted);
  white-space: nowrap;
}
/* A tripped circuit is the most blocking state a task can be in — it should
   read as an alarm, not as another field. */
.ui-v2 .v2-action--urgent {
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--danger-border);
  border-radius: var(--radius-sm);
  background: var(--danger-tint);
}
.ui-v2 .v2-action--urgent .v2-action-label { color: var(--danger-chip); }

/* Priority survives as a word here (the board uses the card border), but it is
   metadata — never the same weight as the state chip beside it. */
.ui-v2 .v2-task-priority {
  font-size: var(--text-2xs);
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: var(--tracking-caps);
}
.ui-v2 .v2-task-priority--urgent { color: var(--danger-chip); }
.ui-v2 .v2-task-priority--high   { color: var(--warning-chip); }

.ui-v2 .v2-details {
  margin-top: var(--space-6);
  border-top: 1px solid var(--border);
  padding-top: var(--space-4);
}
.ui-v2 .v2-details-summary {
  cursor: pointer;
  font-size: var(--text-sm);
  color: var(--text-secondary);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
}
.ui-v2 .v2-details-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: var(--space-4);
  margin-top: var(--space-4);
}

/* The chat thread goes to the client; say so, mirroring the three markers the
   internal notes box already carries directly above it. */
.ui-v2 .v2-chat-client-badge {
  display: inline-flex;
  align-items: center;
  padding: 2px 8px;
  border: 1px solid var(--info-border);
  border-radius: 999px;
  background: var(--info-tint);
  color: var(--info-chip);
  font-size: var(--text-2xs);
  white-space: nowrap;
}

/* ── Fleet: one surface, four tabs (§2.3) ─────────────────────────────────
   Six flat nav siblings encoded no cadence — a continuously-watched surface, a
   monthly model catalog and a mint-time preset editor all demanded the same
   daily scan. */
.ui-v2 .v2-tabs {
  display: flex;
  align-items: center;
  gap: var(--space-1);
  margin-bottom: var(--space-5);
  border-bottom: 1px solid var(--border);
  overflow-x: auto;
}
.ui-v2 .v2-tab {
  padding: var(--space-2) var(--space-3);
  border-bottom: 2px solid transparent;
  color: var(--text-muted);
  font-size: var(--text-base);
  text-decoration: none;
  white-space: nowrap;
}
.ui-v2 .v2-tab:hover { color: var(--text-secondary); }
.ui-v2 .v2-tab.is-active {
  border-bottom-color: var(--accent);
  color: var(--text);
}
.ui-v2 .v2-tabs-action {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin-left: auto;
  padding-bottom: var(--space-2);
}
/* The absorbed pages. Quieter than the primary tabs — they are a second level,
   not a competing one — but present, because a tab that claims a page without
   linking to it has simply deleted that page from the navigation. */
.ui-v2 .v2-subtabs {
  display: flex;
  gap: var(--space-3);
  margin: calc(var(--space-5) * -1) 0 var(--space-5);
  padding-top: var(--space-2);
}
.ui-v2 .v2-subtab {
  color: var(--text-muted);
  font-size: var(--text-sm);
  text-decoration: none;
  white-space: nowrap;
}
.ui-v2 .v2-subtab:hover { color: var(--text-secondary); }
.ui-v2 .v2-subtab.is-active {
  color: var(--accent);
  text-decoration: underline;
  text-underline-offset: 3px;
}

.ui-v2 .v2-global-frozen {
  padding: 2px 8px;
  border-radius: 999px;
  background: var(--danger-tint);
  color: var(--danger-chip);
  font-size: var(--text-2xs);
  font-weight: 600;
  letter-spacing: var(--tracking-caps);
  white-space: nowrap;
}

/* ── Tokenising the fleet pages ───────────────────────────────────────────
   Those pages carry inline <style> blocks with hardcoded GitHub-Primer
   LIGHT-mode hexes (#2ea043, #e0a800, #d1242f, #1a7f37 …) that never touch
   tokens.css — the mechanism by which the design system stopped being
   load-bearing. Measured against the tint they sit on those run 2.71–3.44:1;
   the chip tokens run 7.9–10.3:1, and the worst offender is "needs changes",
   the badge Ali most needs to spot.

   These rules do NOT delete the inline blocks — they out-specify them
   (.ui-v2 .lane beats .lane), so v1 keeps its colours and nothing breaks. The
   dead <style> blocks get removed in step 9, once v1 goes away. */
.ui-v2 .lane {
  border-color: var(--border);
  border-radius: var(--radius-md);
  background: var(--surface);
}
.ui-v2 .lane--waiting {
  border-color: var(--warning-border);
  background: var(--warning-tint);
}
.ui-v2 .lane-dot--running { background: var(--success); }
.ui-v2 .lane-dot--waiting { background: var(--warning); }
.ui-v2 .lane-dot--idle    { background: var(--text-dim); }
.ui-v2 .lane-dot--error   { background: var(--danger); }
.ui-v2 .lane-dot--dead    { background: var(--text-ghost); }
.ui-v2 .lane-prompt {
  background: var(--surface-raised);
  /* #191: full shorthand, not `border-color` alone — a color with no inherited
     border-style paints nothing if the base rule ever fails to load first. */
  border: 1px solid var(--warning-border);
}
.ui-v2 .lane-prompt strong { color: var(--warning-chip); }
.ui-v2 .lane-stale {
  color: var(--danger-chip);
  border-color: var(--danger-border);
}
.ui-v2 .fleet {
  border-color: var(--border);
  border-radius: var(--radius-md);
}
.ui-v2 .fleet--frozen {
  border-color: var(--danger-border);
  background: var(--danger-tint);
}
.ui-v2 .badge-frozen {
  background: var(--danger-tint);
  color: var(--danger-chip);
}
.ui-v2 .fleet-spend--over { color: var(--danger-chip); }
.ui-v2 .tower-needs-you   { color: var(--warning-chip); }

/* ── Triage (§ step 6) ────────────────────────────────────────────────────
   The pipeline chips do the filtering now, so they have to LOOK clickable —
   in v1 they were <span>s showing counts while a separate select did the work,
   which is the wrong control looking like the right one. */
.ui-v2 .v2-pipeline {
  flex-wrap: wrap;
  gap: var(--space-2);
}
.ui-v2 .v2-pipeline-chip {
  border: 1px solid var(--border);
  border-radius: 999px;
  color: var(--text-secondary);
  text-decoration: none;
  cursor: pointer;
}
.ui-v2 .v2-pipeline-chip:hover {
  border-color: var(--border-strong);
  background: var(--surface-hover);
}
.ui-v2 .v2-pipeline-chip.is-active {
  border-color: var(--accent-border);
  background: var(--accent-soft);
  color: var(--accent);
}
.ui-v2 .v2-pipeline-clear {
  font-size: var(--text-xs);
  color: var(--text-muted);
}

/* The dispatch decision. Boxed because it is a decision, not a field — this
   priority orders the whole fleet queue the moment the report is accepted. */
.ui-v2 .v2-accept {
  display: flex;
  align-items: flex-end;
  gap: var(--space-3);
  padding: var(--space-3);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius);
  background: var(--surface-raised);
}
.ui-v2 .v2-accept-priority {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.ui-v2 .v2-accept-hint {
  font-size: var(--text-2xs);
  color: var(--text-muted);
}

/* ── Projects index (§ step 7) ────────────────────────────────────────────
   Five columns; the readiness one is the reason the page exists. Styled here
   rather than in a page stylesheet because it is a v2-only screen. */
.ui-v2 .v2-projects-table .dash-table-head,
.ui-v2 .v2-projects-row {
  grid-template-columns: 2fr 1.2fr 1.8fr 0.6fr 0.7fr;
}
.ui-v2 .v2-readiness {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-1);
}
.ui-v2 .v2-readiness-hold {
  padding: 1px 6px;
  border-radius: var(--radius-xs);
  background: var(--warning-tint);
  color: var(--warning-chip);
  font-size: var(--text-2xs);
  white-space: nowrap;
}
.ui-v2 .v2-projects-settings {
  font-size: var(--text-xs);
  color: var(--accent);
  text-decoration: none;
}
.ui-v2 .v2-projects-settings:hover { text-decoration: underline; }

@media (max-width: 900px) {
  /* The table collapses to stacked rows rather than scrolling sideways — this
     is a page you check on a phone. */
  .ui-v2 .v2-projects-table .dash-table-head { display: none; }
  .ui-v2 .v2-projects-row {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: var(--space-2);
  }
}

/* ── Search palette (§ step 8) ────────────────────────────────────────────
   Keyboard selection needs a visible cursor, or arrowing is invisible. Not
   scoped to .ui-v2: the keyboard nav is additive behaviour that v1 gets too,
   so the selected style has to work there as well. */
.search-result.is-selected {
  background: var(--accent-soft);
  outline: 1px solid var(--accent-border);
  outline-offset: -1px;
}
.search-more {
  display: block;
  padding: var(--space-1) var(--space-3);
  color: var(--text-faint);
  font-size: var(--text-2xs);
}
.ui-v2 .search-result--jump .search-result-title .mono { color: var(--accent); }
.ui-v2 .search-result .state { margin-left: auto; }

@media (max-width: 480px) {
  /* Two metrics per row rather than a four-wide squeeze. */
  .ui-v2 .v2-metric { flex: 1 1 calc(50% - var(--space-2)); }

  /* The escalation head stacks so the title keeps a readable measure and the
     badges do not push it to two characters per line. */
  .ui-v2 .needs-you-escalation-head {
    flex-direction: column;
    align-items: flex-start;
    gap: var(--space-1);
  }
}
