/* ============================================================================
 * Navigation — sidebar rail, horizontal tabs, breadcrumbs. One token-driven
 * class family (ui-nav__…) so every variant re-themes across accents +
 * light/dark. appShell() draws its rail from sidebarNav(), so this file is the
 * page shell's rail as well as a standalone component. States are pure tokens.
 * ========================================================================== */

.ui-nav { font-family: var(--font-sans); }
.ui-nav :where(ul, ol) { list-style: none; margin: 0; padding: 0; } /* floor, not ceiling */

/* -- Sidebar rail -------------------------------------------------------- */
/* The rail's two widths, and the one place they are written. --ui-nav-col is the
   open column. --ui-nav-strip is twice a row's own glyph centre — the row's
   padding plus half a glyph — so a strip that wide has the glyph standing in the
   middle of it, exactly where it stood in the open rail. The fold travels that
   width on the rail and on the boxes inside it, so a folded rail is only as wide
   as it draws and has nothing to clip. layout.css adds the shell rail's own
   inset to both. stories/apps/shell-states.test.js derives the strip from the
   resolved cascade and refuses a number that has drifted from it.
   Declared for the shell as well as the nav, because the shell's rail is this
   nav with an inset around it, and two copies of 41 is the drift itself. */
.ui-nav--side,
.ui-app { --ui-nav-col: 216px; --ui-nav-strip: 41px; }
.ui-nav--side {
  display: flex;
  flex-direction: column;
  gap: 4px;
  width: var(--ui-nav-col);
  /* The width is the only property the fold travels. Nothing is clipped here:
     inside the shell it is the rail that clips, and a clip of its own would have
     been a second scroll box cutting the rows off at the rail's height. */
  transition: width var(--dur-med) var(--ease);
}
/* A block takes a width of its own rather than the rail's travelling one, and travels
   it on the RAIL's clock. Declared here, not beside the fold, so the way OUT carries it:
   a block with no clock snapped open while the rail was still a strip wide. */
.ui-nav--side > * {
  width: var(--ui-nav-col); flex: none;
  transition: width var(--dur-med) var(--ease);
}
.ui-nav__section + .ui-nav__section { margin-top: 14px; }
.ui-nav__list { display: flex; flex-direction: column; gap: 2px; }
.ui-nav__cap {
  /* rank: label */
  /* Words, never a control, at BOTH widths — as __label, __badge and __caret below.
     why: docs/components.md#a-folded-rail-takes-the-pointer-only-where-it-draws */
  pointer-events: none;
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  color: var(--text);
  padding: 4px 12px 8px;
  /* Goes on the labels' clock — a section heading is words, and the fold takes
     every word on the rail together. */
  transition: opacity var(--dur-fast) var(--ease);
}

/* Item row — link, group toggle, and leaf share the same skin */
.ui-nav__item {
  position: relative;
  display: flex;
  align-items: center;
  gap: 11px;
  width: 100%;
  padding: 9px 12px;
  border-radius: 10px;
  text-decoration: none;
  font-size: var(--text-base);
  font-weight: 400;
  line-height: 1.2;
  background: none;
  border: 0;
  cursor: pointer;
  text-align: left;
  font-family: inherit;
  transition: background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}
.ui-nav .ui-nav__item { color: var(--text); } /* (0,2,0): a host sheet's a:link is (0,1,1) — why: docs/components.md#the-page-shell */
.ui-nav__item:hover { background: color-mix(in srgb, var(--surface) 50%, transparent); /* code-bg: inherit — The wash keeps the containing ground. */ color: var(--strong); }
.ui-nav__item.is-active {
  background: var(--surface); /* code-bg: inherit — control paint; the containing surface is the ground, for a chip and for a band alike. */
  color: var(--strong);
  font-weight: 500;
}
/* The current row's one mark is a plate, and nothing closes it: on a rail row an
   outline means focus and only focus. The plate is the quiet fill a rung off the
   ground the rail stands on, so layout.css takes it the next rung where the rail
   is itself --surface. #475 r33/r34. why: docs/components.md#the-page-shell */

