/* Dev Manager styles. Every colour, size and duration comes from tokens.css; the rules each
   component follows are in WslTray/DESIGN.md, and ui/kit.html shows them all.
   Hover and focus selectors also match .is-hover / .is-focus so the kit can show those states. */

/* --- Base --------------------------------------------------------------------------------- */
* { box-sizing: border-box; }
[hidden] { display: none !important; }
html, body { height: 100%; margin: 0; overflow: hidden; }  /* only main and the sidebar's list scroll */
body {
  display: flex;
  background: var(--bg);
  color: var(--text);
  font: var(--fs-body)/var(--lh-body) "Segoe UI Variable Text", "Segoe UI", system-ui, sans-serif;
  -webkit-font-smoothing: antialiased;
  user-select: none;
  text-wrap: pretty;   /* no orphan lines: a paragraph that wraps never ends on one short word */
}
h1, h2, h3, h4 { margin: 0; font-weight: 600; }
h1 { font-size: var(--fs-page); letter-spacing: -.01em; line-height: var(--lh-page); }
h2, h3 { font-size: var(--fs-title); line-height: var(--lh-title); color: var(--text); }
button { font: inherit; color: inherit; }
input, select { font: inherit; color: var(--text); }
pre { margin: 0; font: var(--fs-meta)/1.5 "Cascadia Mono", Consolas, monospace; white-space: pre-wrap; word-break: break-word; user-select: text; }
code, .mono { font-family: ui-monospace, "Cascadia Mono", Consolas, monospace; }
svg { fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.ds-icon { width: 16px; height: 16px; flex: none; vertical-align: -3px; }
.ds-mark { stroke-width: 2.2; }   /* state glyphs: a firmer stroke, so they render at their token's colour */
.spin { animation: spin 1s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }

/* One focus ring for everything you can reach with the keyboard. */
:focus-visible, .is-focus { outline: 2px solid var(--focus); outline-offset: 2px; }
input:focus-visible, select:focus-visible { outline-offset: 0; border-color: var(--focus); }

@media (prefers-reduced-motion: reduce) {
  *, ::before, ::after { animation-duration: .01ms !important; animation-iteration-count: 1 !important; transition-duration: .01ms !important; scroll-behavior: auto !important; }
  .progress.indeterminate i { animation: none; width: 100%; opacity: .5; }
}

/* Scrollbars: thin, themed, and always reserved in main so nothing shifts when one appears. */
::-webkit-scrollbar { width: 12px; height: 12px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--scroll-thumb); border: 3px solid transparent; background-clip: content-box; border-radius: var(--r-pill); }
::-webkit-scrollbar-thumb:hover { background-color: var(--scroll-thumb-hover); }

/* --- Sidebar ------------------------------------------------------------------------------- */
.nav { width: 224px; flex: none; background: var(--nav); border-right: 1px solid var(--border-subtle); display: flex; flex-direction: column; padding: var(--sp-5) var(--sp-3) var(--sp-4); }
.brand { display: flex; gap: var(--sp-3); align-items: center; padding: 0 var(--sp-2) var(--sp-4); }
.logo { width: 34px; height: 34px; border-radius: var(--r-panel); background: var(--accent); color: var(--on-accent); display: grid; place-items: center; }
.logo svg { width: 22px; height: 22px; stroke-width: 2.4; }
.brand-name { font-weight: 600; }
.brand-sub { font-size: var(--fs-meta); line-height: var(--lh-meta); color: var(--muted); }
nav { display: flex; flex-direction: column; gap: 2px; flex: 1 1 auto; min-height: 0; overflow-y: auto; scrollbar-width: none; }
.nav-item { display: flex; align-items: center; gap: var(--sp-3); min-height: var(--ctl-h-md); padding: 0 10px; border: 0; background: none; border-radius: var(--r-control); cursor: pointer; text-align: left; color: var(--muted); }
.nav-item svg { width: 19px; height: 19px; flex: none; }
.nav-item:is(:hover, .is-hover) { background: var(--surface-2); color: var(--text); }
.nav-item.active { background: var(--surface); color: var(--text); font-weight: 600; box-shadow: var(--shadow-1); }
.nav-item.active svg { color: var(--accent); }
.nav-group { font-size: var(--fs-label); line-height: var(--lh-label); font-weight: 600; text-transform: uppercase; letter-spacing: .07em; color: var(--text-hint); padding: var(--sp-3) 10px var(--sp-1); }
.nav-foot { margin-top: auto; display: flex; align-items: center; gap: var(--sp-2); padding: 10px; font-size: var(--fs-meta); line-height: var(--lh-meta); color: var(--muted); }
.nav-state { display: inline-flex; color: var(--text-hint); }
.nav-state.ok { color: var(--ok); } .nav-state.busy { color: var(--muted); } .nav-state.bad { color: var(--bad); }

/* CountBadge: things that need you. Amber; red when something failed; neutral for progress. */
.badge { margin-left: auto; font-style: normal; font-size: var(--fs-meta); line-height: var(--lh-meta); font-weight: 600; min-width: 20px; height: 20px; padding: 0 6px; border-radius: var(--r-pill); display: none; place-items: center; background: var(--warn-soft); color: var(--warn); }
.badge.show { display: grid; }
.badge.bad { background: var(--bad-soft); color: var(--bad); }
.badge:is(.neutral, .busy) { background: var(--idle-soft); color: var(--muted); }

/* --- Main column ---------------------------------------------------------------------------- */
main { flex: 1; overflow-y: auto; padding: 26px 30px 40px; scrollbar-gutter: stable; }
.page { max-width: var(--col-max); margin: 0 auto; display: flex; flex-direction: column; gap: var(--gap-stack); }
.stack { display: flex; flex-direction: column; gap: var(--gap-stack); }

/* PageHead: title and toolbar on one row (the icons sit at the same x on every page), the one
   line about the page under it. */
.page-head { display: grid; grid-template-columns: minmax(0, 1fr) auto; grid-template-areas: "title tools" "sub sub"; align-items: center; column-gap: var(--sp-4); row-gap: 2px; }
.page-head h1 { grid-area: title; }
.ph-tools { grid-area: tools; display: flex; align-items: center; gap: var(--sp-1); }
.ph-primary { display: flex; align-items: center; margin-right: var(--sp-2); }
.ph-primary:empty { display: none; }
.ph-sub { grid-area: sub; display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-1) var(--sp-3); min-height: 24px; }
.ph-meta { margin: 0; color: var(--muted); max-width: 90ch; }
.ph-meta b { color: var(--text); font-weight: 600; }
.ph-meta .pill { margin: 0 2px; }
.ph-extra { display: inline-flex; align-items: center; gap: 2px; }

/* Toolbar icons and the folding search. */
.tool-icon { width: var(--ctl-h-md); height: var(--ctl-h-md); padding: 0; display: inline-grid; place-items: center; border-radius: var(--r-control); color: var(--muted); flex: none; }
.tool-icon.sm { width: var(--ctl-h-sm); height: var(--ctl-h-sm); }
.tool-icon svg { width: 19px; height: 19px; }
.tool-icon.sm svg { width: 16px; height: 16px; }
.tool-icon:is(:hover, .is-hover):not(:disabled) { background: var(--surface-2); color: var(--text); }
.tool-icon:disabled { cursor: default; }
.tool-icon.busy svg { animation: spin 1s linear infinite; }
.search-fold { display: flex; align-items: center; }
.search-fold input.search { width: 0; max-width: none; padding: 0; border-color: transparent; opacity: 0; transition: width var(--dur-base) var(--ease-out), opacity var(--dur-fast); }
.search-fold.open input.search { width: 260px; padding: 0 var(--sp-3); margin-right: var(--sp-1); border-color: var(--border-control); opacity: 1; }
.search-fold.open [data-search-open] { color: var(--link); }
.search { height: var(--ctl-h-md); width: 320px; max-width: 45%; padding: 0 var(--sp-3); border: 1px solid var(--border-control); border-radius: var(--r-control); background: var(--surface); color: var(--text); font: inherit; }

/* GlanceBox: up to four findings, worst first, each with at most one action. */
.glance { padding: var(--sp-2) var(--pad-card-x); border: 1px solid var(--border); border-radius: var(--r-card); background: var(--surface); box-shadow: var(--shadow-1); }
.gl-list { display: flex; flex-direction: column; }
.gl { display: flex; align-items: center; gap: var(--sp-3); min-height: var(--row-compact); font-size: var(--fs-dense); line-height: var(--lh-dense); }
.gl > .ds-mark { color: var(--text-hint); }
.gl.ok > .ds-mark { color: var(--ok); } .gl.warn > .ds-mark { color: var(--warn); } .gl.bad > .ds-mark { color: var(--bad); }
.gl .tick { color: var(--ok); }   /* the skip row's "retried 04:12 ✓": the one thing in it that went well */
.gl-text { flex: 1; min-width: 0; padding: 5px 0; }
.gl:not(.has-act) .gl-text { color: var(--muted); }
.gl:not(.has-act) .gl-text b { color: var(--text); }
.gl .btn { flex: none; }
.gl .btn.ghost { margin-right: calc(var(--sp-3) * -1); }

