/* ═══════════════════════════════════════════════════════════════════════════
   NEXUS THEME — maps USWDS COMPONENTS onto the Nexus tokens.

   USWDS stays for the components: buttons, form controls, accordions, tables,
   sidenav, alerts, focus rings, ARIA behaviour. None of that markup changes.
   This file only re-points its colour, type and elevation.

   NO LITERAL COLOUR HERE by construction — every value is a token from
   tokens.css, which lint-banned.sh enforces as the single definition site.
   ═══════════════════════════════════════════════════════════════════════════ */

html, body {
  background: var(--nx-bg); color: var(--nx-ink);
  font-family: var(--nx-font);
  -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;
}
body, .usa-prose, p, li, td, th, label, .usa-label { font-family: var(--nx-font); }
code, kbd, pre, .font-mono, [class*="font-mono"] { font-family: var(--nx-font-mono); }

/* headings: tighter tracking is what separates a console from a document */
h1, h2, h3, h4, .usa-summary-box__heading {
  font-family: var(--nx-font); color: var(--nx-ink); letter-spacing: -.02em; font-weight: 600;
}
h1 { font-size: 1.35rem; }

/* every figure in a console is compared to another figure */
.nx-count, .usa-summary-box__heading, kpi-tile, td, .font-heading-lg, [data-count] {
  font-variant-numeric: tabular-nums;
}

/* ── ink ─────────────────────────────────────────────────────────────────── */
.text-base, .text-base-dark, .text-base-darker { color: var(--nx-ink-2) !important; }
.text-base-light, .text-base-lighter, .text-base-lightest { color: var(--nx-ink-3) !important; }
.text-ink, .text-black { color: var(--nx-ink) !important; }

/* ── surfaces: hairline borders, no drop shadows. shadows are what date a UI ── */
.usa-card__container, .usa-summary-box, .usa-accordion__content, .usa-table, .usa-alert {
  background: var(--nx-surface); border: 1px solid var(--nx-line);
  border-radius: var(--nx-radius); box-shadow: none; color: var(--nx-ink);
}
.bg-base-lightest, .bg-base-lighter, .bg-white { background: var(--nx-surface-2) !important; }
.usa-accordion__button {
  background: var(--nx-surface-2); color: var(--nx-ink);
  border-radius: var(--nx-radius-sm); font-family: var(--nx-font); font-weight: 550;
}
.usa-accordion__button:hover { background: var(--nx-line); }
.usa-table thead th { background: var(--nx-surface-2); color: var(--nx-ink-2); }
.usa-table td, .usa-table th { border-color: var(--nx-line); }

.border-base-lightest, .border-base-lighter, .border-bottom, .border-top,
.usa-card__container { border-color: var(--nx-line) !important; }

/* ── semantic fills: colour appears only where it carries meaning ────────── */
.bg-success-lighter { background: var(--nx-ok-dim) !important;   color: var(--nx-ok) !important; }
.bg-warning-lighter { background: var(--nx-warn-dim) !important; color: var(--nx-warn) !important; }
.bg-error-lighter   { background: var(--nx-bad-dim) !important;  color: var(--nx-bad) !important; }
.bg-info-lighter    { background: var(--nx-info-dim) !important; color: var(--nx-info) !important; }
.text-success, .text-success-dark, .text-success-darker, .text-green { color: var(--nx-ok) !important; }
.text-warning, .text-gold, .text-orange { color: var(--nx-warn) !important; }
.text-error, .text-error-dark, .text-error-darker, .text-red { color: var(--nx-bad) !important; }
.text-primary, .text-primary-dark { color: var(--nx-accent) !important; }
.bg-success { background: var(--nx-ok) !important; }
.bg-warning { background: var(--nx-warn) !important; }
.bg-error   { background: var(--nx-bad) !important; }