.ui-nav__item:focus-visible { outline: var(--ring); outline-offset: var(--ring-offset); }
.ui-nav__item.is-active:focus-visible { outline: var(--ring); outline-offset: var(--ring-offset); }

.ui-nav__ic { display: inline-flex; flex: none; }
.ui-nav__ic svg { width: 17px; height: 17px; stroke: currentColor; fill: none; stroke-width: 2.2; opacity: 0.72; }
/* The glyph brightens with its row and takes the row's ink, not the accent. A
   rail row carries no accent at all since #475: the plate above is what means
   "here", and the glyph's own step to full ink is the other half of that pair.
   A glyph in --accent beside it was the same sentence said twice, and beside an
   accent counter it was said three times. See #429 and #475. */
.ui-nav__item.is-active .ui-nav__ic svg,
.ui-nav__item.is-current .ui-nav__ic svg { opacity: 1; stroke: currentColor; } /* motion: still — the glyph brightens with its row, whose own highlight already transitions */
.ui-nav__label {
  flex: 1 1 auto; min-width: 0;
  pointer-events: none; /* words, not a control — see .ui-nav__cap */
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  /* The words go before the closing edge reaches them, which is most of why the
     fold is worth animating — a label cut through by that edge reads as the rail
     eating it. --dur-fast against the width's --dur-med, as the reference times
     its own. */
  transition: opacity var(--dur-fast) var(--ease);
}

/* Destructive row (sign out, revoke). Body ink at rest, --pink once a pointer or
   the keyboard reaches it — as .ui-btn--danger and .ui-dropdown__item do. */
.ui-nav__item.is-danger { color: var(--text); }
.ui-nav__item.is-danger:hover { background: var(--glow-pink); /* code-bg: inherit — a wash paints over a ground and behind a chip, so the opaque ground below it is the step. */ color: var(--pink); }
/* Tabbing onto it is the same "about to click this" the pointer means. The ring
   says where you are; only this says what the row does. */
.ui-nav__item.is-danger:focus-visible { background: var(--glow-pink); /* code-bg: inherit — a wash paints over a ground and behind a chip, so the opaque ground below it is the step. */ color: var(--pink); }
/* An unavailable row uses disabled ink directly; opacity would also fade its
   background and pull its label toward the rail behind it (#220). */
.ui-nav__item.is-disabled { /* muted-ink: state — unavailable control */ color: var(--disabled-ink); cursor: default; pointer-events: none; }

/* Per-item badge / counter */
.ui-nav__badge {
  flex: none;
  pointer-events: none; /* a count, not a control — see .ui-nav__cap */
  min-width: 20px;
  height: 19px;
  padding: 0 6px;
  border-radius: var(--radius-pill);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: var(--text-xs);
  font-weight: 600;
  line-height: 1;
  background: var(--surface); /* code-bg: inherit — decorative or text-only paint; nothing nested reads a ground from it. */
  color: var(--text);
  /* The count fades with the words. It is never lost: sidebarNav() spells it
     into the row's aria-label, so "Pending 3" is what a reader hears at either
     width. */
  transition: opacity var(--dur-fast) var(--ease);
}
.ui-nav__badge.is-accent { background: var(--glow-purple); /* code-bg: inherit — a wash paints over a ground and behind a chip, so the opaque ground below it is the step. */ color: var(--accent); }
.ui-nav__badge.is-live { background: var(--chip-success-fill); /* code-bg: inherit — decorative or text-only paint; nothing nested reads a ground from it. */ color: var(--chip-success-ink); }
.ui-nav__badge.is-danger { background: var(--glow-pink); /* code-bg: inherit — a wash paints over a ground and behind a chip, so the opaque ground below it is the step. */ color: var(--pink); }
.ui-nav__item.is-active .ui-nav__badge.is-neutral { background: var(--surface); /* code-bg: inherit — decorative or text-only paint; nothing nested reads a ground from it. */ color: var(--strong); }
/* Same shape, one row up: on the current row the accent counter drops both the
   wash and the accent and reads as the neutral one beside it. The row already
   carries the one mark it is allowed — the plate — and the count is a number,
   not a second answer to "where am I". It also retires the pair #157
   recorded: accent ink on --surface fell under WCAG AA in four of the eight
   theme x accent cells (4.08 in dark Nebula), and no alpha cleared it. Nothing
   now paints that pair. See #429 and docs/foundations.md#colour-and-contrast. */