/* --- Cards ----------------------------------------------------------------------------------- */
.card { background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-card); padding: var(--pad-card); box-shadow: var(--shadow-1); min-width: 0; }
.card-head { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3); min-height: var(--ctl-h-sm); margin-bottom: var(--sp-3); }
.card-head > .muted.small { text-align: right; }
.card-head.untitled { justify-content: flex-end; }   /* a card that fills its tab: no title, the tab names it (#143) */
.card-actions { display: flex; align-items: center; gap: var(--sp-2); flex-wrap: wrap; margin-top: var(--sp-4); }
/* A text button at a card's edge gives back its padding, so its text lines up with the card's. */
.card-actions > .btn.ghost:first-child { margin-left: calc(var(--sp-4) * -1); }
.card-actions > .btn.ghost.small:first-child { margin-left: calc(var(--sp-3) * -1); }
.card-head > .btn.ghost:last-child { margin-right: calc(var(--sp-4) * -1); }
.card-head > .btn.ghost.small:last-child { margin-right: calc(var(--sp-3) * -1); }
.grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--gap-stack); }
.grid.two { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.span2 { grid-column: span 2; }
/* Overview: the Backup card first, full width (its figures on the left, the 30-day strip on the
   right, stacked below 980 px), its figure a step over the other cards'; then four stat cards in
   one row, each a figure, a line or a meter, and one action at its foot; then two lists. */
.hero-body { display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); gap: var(--sp-6); align-items: start; }
.card.hero .big { font-size: var(--fs-hero); line-height: var(--lh-hero); }
.grid.four { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.card.stat { display: flex; flex-direction: column; }
.card.stat > .card-actions { margin-top: auto; padding-top: var(--sp-2); }   /* the one action sits at the foot; Agents' chips stay 12 under the sentence; 8 keeps the row at 223 (#83) */
.card.stat .spark { height: 24px; margin-top: var(--sp-2); }
.card.stat > .card-actions:empty { display: none; }
/* A foot that's a fact, not an action (Agents' "Last worked 14h ago", #83): the height of the other
   cards' button feet, its text centred as their labels are, so the four feet share a baseline. */
.card.stat > .card-foot { margin-top: auto; padding-top: var(--sp-2); min-height: calc(var(--sp-2) + var(--ctl-h-md)); display: flex; flex-wrap: wrap; align-items: center; column-gap: .3em; }   /* a foot that wraps breaks between its parts (#109) */
.card.stat > .card-foot:empty { visibility: hidden; }
.keep { white-space: nowrap; }   /* a part that wraps as a whole */
.card.stat .row b { font-weight: 600; }
@media (max-width: 980px) { .hero-body { grid-template-columns: 1fr; gap: var(--sp-4); } }
@media (max-width: 980px) { .grid, .grid.four { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 760px) { .grid, .grid.two, .grid.four { grid-template-columns: 1fr; } .span2 { grid-column: auto; } }

.big { font-size: var(--fs-figure); line-height: var(--lh-figure); font-weight: 600; letter-spacing: -.01em; margin-bottom: 2px; }
.unit { font-size: var(--fs-dense); line-height: var(--lh-dense); font-weight: 400; color: var(--muted); }
.muted { color: var(--muted); }
.small { font-size: var(--fs-meta); line-height: var(--lh-meta); }
.hint { font-size: var(--fs-meta); line-height: var(--lh-meta); color: var(--text-hint); margin: 6px 0 0; }
.hint.row-note { margin: 0; }   /* a task row's quiet note, right under its description */
.ink { color: var(--text); }      /* a figure inside a muted line: "Up to 70 GB" reclaimable */
.card.stat .hint { margin: 0; }
.err { color: var(--bad); }
.when { white-space: nowrap; }
.ell { display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.clamp2 { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; }
.sub-h { font-size: var(--fs-meta); line-height: var(--lh-meta); font-weight: 600; color: var(--muted); margin: var(--sp-4) 0 var(--sp-1); }
.sub-h .btn { margin-left: var(--sp-2); font-weight: 500; }

/* --- Buttons --------------------------------------------------------------------------------- */
/* Tiers: primary (filled, one per page: in the head, or a form's own submit), secondary (outline:
   card actions), row (quiet: a row's action at rest), text (navigation), danger (outline in red;
   filled only inside a confirmation). Two heights: 34 standalone, 28 in rows and menus. Outlines
   and fields use --border-control (3:1 on a card); cards keep the quieter --border. */
.btn { display: inline-flex; align-items: center; justify-content: center; gap: 6px; height: var(--ctl-h-md); padding: 0 var(--sp-4); border: 1px solid var(--border-control); background: transparent; color: var(--text); border-radius: var(--r-control); cursor: pointer; font-weight: 500; line-height: var(--lh-body); white-space: nowrap; }
.btn:is(:hover, .is-hover):not(:disabled) { background: var(--surface-2); }
.btn.primary { background: var(--accent); border-color: var(--accent); color: var(--on-accent); font-weight: 600; }
.btn.primary:is(:hover, .is-hover):not(:disabled) { background: var(--accent-hover); border-color: var(--accent-hover); }
.btn.ghost { border-color: transparent; color: var(--link); }
.btn.ghost:is(:hover, .is-hover):not(:disabled) { background: var(--accent-soft); }
.btn.danger { color: var(--bad); border-color: var(--bad-line); }
.btn.danger:is(:hover, .is-hover):not(:disabled) { background: var(--bad-soft); }
.btn.ghost.danger { border-color: transparent; }
.btn.primary.danger-fill { background: var(--danger-fill); border-color: var(--danger-fill); color: var(--on-bad); }
.btn.primary.danger-fill:is(:hover, .is-hover):not(:disabled) { background: var(--bad-hover); border-color: var(--bad-hover); }
.btn.small { height: var(--ctl-h-sm); padding: 0 var(--sp-3); font-size: var(--fs-dense); line-height: var(--lh-dense); }
/* The quiet tier: a row's one action at rest is a verb in the link blue at regular weight, with no
   border; the border comes in when the row is hovered or holds focus, or the button itself is.
   Same for the row's "...". A destructive row action looks like the others at rest and turns red
   only then (red at rest made the riskiest click the loudest thing on the page). */
.btn.quiet, .btn.quiet.danger { border-color: transparent; color: var(--link); font-weight: 400; }
:is(tr, li, .update-row):is(:hover, :focus-within, .is-hover) .btn.quiet:not(:disabled), .btn.quiet:is(:hover, :focus-visible, .is-hover):not(:disabled) { border-color: var(--border-control); }
:is(tr, li, .update-row):is(:hover, :focus-within, .is-hover) .btn.quiet.danger:not(:disabled), .btn.quiet.danger:is(:hover, :focus-visible, .is-hover):not(:disabled) { border-color: var(--bad-line); color: var(--bad); }
.icon-btn.ds-more-btn { border: 1px solid transparent; }
:is(tr, li, .update-row):is(:hover, :focus-within, .is-hover) .ds-more-btn, .ds-more-btn:is(:hover, :focus-visible, .is-hover), .ds-more[open] > .ds-more-btn { border-color: var(--border-control); }
.btn:disabled { opacity: .45; cursor: default; }
.btn .ds-icon { width: 15px; height: 15px; }
.icon-btn { border: 0; background: none; font-size: var(--fs-page); line-height: 1; color: var(--muted); cursor: pointer; padding: 2px 6px; border-radius: var(--r-chip); }
.icon-btn:is(:hover, .is-hover) { background: var(--surface-2); color: var(--text); }
.icon-btn.tool-icon { padding: 0; font-size: inherit; }

/* --- Chips and notes ------------------------------------------------------------------------- */
/* StatusChip: a state word with its glyph. */
.pill { display: inline-flex; align-items: center; gap: var(--sp-1); font-size: var(--fs-meta); font-weight: 600; line-height: 20px; padding: 0 var(--sp-2); border-radius: var(--r-pill); background: var(--idle-soft); color: var(--muted); white-space: nowrap; vertical-align: middle; }
.pill:empty { display: none; }
.pill .ds-icon { width: 13px; height: 13px; stroke-width: 2.2; vertical-align: 0; }
.pill.ok { background: var(--ok-soft); color: var(--ok); }
.pill.warn { background: var(--warn-soft); color: var(--warn); }
.pill.bad { background: var(--bad-soft); color: var(--bad); }
/* SideChip: which machine; neutral, with the side's glyph. */
.side { display: inline-flex; align-items: center; gap: 4px; font-size: var(--fs-meta); font-weight: 500; line-height: 18px; padding: 0 6px; border-radius: var(--r-chip); background: var(--side-bg); color: var(--side-fg); border: 1px solid var(--side-border); white-space: nowrap; vertical-align: middle; }
.side .ds-icon { width: 12px; height: 12px; vertical-align: 0; }
/* Tag: a small fact (and the older chips that are facts too). Amber only for "act on this". */
.tag, .kind, .mark, .size, .used { display: inline-flex; align-items: center; gap: 4px; font-size: var(--fs-meta); font-weight: 500; line-height: 18px; padding: 0 6px; border-radius: var(--r-chip); background: var(--surface-2); color: var(--muted); white-space: nowrap; vertical-align: middle; }
.tag.warn { background: var(--warn-soft); color: var(--warn); }
.tag.ok { background: var(--ok-soft); color: var(--ok); }
.tag.bad { background: var(--bad-soft); color: var(--bad); }
.tag.mono, .mark { font-family: ui-monospace, "Cascadia Mono", Consolas, monospace; }
.tag .ds-icon, .kind .ds-icon { width: 12px; height: 12px; vertical-align: 0; }
.mark, .used { margin: 0 4px 3px 0; }
.used.warn { background: var(--warn-soft); color: var(--warn); }
.used .ds-icon { width: 12px; height: 12px; vertical-align: 0; }
.chips { display: flex; flex-wrap: wrap; gap: 6px; margin-top: var(--sp-3); }
.chips span { background: var(--surface-2); border-radius: var(--r-chip); padding: 2px var(--sp-2); font-size: var(--fs-meta); line-height: var(--lh-meta); }
.chips.small span { padding: 1px 6px; }
.chips.tight { margin-top: 0; gap: var(--sp-1); }
.chips.tight span { overflow-wrap: anywhere; max-width: 100%; }
/* Note: a line of consequence or warning, inline in a card. */
.ds-note, .warn-box, .flag { display: flex; align-items: flex-start; gap: var(--sp-2); padding: var(--sp-2) var(--sp-3); border-radius: var(--r-control); font-size: var(--fs-dense); line-height: var(--lh-dense); }
.ds-note .ds-icon { margin-top: 1px; }
.ds-note-text { flex: 1; min-width: 0; }
.ds-note:is(.neutral, .busy) { background: var(--surface-2); color: var(--text); }
.ds-note:is(.neutral, .busy) .ds-icon { color: var(--text-hint); }
.ds-note.ok { background: var(--ok-soft); color: var(--ok); }
.ds-note.warn, .warn-box, .flag { background: var(--warn-soft); color: var(--warn); }
.ds-note.bad { background: var(--bad-soft); color: var(--bad); }
.warn-box, .flag { display: block; }
.warn-box { margin-top: var(--sp-3); }
.warn-box.small { font-size: var(--fs-meta); line-height: var(--lh-meta); }
.warn-box .btn { margin-left: 6px; }
.flag { font-size: var(--fs-meta); line-height: var(--lh-meta); margin: 6px 0; }
/* A form's own submit, at the bottom of its card, beside what it will do (Move: Take a copy). */
.form-submit { display: flex; align-items: center; gap: var(--sp-3); margin-top: var(--sp-4); }
.form-submit .ds-note { flex: 1; }
#off-client { margin: 0 0 var(--sp-3); }
#tl-note { margin: 0; }
/* EmptyState: one sentence, at most one button, suggestions when there are candidates. */
.ds-empty { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2) var(--sp-3); color: var(--muted); }
.ds-empty.clear .ds-mark { color: var(--ok); }
.ds-empty-text { flex: 1 1 320px; }
.ds-empty-sugg { flex-basis: 100%; display: flex; flex-wrap: wrap; gap: var(--sp-2); }

/* --- Progress and meters --------------------------------------------------------------------- */
.progress { height: 6px; border-radius: var(--r-bar); background: var(--surface-2); overflow: hidden; margin-top: var(--sp-2); }
.progress.big { height: 8px; }
.progress i { display: block; height: 100%; width: 0; background: var(--accent); border-radius: var(--r-bar); transition: width var(--dur-slow) var(--ease-in-out); }
.progress.indeterminate i { width: 30%; animation: slide 1.4s ease-in-out infinite; }
@keyframes slide { 0% { transform: translateX(-100%); } 100% { transform: translateX(340%); } }
.run { margin-top: var(--sp-3); padding: var(--sp-3); background: var(--surface-2); border-radius: var(--r-panel); }
.run-line { display: flex; justify-content: space-between; gap: var(--sp-3); }
.meter { display: flex; height: 10px; border-radius: var(--r-chip); background: var(--surface-2); overflow: hidden; margin: var(--sp-3) 0 var(--sp-2); }
.meter i { display: block; height: 100%; transition: width var(--dur-slow) var(--ease-in-out); }
.meter .a, .sw.a { background: var(--meter-a); }
.meter .b, .sw.b { background: var(--meter-b); }
.legend { display: flex; gap: var(--sp-4); font-size: var(--fs-meta); line-height: var(--lh-meta); color: var(--muted); flex-wrap: wrap; }
.legend b { color: var(--text); font-weight: 600; }
.sw { display: inline-block; width: 9px; height: 9px; border-radius: 2px; margin-right: 6px; }
.spark { height: 42px; margin-top: var(--sp-3); }
.rows { display: flex; flex-direction: column; gap: var(--sp-2); margin-top: 2px; }
.row { display: flex; justify-content: space-between; gap: var(--sp-3); }
.row span { color: var(--muted); }
.dots { list-style: none; display: flex; gap: 6px; padding: 0; margin: 10px 0 0; }
.dots li { flex: 1; height: 4px; border-radius: 2px; background: var(--track-tint); }
.dots li.done { background: var(--ok); }
.dots li.now { background: var(--accent); }

/* --- Job bar --------------------------------------------------------------------------------- */
.jobbar { position: sticky; top: -26px; z-index: var(--z-sticky); max-width: var(--col-max); margin: -6px auto var(--sp-4); display: flex; align-items: center; gap: var(--sp-4); padding: var(--sp-3) var(--sp-4); border-radius: var(--r-card); background: var(--surface-2); border: 1px solid var(--border); }
.jobbar.ok { background: var(--ok-soft); }
.jobbar.bad { background: var(--bad-soft); }
.jobbar-main { flex: 1; min-width: 0; }
.jobbar-title { font-weight: 600; }
.jobbar-step { font-size: var(--fs-meta); line-height: var(--lh-meta); color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.jobbar-actions { display: flex; gap: 6px; }
.jobbar .progress { background: var(--track-tint); }

/* --- Forms ----------------------------------------------------------------------------------- */
.form { display: grid; grid-template-columns: 160px 1fr; gap: var(--sp-4) var(--sp-6); margin-top: var(--sp-4); }
.field { display: flex; flex-direction: column; gap: 6px; margin-top: var(--sp-3); }
.form .field { margin-top: 0; }
.field.wide { grid-column: 1 / -1; }
.field label, .field > label { font-size: var(--fs-meta); line-height: var(--lh-meta); font-weight: 600; color: var(--muted); }
input[type=time], input:not([type]), select, input.num { height: var(--ctl-h-md); background: var(--surface); border: 1px solid var(--border-control); border-radius: var(--r-control); padding: 0 10px; outline-color: var(--focus); min-width: 0; }
input[type=time] { width: 130px; }
input.num { height: var(--ctl-h-sm); width: 64px; padding: 0 6px; margin: 0 4px; text-align: center; }
select { padding-right: 28px; }
.daychips { display: flex; gap: 6px; flex-wrap: wrap; }
.daychips button { width: 44px; padding: 6px 0; border-radius: var(--r-control); border: 1px solid var(--border-control); background: var(--surface); cursor: pointer; font-size: var(--fs-dense); line-height: var(--lh-dense); }
.daychips button.on { background: var(--accent); border-color: var(--accent); color: var(--on-accent); font-weight: 600; }
.segmented { display: inline-flex; background: var(--surface-2); border-radius: var(--r-panel); padding: 3px; gap: 2px; flex-wrap: wrap; }
/* 34 px like the buttons and fields beside it (M16): a 28 px option in the 3 px track. */
.segmented button { border: 0; background: none; height: var(--ctl-h-sm); padding: 0 var(--sp-3); border-radius: var(--r-chip); cursor: pointer; color: var(--muted); }
.segmented button:hover { color: var(--text); }
.segmented button.on { background: var(--seg-on); color: var(--text); font-weight: 600; box-shadow: var(--shadow-1); }
#pk-side, #pl-side { align-self: flex-start; }
.toggles { gap: 10px; }
.toggle { display: flex; align-items: center; gap: 10px; cursor: pointer; flex-wrap: wrap; }
.toggle input[type=checkbox] { position: absolute; opacity: 0; width: 1px; height: 1px; }
.toggle > span { width: 34px; height: 20px; border-radius: var(--r-pill); background: var(--border); position: relative; flex: none; transition: background var(--dur-base) var(--ease-out); }
.toggle > span::after { content: ""; position: absolute; top: 3px; left: 3px; width: 14px; height: 14px; border-radius: 50%; background: var(--knob); transition: left var(--dur-base) var(--ease-out); }
.toggle input:checked + span { background: var(--accent); }
.toggle input:checked + span::after { left: 17px; }
.toggle input:focus-visible + span { outline: 2px solid var(--focus); outline-offset: 2px; }
.pathpick { display: flex; gap: 6px; }
.pathpick input { flex: 1; }
.choice { display: grid; gap: var(--sp-2); }
.choice button { text-align: left; border: 1px solid var(--border-control); background: var(--surface); border-radius: var(--r-panel); padding: 10px var(--sp-3); cursor: pointer; display: flex; flex-direction: column; gap: 2px; }
.choice button span { font-size: var(--fs-meta); line-height: var(--lh-meta); color: var(--muted); }
.choice button.on { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
.filebox { border: 1.5px dashed var(--border-control); border-radius: var(--r-panel); padding: 14px; display: flex; flex-direction: column; align-items: flex-start; gap: var(--sp-1); }
.filebox.picked { border-style: solid; background: var(--surface-2); }
.fileinfo { display: grid; grid-template-columns: auto 1fr; gap: 3px 14px; font-size: var(--fs-dense); line-height: var(--lh-dense); margin: 6px 0 4px; }
.fileinfo span { color: var(--muted); }
#im-options { margin-top: var(--sp-1); }
#im-options .toggle { margin-top: var(--sp-3); }

/* --- Rows: tables and lists ------------------------------------------------------------------ */
/* Densities: compact 32 (data rows), default 44 (a row with a visible action), rich 56 (a title
   and a line under it). Rows carry one action at rest; the rest are behind "...". */
.table-wrap { max-height: 340px; overflow-y: auto; }
.table-wrap.tall { max-height: none; }
.table { width: 100%; border-collapse: collapse; font-size: var(--fs-dense); line-height: var(--lh-dense); }
.table th { position: relative; text-align: left; font-weight: 600; font-size: var(--fs-label); line-height: var(--lh-label); text-transform: uppercase; letter-spacing: .07em; color: var(--muted); padding: 6px; background: var(--surface); }
/* The head sticks as one band (round 6g, #99) at the top of whatever scrolls the table: main, whose
   26 px of top padding sticky offsets count from, under any sticky bar over it (--stick-under: the
   job bar while it shows, or a tab bar if one ever sticks); or the box that scrolls it (a
   .table-wrap, an opened bounded list, a split pane), at 0. It sits above the rows, so their "..."
   never paints through it. Stuck, its line turns into a 1 px --border rule, so the row it cuts reads
   as passing under an edge, and it shows its group's name at its left over the labels of the columns
   that name reaches (DS.Table, DS.fitHeads), so you know which table you're in. */
.table thead { position: sticky; top: 0; z-index: calc(var(--z-sticky) - 1); container-type: scroll-state; }
main .table thead { top: calc(var(--stick-under, 0px) - 26px); }
main :is(.table-wrap, .bounded.open, .split-scroll) .table thead { top: 0; }
/* The head owns the one line under it (#132, M70): the first row under a head has no top border, and
   the head draws that line itself, on the first row's top pixel row, where the border was. At rest it
   is the hairline; stuck, the same line turns --border, over whatever row border passes there. It
   moves with the head, so a head stuck at the top of a box that scrolls itself draws one rule, never a
   rule over a hairline, and at rest one hairline wherever the table sits on the pixel grid. */
.table > thead + tbody > tr:first-child > td { border-top: 0; }
.table th::after { content: ""; position: absolute; left: 0; right: 0; bottom: -1px; height: 1px; background: var(--border-subtle); pointer-events: none; }
/* Over the cells it reaches (each a positioned box, for its line). */
.th-group { position: absolute; z-index: 1; left: 0; top: 0; bottom: 0; display: flex; align-items: baseline; padding-top: inherit; visibility: hidden; background: inherit; color: var(--text);
  font-size: var(--fs-meta); line-height: 14px; letter-spacing: 0; text-transform: none; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* The name shares the column labels' baseline (M80): under the head's own top padding, a zero-width
   strut set like a label holds the line's baseline where the labels' is, and the name sits on it
   (its 14 px line box keeps the strut the one that sets the line, whatever the font's metrics).
   Centred on its own, the 12 px name sat a pixel under the 11 px labels. */
.th-group::before { content: "\200b"; font-size: var(--fs-label); line-height: var(--lh-label); }
@container scroll-state(stuck: top) {
  .table th::after { background: var(--border); }
  .th-group { visibility: visible; }
  .th-group + .th-label, .th-under > .th-label { visibility: hidden; }
}
/* A row that opens in place (P3: Repos' detail) holds its detail in a panel on the raised surface. A
   table in it keeps the page's grid (#100): it reaches the row's right edge, giving the panel's right
   padding back, so every column after the first, the verb and the "..." share x with the rows around
   it; only its first column is indented, by the panel's 16 px on the left. */
.table > tbody > tr.row-detail > td { background: var(--surface-2); padding: var(--sp-4) var(--sp-4) var(--sp-3); white-space: normal; }   /* over the first and last cell's 0 */
/* A neutral tag in a row's detail panel steps up to --surface-3: on the panel's --surface-2 its own
   fill would vanish (Dotfiles' version tags). */
.row-detail .tag:not(.warn, .ok, .bad) { background: var(--surface-3); }
.table.nested { width: calc(100% + var(--sp-4)); margin-right: calc(var(--sp-4) * -1); }
.table.nested th { background: var(--surface-2); }
/* Stuck, a nested head lies over its table's own stuck head: as tall as it (compact or not), its band
   and rule reaching left over the panel's 16 px, so none of the outer head shows beside or under it. */
.table.nested th:first-child::before { content: ""; position: absolute; top: 0; bottom: -1px; right: 100%; width: var(--sp-4); background: inherit; }
@container scroll-state(stuck: top) { .table.nested th:first-child::before { box-shadow: inset 0 -1px 0 var(--border); } }
/* A table in a fold keeps the page's grid too (#113, M65): it reaches back over the fold's indent,
   so its columns share x with the tables in the cards around it, and only its first column is
   indented, under the fold's label, as a nested table's is. */
.grp-body > .table { width: calc(100% + var(--fold-indent)); margin-left: calc(var(--fold-indent) * -1); }
.grp-body > .table > * > tr > :first-child { padding-left: var(--fold-indent); }
/* A row that opens in place keeps its chevron in a 24 px gutter column of its own, with no label
   (DS.Table's `disc` column, DS.Disc), so the next column's head sits on its values' x (#115). */
.table :is(th, td).ds-disc { width: 24px; padding-left: 0; padding-right: 0; text-align: center; }
.table td.ds-disc > .disc { vertical-align: middle; }
/* DS.Table's rows are one height (M68): 34 px, whatever a row holds (a 16 px side chip, the 24 px
   chevron, a 28 px verb or "..."), each centred in it, so no row sets its own pitch and a list never
   goes ragged. A table whose rows carry a second line (Repos) is `rich` and keeps its padding; a
   row's detail (one full-width cell) is as tall as it needs. */
.ds-table:not(.rich) > tbody > tr > td:not([colspan]) { height: var(--row-table); padding-top: 0; padding-bottom: 0; vertical-align: middle; }
/* A value that leads with a glyph (a newer version's arrow) puts the glyph's ink on its column's x,
   where the head's label starts (M66). */
.table td > .newer:first-child > .ds-icon:first-child { margin-left: -3px; }
/* A value not read yet says so (DS.Pending): "measuring..." or "—", never a blank that reads as 0. */
.pending { color: var(--text-hint); }
/* A group's head (DS.GroupHead): its name, then "[side] N · checked ..." on the right. */
.group-meta { display: inline-flex; align-items: center; gap: var(--sp-1); }
/* A row's side chip under the majority rule (DS.RowSide) follows its name, so names keep one x. It
   is 16 px high (line-height 1), so it fits a 34 px row instead of setting its height (M68). */
.row-side { display: inline-flex; flex: none; margin-left: var(--sp-2); vertical-align: middle; font-family: "Segoe UI Variable Text", "Segoe UI", system-ui, sans-serif; }
.row-side > .side { height: 16px; line-height: 1; }
.table td { padding: var(--sp-2) 6px; border-top: 1px solid var(--border-subtle); vertical-align: top; }
.table td.note { color: var(--muted); }
.table .actions { text-align: right; white-space: nowrap; }
.table.compact td { padding: 2px 6px; height: var(--row-compact); vertical-align: middle; }
/* A nested head keeps its parent's height, so stuck it covers it. Top and bottom only: a rule that
   pads a cell's sides would outrank the no-outer-padding rule below and move a first column's head
   off its values (M66: 6 px on every compact table's first head). */
.table.compact:not(.nested) th { padding-top: var(--sp-1); padding-bottom: var(--sp-1); }
/* A number column (DS.Table's `num`, td.num): right-aligned in tabular figures, its head on the same
   edge, with a 24 px gutter before the next column, so a figure never reads into it.
   (After the density rules, whose padding it overrides.) */
.table :is(th, td).num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; padding-right: var(--sp-6); }
.row-actions { display: inline-flex; align-items: center; justify-content: flex-end; gap: var(--sp-1); }
.ds-more-slot { width: var(--ctl-h-sm); height: var(--ctl-h-sm); flex: none; }
.ds-primary-slot { flex: none; }
.ds-more-btn svg { width: 18px; height: 18px; }
.table td.actions { padding-top: 3px; }        /* a top-aligned row's action sits on its first line */
.table.compact td.actions { padding-top: 2px; }
/* No outer cell padding, so a table's first column and its row actions sit on the card's content
   edges, at the same x as a list's. (After the density rules, which set padding too. Nothing that
   pads a cell's sides may outrank it but the deliberate indents: a fold's, a row's detail.) */
.table tr > :is(td, th):first-child { padding-left: 0; }
.table tr > :is(td, th):last-child { padding-right: 0; }
.list { list-style: none; margin: var(--sp-1) 0 0; padding: 0; }
.list > li { padding: var(--sp-2) 0; border-top: 1px solid var(--border-subtle); }
.list > li:first-child { border-top: 0; }
.li-split { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3); min-height: var(--row-default); }
.li-main { min-width: 0; }
.list .li-main { flex: 1; overflow: hidden; }
.li-acts { display: flex; gap: 6px; align-items: center; flex: none; }
.activity { list-style: none; margin: 0; padding: 0; }
.activity li { display: flex; align-items: flex-start; gap: var(--sp-3); padding: var(--sp-2) 0; min-height: var(--row-default); border-top: 1px solid var(--border-subtle); }
.activity .act-what { font-weight: 600; margin-right: var(--sp-2); }
.act-mark { display: inline-flex; margin-top: 2px; color: var(--text-hint); }
.act-mark.ok { color: var(--ok); } .act-mark.warn { color: var(--warn); } .act-mark.bad { color: var(--bad); }
/* A skipped run's dash is information, not decoration (M62): muted ink and a 2 px stroke, so the thin
   line reads at 3:1 or better against the card (in hint ink at 1.5 px it measured 2.74). */
.act-mark:not(.ok, .warn, .bad) { color: var(--muted); }
.act-mark:not(.ok, .warn, .bad) svg { stroke-width: 2; }
/* A failed run's row is a button that opens its ErrorDetail underneath. */
.activity li.has-detail { flex-direction: column; align-items: stretch; gap: 0; }
.act-toggle { display: flex; align-items: flex-start; gap: var(--sp-3); width: 100%; padding: 0; border: 0; border-radius: var(--r-control); background: none; color: inherit; font: inherit; text-align: left; cursor: pointer; }
.act-toggle:hover .act-what, .act-toggle.is-hover .act-what { text-decoration: underline; text-underline-offset: 3px; }
.act-toggle > .chev { margin: 2px 0 0 auto; flex: none; color: var(--text-hint); transition: transform var(--dur-fast) var(--ease-out); }
.act-toggle[aria-expanded="true"] > .chev { transform: rotate(90deg); }

/* RunStrip (components.js): a bar a day, for how the day ended; an amber notch on a green bar is
   a day that recovered from a failure, a short bar a skip, a tick a day with no run. */
.ds-strip { display: flex; flex-direction: column; gap: var(--sp-2); min-width: 0; }
.ds-strip-head { font-size: var(--fs-meta); line-height: var(--lh-meta); color: var(--muted); }
.ds-strip-days { display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); gap: 3px; height: 32px; align-items: end; }
.ds-day { display: flex; align-items: center; justify-content: center; height: 100%; border-radius: 2px; background: var(--ok); }
.ds-day.failed { background: var(--bad); }
/* The notch: amber on top, a 2 px gap in the card's colour, then the green the day ended on. */
.ds-day.recovered { background: linear-gradient(var(--warn) 0 6px, var(--surface) 6px 8px, var(--ok) 8px); }
.ds-day.failed .ds-icon { width: 12px; height: 12px; color: var(--surface); stroke-width: 3; }
.ds-day.skipped { height: 12px; background: var(--text-hint); }
.ds-day.none { height: 3px; background: var(--border-control); }
.ds-strip-days .ds-day:hover { outline: 1px solid var(--text); outline-offset: 1px; }   /* the bar its tooltip describes */
.ds-strip-axis { display: flex; justify-content: space-between; font-size: var(--fs-meta); line-height: var(--lh-meta); color: var(--text-hint); }
.ds-strip-key { display: flex; flex-wrap: wrap; gap: var(--sp-1) var(--sp-4); font-size: var(--fs-meta); line-height: var(--lh-meta); color: var(--muted); }
.ds-strip-key span { display: inline-flex; align-items: flex-end; gap: 6px; }
.ds-strip-key b { color: var(--text); font-weight: 600; margin-right: -2px; }
/* The key's swatches are the bars at half size (16x32, 16x12, 16x3 -> 8x16, 8x6, 8x2). */
.ds-strip-key .ds-day { flex: none; width: 8px; height: 16px; }
.ds-strip-key .ds-day.skipped { height: 6px; }
.ds-strip-key .ds-day.none { height: 2px; }
.ds-strip-key .ds-day.recovered { background: linear-gradient(var(--warn) 0 3px, var(--surface) 3px 4px, var(--ok) 4px); }
.ds-strip-key .ds-day.failed .ds-icon { width: 6px; height: 6px; stroke-width: 3.5; }
.ds-strip-unit { color: var(--muted); margin-right: calc(var(--sp-1) * -2); }

/* ErrorDetail (components.js): under a failed run, on the card, set off by a red edge. */
.ds-err { display: flex; flex-direction: column; gap: var(--sp-2); margin: var(--sp-3) 0 var(--sp-1) calc(16px + var(--sp-3)); padding: 2px 0 2px var(--sp-4); border-left: 2px solid var(--bad-line); }
.ds-err p { margin: 0; max-width: 75ch; }
.ds-err-cause { display: flex; flex-direction: column; gap: var(--sp-1); }
.ds-err-cause b { font-weight: 600; }
.ds-err-next { color: var(--muted); }
.ds-err-since { color: var(--text); }
.ds-err-acts { display: flex; align-items: center; gap: var(--sp-2); }
/* A text button first in the row gives back its padding, so "Open log" lines up with the text above. */
.ds-err-acts > .btn.ghost:first-child { margin-left: calc(var(--sp-3) * -1); }
.ds-err-resolved { display: inline-flex; align-items: center; gap: 6px; margin-right: var(--sp-2); font-size: var(--fs-dense); line-height: var(--lh-dense); font-weight: 600; }
.ds-err-resolved .ds-mark { color: var(--ok); }
.ds-err-facts, .ds-err-wait { font-size: var(--fs-meta); line-height: var(--lh-meta); color: var(--muted); }
.ds-err-facts { display: flex; flex-direction: column; gap: 2px; }
.ds-err-facts code { font: inherit; font-family: ui-monospace, "Cascadia Mono", Consolas, monospace; }
.ds-err-log { max-height: 220px; overflow: auto; padding: var(--sp-2) var(--sp-3); background: var(--surface-2); border-radius: var(--r-control); color: var(--muted); }
.ds-err-log > span { display: block; }
/* The ERROR line: bold, and a red tick at the log's left edge (the text stays in line). */
.ds-err-log > .ds-err-hit { color: var(--text); font-weight: 600; margin-left: calc(var(--sp-3) * -1); padding-left: calc(var(--sp-3) - 2px); border-left: 2px solid var(--bad); }
#act-more { margin-top: 6px; }
/* FilterLine (components.js): the list is narrowed; says by what, with the way back. */
.ds-filter { display: flex; align-items: center; gap: var(--sp-2); min-height: var(--row-compact); padding: 0 var(--sp-1) 0 var(--sp-3); border-radius: var(--r-control); background: var(--accent-soft); font-size: var(--fs-dense); line-height: var(--lh-dense); }
.ds-filter > .ds-icon { width: 15px; height: 15px; color: var(--link); }
.ds-filter-text { flex: 1; min-width: 0; }
/* Its slot: under a card's head, or above a page's stack of cards (Packages, Places). */
.filter-slot:empty { display: none; }
.card > .filter-slot { margin-bottom: var(--sp-2); }
.actlist { list-style: none; margin: 0; padding: 0; }
.actlist li { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-4); min-height: var(--row-rich); padding: var(--sp-2) 0; border-top: 1px solid var(--border-subtle); }
.actlist b { font-weight: 600; }
/* A task's payoff (#72, #73, M27): its own right-aligned column before the verb, plain text in
   tabular figures, so it reads as what the task gives back and never as a tag like "Admin"; what
   frees nothing worth having is hint grey. The description wraps short of it. */
.actlist .act-main { flex: 1 1 auto; min-width: 0; }
.act-payoff { flex: none; width: 120px; text-align: right; font-size: var(--fs-dense); line-height: var(--lh-dense); font-variant-numeric: tabular-nums; white-space: nowrap; color: var(--text); }
.act-payoff .none { color: var(--text-hint); }
/* What a link brought into sight (go(page, {anchor})) takes the selection tint, holds it for a third
   of --dur-flash and lets it go; under reduced motion it holds the tint until the class goes. */
.flash { border-radius: var(--r-control); animation: flash var(--dur-flash) var(--ease-in-out) both; }
@keyframes flash { 0%, 35% { background-color: var(--accent-soft); box-shadow: 0 0 0 var(--sp-2) var(--accent-soft); } 100% { background-color: transparent; box-shadow: 0 0 0 var(--sp-2) transparent; } }
@media (prefers-reduced-motion: reduce) { .flash { animation: none; background-color: var(--accent-soft); box-shadow: 0 0 0 var(--sp-2) var(--accent-soft); } }
.update-row { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-4); min-height: var(--row-rich); padding: var(--sp-2) 0; border-top: 1px solid var(--border-subtle); }
.update-row:first-of-type { padding-top: 2px; }
/* Lines separate rows, never a heading from its first row, nor a card's top from it (a card that
   fills its tab has no heading, #143). */
:is(.card-head, .sub-h, h4) + :is(.update-row, details.grp, .ident, .hist),
.card > :is(.update-row, details.grp, .ident, .hist):first-child,
:is(.activity, .actlist, .hist-log) > li:first-child { border-top: 0; }
:is(.card-head, .sub-h) + .hist { margin-top: 0; padding-top: 0; }

/* Menus: "..." on rows, labelled menus elsewhere. Danger entries go last, after a rule. */
details.menu { display: inline-block; position: relative; vertical-align: middle; }
details.menu > summary { list-style: none; }
details.menu > summary::-webkit-details-marker { display: none; }
details.menu:not(.ds-more) > summary::after { content: "\25BE"; margin-left: 2px; font-size: var(--fs-meta); line-height: var(--lh-meta); opacity: .7; }
details.menu[open] > summary { background: var(--surface-2); color: var(--text); }
details.menu[open] > summary.primary { background: var(--accent-hover); border-color: var(--accent-hover); color: var(--on-accent); }
.menu-pop { position: absolute; right: 0; top: calc(100% + 4px); z-index: var(--z-menu); min-width: 180px; display: flex; flex-direction: column; background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-panel); box-shadow: var(--shadow-2); padding: var(--sp-1); }
.menu-pop .btn { justify-content: flex-start; text-align: left; margin: 0; border-radius: var(--r-chip); color: var(--text); }
.menu-pop .btn.danger { color: var(--bad); }
.menu-pop .btn:hover:not(:disabled) { background: var(--surface-2); }
.menu-pop .btn.danger:hover:not(:disabled) { background: var(--bad-soft); }
.menu-sep { border: 0; border-top: 1px solid var(--border-subtle); margin: var(--sp-1) 0; }
:is(.ph-tools, .head-tools) details.menu .menu-pop { min-width: 240px; }
.card-head details.menu .menu-pop { min-width: 190px; }