/* ── alerts keep USWDS structure and behaviour, take our tone ────────────── */
.usa-alert { border-left: 3px solid var(--nx-line-2); }
.usa-alert--info    { background: var(--nx-info-dim); border-left-color: var(--nx-info); }
.usa-alert--success { background: var(--nx-ok-dim);   border-left-color: var(--nx-ok); }
.usa-alert--warning { background: var(--nx-warn-dim); border-left-color: var(--nx-warn); }
.usa-alert--error   { background: var(--nx-bad-dim);  border-left-color: var(--nx-bad); }
.usa-alert__text, .usa-alert__heading { color: var(--nx-ink); }

/* ── navigation ──────────────────────────────────────────────────────────── */
.usa-sidenav, .usa-sidenav__item { background: transparent; border-color: var(--nx-line); }
.usa-sidenav a, .nav-link {
  color: var(--nx-ink-2); border-radius: var(--nx-radius-sm); border-left: 0;
  font-size: .93rem; padding: .35rem .65rem;
}
.usa-sidenav a:hover, .nav-link:hover {
  background: var(--nx-surface-2); color: var(--nx-ink); text-decoration: none;
}
.usa-sidenav a.usa-current, .nav-link.usa-current, .nav-link[aria-current] {
  color: var(--nx-accent); background: var(--nx-accent-dim); font-weight: 550;
}
.nav-group { color: var(--nx-ink-3) !important; letter-spacing: .08em; }
.usa-header, .usa-banner, header { background: var(--nx-surface); border-bottom: 1px solid var(--nx-line); }

/* ── controls ────────────────────────────────────────────────────────────── */
.usa-button {
  background: var(--nx-accent); color: var(--nx-accent-ink);
  border-radius: var(--nx-radius-sm); font-family: var(--nx-font); font-weight: 550;
}
.usa-button:hover { background: var(--nx-ink); }
.usa-button--unstyled { color: var(--nx-accent); background: transparent; }
.usa-button--outline {
  background: transparent; color: var(--nx-accent); box-shadow: inset 0 0 0 1px var(--nx-line-2);
}
.usa-input, .usa-select, .usa-textarea {
  background: var(--nx-surface-2); color: var(--nx-ink);
  border: 1px solid var(--nx-line-2); border-radius: var(--nx-radius-sm);
  font-family: var(--nx-font);
}
.usa-input:focus, .usa-select:focus, .usa-button:focus, a:focus {
  outline: 2px solid var(--nx-accent); outline-offset: 2px;
}

/* ── the lively layer reads these ────────────────────────────────────────── */
.nx-meter { background: var(--nx-line-2); color: var(--nx-accent); opacity: 1; height: .3rem; }
.nx-meter > i { background: currentColor; }
.nx-lift:hover { box-shadow: none; border-color: var(--nx-line-2); transform: translateY(-1px); }
.nx-dot { background: currentColor; }

/* ═══ merged from app.css — shell density + skeleton ═══════════════════════ */
html.nx-compact { font-size: 93.75%; }
.cursor-pointer { cursor: pointer; }
/* N1-3 <data-state> loading: USWDS bg colour, opacity-only pulse (no colour/typeface value). */
.nx-skeleton { animation: nx-pulse 1.4s ease-in-out infinite; }
@keyframes nx-pulse { 50% { opacity: .45; } }

/* ═══ merged from nx-live.css — the motion layer ═══════════════════════════ */

