/* kapable-dock.css — shared footer dock component (IMP-2598).
 * Promoted from kv2-launchpad/static/styles.css (IMP-2590 lane treatment),
 * then substantially reworked per a K3 design consult (2026-07-22, C0.5):
 * priority+ round-robin overflow collapse + a disclosure-nav "⋯" control,
 * replacing the ⌘K spotlight pill and the old scroll-fallback/tail-drain
 * collapse. At dock-v0.2.0 (operator call, 2026-07-25) the chip strip went
 * away entirely: ALL platform nav lives in the (renamed) menu panel, always,
 * so the collapse engine's rules (.lp-dock-groups/-group/-chips/-sep/-label)
 * are gone and `.lp-dock-overflow-*` is now `.lp-dock-menu-*`.
 * kv2-launchpad remains the reference consumer. Include after
 * kapable-theme.css.
 *
 * The dock's chip markup (kapable-dock.js#renderChip) uses `.lp-chip`, NOT
 * the generic `.chip` (dock-v0.1.1) — a shared asset must not squat a
 * classname a consumer plausibly already owns. Found live: kv2-console
 * defines its own 13 `.chip` rules, and the dock's chips were inheriting
 * them (flex-direction:column, icon stacked over label) instead of this
 * file's inline dock grammar. `.chips` (the flex-wrap grid container used
 * by launchpad's own tool grid, not the dock) was never extracted here —
 * it doesn't belong to the dock component. Since dock-v0.2.0 every `.lp-chip`
 * lives in the menu panel, where it reads as a full-width row rather than a
 * pill — see `.lp-dock-menu-list .lp-chip` below for that context's look.
 */

/* The `hidden` attribute drives all three disclosure panels below (the
 * overflow trigger/panel/sections, the accent panel) plus their empty
 * sections. Author display rules elsewhere in this file carry the SAME
 * specificity as the UA [hidden] default and come later in the cascade, so
 * without this they would silently win and the "hidden" element would still
 * render — this is the one !important in the file, and it's load-bearing. */
[hidden] { display: none !important; }

.lp-chip {
  display: inline-flex; align-items: center; gap: 7px;
  flex-shrink: 0; /* a flex-item chip WOULD otherwise silently compress below its own
    label's width once its flex row runs out of room (the browser "solves" the overflow
    by shrinking instead of overflowing), which reads as a clipped mid-label chip and
    defeats navWrap's scrollWidth/clientWidth measurement entirely (shrinking absorbs the
    overflow before it can ever show up at the ancestor .lp-dock-nav that JS actually
    measures) — verified live in Chrome, 2026-07-22, IMP-2598 C0.5 round 4. */
  border: 1px solid var(--kp-border); border-radius: 3px;
  padding: 6px 11px; font-size: 12.5px; font-weight: 550;
  color: var(--kp-text); background: var(--kp-surface);
  text-decoration: none; cursor: pointer; font-family: var(--kp-font);
  transition: border-color 0.15s, color 0.15s;
}
.lp-chip svg { color: var(--kp-text-dim); flex-shrink: 0; transition: color 0.15s; }
/* ── Accent is a SIGNAL, not an ink (dock-v0.5.1) ─────────────────────────
   Every rule below used to recolour small TEXT to --kp-accent on hover, focus
   or active. That is only safe if the accent happens to contrast with the
   surface — and it is not ours to assume: theme.js `setBrand` takes each
   org's own brand colour. Measured on prod with this org's gold (#c6a853) in
   light theme, the menu trigger's label read 2.24:1 against a 4.5:1
   requirement; the same rule fires on plain hover, so it was not an
   edge state.

   So the accent now lands only where the 3:1 non-text threshold applies —
   borders, glyphs, background tints — and text keeps a readable token. The
   affordance survives (a hovered control still gets an accent border AND an
   accent glyph); what goes away is unreadable text. Same move the overdue
   badge makes: red on the border, --kp-text on the number. */