.ui-nav__item.is-active .ui-nav__badge.is-accent { background: var(--surface); /* code-bg: inherit — decorative or text-only paint; nothing nested reads a ground from it. */ color: var(--strong); }

/* Collapsible group */
.ui-nav__group { display: flex; flex-direction: column; }
.ui-nav__caret {
  flex: none;
  pointer-events: none; /* a mark on the toggle, not a control — see .ui-nav__cap */
  width: 7px; height: 7px;
  border-right: 1.6px solid var(--muted);
  border-bottom: 1.6px solid var(--muted);
  transform: rotate(-45deg);
  transition: transform var(--dur-fast) var(--ease), opacity var(--dur-fast) var(--ease);
}
.ui-nav__group.is-open > .ui-nav__toggle .ui-nav__caret { transform: rotate(45deg); }
.ui-nav__sub {
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin: var(--space-1) 0 var(--space-1) var(--space-4);
  padding-left: var(--space-3);
  border-left: 1px solid var(--border);
}
.ui-nav__sub[hidden] { display: none; }
/* An opened group's list fades in and drops --space-1 into place. wireNav() adds
   the class when the reader opens it, never at first render. */
.ui-nav__sub.is-entering {
  --m-dist: var(--space-1);
  animation: m-slide-down var(--dur-fast) var(--ease-out) both;
}
.ui-nav__item--sub { font-size: calc(var(--text-base) - 0.5px); padding: 7px 12px; }
/* A nested current row takes the plate whole, like a top-level one. It used to
   take neither half — the bar hung back onto the guide hairline and the plate's
   own hairline was switched off so the two would not stack — and a fill with no
   edge is not a mark the kit accepts. See #475. */

/* Footer slot (divider + trailing links, e.g. sign-out) */
.ui-nav__foot { margin-top: 12px; padding-top: 10px; border-top: 1px solid var(--border); }

/* A row with no glyph, on a rail folded to its glyphs, would be a blank target.
   It gets a dot on the glyph column instead — out of flow, so the open rail's
   labels stay where they are, and resting at nothing, so what the fold does is
   raise it rather than conjure it. 18px is the row's own 12px padding plus half
   a 17px glyph less half the dot: the column the glyph beside it stands on.
   sidebarNav() takes `icon` as optional at every level, sub rows included. */
.ui-nav--side .ui-nav__item:not(:has(.ui-nav__ic))::after {
  content: "";
  position: absolute;
  left: 18px; top: 50%;
  width: 5px; height: 5px;
  margin-top: -2.5px;
  border-radius: 50%;
  background: currentColor;
  opacity: 0;
  transition: opacity var(--dur-fast) var(--ease);
}

/* The nested list's indent, which the strip has no room for. It travels with the
   width rather than vanishing under it: the guide hairline thins to nothing and
   the children walk back onto the glyph column their parent stands on. */
.ui-nav__sub {
  transition: margin-inline-start var(--dur-med) var(--ease),
    padding-inline-start var(--dur-med) var(--ease),
    border-inline-start-width var(--dur-med) var(--ease);
}