/* --- Long pages: tabs, bounded lists, master-detail (DESIGN.md "Long pages") ------------------ */
/* Tabs (P1): text on the page's own background, no track. The picked tab is text ink at 600 over a
   2 px accent underline that slides; the others are muted at 400. A label reserves its 600 width
   (the hidden copy in ::after), so picking a tab never moves its neighbours. */
.tabs { position: relative; display: flex; align-items: stretch; border-bottom: 1px solid var(--border); }
.tabs-list { display: flex; align-items: stretch; gap: var(--sp-6); }
.tab { display: inline-flex; align-items: center; gap: var(--sp-2); height: 42px; padding: 0 2px; margin-bottom: -1px; border: 0; background: none; cursor: pointer; color: var(--muted); font: inherit; font-weight: 400; border-radius: var(--r-chip) var(--r-chip) 0 0; transition: color var(--dur-fast) var(--ease-out); }
.tab:hover { color: var(--text); }
.tab[aria-selected="true"] { color: var(--text); font-weight: 600; }
.tab:focus-visible { outline-offset: -2px; }
.tab-label { display: inline-grid; }
.tab-label::after { content: attr(data-text); font-weight: 600; height: 0; visibility: hidden; overflow: hidden; user-select: none; pointer-events: none; }
.tab-count { color: var(--text-hint); font-weight: 400; font-size: var(--fs-dense); line-height: var(--lh-dense); font-variant-numeric: tabular-nums; }
.tab .badge { margin-left: 0; }
.tabs-ink { position: absolute; left: 0; bottom: -1px; height: 2px; width: 0; background: var(--accent); border-radius: 2px 2px 0 0; transition: transform var(--dur-tab) var(--ease-out-quart), width var(--dur-tab) var(--ease-out-quart); pointer-events: none; }
.tabs-ink.no-anim { transition: none; }
/* A content toolbar sits directly under the tabs and over the cards: the side filter on the left,
   the tab's own search or filters on the right. It never moves between cards. */