.lp-chip:hover, .lp-chip:focus-visible {
  border-color: var(--kp-accent); color: var(--kp-text);
  text-decoration: none;
}
.lp-chip:hover svg, .lp-chip:focus-visible svg { color: var(--kp-accent); }
.lp-chip:focus:not(:focus-visible) { outline: none; }
.lp-chip[aria-disabled="true"] { opacity: 0.55; cursor: default; pointer-events: none; }

/* ── Footer dock — the OS-shell concept's grammar (IMP-2590 v2) ───────────
   Fixed platform nav: grouped compact chips (reusing .lp-chip above) + a
   live mono clock. Machined corners (the .lp-chip radius), ink rules, no
   cards. */
:root { --lp-dock-h: 56px; }
.lp-dock {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 40;
  display: flex; align-items: center; gap: 10px;
  height: var(--lp-dock-h);
  padding: 0 12px;
  background: var(--kp-surface);
  border-top: 1px solid var(--kp-border);
  max-width: 100vw;
}
/* Every page ships this as an EMPTY `<footer>` shell — `KapableDock.mount()`
   is what fills it, after load. With JavaScript off (or not yet run) it never
   fills, so a full-width, 56px-tall FIXED box sits over whatever content is
   underneath it, invisibly eating clicks. Found live on the /todos no-JS gate:
   a date popover could not be opened for a row that happened to render in the
   bottom 56px, because the click landed on this footer and Chromium reported it
   as the element "intercepting pointer events". Every fleet surface ships the
   same empty shell, so every one of them has this with JS off.
   `:empty` matches exactly the two states that need it (no JS, or JS not run
   yet) and stops matching the instant `mount()` appends content — the
   JS-enabled dock is unaffected. */
.lp-dock:empty { pointer-events: none; }
/* .lp-dock-nav holds the platform-menu trigger as one flex unit within
   .lp-dock's row. overflow:hidden here is now only a backstop: dock-v0.2.0
   moved every chip into the body-appended menu panel, so there is no chip
   strip left to clip and no width measurement to do (the pre-0.2.0 collapse
   engine measured THIS box's clientWidth against .lp-dock-groups'
   scrollWidth — both that engine and .lp-dock-groups are gone, along with
   .lp-dock-group/-chips/-sep and the strip's mono group kickers). Kept
   because the trigger's label is consumer-supplied text (a tile's
   display_name), which must never be able to shove the clock/accent
   furniture off the dock's edge — see .lp-dock-menu-trigger-label's
   ellipsis, of which this is the second half. */
.lp-dock-nav {
  display: flex; align-items: center; gap: 8px;
  flex: 1 1 0%; min-width: 0; max-width: 100%;
  overflow: hidden;
}
/* Status pill (IMP-2590 v3) — honest production-deploy health from data the
   page already fetches (opts.fleet); omitted entirely when there's nothing
   usable (see computeFleetStatus in kapable-dock.js). */
.lp-dock-status {
  flex-shrink: 0; display: flex; align-items: center; gap: 7px;
  padding-right: 10px; margin-right: 2px; border-right: 1px solid var(--kp-border);
  font-family: var(--kp-font-mono); font-size: 11px; color: var(--kp-text-dim);
  text-decoration: none; white-space: nowrap; transition: color 0.15s;
}
.lp-dock-status:hover, .lp-dock-status:focus-visible { color: var(--kp-text); text-decoration: none; }
.lp-dock-status-dot { width: 6px; height: 6px; border-radius: 50%; flex-shrink: 0; }
.lp-dock-status-dot.ok { background: var(--kp-success); }
.lp-dock-status-dot.warn { background: var(--kp-warn); }
.lp-dock-status-dot.bad { background: var(--kp-danger); }
/* ── Todos readout (dock-v0.4.0) ──────────────────────────────────────────
   A peer of the status pill above, deliberately built from the same rules:
   mono, 11px, --kp-text-dim, a hairline separator, brightening to --kp-text
   on hover. It is NOT a chip and does not reopen dock-v0.2.0's "all platform
   NAV lives in the menu" — navigation is still menu-only, and Todos has its
   chip in there like everything else. This is a live readout that happens to
   be clickable, which is exactly what .lp-dock-status already is. */