/* Collapsed (icon-only) rail — the same fold the shell's rail makes. A group's
   children stay rows here, because wireNav() toggles the list's `hidden` attribute
   and nothing else, so folding .ui-nav__sub away left the toggle announcing a list it
   could not open. What goes is the indent and the words, and sidebarNav({ collapsed })
   hands each row its name as a `title` so a pointer can still read it. The shell's
   rail draws a chip of its own instead, on keyboard focus as well — see layout.css. */
.ui-nav--side.is-collapsed { width: var(--ui-nav-strip); }
/* Every box in the rail closes with it, whether it paints or not. A block that keeps
   the open column paints nothing and still takes the pointer off 175px of the page
   beside a positioned rail (#588); clipping it instead cut the rows' ring (#575).
   why: docs/components.md#a-folded-rail-takes-the-pointer-only-where-it-draws */
.ui-nav--side.is-collapsed > * { width: var(--ui-nav-strip); }
.ui-nav--side.is-collapsed .ui-nav__item { width: var(--ui-nav-strip); }
/* The heading is the one box that keeps the open column: its line breaks are the rail's
   height. Inert at both widths, so the column draws and takes nothing; the 175px it adds
   to a page's scrollable width is the one thing this rail does not promise. */
.ui-nav--side.is-collapsed .ui-nav__cap { width: var(--ui-nav-col); }
/* The row takes the rail's clock too, so its box IS the rail's box in every frame and
   not only at either end. Waiting out the words on a --dur-fast delay left the open
   column's hit area inside a half-shut rail. (Restates the base it replaces.) */
.ui-nav--side.is-collapsed .ui-nav__item {
  transition: background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease),
    width var(--dur-med) var(--ease);
}
/* What that delay was protecting, kept without it: the words hold their own width
   instead of being squeezed out by the closing row. They overflow it and cost nothing —
   inert at either width, and painting nothing at opacity 0. */
.ui-nav--side.is-collapsed .ui-nav__label { min-width: max-content; }
.ui-nav--side.is-collapsed .ui-nav__cap,
.ui-nav--side.is-collapsed .ui-nav__label,
.ui-nav--side.is-collapsed .ui-nav__badge,
.ui-nav--side.is-collapsed .ui-nav__caret { opacity: 0; }
.ui-nav--side.is-collapsed .ui-nav__sub {
  margin-inline-start: 0; padding-inline-start: 0; border-inline-start-width: 0;
}
.ui-nav--side.is-collapsed .ui-nav__item:not(:has(.ui-nav__ic))::after { opacity: 0.62; }

/* The current row on a folded rail: one plate on the glyph column, and nothing else.
   The open rail's 3px marker would stand in the rail's edge at this width, and a
   nested row would put it outside the rail; the hairline would be the same mark said
   twice. The plate is the strip, so it is centred on the glyph, and its fill is the
   rung the open row takes — one off the ground the rail stands on, which layout.css
   takes one further in the shell — so a rail marks the same row with the same
   material at both widths. The glyph's own step from 0.66 to full ink is the second
   half of that pair. `isolation` is what puts the plate behind the glyph: a
   positioned ::before paints over its row's content, and a negative z-index with no
   stacking context of its own would drop it behind the rail.
   why: #429 and #475 */
.ui-nav--side.is-collapsed .ui-nav__item.is-active { isolation: isolate; background: none; }
.ui-nav--side.is-collapsed .ui-nav__item.is-active::before {
  content: "";
  position: absolute;
  left: 0; top: 50%;
  width: var(--ui-nav-strip);
  height: 100%;
  border-radius: 10px;
  transform: translateY(-50%); /* motion: still — a mark on the current row, whose own highlight already transitions; this centres it, it does not travel */
  background: var(--surface); /* code-bg: inherit — The plate contains no focus target. */
  z-index: -1;
}
/* Nothing switches the hover wash off here: since #588 a folded row is only as wide
   as the rail draws, so the wash is the box the plate paints, a rung quieter. It is
   the whole answer a pointer gets outside the shell, where the floating name is
   layout.css's. (The `outline: none` that stood here switched off an edge #475
   removed.) #475 */