.tab-toolbar { display: flex; align-items: center; gap: var(--sp-3); min-height: var(--ctl-h-md); }
.tab-toolbar > .tb-end { margin-left: auto; display: flex; align-items: center; gap: var(--sp-2); }
.tab-toolbar .search { width: 280px; max-width: none; }
.tabpanels { position: relative; }
.tabpanel { display: flex; flex-direction: column; gap: var(--gap-stack); opacity: 1; transition: opacity var(--dur-tab-fade) linear; }
.tabpanel.fade-in { opacity: 0; }
.tabpanel.fade-out { position: absolute; inset: 0 0 auto 0; opacity: 0; pointer-events: none; }
.tabpanel:focus-visible { outline-offset: 4px; border-radius: var(--r-card); }
/* Bounded (P2): 8 rows, then steps; opened, the list scrolls inside its card (about one screen). */
.bounded.open { max-height: 640px; overflow-y: auto; overscroll-behavior: contain; }
/* The step's words sit midway between the foot's rule and the card's edge (M72), 22 px of each: the
   label's 20 px line splits its 28 px button evenly, so the words keep that place on whole pixels
   wherever the card sits. */
.bounded-foot { display: flex; align-items: center; gap: var(--sp-2); margin-top: var(--sp-2); padding-top: var(--sp-3); border-top: 1px solid var(--border-subtle); }
.bounded-foot:last-child { margin-bottom: calc(var(--sp-1) * -1); }
.bounded-foot .btn { line-height: var(--lh-body); }
.bounded-foot .btn.ghost:first-child { margin-left: calc(var(--sp-3) * -1); }
.bounded-count { margin-left: auto; color: var(--muted); font-size: var(--fs-meta); line-height: var(--lh-meta); font-variant-numeric: tabular-nums; }
/* FilterChips: a row of 28 px toggles that narrows a list to one of its groups (Packages' managers);
   the picked one on the selection tint, like a master-detail list's pick (--seg-on would vanish on
   a light card). */