.lp-dock-todos {
  flex-shrink: 0; display: flex; align-items: center; gap: 6px;
  /* dock-v0.5.1: this became a <button> when it stopped navigating, and a
     button arrives with UA chrome an <a> never had — `background: buttonface`,
     an outset border, its own font and padding. Without this reset it drew a
     raised grey box on the strip beside a borderless status pill, and the
     buttonface fill silently changed what the contrast probe was measuring
     AGAINST (6.19:1 where the clock, on the same token, read 6.94:1). Reset
     first, then restore the one border this control actually wants. */
  appearance: none; -webkit-appearance: none;
  background: none; border: 0; padding: 0; margin: 0;
  text-align: left; line-height: inherit; cursor: pointer;
  padding-right: 10px; margin-right: 2px; border-right: 1px solid var(--kp-border);
  font-family: var(--kp-font-mono); font-size: 11px; color: var(--kp-text-dim);
  text-decoration: none; white-space: nowrap; transition: color 0.15s;
}
.lp-dock-todos:focus:not(:focus-visible) { outline: none; }
.lp-dock-todos:hover, .lp-dock-todos:focus-visible { color: var(--kp-text); text-decoration: none; }
.lp-dock-todos svg { flex-shrink: 0; }

/* The badge's BOX is identical in every state — same padding, same
   min-width, and a transparent border rather than no border — so the strip
   cannot reflow when a todo comes due, the count crosses from 9 to 10, or
   the transport drops. Only colour changes between states. box-sizing is
   inherited border-box from the consumer's reset; the transparent border is
   what makes this hold even where it isn't. */
.lp-dock-todos-badge {
  flex-shrink: 0; box-sizing: border-box;
  /* 2.35em ≈ 25.9px at this font-size, which is wider than a rendered TWO
     digit count (measured 25.2px in Chrome, 2026-07-27). Sized off that
     measurement, not guessed: the first cut used 1.65em, and driving the
     specimen showed the menu trigger sliding 213.1 → 213.6 → 220.2px as the
     count went empty → "3" → "12". The empty→one-digit step was sub-pixel,
     but ten-to-eleven todos is not a rare event and 6.6px of strip lurch is.
     Counts of 100+ will still grow the box; at that point the reflow is the
     least of the reader's problems. */
  min-width: 2.35em; padding: 1px 5px;
  border: 1px solid transparent; border-radius: 3px;
  font-variant-numeric: tabular-nums; font-weight: 600;
  text-align: center; line-height: 1.35;
  color: var(--kp-text); background: var(--kp-surface-hi);
  border-color: var(--kp-border);
}
/* Something is LATE. Measured against the dock surface: --kp-text on
   --kp-danger-bg is 8.97:1 dark / 15.29:1 light. The obvious-looking
   --kp-danger-on---kp-danger-bg scores 3.77:1 in dark and FAILS AA, so the
   red is spent on the border (a non-text boundary, 6.44:1 / 5.47:1 against
   the surface — comfortably past the 3:1 that applies to it) and the text
   keeps the readable token. */
.lp-dock-todos-badge.is-overdue {
  background: var(--kp-danger-bg); border-color: var(--kp-danger);
}
/* Count unreadable. An em-dash in the quiet-but-legible token: the reader
   is told the number is missing, never told it is zero. */
.lp-dock-todos-badge.is-unavailable {
  color: var(--kp-text-dim); background: none; border-color: transparent;
}
/* Nothing due. The link stays (it has to be findable on a quiet day) and the
   badge keeps its width, but renders as empty space rather than a "0". */
.lp-dock-todos.is-clear .lp-dock-todos-badge {
  background: none; border-color: transparent;
}