/* ---- entry: sections and their children arrive, they do not just appear (mock @keyframes fade) */
@keyframes nx-fade { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
.nx-enter { animation: nx-fade .22s ease both; }
.nx-stagger > * { animation: nx-fade .26s ease both; }
.nx-stagger > *:nth-child(1) { animation-delay: .02s } .nx-stagger > *:nth-child(2) { animation-delay: .06s }
.nx-stagger > *:nth-child(3) { animation-delay: .10s } .nx-stagger > *:nth-child(4) { animation-delay: .14s }
.nx-stagger > *:nth-child(5) { animation-delay: .18s } .nx-stagger > *:nth-child(6) { animation-delay: .22s }
.nx-stagger > *:nth-child(7) { animation-delay: .26s } .nx-stagger > *:nth-child(8) { animation-delay: .30s }

/* ---- live: a heartbeat you can see. Only ever attached to a genuinely live reading. */
@keyframes nx-blink { 50% { opacity: .25; } }
.nx-dot { display:inline-block; width:.5rem; height:.5rem; border-radius:50%; background:currentColor;
          vertical-align:middle; margin-right:.25rem; }
.nx-dot--live { animation: nx-blink 1.6s ease-in-out infinite; }
@keyframes nx-ring { 0% { box-shadow:0 0 0 0 currentColor; opacity:.55 } 70% { box-shadow:0 0 0 .55rem currentColor; opacity:0 } 100% { opacity:0 } }
.nx-pulse::after { content:""; position:absolute; inset:0; border-radius:inherit; animation:nx-ring 2s ease-out infinite; pointer-events:none; }
.nx-pulse { position:relative; }

/* ---- depth + hover lift (mock: nav.side a:hover box-shadow) */
.nx-lift { transition: transform .18s ease, box-shadow .18s ease; }
.nx-lift:hover { transform: translateY(-2px); box-shadow: 0 .5rem 1rem rgba(0,0,0,.13); }

/* ---- meters: a bar that fills tells a story a bare number cannot. Width is set from real data. */
.nx-meter { height:.5rem; border-radius:.25rem; background:currentColor; opacity:.16; overflow:hidden; }
.nx-meter > i { display:block; height:100%; border-radius:.25rem; background:currentColor; opacity:1;
                width:0; transition: width .9s cubic-bezier(.22,.61,.36,1); }

/* ---- sparkline strokes draw themselves */
.nx-spark path { stroke-dasharray: 260; stroke-dashoffset: 260; animation: nx-draw 1.1s ease forwards; }
@keyframes nx-draw { to { stroke-dashoffset: 0; } }

/* ---- number roll: the count-up target. JS writes the value; this only smooths it. */
.nx-count { font-variant-numeric: tabular-nums; }

/* ---- accent rail on cards, tone supplied by a USWDS text-* class on the element */
.nx-rail { border-left:.25rem solid currentColor; }

/* ---- skeleton shimmer while a surface is still reading */
@keyframes nx-shimmer { 100% { transform: translateX(100%); } }
.nx-shim { position:relative; overflow:hidden; }
.nx-shim::after { content:""; position:absolute; inset:0; transform:translateX(-100%);
  background:linear-gradient(90deg, transparent, rgba(255,255,255,.45), transparent);
  animation: nx-shimmer 1.5s infinite; }

@media (prefers-reduced-motion: reduce) {
  .nx-enter, .nx-stagger > *, .nx-dot--live, .nx-pulse::after, .nx-spark path, .nx-shim::after { animation: none !important; }
  .nx-meter > i { transition: none !important; }
  .nx-lift { transition: none !important; }
  .nx-lift:hover { transform: none; }
  .nx-spark path { stroke-dashoffset: 0; }
}

/* ═══ font: override every selector where USWDS sets font-family itself ═══════
   Load order only wins where a matching selector EXISTS. USWDS sets font-family
   directly on cards, alerts, accordions, forms and nav, so without these the
   page would be IBM Plex on body and headings and Public Sans inside every
   card - the font "not reflecting", half-applied and easy to miss.
   Enumerated from the vendored uswds.min.css, not guessed. */
.usa-accordion, .usa-accordion__heading, .usa-alert .usa-alert__body,
.usa-alert .usa-alert__heading, .usa-button, .usa-card__container, .usa-card__heading,
.usa-checkbox__label, .usa-checklist, .usa-combo-box__input, .usa-combo-box__list,
.usa-display, .usa-fieldset, .usa-form, .usa-form__note, .usa-header, .usa-hint,
.usa-input, .usa-input-group, .usa-intro, .usa-label, .usa-legend, .usa-modal,
.usa-modal__heading, .usa-nav, .usa-pagination, .usa-process-list,
.usa-process-list__heading, .usa-prose, .usa-summary-box, .usa-summary-box__heading,
.usa-table, .usa-tag, .usa-sidenav, .usa-tooltip__body,
.font-family-body, .font-family-heading, .font-family-sans, .font-family-ui, .font-family-alt {
  font-family: var(--nx-font);
}
.font-family-mono, .font-family-code, code, kbd, pre, samp {
  font-family: var(--nx-font-mono);
}

/* usa-tag: USWDS ships it as a LIGHT grey chip with near-black text. Readable, but a pale pill
   on a dark console is obviously off-theme. Re-toned to the surface ramp: 7.43:1, passes AA. */
.usa-tag {
  background-color: var(--nx-surface-2); color: var(--nx-ink-2);
  border: 1px solid var(--nx-line); border-radius: var(--nx-radius-sm);
  font-family: var(--nx-font); font-weight: 500;
}

/* ═══ links and chrome USWDS styles that the theme had missed ═════════════════
   Found by lint-theme-coverage, and it was an ACCESSIBILITY defect I introduced:
   the USWDS link blue scores 2.87:1 on this page and its visited purple 1.90:1 -
   both well under AA. They are tuned for a white background. Every link on the
   site would have failed, invisibly to me. */
.usa-link, a:not(.usa-button):not(.nav-link) { color: var(--nx-accent); }        /* 7.57:1 */
.usa-link:visited, a:not(.usa-button):not(.nav-link):visited { color: var(--nx-visited); } /* 9.40:1 */
.usa-link:hover, a:not(.usa-button):not(.nav-link):hover { color: var(--nx-ink); }
.usa-skipnav { background: var(--nx-surface-2); color: var(--nx-accent); }
.usa-menu-btn { background: var(--nx-accent); color: var(--nx-accent-ink); }
.usa-breadcrumb { background: transparent; color: var(--nx-ink-2); }

/* ═══ collapsible sidebar ═════════════════════════════════════════════════════
   USWDS hides .usa-menu-btn above 64em because it is built for a mobile nav
   pattern. On a desktop console that leaves the sidebar as a permanent tile with
   no way to reclaim the width - and no visible control at all, which reads as
   "nothing works". app.js already had the toggle handler; the button it binds to
   was simply invisible. */
.usa-menu-btn {
  display: inline-flex !important; align-items: center; gap: .5rem;
  background: transparent !important; color: var(--nx-ink-2) !important;
  border: 1px solid var(--nx-line); border-radius: var(--nx-radius-sm);
  padding: .3rem .6rem; font-family: var(--nx-font); font-size: .8rem; cursor: pointer;
}
.usa-menu-btn:hover { background: var(--nx-surface-2); color: var(--nx-ink) !important; }
.usa-menu-btn::before {                       /* the hamburger itself, drawn not imported */
  content: ""; width: 14px; height: 10px; flex: 0 0 14px;
  border-top: 2px solid currentColor; border-bottom: 2px solid currentColor;
  box-shadow: inset 0 0 0 1px transparent; position: relative;
}
.usa-menu-btn::after {
  content: ""; width: 14px; height: 2px; background: currentColor;
  margin-left: -22px; align-self: center;     /* the middle bar */
}

/* reclaim the width when the nav is collapsed - otherwise the column just goes blank */
.grid-row:has(> #sidenav-wrap.display-none) > #main-content {
  flex: 0 0 100%; max-width: 100%;
}

/* Wordmark reads as a wordmark, not as a link. The broad a:not(...) accent rule caught it because
   the anchor carries no class, so the product name rendered in the same colour as every link on the
   page - hierarchy flattened by a rule written for something else. */
.usa-logo__text a, .usa-logo a { color: var(--nx-ink); text-decoration: none; font-weight: 600; }
.usa-logo__text a:hover, .usa-logo a:hover { color: var(--nx-accent); }


/* ── moved out of components.js's runtime <style> injector ────────────────────────────────────
   Those rules were appended to <head> at module load, so they overrode BOTH stylesheets. The
   colour half of that block was a light-mode palette beating the dark one; it is gone. These four
   are layout and semantic-segment fills, and they belong in CSS. */
.nx-seg-wait { background-color: var(--nx-wait) !important; }
.nx-seg-gap  { background-color: var(--nx-gap)  !important; }
/* the shared wrapper is layout-transparent so the label centres in every context */
nx-button { display: contents; }
.usa-button { display: inline-flex; align-items: center; justify-content: center; text-align: center; }


/* ── OUTRANKED AND OVERPAINTED ────────────────────────────────────────────────────────────────
   Found by rendering in a real browser: three places where the theme was correct and still lost.

   1. USWDS ships `.usa-sidenav a:not(.usa-button):not(.usa-current)` at specificity (0,3,1). The
      rule above is (0,1,1), so nav links rendered in USWDS grey on the page background at
      2.86:1, under the 4.5 needed. Matching the specificity is the whole fix.
   2 & 3. USWDS PAINTS THE CHILD, not the element I themed: `.usa-alert--info .usa-alert__body`
      and `.usa-table td` carry their own pale backgrounds, so a dark parent sat underneath a light
      slab with light text on it - 1.05:1, invisible.

   lint-theme-targets passed all three: it checks that an override AIMS at a real USWDS class, not
   that it WINS. Aim and outcome are different questions. */
.usa-sidenav a:not(.usa-button):not(.usa-current),
.nav-link:not(.usa-current) { color: var(--nx-ink-2); }

.usa-alert__body { background: transparent; color: var(--nx-ink); }
.usa-alert--info .usa-alert__body    { background: var(--nx-info-dim); }
.usa-alert--success .usa-alert__body { background: var(--nx-ok-dim); }
.usa-alert--warning .usa-alert__body { background: var(--nx-warn-dim); }
.usa-alert--error .usa-alert__body   { background: var(--nx-bad-dim); }

.usa-table td, .usa-table th { background: var(--nx-surface); color: var(--nx-ink); }
.usa-table thead th { background: var(--nx-surface-2); color: var(--nx-ink-2); }


/* ── ROWS MUST WRAP ON NARROW SCREENS ─────────────────────────────────────────────────────────
   Measured at 375px in a real browser: the document rendered 433px wide with 105 elements past the
   viewport. Worst were the session cards' Halt/Restart pairs - a display-flex row with no wrap
   cannot shrink below its content, so it pushes the whole page sideways instead of stacking.
   Twelve card bodies share this pattern and the theme set no wrap at all.
   row-gap only: wrapped rows need vertical breathing space, and touching column-gap would change
   desktop spacing that is already correct. */
.display-flex.flex-justify,
.display-flex.flex-justify-end { flex-wrap: wrap; row-gap: .35rem; }

/* Long unbroken strings - task titles, tree hashes, actor ids - ran up to 200px past their box at
   375px. break-word only splits when a word genuinely cannot fit, so ordinary prose is untouched. */
.usa-card__container, .usa-alert__body, td, th, p, li, span { overflow-wrap: break-word; }

/* Tables cannot shrink below their columns. On narrow screens let the TABLE scroll inside its own
   box rather than clipping cells or widening the page - the reader can still reach every column. */
@media (max-width: 40em) {
  .usa-table { display: block; overflow-x: auto; -webkit-overflow-scrolling: touch; }
}

/* A flex item defaults to min-width:auto, so it refuses to shrink below its content and overhangs
   its row - the last two overflows at 375px were session-card metadata doing exactly that.
   min-width:0 lets them shrink so the break-word above can act. */
.display-flex.flex-justify > *,
.display-flex.flex-justify-end > * { min-width: 0; }