.chip-row { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2); }
.chip-btn { display: inline-flex; align-items: center; gap: var(--sp-2); height: var(--ctl-h-sm); padding: 0 var(--sp-3); border: 1px solid var(--border-control); border-radius: var(--r-pill); background: none; color: var(--muted); font: inherit; font-size: var(--fs-dense); line-height: var(--lh-dense); cursor: pointer; white-space: nowrap; }
.chip-btn:hover { color: var(--text); background: var(--surface-2); }
.chip-btn.on { color: var(--text); background: var(--accent-soft); font-weight: 600; }
.chip-btn .n { color: var(--text-hint); font-weight: 400; font-variant-numeric: tabular-nums; }
.chip-btn.on .n { color: var(--muted); }   /* on the tint: 5.7:1 dark, 6.8:1 light (hint grey is 4.1:1 there) */
/* A path cut in the middle: the folder part gives way, the file name stays. */
.midpath { display: inline-flex; max-width: 100%; min-width: 0; vertical-align: bottom; }
.midpath .mp-head { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 1ch; }
.midpath .mp-tail { white-space: nowrap; flex: none; }
/* Split (P4): the list (320) and the pane each scroll on their own; the page doesn't. */
.split { display: grid; grid-template-columns: 320px minmax(0, 1fr); gap: var(--gap-stack); align-items: start; }
.split-list, .split-pane { padding: 0; display: flex; flex-direction: column; min-height: 0; max-height: calc(100vh - 220px); overflow: hidden; }
.split-list { position: sticky; top: 0; }
.split-list-head { padding: var(--sp-3) var(--sp-4) var(--sp-2); border-bottom: 1px solid var(--border-subtle); display: flex; align-items: center; justify-content: space-between; gap: var(--sp-2); }
.split-scroll { flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior: contain; }
.split-items { list-style: none; margin: 0; padding: var(--sp-1); }
.split-item { display: flex; align-items: center; gap: var(--sp-2); width: 100%; height: var(--row-list); padding: 0 var(--sp-3); border: 0; background: none; border-radius: var(--r-control); cursor: pointer; text-align: left; color: var(--text); font: inherit; }
.split-item:hover { background: var(--surface-2); }
.split-item[aria-selected="true"] { background: var(--accent-soft); font-weight: 600; }
.split-item .nm { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.split-item .n { color: var(--muted); font-weight: 400; font-size: var(--fs-dense); line-height: var(--lh-dense); font-variant-numeric: tabular-nums; min-width: 2ch; text-align: right; }
.split-mark { width: 16px; height: 16px; flex: none; display: inline-grid; place-items: center; }
.split-pane > .split-scroll { padding: 0 calc(var(--pad-card-x) - 12px) var(--sp-4) var(--pad-card-x); scrollbar-gutter: stable; }   /* the 12 px scrollbar sits in the card's padding */
.split-pane-head { padding: var(--sp-4) var(--pad-card-x) var(--sp-3); border-bottom: 1px solid var(--border-subtle); display: flex; flex-direction: column; align-items: flex-start; gap: var(--sp-3); }
/* A table in the pane keeps to the pane's width, so a long path is cut (DS.MidPath) instead of pushing the actions out. */
.split-pane .table { table-layout: fixed; }
.split-pane .table td.actions { width: 164px; }
.split-pane .table td { overflow: hidden; }

/* --- Charts ---------------------------------------------------------------------------------- */
.chart { height: 220px; position: relative; }
.chart svg, .spark svg { width: 100%; height: 100%; display: block; overflow: visible; }
.chart .axis { fill: var(--text-hint); stroke: none; font-size: var(--fs-label); line-height: var(--lh-label); }
.chart .grid-line { stroke: var(--border-subtle); stroke-width: 1; }
.chart-tip { position: absolute; pointer-events: none; background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-control); padding: 6px 9px; font-size: var(--fs-meta); line-height: var(--lh-meta); box-shadow: var(--shadow-2); white-space: nowrap; }
.chart-legend { display: flex; gap: var(--sp-4); font-size: var(--fs-meta); line-height: var(--lh-meta); color: var(--muted); margin-bottom: 6px; }
.chart-legend i { display: inline-block; width: 12px; height: 3px; border-radius: 2px; margin-right: 6px; vertical-align: 3px; }