/* -- Horizontal tabs ----------------------------------------------------- */
.ui-nav--tabs {
  /* A scroll box clips at its padding edge, so the ring needs padding, not bare
     paint room. Equal negative margins give the row back its place on the gutter
     and in the flow, and the rule is painted as a background line one pixel above
     the padding — a border-bottom would sit below it and lift the active
     underline off the rule. */
  --ui-tabs-ring-room: var(--space-1);
  --ui-tabs-rule: 1px;
  --ui-tabs-ground: var(--bg);
  --ui-tabs-edge: color-mix(in srgb, var(--sheen) 12%, transparent);
  min-width: 0;
  max-width: calc(100% + 2 * var(--ui-tabs-ring-room));
  overflow-x: auto;
  padding: var(--ui-tabs-ring-room);
  margin: calc(-1 * var(--ui-tabs-ring-room)) calc(-1 * var(--ui-tabs-ring-room))
    calc(var(--ui-tabs-rule) - var(--ui-tabs-ring-room));
  display: flex;
  align-items: stretch;
  gap: 4px;
  /* Local covers hide the table-style shades when their edge is reached.
     The row rule stays above the covers and keeps its original position. */
  background-image:
    linear-gradient(var(--border), var(--border)),
    linear-gradient(to right, var(--ui-tabs-ground) 50%, transparent),
    linear-gradient(to left, var(--ui-tabs-ground) 50%, transparent),
    radial-gradient(farthest-side at 0 50%, var(--ui-tabs-edge), transparent),
    radial-gradient(farthest-side at 100% 50%, var(--ui-tabs-edge), transparent);
  background-repeat: no-repeat;
  background-position:
    center bottom calc(var(--ui-tabs-ring-room) - var(--ui-tabs-rule)),
    0 0, 100% 0, 0 0, 100% 0;
  background-size:
    calc(100% - 2 * var(--ui-tabs-ring-room)) var(--ui-tabs-rule),
    var(--space-6) 100%, var(--space-6) 100%, var(--space-3) 100%, var(--space-3) 100%;
  background-attachment: scroll, local, local, scroll, scroll;
}
/* Fitting rows keep overflow visible. Measurements retain the same padding and margins,
   so switching containment does not move the links. Unwired rows keep containment. */
.ui-nav--tabs[data-nav-fit] { overflow: visible; }
.ui-nav--tabs.is-pill { --ui-tabs-rule: 0px; gap: 6px; }
.ui-card .ui-nav--tabs { --ui-tabs-ground: var(--ui-card-ground); }
:root[data-theme="light"] .ui-nav--tabs {
  --ui-tabs-edge: color-mix(in srgb, var(--shadow-ink) 13%, transparent);
}
/* The row is a keyboard stop of its own only while it scrolls AND holds no focusable
   link — every tab disabled — and Chromium answers that stop with its black outline. It
   is a scroll region, so it takes the kit's inward band like the other six: an outset
   ring would be clipped by the very box that scrolls. #531's reading, on #429's row. */