/* ── Todos panel (dock-v0.5.0) ────────────────────────────────────────────
   The readout stopped being a signpost. Clicking it used to navigate to
   /todos?scope=all; it now opens a panel you can actually finish work from,
   because the whole point of an ambient count is to act on it without
   leaving the surface you are on. The full list is still one click away at
   the foot of the panel.

   Row grammar deliberately echoes the /todos page's own (.td-row/.td-check
   in kv2-launchpad): a BUTTON with aria-pressed, not an <input type=checkbox>
   — it posts, it is not a form field — and a blocked row keeps the slot but
   renders it dashed and inert rather than offering an action the server will
   refuse. */
.lp-dock-todos-panel {
  width: 340px; max-width: calc(100vw - 16px); padding: 6px;
  display: block;
}
.lp-dock-todos-head {
  display: flex; align-items: baseline; gap: 6px;
  font-family: var(--kp-font-mono); font-size: 9px; font-weight: 600;
  letter-spacing: 0.08em; text-transform: uppercase; color: var(--kp-text-dim);
  padding: 4px 8px 6px;
}
.lp-dock-todos-head-n { margin-left: auto; font-variant-numeric: tabular-nums; }
.lp-dock-todos-list { display: block; list-style: none; margin: 0; padding: 0; }
.lp-dock-todos-list li { display: block; }
.lp-dock-todo-row {
  display: grid; grid-template-columns: 1rem minmax(0, 1fr); gap: 8px;
  align-items: start; padding: 6px 8px; border-radius: 3px;
}
.lp-dock-todo-row:hover { background: var(--kp-surface-hi); }
/* Echoes .td-check on the /todos page: a real button, checked state via
   aria-pressed, and the tick drawn with a rotated border rather than a glyph
   so it inherits the accent's ink colour. */