/* --- Consoles, folds, dialogs ---------------------------------------------------------------- */
.console pre, .log pre, pre.logbox { background: var(--surface-2); border-radius: var(--r-control); padding: 10px var(--sp-3); max-height: 260px; overflow-y: auto; }
.fold { padding: 14px var(--pad-card-x); }
:is(.fold, .log) summary { display: flex; align-items: center; justify-content: space-between; cursor: pointer; list-style: none; }
:is(.fold, .log) summary::-webkit-details-marker { display: none; }
:is(.fold, .log) summary h2::before { content: "\25B8"; display: inline-block; margin-right: var(--sp-2); transition: transform var(--dur-fast) var(--ease-out); }
:is(.fold, .log)[open] summary h2::before { transform: rotate(90deg); }
:is(.fold, .log)[open] summary { margin-bottom: var(--sp-3); }
.row-card { display: flex; align-items: center; gap: 14px; padding: 14px var(--pad-card-x); }
.row-icon { width: 36px; height: 36px; border-radius: var(--r-panel); background: var(--surface-2); color: var(--muted); display: grid; place-items: center; flex: none; }
.row-icon svg { width: 20px; height: 20px; }
.row-text { flex: 1; min-width: 0; }
.row-title { font-weight: 600; }
dialog { border: 1px solid var(--border); border-radius: var(--r-card); background: var(--surface); color: var(--text); padding: 0; width: min(640px, calc(100vw - 48px)); box-shadow: var(--shadow-3); }
dialog::backdrop { background: var(--scrim); }
.dlg-head { display: flex; align-items: center; justify-content: space-between; padding: var(--sp-4) var(--pad-card-x) 0; }
.dlg-head h3 { font-size: var(--fs-title); line-height: var(--lh-title); }
dialog .form { padding: var(--sp-1) var(--pad-card-x) 6px; margin-top: var(--sp-3); grid-template-columns: 150px 1fr; }
.dlg-foot { display: flex; align-items: center; gap: var(--sp-2); padding: 14px var(--pad-card-x) var(--sp-4); border-top: 1px solid var(--border-subtle); margin-top: 14px; }

/* ConfirmDialog (O9, #77, #80, #81; slots in DESIGN.md): one step up from the cards, as the tooltip
   is; 560 wide, so a row's items fit a line; the count leads each row in text ink, its items muted
   under it, each kept whole; the working agent first, on the amber band. */
dialog.confirm { width: min(560px, calc(100vw - 48px)); background: var(--surface-raised); }
.ds-confirm { display: flex; flex-direction: column; gap: var(--sp-3); padding: var(--sp-5) var(--pad-card-x) 0; text-wrap: pretty; }
.ds-confirm-title { margin: 0; font-size: var(--fs-figure); line-height: var(--lh-figure); font-weight: 600; text-wrap: balance; }
.ds-confirm-lede { margin: calc(var(--sp-1) * -1) 0 0; color: var(--muted); white-space: pre-line; }   /* a body in two sentences keeps one a line (M44) */
.ds-confirm-steps { display: flex; flex-direction: column; gap: var(--sp-1); margin: 0; padding-left: var(--sp-5); font-size: var(--fs-dense); line-height: var(--lh-dense); }
.ds-confirm-list { display: flex; flex-direction: column; gap: var(--sp-1); }
.ds-confirm-row { align-items: flex-start; min-height: 0; padding: var(--sp-1) var(--sp-3); }
.ds-confirm-row > .gl-text { padding: 0; }
.ds-confirm-row > .ds-mark { margin-top: 2px; }
.ds-confirm-detail { display: block; font-size: var(--fs-meta); line-height: var(--lh-meta); }
.ds-confirm-detail > span { white-space: nowrap; }
.ds-confirm-detail .ds-sep { font-style: normal; }
.ds-confirm-detail .ds-sep.eol { visibility: hidden; }   /* the line wraps after it: no line ends on a separator */
/* The amber row (#98): 14 px on the right as on the left (there, 12 and the mark's own 2 px inset), and
   an item too long for the row is cut with "…" inside that padding rather than running to the edge. */
/* The amber row's words sit with 11 px of fill over their ink and 11 under it (M73): its first line's
   ink starts 4 px into its line and the second's descenders end 1 px above its line, so 7 over and
   10 under. Line 2 sits under line 1's words, with the mark hanging to their left, like every glance
   and stop row. */
.ds-confirm-list > .ds-confirm-alert { padding: calc(var(--sp-2) - 1px) calc(var(--sp-3) + 2px) calc(var(--sp-2) + 2px) var(--sp-3); border-radius: var(--r-control); background: var(--warn-soft); }
.ds-confirm-alert .ds-confirm-detail > span { display: inline-block; max-width: 100%; overflow: hidden; text-overflow: ellipsis; vertical-align: top; }
.ds-confirm-list > .ds-confirm-alert .gl-text { color: var(--text); }
.ds-confirm-list > .ds-confirm-alert .ds-confirm-detail { color: var(--muted); }
.ds-confirm-payoff { margin: 0; color: var(--muted); }
.ds-confirm-payoff b { color: var(--text); }   /* bold as a glance row's count */
.ds-confirm-note { margin: 0; font-size: var(--fs-meta); line-height: var(--lh-meta); color: var(--muted); }   /* muted, not hint: the hint grey is 4.5:1 on the raised surface */
.ds-confirm-type { display: flex; flex-direction: column; gap: var(--sp-2); color: var(--muted); }
.ds-confirm-type b { color: var(--text); }
.ds-confirm-type input { width: 100%; }
.dlg-foot.ds-confirm-foot { justify-content: flex-end; gap: var(--sp-3); margin: var(--sp-2) calc(var(--pad-card-x) * -1) 0; padding: var(--sp-4) var(--pad-card-x); border-top-color: var(--border); }   /* --border-subtle vanishes on the raised surface */
.ds-confirm-foot > .btn { min-width: 112px; }
/* In the dialog the ring is text ink, so it never sits blue beside the blue verb (#90). */
dialog.confirm :focus-visible, dialog.confirm .is-focus { outline-color: var(--text); }
dialog.confirm .btn:not(.primary), dialog.confirm input:not(:focus-visible) { border-color: var(--border-control-raised); }   /* 3:1 on the raised surface */
dialog.confirm .btn:not(.primary):is(:hover, .is-hover):not(:disabled) { background: var(--surface-3); }   /* the hover step, over the raised surface */
.spacer { flex: 1; }

/* Ctrl+K: find a page, an action, or a section of the page it was opened from. */
dialog.palette { width: min(600px, calc(100vw - 48px)); margin-top: 12vh; }
.pal-input { display: flex; align-items: center; gap: var(--sp-3); padding: 0 var(--pad-card-x); border-bottom: 1px solid var(--border-subtle); color: var(--text-hint); }
.pal-input:focus-within { box-shadow: inset 0 -2px 0 var(--focus); }
.pal-input input { flex: 1; height: 52px; border: 0; padding: 0; background: transparent; color: var(--text); font-size: var(--fs-body); line-height: var(--lh-body); }
.pal-input input:focus-visible { outline: 2px solid transparent; }   /* the row's underline is the focus mark */
.pal-list { list-style: none; margin: 0; padding: var(--sp-1); max-height: min(52vh, 440px); overflow-y: auto; }
.pal-row { display: flex; align-items: center; gap: var(--sp-3); min-height: var(--ctl-h-md); padding: 0 var(--sp-3); border-radius: var(--r-control); cursor: pointer; }
.pal-row .ds-icon { color: var(--text-hint); }
.pal-row.at { background: var(--accent-soft); }
.pal-row.danger .pal-label { color: var(--bad); }
.pal-label { flex: none; font-weight: 500; white-space: nowrap; }
.pal-hint { flex: 1; min-width: 0; color: var(--muted); font-size: var(--fs-meta); line-height: var(--lh-meta); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pal-kind { flex: none; margin-left: auto; color: var(--text-hint); font-size: var(--fs-label); line-height: var(--lh-label); text-transform: uppercase; letter-spacing: .07em; }
.pal-none { padding: var(--sp-3); color: var(--muted); }
.pal-foot { display: flex; align-items: center; gap: var(--sp-4); padding: var(--sp-2) var(--pad-card-x); border-top: 1px solid var(--border-subtle); color: var(--text-hint); font-size: var(--fs-meta); line-height: var(--lh-meta); }
.pal-foot kbd { font: inherit; padding: 0 var(--sp-1); border: 1px solid var(--border); border-radius: var(--r-chip); color: var(--muted); }
.toast { position: fixed; bottom: 22px; left: 50%; transform: translateX(-50%); z-index: var(--z-tip); background: var(--text); color: var(--bg); padding: 9px var(--sp-4); border-radius: var(--r-panel); font-weight: 500; box-shadow: var(--shadow-2); }

/* --- Tools ----------------------------------------------------------------------------------- */
.table.tools tbody tr { cursor: pointer; }
.table.tools tbody tr:hover td { background: var(--surface-2); }
.table.tools tbody tr.sel td { background: var(--accent-soft); }
.table.tools td:first-child { width: 28%; }
.table.tools td { width: 36%; }
.tool-sides { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 28px; }
.tool-sides h3 { font-size: var(--fs-label); line-height: var(--lh-label); font-weight: 600; text-transform: uppercase; letter-spacing: .07em; color: var(--muted); margin: 0 0 var(--sp-2); }
ul.plain { list-style: none; margin: 0 0 6px; padding: 0; }
ul.plain li { padding: var(--sp-1) 0; }
.path { font-family: ui-monospace, "Cascadia Mono", Consolas, monospace; font-size: var(--fs-meta); line-height: var(--lh-meta); color: var(--muted); word-break: break-all; }
.ident { border-top: 1px solid var(--border-subtle); padding-top: 10px; margin-top: 10px; }
.ident-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 6px; }
.fact { display: grid; grid-template-columns: 130px minmax(0, 1fr); gap: 10px; padding: 5px 0; align-items: start; }
.fact > span { color: var(--muted); font-size: var(--fs-meta); line-height: var(--lh-meta); padding-top: 2px; }
.fact > div { min-width: 0; }
.fact i { font-style: normal; color: var(--text-hint); margin-left: 3px; }
details.fp summary { cursor: pointer; color: var(--muted); font-size: var(--fs-meta); line-height: var(--lh-meta); margin-top: 10px; }
details.fp > summary, details.grp > summary { list-style: none; }
details.fp > summary::-webkit-details-marker, details.grp > summary::-webkit-details-marker { display: none; }
details.fp > summary::before, details.grp > summary::before { content: "\25B8"; display: inline-block; width: var(--fold-indent); color: var(--text-hint); transition: transform var(--dur-fast) var(--ease-out); }
details.fp[open] > summary::before, details.grp[open] > summary::before { transform: rotate(90deg); }
details.fp .table td { padding-top: 5px; padding-bottom: 5px; }
.hist { margin-top: 18px; border-top: 1px solid var(--border-subtle); padding-top: var(--sp-3); }
.hist h4 { margin: 0 0 var(--sp-1); font-size: var(--fs-dense); line-height: var(--lh-dense); }
.hist-repo { margin-top: var(--sp-2); font-size: var(--fs-meta); line-height: var(--lh-meta); }
.hist-log { list-style: none; margin: 10px 0 0; padding: 0; }
.hist-log > li { border-top: 1px solid var(--border-subtle); }
.hist-row { padding: 7px var(--sp-1); cursor: pointer; font-size: var(--fs-meta); line-height: var(--lh-meta); border-radius: var(--r-chip); }
.hist-row:hover { background: var(--surface-2); }
.hist-log > li.open > .hist-row { background: var(--accent-soft); }
.cause { font-size: var(--fs-meta); line-height: var(--lh-meta); color: var(--muted); margin-top: 2px; }
.hdiff { margin: 6px 0 10px; }
.hdiff-head { display: flex; gap: var(--sp-2); align-items: center; flex-wrap: wrap; margin-bottom: var(--sp-1); }
.hdiff pre { margin: 0; max-height: 320px; overflow: auto; background: var(--surface-2); border-radius: var(--r-chip); padding: var(--sp-2) 10px; font-family: ui-monospace, "Cascadia Mono", Consolas, monospace; font-size: var(--fs-meta); line-height: 1.5; white-space: pre-wrap; word-break: break-all; }
.hdiff .add { color: var(--ok); }
.hdiff .del { color: var(--bad); }
.hdiff .hunk { color: var(--text-hint); }
.cmp-pick { display: flex; align-items: center; gap: var(--sp-2); flex-wrap: wrap; margin-bottom: var(--sp-2); }
.cmp-pick select { min-width: 0; flex: 1; }
details.grp { border-top: 1px solid var(--border-subtle); }
details.grp > summary { cursor: pointer; padding: var(--sp-2) 0; }
details.grp > summary:hover b { color: var(--link); }
details.grp > summary .act-mark { margin-top: 0; vertical-align: -3px; }
.grp-body { padding: 0 0 var(--sp-2) var(--fold-indent); }