.ui-nav--tabs:focus-visible { outline: var(--ring-scroll); outline-offset: var(--ring-scroll-offset); }
.ui-nav__tab {
  flex: none;
  position: relative;
  max-width: 100%;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 11px 14px;
  color: var(--text);
  text-decoration: none;
  font-size: calc(var(--text-base) - 0.5px);
  font-weight: 500;
  border-radius: 10px 10px 0 0;
  transition: color var(--dur-fast) var(--ease), background var(--dur-fast) var(--ease);
}
.ui-nav__tab:hover { color: var(--strong); }
.ui-nav__tab:focus-visible { outline: var(--ring); outline-offset: var(--ring-offset); border-radius: 8px; }
.ui-nav__tab.is-active { color: var(--strong); }
.ui-nav__tab-label { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* underline variant */
.ui-nav--tabs.is-underline .ui-nav__tab::after {
  content: "";
  position: absolute;
  left: 10px; right: 10px; bottom: -1px;
  height: 2px;
  border-radius: 2px;
  background: var(--accent);
  opacity: 0;
  transform: scaleX(0.4);
  transition: opacity var(--dur-fast) var(--ease), transform var(--dur-fast) var(--ease);
}
.ui-nav--tabs.is-underline .ui-nav__tab.is-active::after { opacity: 1; transform: scaleX(1); }

/* pill variant */
.ui-nav--tabs.is-pill .ui-nav__tab { border-radius: var(--radius-pill); padding: 8px 15px; }
.ui-nav--tabs.is-pill .ui-nav__tab:hover { background: var(--surface); /* code-bg: inherit — control paint; its focus indicator uses the containing surface. */ }
/* The current route keeps its quiet fill and uses accent ink. */
.ui-nav--tabs.is-pill .ui-nav__tab.is-active {
  color: var(--accent);
  background: var(--glow-purple); /* code-bg: inherit — translucent wash retains the opaque containing gap. */
}

/* Forced colours: the selected-tab marks are in the block below. */
@media (forced-colors: active) {
  /* Forced colours drop background images, so the row's rule comes back as a border.
     The last pixel of the bottom padding pays for it and the row keeps its size. The
     border image leaves the ring room at both ends bare, so the rule ends on the gutter
     as the background line does. */
  .ui-nav--tabs {
    padding-bottom: calc(var(--ui-tabs-ring-room) - var(--ui-tabs-rule));
    border-bottom: var(--ui-tabs-rule) solid;
    border-image: linear-gradient(to right, transparent var(--ui-tabs-ring-room),
      CanvasText var(--ui-tabs-ring-room) calc(100% - var(--ui-tabs-ring-room)),
      transparent calc(100% - var(--ui-tabs-ring-room))) 0 0 1 0;
  }
}

.ui-nav__tab.is-disabled { /* muted-ink: state — unavailable control */ color: var(--disabled-ink); cursor: default; }
.ui-nav__tab .ui-nav__badge { height: 18px; }

/* -- Breadcrumbs --------------------------------------------------------- */
/* The chip hangs out by its own padding so the first LABEL lands on the column's edge,
   level with the page title under it. */
.ui-nav__crumbs { display: flex; flex-wrap: wrap; align-items: center; gap: 2px; margin-inline-start: -6px; }
.ui-nav__crumb-item { display: inline-flex; align-items: center; }
.ui-nav__crumb-item + .ui-nav__crumb-item::before {
  content: "";
  width: 6px; height: 6px;
  margin: 0 8px;
  border-right: 1.4px solid var(--muted);
  border-bottom: 1.4px solid var(--muted);
  transform: rotate(-45deg);
  opacity: 0.7;
}
.ui-nav__crumb {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 3px 6px;
  border-radius: 7px;
  text-decoration: none;
  font-size: var(--text-sm);
  transition: color var(--dur-fast) var(--ease), background var(--dur-fast) var(--ease);
}
/* Carries the block's class as well as its own, for the reason .ui-nav__item
   does above: a linked crumb is an <a>, and a host stylesheet's `a:link` is
   (0,1,1), which outranks a bare (0,1,0) class. */
.ui-nav .ui-nav__crumb { color: var(--text); }
a.ui-nav__crumb:hover { color: var(--strong); background: var(--surface); /* code-bg: inherit — control paint; the containing surface is the ground, for a chip and for a band alike. */ }
a.ui-nav__crumb:focus-visible { outline: var(--ring); outline-offset: var(--ring-offset); }
.ui-nav__crumb.is-current { color: var(--strong); font-weight: 500; }
.ui-nav__crumb .ui-nav__ic svg { width: 15px; height: 15px; stroke: currentColor; fill: none; stroke-width: 2.5; }

/* Forced colours replace every author background, so a selected item takes the system
   pair as its fill. `forced-color-adjust: none` is what keeps the pair from sitting on
   Chromium's Canvas backplate, which would leave the label unreadable. Focus keeps its
   own ring, drawn in CanvasText so the fill is never mistaken for it.
   The pair is `!important` because it is the reader's palette: a danger wash, a hover
   or a focus state must never repaint it. A child of the row inherits the adjust, so
   each child that paints its own colour is repainted here as well. */
@media (forced-colors: active) {
  .ui-nav__item.is-active:not(.is-disabled),
  .ui-nav__item.is-current:not(.is-disabled),
  .ui-nav__tab.is-active:not(.is-disabled),
  .ui-nav--tabs.is-pill .ui-nav__tab.is-active:not(.is-disabled),
  .ui-nav__crumb.is-current {
    forced-color-adjust: none;
    background: Highlight !important;
    color: HighlightText !important;
    --ring: var(--ring-width) solid CanvasText;
  }
  .ui-nav__item.is-active:not(.is-disabled) .ui-nav__ic svg,
  .ui-nav__item.is-current:not(.is-disabled) .ui-nav__ic svg,
  .ui-nav__tab.is-active:not(.is-disabled) .ui-nav__ic svg,
  .ui-nav__crumb.is-current .ui-nav__ic svg { stroke: HighlightText; }
  .ui-nav__item.is-active .ui-nav__caret,
  .ui-nav__item.is-current .ui-nav__caret { border-color: currentColor; }
  .ui-nav__item.is-active:not(.is-disabled) .ui-nav__badge,
  .ui-nav__item.is-current:not(.is-disabled) .ui-nav__badge,
  .ui-nav__tab.is-active:not(.is-disabled) .ui-nav__badge {
    background: HighlightText !important;
    color: Highlight !important;
  }
  /* A selected item that is unavailable must not look live, so it takes the disabled system pair. */
  .ui-nav__item.is-active.is-disabled,
  .ui-nav__item.is-current.is-disabled,
  .ui-nav__tab.is-active.is-disabled {
    forced-color-adjust: none;
    background: GrayText !important;
    color: Canvas !important; /* muted-ink: state — unavailable control */
  }
  .ui-nav__item.is-active.is-disabled .ui-nav__ic svg,
  .ui-nav__item.is-current.is-disabled .ui-nav__ic svg,
  .ui-nav__tab.is-active.is-disabled .ui-nav__ic svg { stroke: Canvas; }
  .ui-nav__item.is-active.is-disabled .ui-nav__badge,
  .ui-nav__item.is-current.is-disabled .ui-nav__badge,
  .ui-nav__tab.is-active.is-disabled .ui-nav__badge {
    background: Canvas !important;
    color: GrayText !important; /* muted-ink: state — unavailable control */
  }
  /* A folded row is only an icon strip: the plate carries the fill, so the row paints none.
     A current group takes the same plate as the current row it holds. */
  .ui-nav--side.is-collapsed .ui-nav__item:is(.is-active, .is-current) { isolation: isolate; background: none !important; }
  .ui-nav--side.is-collapsed .ui-nav__item.is-current:not(.is-active)::before {
    content: ""; position: absolute; left: 0; top: 50%; width: var(--ui-nav-strip); height: 100%; border-radius: 10px;
    transform: translateY(-50%); /* motion: still — a mark on the current group, centred and not travelling */
    z-index: -1;
  }
  .ui-nav--side.is-collapsed .ui-nav__item:is(.is-active, .is-current):not(.is-disabled)::before { background: Highlight; }
  .ui-nav--side.is-collapsed .ui-nav__item:is(.is-active, .is-current).is-disabled::before { background: GrayText; }
  /* The fill is the one mark, so the underline bar, which would paint the accent inside it, is gone. */
  .ui-nav--tabs.is-underline .ui-nav__tab.is-active::after { display: none; /* motion: still — the bar is not drawn while the fill marks the tab */ }
}