.lp-dock-todo-check {
  width: 1rem; height: 1rem; padding: 0; margin-top: 1px; cursor: pointer;
  background: transparent; border: 1px solid var(--kp-border-strong);
  border-radius: 3px; flex-shrink: 0;
}
.lp-dock-todo-check:hover { border-color: var(--kp-accent); }
.lp-dock-todo-check[aria-pressed="true"] { background: var(--kp-accent); border-color: var(--kp-accent); }
.lp-dock-todo-check[aria-pressed="true"] > span::after {
  content: ""; display: block; width: 0.25rem; height: 0.5rem;
  margin: -0.0625rem auto 0; transform: rotate(45deg);
  border: solid var(--kp-on-accent, #fff); border-width: 0 1.5px 1.5px 0;
}
.lp-dock-todo-title {
  font-size: 12.5px; font-weight: 500; color: var(--kp-text);
  text-decoration: none; display: block; line-height: 1.35;
}
.lp-dock-todo-title:hover, .lp-dock-todo-title:focus-visible {
  color: var(--kp-text); text-decoration: underline;
}
.lp-dock-todo-meta {
  display: block; font-family: var(--kp-font-mono); font-size: 10px;
  color: var(--kp-text-dim); margin-top: 2px;
}
.lp-dock-todo-meta.is-overdue { color: var(--kp-danger); }
.lp-dock-todo-row.is-doing { opacity: 0.5; }

.lp-dock-todos-empty {
  padding: 10px 8px 12px; font-size: 12.5px; color: var(--kp-text-dim);
}
.lp-dock-todos-sep { height: 1px; background: var(--kp-border); margin: 6px 2px; }

.lp-dock-todos-add { display: flex; gap: 6px; padding: 2px 4px 4px; }
.lp-dock-todos-add input {
  flex: 1; min-width: 0; font-family: var(--kp-font); font-size: 12.5px;
  padding: 6px 8px; border-radius: 3px; color: var(--kp-text);
  background: var(--kp-bg, var(--kp-surface)); border: 1px solid var(--kp-border);
}
.lp-dock-todos-add input::placeholder { color: var(--kp-text-dim); }
.lp-dock-todos-add input:focus-visible { border-color: var(--kp-accent); outline: none; }
.lp-dock-todos-add button {
  font-family: var(--kp-font); font-size: 12.5px; font-weight: 550;
  padding: 6px 10px; border-radius: 3px; cursor: pointer;
  color: var(--kp-text); background: var(--kp-surface-hi);
  border: 1px solid var(--kp-border);
}
.lp-dock-todos-add button:hover { border-color: var(--kp-accent); color: var(--kp-text); }
.lp-dock-todos-add button[disabled] { opacity: 0.55; cursor: default; }

/* Never-silent receipt. Every refusal the server sends — a blocked todo, a
   rejected title — is PRINTED here verbatim rather than swallowed, because
   those messages are written to tell the caller how to fix the thing. */
.lp-dock-todos-msg {
  padding: 6px 8px; font-size: 12px; line-height: 1.4;
  color: var(--kp-text); background: var(--kp-danger-bg);
  border: 1px solid var(--kp-danger); border-radius: 3px; margin: 2px 4px 4px;
}
.lp-dock-todos-msg.is-ok { background: var(--kp-success-bg); border-color: var(--kp-success); }

.lp-dock-todos-foot {
  display: flex; align-items: center; gap: 6px; padding: 6px 8px 4px;
  font-size: 12px; color: var(--kp-text-dim); text-decoration: none;
}
.lp-dock-todos-foot:hover, .lp-dock-todos-foot:focus-visible {
  color: var(--kp-text); text-decoration: underline;
}

.lp-dock-right {
  flex-shrink: 0; display: flex; align-items: center; gap: 10px;
  padding-left: 10px; border-left: 1px solid var(--kp-border);
}
/* The ⌘K spotlight pill (.lp-dock-cmdk, a plain "launchpad" link on the
   static apps.html/drops.html dock — the launchpad's own index.html shell
   has a real ⌘K palette via app.js, unrelated to this file) was removed in
   IMP-2598: redundant with the shared header's own "jump to a tool…"
   switcher popup. The header keeps its ⌘K behavior (kapable-header.js is
   untouched); the dock no longer duplicates it. */

/* ── Platform menu disclosure control (dock-v0.2.0, operator call
   2026-07-25) ─────────────────────────────────────────────────────────────
   Formerly the "⋯" overflow control — the narrow-width retreat path — now the
   dock's ONLY nav affordance: a labeled trigger at the start of the nav strip
   carrying the current surface's name, and a panel holding every platform
   chip, grouped. The panel is body-appended + position:fixed (NOT nested
   inside .lp-dock, whose .lp-dock-nav overflow:hidden would clip it — a
   fixed element's containing block is the viewport, not that ancestor),
   anchored by JS to the trigger's LEFT edge and clamped to an 8px gutter.
   Disclosure pattern, not role="menu" — see kapable-dock.js's
   createMenuControl doc comment for the full a11y reasoning. */
.lp-dock-menu-trigger {
  flex-shrink: 0; min-width: 0;
  display: inline-flex; align-items: center; gap: 7px;
  height: 26px; padding: 0 10px; border-radius: 3px;
  border: 1px solid var(--kp-border); background: var(--kp-surface);
  color: var(--kp-text); font-family: var(--kp-font);
  font-size: 12px; font-weight: 550; line-height: 1;
  cursor: pointer; transition: border-color 0.15s, color 0.15s;
}
.lp-dock-menu-trigger svg { color: var(--kp-text-dim); flex-shrink: 0; transition: color 0.15s; }
.lp-dock-menu-trigger:hover,
.lp-dock-menu-trigger:focus-visible,
.lp-dock-menu-trigger[aria-expanded="true"] {
  border-color: var(--kp-accent); color: var(--kp-text);
}
.lp-dock-menu-trigger:hover svg,
.lp-dock-menu-trigger:focus-visible svg,
.lp-dock-menu-trigger[aria-expanded="true"] svg { color: var(--kp-accent); }
/* The label is a tile's display_name — ellipsize rather than let a long one
   widen the trigger past the strip (the other half of .lp-dock-nav's clip). */
.lp-dock-menu-trigger-label {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0;
}
/* On a recognised surface the trigger IS the "you are here" signal (the
   strip's active chip is gone), so it earns a marked resting state — the
   accent glyph + a stronger rule, stopping short of the full filled accent
   treatment so the dock doesn't read as permanently "on". */
.lp-dock-menu-trigger.has-current { border-color: var(--kp-border-strong); }
.lp-dock-menu-trigger.has-current svg { color: var(--kp-accent); }

/* The popover SHELL, shared by the platform menu and the todos panel
   (dock-v0.5.0). Extracted alongside createDisclosure() in the JS for the same
   reason: two panels anchored to the same strip must open at the same height,
   with the same surface, border, shadow and entrance — and a second
   hand-maintained copy is how they stop matching. Only the CONTENT layout
   below is per-panel. */
.lp-dock-pop {
  position: fixed; z-index: 50; /* dock is 40; content stays below both */
  bottom: calc(var(--lp-dock-h) + 8px);
  max-height: calc(100vh - var(--lp-dock-h) - 16px); overflow-y: auto;
  padding: 8px; border-radius: var(--kp-radius, 4px);
  background: var(--kp-surface); border: 1px solid var(--kp-border);
  box-shadow: var(--kp-shadow-lg, 0 8px 24px rgba(15, 23, 42, 0.14));
  opacity: 0; transform: translateY(4px);
  transition: opacity 0.12s ease-out, transform 0.12s ease-out;
}
.lp-dock-pop.is-open { opacity: 1; transform: translateY(0); }
@media (prefers-reduced-motion: reduce) {
  .lp-dock-pop { transition: none; opacity: 1; transform: none; }
}

.lp-dock-menu-panel {
  /* Every group is open at once now, so this is a menu to SCAN, not the
     short overflow list it used to be (a 208px single column would run ~17
     rows tall). Sections lay out as columns side by side; the JS clamp keeps
     the result inside the viewport, and the narrow-viewport rule below
     collapses it back to one column.
     align-items:stretch (not flex-start) is what makes the column rules read
     as deliberate: the groups have wildly different lengths (build 6, operate
     7, more 3), so a shrink-to-fit section leaves each border-left ending at
     a different height — four ragged hairlines instead of columns. Verified
     in Chrome, 2026-07-25.
     flex-wrap + max-width added at dock-v0.3.0: the re-derived DOCK_GROUPS has FIVE
     groups (was three), so at min-width:148px per section the panel wants ~776px. Without
     a cap it would simply exceed a narrow desktop viewport — the JS clamp can only slide
     the panel back to the 8px gutter, it cannot make it narrower. Wrapping to a second row
     is the graceful answer, and it means adding a sixth group later can't break the
     layout either. */
  display: flex; align-items: stretch; gap: 0;
  /* width:max-content is load-bearing, not tidiness. A position:fixed box with
     no width is shrink-to-fit, and with flex-wrap:wrap that intrinsic width
     computed ONE pixel short of its own five columns (sections summed to 740px
     against 739px available), so the last group wrapped to a second row — where
     section heights stop matching and the `+ .lp-dock-menu-section` border-left
     lands on the first item of the wrapped row as a stray hairline. max-content
     sizes the panel to its unwrapped content, so the row either fits or the
     max-width below clamps it. Verified in Chrome, 2026-07-25. */
  width: max-content; flex-wrap: wrap; max-width: calc(100vw - 16px);
}
.lp-dock-menu-section { flex: 0 0 auto; min-width: 148px; padding: 0 4px; }
.lp-dock-menu-section + .lp-dock-menu-section {
  border-left: 1px solid var(--kp-border);
}
/* dock-v0.4.0: same token defect as .lp-dock-clock below, found while fixing
   it — --kp-text-disabled measured 2.49:1 dark / 2.72:1 light here too, on
   9px uppercase text (the hardest size to read in the whole component). It
   escaped the contrast gates only because this text lives inside a panel
   that is display:none until opened, so a sweep of a page with the menu shut
   examines zero of these nodes and passes vacuously. */
.lp-dock-menu-label {
  font-family: var(--kp-font-mono); font-size: 9px; font-weight: 600;
  letter-spacing: 0.08em; text-transform: uppercase; color: var(--kp-text-dim);
  padding: 4px 10px 6px;
}
/* A real <ul> (list semantics — screen readers announce position/count),
   not a styling div: reset the UA list box model before laying out as a
   column. Each <li> is a plain wrapper around one chip and carries no look
   of its own. */
.lp-dock-menu-list { display: flex; flex-direction: column; list-style: none; margin: 0; padding: 0; }
.lp-dock-menu-list li { display: block; }
/* Chips read as full-width rows here, not pills — the base .lp-chip rules
   (border/background/inline-flex) are overridden accordingly. */
.lp-dock-menu-list .lp-chip {
  display: flex; width: 100%;
  border: none; background: none; border-radius: 3px;
  padding: 7px 10px; font-size: 12.5px; font-weight: 500;
  white-space: nowrap;
}
.lp-dock-menu-list .lp-chip:hover, .lp-dock-menu-list .lp-chip:focus-visible {
  background: var(--kp-surface-hi); border-color: transparent;
}
/* Active is carried by the tint + the accent glyph; the label stays legible. */
.lp-dock-menu-list .lp-chip.is-active { color: var(--kp-text); background: var(--kp-accent-bg); }
.lp-dock-menu-list .lp-chip.is-active svg { color: var(--kp-accent); }
/* The Todos chip carries the same count as the strip readout, pushed to the
   row's trailing edge. Same badge element, same builder in the JS — the two
   sites cannot print different numbers for the same fact. min-width on the
   section (148px) already leaves room, so this adds no wrapping risk. */
.lp-dock-menu-list .lp-chip.has-badge { gap: 7px; }
.lp-dock-menu-list .lp-chip .lp-dock-todos-badge {
  margin-left: auto; font-family: var(--kp-font-mono); font-size: 10.5px;
}
/* Below the width where multiple columns stop fitting, go back to one 208px
   column and let the panel's own max-height scroll it. Raised 720px → 800px at
   dock-v0.3.0: five groups want ~776px, and the band between the old breakpoint
   and that width would have wrapped to a second row — where the
   `.lp-dock-menu-section + .lp-dock-menu-section` border-left lands on the first
   item of the wrapped row and reads as a stray leading hairline. Folding to one
   column just above the five-column width removes that band entirely; the
   panel's flex-wrap stays as a backstop for a future sixth group. */
@media (max-width: 800px) {
  .lp-dock-menu-panel { display: block; width: 208px; }
  .lp-dock-menu-section { min-width: 0; padding: 0; }
  .lp-dock-menu-section + .lp-dock-menu-section {
    border-left: none; margin-top: 2px;
  }
}

/* ── Accent auditioner (IMP-2590, dropdown redesign IMP-2598, disclosure
   pattern refined by the same K3 consult) ─────────────────────────────────
   A single trigger button showing the currently-painted accent as a dot
   (org default, or the active preview override); opens an upward,
   body-appended panel (same clipping reason as the overflow control above)
   listing the 6 candidates + "Reset to org accent". See
   kapable-accent-audition.js for the a11y mechanics and the derivation. */
.lp-accent-audit { display: flex; align-items: center; flex-shrink: 0; }
.lp-accent-trigger {
  display: inline-flex; align-items: center; justify-content: center;
  width: 22px; height: 22px; border-radius: 50%; padding: 0;
  border: 1px solid var(--kp-border-strong); background: var(--kp-surface);
  cursor: pointer; transition: border-color 0.15s, transform 0.12s;
}
.lp-accent-trigger:hover { transform: scale(1.1); }
.lp-accent-trigger[aria-expanded="true"] { border-color: var(--kp-text); }
.lp-accent-trigger-dot {
  width: 12px; height: 12px; border-radius: 50%; background: var(--kp-accent);
}
.lp-accent-panel {
  position: fixed; z-index: 50; /* dock is 40; content stays below both */
  bottom: calc(var(--lp-dock-h) + 8px);
  min-width: 200px; padding: 4px;
  border-radius: var(--kp-radius, 4px);
  background: var(--kp-surface); border: 1px solid var(--kp-border);
  box-shadow: var(--kp-shadow-lg, 0 8px 24px rgba(15, 23, 42, 0.14));
  opacity: 0; transform: translateY(4px);
  transition: opacity 0.12s ease-out, transform 0.12s ease-out;
}
.lp-accent-panel.is-open { opacity: 1; transform: translateY(0); }
@media (prefers-reduced-motion: reduce) {
  .lp-accent-panel { transition: none; opacity: 1; transform: none; }
}
.lp-accent-item {
  display: flex; align-items: center; gap: 8px; width: 100%;
  padding: 7px 8px; border-radius: 3px; border: none; background: none;
  font-family: var(--kp-font); font-size: 12.5px; color: var(--kp-text);
  cursor: pointer; text-align: left;
}
.lp-accent-item:hover, .lp-accent-item:focus-visible { background: var(--kp-surface-hi); }
.lp-accent-item.is-active { color: var(--kp-text); background: var(--kp-accent-bg); }
.lp-accent-item-dot {
  width: 11px; height: 11px; border-radius: 50%; flex-shrink: 0;
  border: 1px solid var(--kp-border-strong); background: var(--sw);
}
.lp-accent-panel-sep { height: 1px; background: var(--kp-border); margin: 4px 2px; }
.lp-accent-item-reset { color: var(--kp-text-dim); font-weight: 550; }

/* dock-v0.4.0: was --kp-text-disabled, which is a DISABLED-CONTROL token
   being spent on live, current information. Measured against the dock
   surface it scored 2.49:1 dark / 2.72:1 light against a 4.5:1 requirement
   — the clock was the least legible thing on the strip while being one of
   the few that changes. --kp-text-dim is the "quiet but readable" token:
   7.14:1 dark / 6.74:1 light. kv2-launchpad's vendored copy was fixed
   locally first, so until this landed the two copies were drifting and every
   OTHER fleet surface still failed. */
.lp-dock-clock {
  font-family: var(--kp-font-mono); font-size: 11px;
  font-variant-numeric: tabular-nums;
  color: var(--kp-text-dim);
}
/* Reserve room so the fixed dock never overlaps content or the in-flow
   footer; lift the concierge FAB and toast host above it too. */
body.has-lp-dock { padding-bottom: var(--lp-dock-h); }
body.has-lp-dock #kp-toast-host { bottom: calc(var(--lp-dock-h) + 16px) !important; }
/* min-width guard: below 601px the FAB already gets relocated to
   top:105px/bottom:auto (mobile override in the consumer's own stylesheet,
   pinned to the onboarding rail) — this rule must not fight that one. Higher
   specificity here would otherwise win over that lower-specificity mobile
   rule even though both carry !important. */
@media (min-width: 601px) {
  body.has-lp-dock [data-kpc-launcher] { bottom: calc(var(--lp-dock-h) + 16px) !important; }
}
@media print {
  .lp-dock { display: none !important; }
}
/* NOTE: the pre-0.2.0 `.lp-dock-label { display: none }` rule lived here — it
   hid the STRIP's mono group kickers on narrow viewports. Those kickers are
   gone; the surviving `.lp-dock-menu-label` is inside the panel and must
   stay visible at every width (it's what makes the menu scannable). */
@media (max-width: 760px) {
  .lp-dock { gap: 10px; padding: 0 12px; }
  .lp-dock-right { gap: 8px; padding-left: 8px; }
  .lp-dock-status { padding-right: 8px; }
  .lp-dock-todos { padding-right: 8px; }
}
@media (max-width: 560px) {
  .lp-dock-clock { display: none; }
}
@media (max-width: 460px) {
  .lp-dock-status-label { display: none; } /* dot only */
  /* Glyph + count only. The COUNT is the whole point of this control, so it
     is the last thing to go — unlike the status label, which is redundant
     with its own dot's colour. */
  .lp-dock-todos-label { display: none; }
}