/* --- Repos and Places ------------------------------------------------------------------------ */
/* Repos (#11, round 6b) on the table spec: fixed columns, one line a cell (the branch cut with its
   name in the tooltip), the size right-aligned with the 24 px gutter, a row's second line muted. */
.table.repos { table-layout: fixed; }
.table.repos th:nth-child(2) { width: 168px; }   /* Branch */
.table.repos th:nth-child(3) { width: 196px; }   /* Changes: "1870 changed · 6 to push" */
.table.repos th:nth-child(4) { width: 100px; }   /* On disk, with its gutter */
.table.repos th:nth-child(5) { width: 84px; }    /* Active */
.table.repos th:nth-child(6) { width: 160px; }   /* "Open in Claude" and the "..." */
.table.repos :is(.rp-branch, .rp-git) { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* A cell that says several things (DS.Parts): the parts that don't fit give way to "+N", muted, so the
   cell is never cut (#133: Repos' Changes). */
.ds-part-more { color: var(--muted); }
.table.repos .rp-branch > span { display: block; overflow: hidden; text-overflow: ellipsis; }
.table.repos .rp-name { overflow: hidden; }
.table.repos .rp-sub { color: var(--muted); font-size: var(--fs-meta); line-height: var(--lh-meta); margin-top: 2px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }   /* one line */
/* Repos' own rows on the template's heights (M79): a one-line row is 34 px, as every DS.Table row; a
   row with a second line is 53 (--row-table-2), whether that line is text or a tag. Under the row's
   1 px rule, every cell's first line is a 33 px line box, so the name, the branch, the changes, the
   verb and the "..." share the one-line rows' centre; the second line hangs under the name in an
   18 px box, as close to it as before (a tag no longer makes its line taller). */
.table.repos.rich > tbody > tr.repo-row > td { height: var(--row-table); padding-top: 0; padding-bottom: 0; line-height: calc(var(--row-table) - 1px); }
.table.repos.rich > tbody > tr.repo-row:has(.rp-sub) > td { height: var(--row-table-2); }
/* The name's line is centred where the other cells' are (2 + 29 / 2 = 33 / 2), and the second line
   tucks 3 px under it, so the two lines sit as far apart as before. */
.table.repos.rich > tbody > tr.repo-row > td.rp-name > div:first-child { padding-top: 2px; line-height: 29px; }
.table.repos.rich .rp-sub { height: 18px; line-height: 18px; margin-top: -3px; }
.table.repos.rich .rp-sub .tag { vertical-align: top; }
/* The actions keep the table's own line: on the 33 px one, the "..." menu's line box grows and lifts
   its dots 3 px over the verb's middle. */
.table.repos.rich > tbody > tr.repo-row > td.actions > .row-actions { display: flex; height: calc(var(--row-table) - 1px); line-height: var(--lh-dense); }
.table.repos .path { overflow-wrap: anywhere; }
/* Places as master-detail (P4, round 6e): the page fills the window and doesn't scroll; the tool
   list and the pane scroll on their own. The pane's scrollbar sits in its card's padding, so the
   rows' "..." ends at the same x as on every other page. */
.page.fill { height: 100%; min-height: 0; }
.page.fill > .split-slot { flex: 1; min-height: 0; }
.page.fill .split { height: 100%; align-items: stretch; }
.page.fill :is(.split-list, .split-pane) { max-height: none; height: 100%; }
.page.fill .split-list { position: static; }
.pl-title { display: flex; align-items: center; flex-wrap: wrap; gap: var(--sp-2); width: 100%; }
.pl-title h2 { margin-right: var(--sp-1); }
.pl-title > .group-meta { margin-left: auto; }   /* the head's one form: the side and count at the right (#119) */
.pl-toolbar { display: flex; align-items: center; gap: var(--sp-3); width: 100%; }
.pl-lock { color: var(--muted); }   /* holding a secret is a fact: grey, like the "secret" chips (#116) */
.pl-lock .ds-icon { width: 14px; height: 14px; }
.table.places { table-layout: fixed; }
.table.places th:nth-child(1) { width: 84px; } .table.places th:nth-child(3) { width: 164px; }   /* "Show in Explorer" and the "..." fit, so every row's "..." keeps one x */
.table.places td { vertical-align: middle; }
.table.places .path { overflow: hidden; }
.pl-path { display: flex; align-items: baseline; gap: 6px; min-width: 0; font: var(--fs-meta)/var(--lh-meta) "Cascadia Mono", Consolas, monospace; }
.pl-path > .midpath { flex: 0 1 auto; min-width: 0; }
.pl-path > .muted { flex: none; font-family: inherit; }
/* Free up space's backup files (DS.Table): each path on one line, cut in the middle (the file name
   stays), the side chip after it on a file the head's side doesn't cover. */
.table.baks { table-layout: fixed; }
.table.baks th:nth-child(2) { width: 96px; }    /* File size, with its gutter */
.table.baks th:nth-child(3) { width: 248px; }   /* "Too large to keep in history first." */
.table.baks .path { overflow: hidden; }
/* Opened, a repo's row lands under its table's sticky head (28 high), and under any bar the head
   sticks under (--stick-under), with its top pixel row behind the head: the head is then one pixel
   past its resting place, so it's stuck and draws its stuck form (the group's name, the --border
   rule), the table's first row included. At 28 the first row's head sat exactly at rest, which isn't
   stuck: "REPO" over the hairline (#135 = M76). Until the template patch took the first row's top
   border off (#132), half of it made the head 28.5 high, so 28 left it half a pixel past rest. */
.table.repos tr.repo-row { cursor: pointer; scroll-margin-top: calc(var(--stick-under, 0px) + 27px); }
.table.repos .rp-sub .tag { margin-right: var(--sp-1); }
.table.repos tr.repo-row:hover td { background: var(--surface-2); }
.table.repos tr.repo-row.sel td { background: var(--accent-soft); }
.rp-detail > * + * { margin-top: var(--sp-3); }
/* Its worktrees are a bounded list (#129): the list's box reaches the row's right edge instead of the
   nested table, so an opened list scrolls without a sideways bar, and its foot does too, the count at
   the rows' right edge; the foot keeps its own spacing. */
.row-detail .bounded:has(> .table.nested), .row-detail .bounded:has(> .table.nested) + .bounded-foot { margin-right: calc(var(--sp-4) * -1); }
.row-detail .bounded > .table.nested { width: 100%; margin-right: 0; }
.rp-detail > .bounded-foot { margin-top: var(--sp-2); }
.rp-facts .fact { grid-template-columns: 140px minmax(0, 1fr); }
/* Recent commits (#102a): the hash, the subject on one line cut with "…", and the age in a muted
   column at the right edge, the author before it only when it isn't you. */
.rp-commits { list-style: none; margin: 0; padding: 0; }
.rp-commits li { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; column-gap: var(--sp-2); align-items: baseline; }
.rp-commits code { color: var(--muted); }
.rp-commits .rp-subj { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rp-commits .rp-when { color: var(--muted); white-space: nowrap; text-align: right; padding-left: var(--sp-4); font-variant-numeric: tabular-nums; }
.rp-files { font-family: ui-monospace, "Cascadia Mono", Consolas, monospace; font-size: var(--fs-meta); line-height: var(--lh-meta); }
.rp-detail .card-actions.rp-verbs { flex-wrap: nowrap; margin-top: var(--sp-3); }   /* one row of verbs, right under the facts (#102e) */
.rp-detail details.grp > summary { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }   /* one line; the rest when it's opened (#102d) */
.rp-diff { margin: 0 0 var(--sp-3); }
.diff-line { font-weight: 600; margin-bottom: var(--sp-3); }
.agent-cards { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--sp-3); }
.agent-card { background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-panel); padding: var(--sp-3) 14px; min-width: 0; }
.agent-card.warn { border-color: var(--warn); }
.agent-card.off { opacity: .7; }
.agent-head { display: flex; align-items: center; gap: 10px; margin-bottom: 6px; }
.agent-head h3 { margin: 0; flex: 1; }

/* --- Packages, Setups, Servers, Help --------------------------------------------------------- */
/* Servers (#10, #96; DESIGN.md "Tables"): a table per group, the biggest first; memory right-
   aligned in tabular figures with a 24 px gutter after it, so a figure never reads into the next
   column ("10.5 GB 21h ago"); one port and "+2", never a wrapped port cell. */
.table.servers { table-layout: fixed; }
.table.servers th:nth-child(1) { width: 104px; }   /* Port; then the chevron's 24 px gutter (.ds-disc) */
.table.servers th:nth-child(4) { width: 180px; }   /* Folder */
.table.servers th:nth-child(5) { width: 108px; }   /* Memory, a number column with its gutter */
.table.servers th:nth-child(6) { width: 84px; }    /* Started */
.table.servers th:nth-child(7) { width: 176px; }   /* "Open in browser" and the "..." with room to spare */
.table.servers .sv-port { white-space: nowrap; }
.table.servers .sv-port .muted { font-weight: 400; }
.table.servers .sv-folder { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.table.servers .sv-line { display: flex; align-items: baseline; gap: var(--sp-2); min-width: 0; margin-top: 2px; }
.table.servers .sv-sub { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--muted); font-size: var(--fs-meta); line-height: var(--lh-meta); }
.table.servers .sv-line > .muted { flex: none; }
/* One line at rest (P6, round 6e): the name, then what tells it apart, muted, on the same line; the
   command line, pid and notes in the row's detail, behind the chevron or a click on the row. */
.table.servers tr.sv-row { cursor: pointer; }
.table.servers td { vertical-align: middle; }
.table.servers .sv-name { display: flex; align-items: center; gap: var(--sp-2); min-width: 0; white-space: nowrap; }
.table.servers .sv-name .nm { flex: none; }
.table.servers .sv-name .row-side { margin-left: 0; }   /* the row's gap spaces it */
.table.servers .sv-note { display: inline-flex; flex: none; color: var(--warn); }
.disc { display: inline-grid; place-items: center; width: 24px; height: 24px; padding: 0; border: 0; background: none; border-radius: var(--r-chip); color: var(--text-hint); cursor: pointer; flex: none; }
.disc:hover { background: var(--surface-2); color: var(--text); }
.disc .chev { width: 14px; height: 14px; transition: transform var(--dur-fast) var(--ease-out); }
.disc[aria-expanded="true"] > .chev { transform: rotate(90deg); }
.table.servers tr.sv-open > td { border-bottom: 0; }
.table.servers tr.sv-detail > td { padding: 0 0 var(--sp-3) 0; border-top: 0; }
.sv-cmd { margin-left: 104px; display: flex; flex-direction: column; gap: var(--sp-2); padding: var(--sp-2) var(--sp-3); background: var(--surface-2); border-radius: var(--r-control); }
.sv-cmd code { font: var(--fs-meta)/1.5 "Cascadia Mono", Consolas, monospace; color: var(--text); word-break: break-all; user-select: text; }
.sv-facts { display: flex; flex-wrap: wrap; align-items: center; column-gap: var(--sp-4); row-gap: var(--sp-1); color: var(--muted); font-size: var(--fs-meta); line-height: var(--lh-meta); }
.sv-facts .btn { margin-left: auto; }
/* Host names (#94, P2): name and address in the code face, the side as a chip; each side's count in the head. */
.table.hosts { table-layout: fixed; }
.table.hosts td { vertical-align: middle; }
.table.hosts th:nth-child(2) { width: 180px; }
.table.hosts .hn { display: flex; align-items: center; min-width: 0; }
.table.hosts .hn-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.table.hosts td.path { font: var(--fs-meta)/var(--lh-meta) "Cascadia Mono", Consolas, monospace; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sv-hosts-side { display: inline-flex; align-items: center; gap: var(--sp-1); margin-left: var(--sp-3); }
.sv-head { display: inline-flex; align-items: center; gap: var(--sp-1); }
/* Packages (round 6e, row 7): Updates and All are each one table on the template, with a Manager
   column; the manager chips and the picked manager's Update all over it. */
.table.pk { table-layout: fixed; }
.table.pk th:nth-child(2) { width: 208px; }   /* Manager: "npm · Node v24.14.0" */
.table.pk th:nth-child(3) { width: 136px; }   /* Installed */
.table.pk th:nth-child(4) { width: 152px; }   /* Latest, its arrow on the column's x */
.table.pk th:nth-child(5) { width: 112px; }   /* "Update" and the "..." */
.table.pk :is(.pk-name, .pk-mgr, .pk-ver) { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.table.pk.picked td.pk-mgr { color: var(--text-hint); }   /* one manager picked: its name on every row is context (owner, §9) */
.pk-tools { display: flex; align-items: flex-start; gap: var(--sp-3); margin-bottom: var(--sp-3); }
.pk-tools > .chip-row { flex: 1; min-width: 0; }
.pk-tools > .btn { flex: none; }
.pk-note { margin: calc(var(--sp-1) * -1) 0 var(--sp-3); }
.newer { display: inline-flex; align-items: center; gap: 2px; color: var(--warn); font-weight: 600; }
.newer .ds-icon { width: 13px; height: 13px; }
.head-tools { display: flex; align-items: center; gap: var(--sp-2); flex: none; }
.chip-at { display: inline-flex; align-items: center; gap: var(--sp-1); margin: var(--sp-1) var(--sp-3) 0 0; color: var(--muted); }
code.cmd { display: block; max-width: 100%; font-size: var(--fs-meta); line-height: var(--lh-meta); color: var(--text-hint); margin-top: 2px; }
.notes { font-size: var(--fs-meta); color: var(--muted); max-height: 220px; overflow-y: auto; line-height: 1.5; }
.term { text-decoration: underline dotted var(--text-hint); text-underline-offset: 3px; cursor: help; }
.term:is(:hover, :focus-visible) { text-decoration-color: var(--link); color: var(--text); }
body.no-terms .term { text-decoration: none; cursor: inherit; }
/* 8 over, 11 under: the line's own leading puts 4 above the capitals and 1 under the descenders, so
   the ink sits 12 from every edge (M42). */
.tip { position: fixed; z-index: var(--z-tip); max-width: 300px; padding: 8px var(--sp-3) 11px; border-radius: var(--r-control); border: 1px solid var(--tip-edge); background: var(--tip-bg); color: var(--tip-fg); font-size: var(--fs-meta); line-height: var(--lh-meta); box-shadow: var(--shadow-tip); pointer-events: none; }
.tip b { display: block; margin-bottom: 2px; }
.tip-lines { white-space: pre-line; }   /* one item a line (a strip bar's runs): no line ends on a separator */
.tip-more { margin-top: var(--sp-1); opacity: .65; }
.help-panel { position: fixed; top: 0; right: 0; bottom: 0; width: var(--panel-w); z-index: var(--z-panel); background: var(--surface); border-left: 1px solid var(--border); box-shadow: var(--shadow-2); display: flex; flex-direction: column; }
.help-head { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-2); padding: 18px var(--pad-card-x) 10px; }
.help-scroll { overflow-y: auto; padding: 0 var(--pad-card-x) var(--sp-6); font-size: var(--fs-meta); line-height: 1.5; }
.help-scroll p { margin: var(--sp-1) 0 10px; }
.help-terms > li .muted { margin-top: 2px; line-height: 1.5; max-width: 75ch; }
.help-terms > li.focus b { color: var(--link); }
@media (min-width: 1500px) { body.with-help main { padding-right: calc(var(--panel-w) + 30px); } }

/* --- Dotfiles and sizes ---------------------------------------------------------------------- */
pre.file-view { white-space: pre-wrap; word-break: break-word; font-size: var(--fs-meta); line-height: 1.5; background: var(--surface-2); border-radius: var(--r-control); padding: 10px var(--sp-3); margin: 6px 0 0; }
.dl { display: block; }
.dl.del { color: var(--bad); background: var(--bad-soft); }
.dl.add { color: var(--ok); background: var(--ok-soft); }
/* Dotfiles (round 6e, row 8): three tabs, each one table on the template, its rows 34 px. Differ and
   Shared open a name in place to its copies (P3), a nested table on the same columns, so the two share
   x; One copy's rows say where the copy is instead, under the same empty gutter, so a name keeps one
   x on every tab. A name's line: the name, its side chip when it's mostly on the other side, the kind
   of place muted, then its grey facts (holds secrets, master). */
.table.df { table-layout: fixed; }
.table.df td { vertical-align: middle; }
.table.df tr.df-opens { cursor: pointer; }
.table.df :is(.df-name, .df-where) { overflow: hidden; }
.table.df .df-nm { display: flex; align-items: center; min-width: 0; white-space: nowrap; }
.table.df .df-nm > :is(b, .df-place) { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.table.df .df-nm > .tag { flex: none; margin-left: var(--sp-2); }
.table.df .df-scope { flex: 0 100 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; margin-left: var(--sp-2); color: var(--muted); font-size: var(--fs-meta); line-height: var(--lh-meta); }
.table.df .df-folder { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.table.df tr.df-copy.picked > td { background: var(--accent-soft); }
.table.df-differ th:nth-child(3), .table.df-shared th:nth-child(3) { width: 96px; }   /* Copies, a number column with its gutter */
.table.df-differ th:nth-child(4) { width: 144px; }   /* Versions: "12 of 53 differ" */
.table.df-differ th:nth-child(5), .table.df-shared th:nth-child(4) { width: 100px; }   /* Changed */
.table.df-differ th:nth-child(6), .table.df-shared th:nth-child(5) { width: 176px; }   /* "Compare with picked" and the "..." */
.table.df-one th:nth-child(3) { width: 240px; }   /* Folder: the repo, or "home folder" */
.table.df-one th:nth-child(4) { width: 100px; }   /* Changed */
.table.df-one th:nth-child(5) { width: 176px; }   /* "View" and the "..." */
.size { font-weight: 600; }
/* Tools' drill-in (P5, round 6e row 10): it replaces the table. "← Tools" over the tool's name and
   what it is, then its own tabs and their cards, the page's stack gap between each. */
.drill { display: flex; flex-direction: column; gap: var(--gap-stack); }
.drill-head { display: flex; flex-direction: column; align-items: flex-start; gap: var(--sp-1); }
.drill-head > .btn { margin-left: calc(var(--sp-2) * -1); }
.drill-title { display: flex; align-items: baseline; gap: var(--sp-3); min-width: 0; }
.drill-title h2 { margin: 0; }
.ident-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ident-counts { margin-top: var(--sp-1); }
.ident .sub-h { margin-top: var(--sp-3); }
/* Help as master-detail (P4, round 6e row 11): a guide reads as its parts, each a small head over its
   text, at a reading measure; a part the search matched carries the selection tint's edge. */
.hp-guide > * { max-width: 72ch; }
.hp-sec { padding-top: var(--sp-4); }
.hp-sec h3 { margin: 0 0 var(--sp-1); }
.hp-sec p { margin: 0; }
.hp-sec.hp-hit { box-shadow: inset 2px 0 0 var(--accent); padding-left: var(--sp-3); margin-left: calc(var(--sp-3) * -1); }
.hp-guide > .hint { margin-top: var(--sp-4); }
.hp-guide > .card-actions { margin-top: var(--sp-4); }
