/* Loom — component recipes. Load after tokens.css (compiled from tokens.json).
   Fonts: tokens.css carries the @font-face for Geist and Geist Mono from fonts/ (OFL, vendored);
   nothing here reaches the network, so a strict CSP (font-src 'self') holds.
   Every colour, space, radius, type style, duration and layer below is a token. Type, motion and
   layering come from the generated block that follows; the 2px focus and selection widths are
   the only literals. */

/* Everything is in one cascade layer, loom. A product's own rules, written outside any layer,
   win over the system's whatever their specificity, so an override never needs !important and a
   reset written after this file cannot be undone by it. */
@layer loom {

/* @generated:start — written by checks/compile-tokens.mjs from tokens.json (type) and tokens.ext.json
   (motion, layering). Do not edit by hand: change the source and run the compiler. */
:root {
  --type-display: 600 56px/60px var(--font-sans);
  --type-display-tracking: -1.4px;
  --type-hero: 600 40px/44px var(--font-sans);
  --type-hero-tracking: -0.8px;
  --type-title: 600 24px/30px var(--font-sans);
  --type-title-tracking: -0.3px;
  --type-heading: 600 18px/24px var(--font-sans);
  --type-heading-tracking: -0.1px;
  --type-panel-title: 600 15px/20px var(--font-sans);
  --type-body: 400 14px/22px var(--font-sans);
  --type-dense: 500 13.5px/18px var(--font-sans);
  --type-small: 400 13px/20px var(--font-sans);
  --type-label: 500 12px/16px var(--font-sans);
  --type-caption: 400 12px/16px var(--font-sans);
  --type-control: 500 13px/16px var(--font-sans);
  --type-field: 400 14px/20px var(--font-sans);
  --type-item: 500 13px/18px var(--font-sans);
  --type-pill: 600 12px/12px var(--font-sans);
  --type-stat: 600 28px/32px var(--font-sans);
  --type-stat-tracking: -0.5px;
  --type-strip: 500 12.5px/18px var(--font-sans);
  --type-id: 400 12.5px/18px var(--font-mono);
  --type-mark-info: 600 11px/11px var(--font-sans);
  --type-mark-error: 600 10px/14px var(--font-sans);
  --motion-fast: 120ms;
  --motion-base: 200ms;
  --motion-pivot: 400ms;
  --motion-pulse: 1200ms;
  --ease-out: cubic-bezier(.2, .7, .3, 1);
  --ease-pivot: cubic-bezier(.34, 1.3, .4, 1);
  --z-nav: 5;
  --z-popover: 10;
  --z-dialog: 100;
  --z-toast: 110;
}
@media (prefers-reduced-motion: reduce) {
  :root { --motion-fast: 0ms; --motion-base: 0ms; --motion-pivot: 0ms; --motion-pulse: 0ms; }
}
.lm-type-display { font: var(--type-display); letter-spacing: var(--type-display-tracking); }
.lm-type-hero { font: var(--type-hero); letter-spacing: var(--type-hero-tracking); }
.lm-type-title { font: var(--type-title); letter-spacing: var(--type-title-tracking); }
.lm-type-heading { font: var(--type-heading); letter-spacing: var(--type-heading-tracking); }
.lm-type-panel-title { font: var(--type-panel-title); }
.lm-type-body { font: var(--type-body); }
.lm-type-dense { font: var(--type-dense); }
.lm-type-small { font: var(--type-small); }
.lm-type-label { font: var(--type-label); }
.lm-type-caption { font: var(--type-caption); }
.lm-type-control { font: var(--type-control); }
.lm-type-field { font: var(--type-field); }
.lm-type-item { font: var(--type-item); }
.lm-type-pill { font: var(--type-pill); }
.lm-type-stat { font: var(--type-stat); letter-spacing: var(--type-stat-tracking); }
.lm-type-strip { font: var(--type-strip); }
.lm-type-id { font: var(--type-id); }
.lm-type-mark-info { font: var(--type-mark-info); }
.lm-type-mark-error { font: var(--type-mark-error); }
@media (width < 720px) { .lm-type-display { font: var(--type-hero); letter-spacing: var(--type-hero-tracking); } }
/* @generated:end */

/* ---- Base ------------------------------------------------------------------------------ */
/* The base styles apply inside lm-root: put the class on <body> (or on the element that holds
   Loom's screens, where a page has other things on it). Nothing here styles an element outside it.
   Until v2.1 a page with no lm-root anywhere is treated as before, the whole page as Loom's
   (DEPRECATED.md): that is what the second selector in each rule below is for. */
.lm-root, :where(html:not(:has(.lm-root))) body {
  margin: 0;
  background: var(--surface-ground);
  color: var(--text-body);
  font: var(--type-body);
  font-variant-numeric: tabular-nums;
  -webkit-font-smoothing: antialiased;
}
/* An id takes the weight of the line it sits in. lm-mono is the old name for lm-id: it still works, and new markup uses lm-id. */
.lm-id, .lm-mono { font: var(--type-id); font-weight: inherit; font-variant-numeric: inherit; color: var(--text-secondary); font-variant-ligatures: none; }
.lm-sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
:where(.lm-root, html:not(:has(.lm-root))) :where(a, button, input, select, textarea, summary, [tabindex]):focus-visible { outline: 2px solid var(--ember); outline-offset: 2px; }
:where(.lm-root, html:not(:has(.lm-root))) a { color: var(--text-strong); text-decoration: underline; text-decoration-color: var(--line-control); text-decoration-thickness: 1px; text-underline-offset: 3px; }
@media (hover: hover) { :where(.lm-root, html:not(:has(.lm-root))) a:hover { text-decoration-color: var(--text-strong); } }

/* ---- Layout ---------------------------------------------------------------------------- */
.lm-stack { display: flex; flex-direction: column; gap: var(--space-4); }
.lm-row { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3); }
.lm-hit { min-height: var(--hit); display: flex; align-items: center; }

/* ---- Shell (the page frame) ------------------------------------------------------------- */
/* strip, rail, top bar, content. Breakpoints are the constants in tokens.ext.json: the rail is open
   from 1280px, folded to its icons from 720px, and the bottom tab bar on a phone. The shell fills
   the window and its content scrolls; the rail and the top bar stay put. */
.lm-shell {
  display: grid; height: 100vh; height: 100dvh;
  grid-template-columns: var(--rail-w) minmax(0, 1fr); grid-template-rows: auto auto minmax(0, 1fr);
  grid-template-areas: "strip strip" "rail top" "rail content";
}
.lm-shell > .lm-strip { grid-area: strip; }
.lm-shell > .lm-rail { grid-area: rail; width: auto; overflow-y: auto; }
.lm-topbar {
  grid-area: top; display: flex; align-items: center; gap: var(--space-3); min-height: var(--topbar-h); box-sizing: border-box;
  padding: 0 var(--space-6); background: var(--surface-panel); border-bottom: 1px solid var(--line-hairline); color: var(--text-secondary);
}
.lm-topbar-actions { display: flex; align-items: center; gap: var(--space-2); margin-inline-start: auto; }
.lm-content { grid-area: content; min-width: 0; overflow-y: auto; padding: var(--space-6); }
.lm-page { display: flex; flex-direction: column; gap: var(--space-6); max-width: var(--content-max); margin: 0 auto; }
/* The content grid: 12 columns from 960px, one column below. */
.lm-grid { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); gap: var(--space-6); }
.lm-col-3 { grid-column: span 3; } .lm-col-4 { grid-column: span 4; } .lm-col-6 { grid-column: span 6; }
.lm-col-8 { grid-column: span 8; } .lm-col-9 { grid-column: span 9; } .lm-col-12 { grid-column: span 12; }
@media (width < 960px) { .lm-grid > * { grid-column: 1 / -1; } }

/* A rail with more than five destinations: mark the ones the tab bar leaves out lm-rail-item--desk,
   and add one lm-rail-item--more ("More"), which only the tab bar shows and which leads to them. */
.lm-rail-item.lm-rail-item--more { display: none; }
@media (width < 720px) { .lm-shell > .lm-rail .lm-rail-item.lm-rail-item--more { display: flex; } }

/* Folded: the rail keeps its icons; a label shows beside its item on hover and on focus. */
@media (width < 1280px) {
  .lm-shell { grid-template-columns: var(--rail-w-folded) minmax(0, 1fr); }
  .lm-shell > .lm-rail { overflow: visible; padding-inline: var(--space-2); }
  .lm-shell > .lm-rail .lm-rail-brand { justify-content: center; padding-inline: 0; }
  .lm-shell > .lm-rail .lm-rail-brand span, .lm-shell > .lm-rail .lm-rail-heading { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
  .lm-shell > .lm-rail .lm-rail-item { justify-content: center; padding: 0; }
  .lm-shell > .lm-rail .lm-rail-label {
    position: absolute; inset-inline-start: calc(100% + var(--space-2)); top: 50%; transform: translateY(-50%); z-index: var(--z-popover);
    padding: var(--space-1) var(--space-2); border-radius: var(--radius-control); background: var(--surface-inverse); color: var(--on-inverse);
    font: var(--type-label); white-space: nowrap; box-shadow: var(--shadow-pop); opacity: 0; pointer-events: none;
  }
  .lm-shell > .lm-rail .lm-rail-item:hover .lm-rail-label, .lm-shell > .lm-rail .lm-rail-item:focus-visible .lm-rail-label { opacity: 1; }
  .lm-shell > .lm-rail .lm-rail-count { position: absolute; top: 4px; inset-inline-end: 4px; margin: 0; min-width: 16px; height: 16px; padding: 0 4px; }
  .lm-shell > .lm-rail .lm-rail-divider { margin-inline: var(--space-2); }
}
/* Phone: the rail is the bottom tab bar, with its own labels under the icons; at most five items.
   Gutters drop to space-5, and the content leaves room for the bar. */
@media (width < 720px) {
  .lm-shell { grid-template-columns: minmax(0, 1fr); grid-template-areas: "strip" "top" "content"; }
  .lm-shell > .lm-rail {
    position: fixed; inset-inline: 0; bottom: 0; z-index: var(--z-nav); flex-direction: row; align-items: stretch; gap: 0;
    height: auto; min-height: var(--tabbar-h); padding: 0 var(--space-1) env(safe-area-inset-bottom, 0px); overflow: visible;
  }
  .lm-shell > .lm-rail .lm-rail-brand, .lm-shell > .lm-rail .lm-rail-heading, .lm-shell > .lm-rail .lm-rail-divider, .lm-shell > .lm-rail .lm-rail-item--desk { display: none; }
  .lm-shell > .lm-rail .lm-rail-item { flex: 1 1 0; min-width: 0; flex-direction: column; gap: 2px; min-height: var(--tabbar-h); border-radius: 0; background: none; }
  .lm-shell > .lm-rail .lm-rail-label {
    position: static; transform: none; padding: 0; background: none; box-shadow: none; opacity: 1; color: inherit;
    font: var(--type-label); max-width: 100%; overflow: hidden; text-overflow: ellipsis;
  }
  .lm-shell > .lm-rail .lm-rail-item[aria-current="page"]::before { inset-inline: var(--space-3); top: 0; bottom: auto; width: auto; height: 3px; border-radius: 0 0 var(--radius-bar) var(--radius-bar); }
  .lm-shell > .lm-rail .lm-rail-count { top: 6px; inset-inline-end: calc(50% - 22px); }
  .lm-topbar { padding: 0 var(--space-5); }
  .lm-content { padding: var(--space-5) var(--space-5) calc(var(--tabbar-h) + var(--space-5) + env(safe-area-inset-bottom, 0px)); }
}

/* ---- Page header ----------------------------------------------------------------------- */
/* Where you are (breadcrumb), the page's question or object as its title, and the page's actions. */
.lm-crumbs { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); margin: 0; padding: 0; list-style: none; font: var(--type-label); color: var(--text-secondary); }
.lm-crumbs li + li::before { content: "/"; margin-inline-end: var(--space-2); color: var(--text-muted); }
.lm-crumbs [aria-current="page"] { color: var(--text-strong); }
@media (pointer: coarse) { .lm-crumbs li { display: inline-flex; align-items: center; min-height: var(--hit); } }
.lm-pagehead { display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between; gap: var(--space-3) var(--space-5); }
.lm-pagehead-text { display: flex; flex-direction: column; gap: var(--space-2); min-width: 0; }
.lm-pagehead-title { margin: 0; font: var(--type-title); letter-spacing: var(--type-title-tracking); color: var(--text-strong); }
.lm-pagehead-sub { margin: 0; max-width: 72ch; color: var(--text-secondary); }
.lm-pagehead-actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3); }
@media (width < 720px) { .lm-pagehead-actions { width: 100%; } }

/* ---- Answer header ---------------------------------------------------------------------- */
/* A page that answers a question says the answer in its first line, under the title. The mark
   before it is ink in every case: "Yes." and "No." look the same, and the status is in the page. */
.lm-answer { display: flex; align-items: baseline; gap: var(--space-3); margin: 0; max-width: 72ch; font: var(--type-heading); font-weight: 400; letter-spacing: var(--type-heading-tracking); color: var(--text-strong); }
.lm-answer strong { font-weight: 600; }
.lm-answer::before { content: ""; flex: none; width: 9px; height: 9px; border-radius: var(--radius-bar); background: var(--text-strong); transform: translateY(-1px) rotate(45deg); }
.lm-answer-next { margin: 0; max-width: 72ch; color: var(--text-secondary); }

/* ---- Provenance ------------------------------------------------------------------------- */
/* Where a figure comes from: evidenced (read from a system of record), declared (someone's
   record of it) or can't tell. A tag, not a pill, and never a status colour: the three differ by
   word and by edge (filled, outlined, dashed). */
.lm-prov { display: inline-flex; align-items: center; gap: var(--space-1); height: 22px; padding: 0 var(--space-2); box-sizing: border-box; border: 1px solid transparent; border-radius: var(--radius-tag); font: var(--type-pill); font-weight: 500; white-space: nowrap; }
.lm-prov-src { font-weight: 400; }
.lm-prov-src::before { content: "\00b7"; margin-inline-end: var(--space-1); }
.lm-prov--evidenced { background: var(--surface-sunken); border-color: var(--text-secondary); color: var(--text-strong); }
.lm-prov--declared { background: var(--surface-panel); border-color: var(--line-control); color: var(--text-secondary); }
.lm-prov--unknown { background: var(--unknown-dim); border: 1px dashed var(--unknown-line); color: var(--unknown-text); }

/* ---- Evidence link ----------------------------------------------------------------------- */
/* A link to the record that proves something, named by what it proves. The arrow says it leaves
   the page for the evidence; the name carries the meaning. */
.lm-evidence { display: inline-flex; align-items: baseline; gap: var(--space-1); font-weight: 500; }
.lm-evidence::after { content: "\2197"; content: "\2197" / ""; flex: none; color: var(--text-secondary); text-decoration: none; }
@media (pointer: coarse) { .lm-evidence { min-height: var(--hit); align-items: center; } }

/* ---- Priority mark ----------------------------------------------------------------------- */
/* P1 to P4, in ink. Priority is how soon, not how bad: it is never red, amber or green. The four
   step down in weight: filled, ink edge, quiet edge, sunken. */
.lm-priority { display: inline-flex; align-items: center; justify-content: center; min-width: 28px; height: 22px; padding: 0 var(--space-1); box-sizing: border-box; border: 1px solid transparent; border-radius: var(--radius-tag); font: var(--type-pill); white-space: nowrap; }
.lm-priority--p1 { background: var(--action-ink); color: var(--on-action-ink); }
.lm-priority--p2 { background: var(--surface-panel); border-color: var(--text-strong); color: var(--text-strong); }
.lm-priority--p3 { background: var(--surface-panel); border-color: var(--line-control); color: var(--text-secondary); font-weight: 500; }
.lm-priority--p4 { background: var(--surface-sunken); color: var(--text-secondary); font-weight: 500; }

/* ---- Count badge ------------------------------------------------------------------------- */
/* A count and what it counts: "1 yours", "5 group". A number, not a status, so it is neutral
   whatever it counts, and zero looks like any other count. */
.lm-badge { display: inline-flex; align-items: center; gap: var(--space-1); height: 22px; padding: 0 var(--space-2); box-sizing: border-box; border-radius: var(--radius-pill); background: var(--surface-sunken); color: var(--text-secondary); font: var(--type-pill); font-weight: 500; white-space: nowrap; }
.lm-badge b { color: var(--text-strong); font-weight: 600; }

/* ---- Deadline ------------------------------------------------------------------------------ */
/* One date and one countdown, written the same everywhere: "Fri 6 Nov, in 4 days". The countdown
   is in whole days. A date that has passed says so in words and weight, not in red. */
.lm-deadline { white-space: nowrap; color: var(--text-body); }
.lm-deadline-in { color: var(--text-secondary); }
.lm-deadline--past .lm-deadline-in { color: var(--text-strong); font-weight: 600; }

/* ---- Work state ---------------------------------------------------------------------------- */
/* Where a piece of work stands: done, in review, doing, moved, owed. A different question from
   control status, so a different look: ink glyphs from the pivot's family and plain words, never
   a pill and never red, amber or green. */
.lm-work { display: inline-flex; align-items: center; gap: var(--space-2); font: var(--type-label); color: var(--text-body); white-space: nowrap; }
.lm-work::before { content: ""; flex: none; box-sizing: border-box; width: 10px; height: 10px; border-radius: var(--radius-bar); }
.lm-work--done::before { background: var(--text-strong); }
.lm-work--review::before { border: 1.5px solid var(--text-strong); }
.lm-work--doing::before { width: 9px; height: 9px; background: var(--text-strong); transform: rotate(45deg); }
.lm-work--moved::before { width: 10px; height: 2px; border-radius: 0; background: var(--text-secondary); }
.lm-work--moved { color: var(--text-secondary); }
.lm-work--owed::before { border: 1.5px dashed var(--unknown-line); }
.lm-work--owed { color: var(--unknown-text); }

/* ---- Filters (a toolbar of chips that folds on a phone) -------------------------------- */
/* From 720px the filters are all on show and the Filter button is not. Below, one Filter button,
   which says how many are set, opens them: aria-expanded on the button decides. */
.lm-filters { display: flex; flex-direction: column; gap: var(--space-2); }
.lm-btn.lm-filters-toggle { display: none; align-self: flex-start; }
.lm-filters-body { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2) var(--space-5); }
@media (width < 720px) {
  .lm-btn.lm-filters-toggle { display: inline-flex; }
  .lm-filters-toggle[aria-expanded="false"] + .lm-filters-body { display: none; }
  .lm-filters-body { flex-direction: column; align-items: stretch; }
}

/* ---- Button ---------------------------------------------------------------------------- */
.lm-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--space-2);
  min-height: var(--hit); padding: 0 var(--space-4);
  border: 1px solid transparent; border-radius: var(--radius-control);
  font: var(--type-control); letter-spacing: 0; text-transform: none;
  cursor: pointer; white-space: nowrap; text-decoration: none;
  transition: background-color var(--motion-fast) var(--ease-out), border-color var(--motion-fast) var(--ease-out);
}
@media (pointer: fine) { .lm-btn { min-height: var(--control-h); } }
/* States follow the contract in the brand book: hover (only where the pointer can hover), then
   pressed, then disabled and busy, in that order so the later one wins. */
.lm-btn--primary { background: var(--action-ink); color: var(--on-action-ink); }
.lm-btn--ember { background: var(--ember-fill); color: var(--on-ember); }
.lm-btn--secondary { background: var(--surface-panel); color: var(--text-strong); border-color: var(--line-control); }
.lm-btn--ghost { background: transparent; color: var(--text-strong); }
.lm-btn--danger { background: var(--surface-panel); color: var(--critical-text); border-color: var(--critical); }
.lm-btn--danger-confirm { background: var(--danger-fill); color: var(--on-danger); }
@media (hover: hover) {
  .lm-btn--primary:hover:not(:disabled, [aria-disabled="true"]) { background: var(--action-ink-hover); }
  .lm-btn--ember:hover:not(:disabled, [aria-disabled="true"]) { background: var(--ember-fill-hover); }
  .lm-btn--secondary:hover:not(:disabled, [aria-disabled="true"]) { background: var(--surface-hover); }
  .lm-btn--ghost:hover:not(:disabled, [aria-disabled="true"]) { background: var(--surface-hover); }
  .lm-btn--danger:hover:not(:disabled, [aria-disabled="true"]) { background: var(--critical-dim); }
  .lm-btn--danger-confirm:hover:not(:disabled, [aria-disabled="true"]) { background: var(--danger-fill-hover); }
}
.lm-btn--primary:active:not(:disabled, [aria-disabled="true"]) { background: var(--action-ink-pressed); }
.lm-btn--ember:active:not(:disabled, [aria-disabled="true"]) { background: var(--ember-fill-pressed); }
.lm-btn--secondary:active:not(:disabled, [aria-disabled="true"]) { background: var(--surface-pressed); border-color: var(--text-secondary); }
.lm-btn--ghost:active:not(:disabled, [aria-disabled="true"]) { background: var(--surface-pressed); }
.lm-btn--danger:active:not(:disabled, [aria-disabled="true"]) { background: var(--critical-dim); box-shadow: inset 0 0 0 1px var(--critical); }
.lm-btn--danger-confirm:active:not(:disabled, [aria-disabled="true"]) { background: var(--danger-fill-pressed); }
/* aria-disabled keeps the button focusable, so the line that says why (lm-reason) can be reached. */
.lm-btn:disabled, .lm-btn[aria-disabled="true"] { background: var(--surface-sunken); color: var(--text-disabled); border-color: transparent; cursor: not-allowed; }
/* Busy: the button keeps its width, its label gives way to the pivot loader, and it ignores clicks. */
.lm-btn[aria-busy="true"] { position: relative; color: transparent; pointer-events: none; cursor: progress; }
.lm-btn[aria-busy="true"]::after {
  content: ""; position: absolute; left: 50%; top: 50%; width: 10px; height: 10px; margin: -5px 0 0 -5px; border-radius: var(--radius-bar);
  animation: lm-pivot var(--motion-pivot) var(--ease-pivot) infinite alternate;
}
.lm-btn--primary[aria-busy="true"]::after { background: var(--on-action-ink); }
.lm-btn--ember[aria-busy="true"]::after { background: var(--on-ember); }
.lm-btn--secondary[aria-busy="true"]::after, .lm-btn--ghost[aria-busy="true"]::after { background: var(--text-strong); }
.lm-btn--danger[aria-busy="true"]::after { background: var(--critical-text); }
.lm-btn--danger-confirm[aria-busy="true"]::after { background: var(--on-danger); }
@media (prefers-reduced-motion: reduce) { .lm-btn[aria-busy="true"]::after { animation: none; transform: rotate(45deg); } }
/* Disabled with a reason: one visible line under the control saying why, and what unlocks it. */
.lm-reason { margin: var(--space-1) 0 0; font: var(--type-caption); color: var(--text-secondary); }
.lm-btn svg { width: 16px; height: 16px; }

/* ---- Field ----------------------------------------------------------------------------- */
.lm-field { display: flex; flex-direction: column; gap: var(--space-1); max-width: 360px; }
.lm-label { font: var(--type-label); color: var(--text-secondary); }
.lm-input {
  min-height: var(--hit); padding: 0 var(--space-3); box-sizing: border-box; width: 100%;
  background: var(--surface-field); color: var(--text-strong);
  border: 1px solid var(--line-control); border-radius: var(--radius-control);
  font: var(--type-field);
}
@media (pointer: fine) { .lm-input { min-height: var(--control-h); } }
.lm-input::placeholder { color: var(--text-muted); }
@media (hover: hover) { .lm-input:hover:not(:disabled, [readonly]) { border-color: var(--text-secondary); } }
.lm-input:focus-visible { outline: 2px solid var(--ember); outline-offset: 1px; }
/* An error is a 2px critical edge plus a mark and a sentence, so it never rests on colour alone and
   stays apart from the ember focus ring (ember and critical are only 1.49:1 apart). */
.lm-input[aria-invalid="true"], .lm-select[aria-invalid="true"] { border-color: var(--critical); box-shadow: inset 0 0 0 1px var(--critical); }
.lm-input[aria-invalid="true"]:focus-visible, .lm-select[aria-invalid="true"]:focus-visible { outline-offset: 2px; }
/* Read-only stays focusable and readable: a sunken fill and a quiet edge say it cannot be changed. */
.lm-input[readonly] { background: var(--surface-sunken); border-color: var(--line-hairline); }
.lm-input:disabled, .lm-select:disabled { background: var(--surface-sunken); color: var(--text-disabled); border-color: var(--line-hairline); cursor: not-allowed; }
.lm-input:disabled::placeholder { color: var(--text-disabled); }
.lm-help { font: var(--type-caption); color: var(--text-muted); }
.lm-help--error { display: flex; align-items: flex-start; gap: var(--space-1); color: var(--critical-text); }
.lm-help--error::before {
  content: "!"; content: "!" / ""; flex: none; width: 14px; height: 14px; margin-top: 1px; border-radius: 50%;
  background: var(--critical); color: var(--on-critical); font: var(--type-mark-error); text-align: center;
}

/* ---- Segmented control ----------------------------------------------------------------- */
.lm-seg { display: inline-flex; gap: 2px; padding: 3px; background: var(--surface-sunken); border-radius: var(--radius-control); }
.lm-seg button {
  min-height: 38px; padding: 0 var(--space-3); border: 1px solid transparent; border-radius: var(--radius-inner);
  background: transparent; color: var(--text-secondary); font: var(--type-control); cursor: pointer;
}
@media (hover: hover) { .lm-seg button:hover:not(:disabled) { color: var(--text-strong); } }
.lm-seg button:active:not(:disabled) { background: var(--surface-pressed); color: var(--text-strong); }
.lm-seg button[aria-pressed="true"] { background: var(--surface-panel); color: var(--text-strong); font-weight: 600; border-color: var(--line-control); box-shadow: var(--shadow-thumb); }
.lm-seg button:disabled { color: var(--text-disabled); cursor: not-allowed; }

/* ---- Chips (filters) ------------------------------------------------------------------- */
.lm-chips { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.lm-chip {
  display: inline-flex; align-items: center; gap: var(--space-1); min-height: var(--hit); padding: 0 var(--space-3);
  border: 1px solid var(--line-control); border-radius: var(--radius-pill);
  background: var(--surface-panel); color: var(--text-body); font: var(--type-control); cursor: pointer;
  /* 44px on touch; 32px with a fine pointer, where its row (.lm-chips in a 44px band) keeps the target */
}
@media (pointer: fine) { .lm-chip { min-height: 32px; } }
@media (hover: hover) { .lm-chip:hover:not(:disabled, [aria-disabled="true"]) { background: var(--surface-hover); } }
.lm-chip:active:not(:disabled, [aria-disabled="true"]) { background: var(--surface-pressed); border-color: var(--text-secondary); }
.lm-chip[aria-pressed="true"] { background: var(--action-ink); border-color: var(--action-ink); color: var(--on-action-ink); }
.lm-chip:disabled, .lm-chip[aria-disabled="true"] { background: var(--surface-sunken); border-color: var(--line-hairline); color: var(--text-disabled); cursor: not-allowed; }
.lm-chip .lm-count { font-weight: 600; }
.lm-tag { display: inline-flex; align-items: center; height: 22px; padding: 0 var(--space-2); border-radius: var(--radius-tag); background: var(--surface-sunken); color: var(--text-secondary); font: var(--type-pill); font-weight: 500; }

/* ---- Status pill ----------------------------------------------------------------------- */
.lm-pill {
  display: inline-flex; align-items: center; gap: 6px; height: 22px; padding: 0 10px;
  border-radius: var(--radius-pill); border: 1px solid transparent;
  font: var(--type-pill); white-space: nowrap;
}
.lm-pill--positive { background: var(--positive); color: var(--on-positive); }
.lm-pill--caution { background: var(--caution); color: var(--on-caution); }
.lm-pill--critical { background: var(--critical); color: var(--on-critical); }
.lm-pill--info { background: var(--info); color: var(--on-info); }
.lm-pill--unknown { background: var(--unknown-dim); color: var(--unknown-text); border: 1px dashed var(--unknown-line); }
.lm-pill--soft.lm-pill--positive { background: var(--positive-dim); color: var(--positive-text); }
.lm-pill--soft.lm-pill--caution { background: var(--caution-dim); color: var(--caution-text); }
.lm-pill--soft.lm-pill--critical { background: var(--critical-dim); color: var(--critical-text); }
.lm-pill--soft.lm-pill--info { background: var(--info-dim); color: var(--info-text); }

/* ---- Status mark ------------------------------------------------------------------------- */
/* Positive, caution and critical are too close in lightness to be told apart by hue alone
   (1.31:1 and less), so a status mark is a shape as well as a colour: positive a circle, caution
   a triangle, critical a square, unknown a dashed ring. lm-mark is the mark on its own (a legend,
   a list); a status tile's label and a status toast draw the same shapes themselves. */
.lm-mark { display: inline-block; flex: none; width: 10px; height: 10px; }
.lm-mark::before, .lm-tile--positive .lm-tile-label::before, .lm-tile--caution .lm-tile-label::before, .lm-tile--critical .lm-tile-label::before, .lm-toast--positive::before, .lm-toast--critical::before {
  content: ""; display: block; flex: none; box-sizing: border-box; width: 10px; height: 10px;
}
.lm-mark--positive::before, .lm-tile--positive .lm-tile-label::before, .lm-toast--positive::before { border-radius: 50%; }
.lm-mark--caution::before, .lm-tile--caution .lm-tile-label::before { clip-path: polygon(50% 0, 100% 100%, 0 100%); }
.lm-mark--positive::before { background: var(--positive); }
.lm-mark--caution::before { background: var(--caution-edge); }
.lm-mark--critical::before { background: var(--critical); }
.lm-mark--unknown::before { border: 1.5px dashed var(--unknown-line); border-radius: 50%; }

/* ---- Panel (card) ---------------------------------------------------------------------- */
.lm-panel { background: var(--surface-panel); border: 1px solid var(--line-hairline); border-radius: var(--radius-panel); box-shadow: var(--shadow-panel); padding: var(--space-5); }
.lm-panel-head { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--space-1) var(--space-3); margin-bottom: var(--space-3); }
.lm-panel-title { margin: 0; font: var(--type-panel-title); color: var(--text-strong); }
.lm-panel-meta { font: var(--type-caption); color: var(--text-muted); }
/* Selected and current are states, so they are aria-current on the panel. The --selected and
   --current modifiers are the old way and work until v2.1 (DEPRECATED.md). */
.lm-panel[aria-current="true"], .lm-panel--selected { box-shadow: inset 3px 0 0 var(--ember); background: var(--surface-hover); }
.lm-panel[aria-current="step"], .lm-panel--current { box-shadow: inset 3px 0 0 var(--ember); background: var(--ember-wash); }
/* An inset shadow has no logical side, so the bar is mirrored by hand where the text runs right to left. */
.lm-panel[aria-current]:dir(rtl), .lm-panel--selected:dir(rtl), .lm-panel--current:dir(rtl) { box-shadow: inset -3px 0 0 var(--ember); }
@media (hover: hover) { a.lm-panel:hover, .lm-panel--link:hover { border-color: var(--line-control); } }
/* A pressed card takes surface-hover, not surface-pressed: its muted meta line would fall under 4.5:1 on the darker fill. */
a.lm-panel:active, .lm-panel--link:active { background: var(--surface-hover); border-color: var(--line-control); }

/* ---- Tile (stat card) ------------------------------------------------------------------ */
.lm-tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: var(--space-3); }
@media (width < 520px) { .lm-tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.lm-tile {
  position: relative; display: flex; flex-direction: column; gap: var(--space-1);
  padding: var(--space-4); background: var(--surface-panel);
  border: 1px solid var(--line-hairline); border-radius: var(--radius-panel); overflow: hidden;
}
.lm-tile-label { display: flex; align-items: center; gap: 6px; font: var(--type-item); color: var(--text-body); }
.lm-tile-value { font: var(--type-stat); letter-spacing: var(--type-stat-tracking); color: var(--text-strong); }
.lm-tile-value small { font: var(--type-control); letter-spacing: 0; color: var(--text-muted); }
.lm-tile-note { font: var(--type-caption); color: var(--text-muted); }
.lm-tile::after { content: ""; position: absolute; inset-inline: 0; bottom: 0; height: 3px; background: transparent; }
.lm-tile--positive::after { background: var(--positive); }
.lm-tile--caution::after { background: var(--caution-edge); }
.lm-tile--critical::after { background: var(--critical); }
/* The label's status mark is drawn in the Status mark section: a shape as well as a colour. */
.lm-tile--positive .lm-tile-label::before { background: var(--positive); }
.lm-tile--caution .lm-tile-label::before { background: var(--caution-edge); }
.lm-tile--critical .lm-tile-label::before { background: var(--critical); }
.lm-tile--owed { background: var(--unknown-dim); border: 1px dashed var(--unknown-line); }
.lm-tile--owed .lm-tile-value { color: var(--unknown-text); }
.lm-tile--inverse { background: var(--surface-inverse); border-color: var(--surface-inverse); }
.lm-tile--inverse .lm-tile-label, .lm-tile--inverse .lm-tile-value, .lm-tile--inverse .lm-tile-value small, .lm-tile--inverse .lm-tile-note { color: var(--on-inverse); }

/* ---- Table rows ------------------------------------------------------------------------ */
.lm-table { width: 100%; border-collapse: collapse; font: var(--type-dense); font-weight: 400; }
.lm-table th { text-align: start; padding: 0 var(--space-3); height: 36px; border-bottom: 1px solid var(--line-hairline); color: var(--text-secondary); font: var(--type-label); }
.lm-table td { padding: 0 var(--space-3); height: var(--hit); border-bottom: 1px solid var(--line-hairline); color: var(--text-body); vertical-align: middle; }
@media (hover: hover) { .lm-table tbody tr:hover td { background: var(--surface-hover); } }
/* A row that opens a detail pane carries aria-selected (true or false) and shows a press. */
.lm-table tbody tr[aria-selected]:active td { background: var(--surface-pressed); }
.lm-table tbody tr[aria-selected="true"] td { background: var(--surface-hover); }
.lm-table tbody tr[aria-selected="true"] td:first-child { box-shadow: inset 3px 0 0 var(--ember); }
.lm-table:dir(rtl) tbody tr[aria-selected="true"] td:first-child { box-shadow: inset -3px 0 0 var(--ember); }
.lm-table td a { font-weight: 500; color: var(--text-strong); }   /* underlined at rest, as every link is: a name that is a link looks like one */
/* A caption says what the table lists. lm-sr on it keeps it for screen readers only. */
.lm-table-caption { padding: var(--space-3); text-align: start; color: var(--text-strong); font: var(--type-panel-title); }
/* A head you can sort by: a button in the th, and aria-sort on the th says which way. */
.lm-table-sort { display: inline-flex; align-items: center; gap: var(--space-1); min-height: var(--hit); margin: 0; padding: 0; border: 0; background: none; color: inherit; font: inherit; cursor: pointer; }
@media (pointer: fine) { .lm-table-sort { min-height: 32px; } }
.lm-table-sort::after { content: ""; flex: none; width: 0; height: 0; border-inline: 4px solid transparent; border-top: 5px solid var(--line-control); }
.lm-table th[aria-sort="ascending"], .lm-table th[aria-sort="descending"] { color: var(--text-strong); }
.lm-table th[aria-sort="ascending"] .lm-table-sort::after { border-top: 0; border-bottom: 5px solid var(--text-strong); }
.lm-table th[aria-sort="descending"] .lm-table-sort::after { border-top-color: var(--text-strong); }
@media (hover: hover) { .lm-table-sort:hover { color: var(--text-strong); } }
/* The head stays while the rows scroll, inside whatever scrolls them. */
.lm-table--sticky thead th { position: sticky; top: 0; background: var(--surface-panel); border-bottom: 0; box-shadow: inset 0 -1px 0 var(--line-hairline); }
/* Compact: for a table read with a mouse, many rows at a time. Touch keeps 44px rows. */
@media (pointer: fine) { .lm-table--compact th { height: 32px; } .lm-table--compact td { height: 36px; } }
/* A table whose rows open a detail pane is a grid: one row is in the tab order and takes the focus ring. */
.lm-table tbody tr:focus-visible { outline: 2px solid var(--ember); outline-offset: -2px; }
.lm-table .lm-num { text-align: end; font-variant-numeric: tabular-nums; }
/* A wide table has two ways to fit a phone. Scroll: wrap it in lm-table-scroll and it scrolls
   inside its panel with the first column held in place. Cards: lm-table--cards turns each row
   into a card below 720px; each cell then needs data-label, its column's heading. */
.lm-table-scroll { overflow-x: auto; }
.lm-table-scroll .lm-table { min-width: 640px; }
.lm-table-scroll .lm-table th:first-child, .lm-table-scroll .lm-table td:first-child { position: sticky; inset-inline-start: 0; background: var(--surface-panel); }
@media (hover: hover) { .lm-table-scroll .lm-table tbody tr:hover td:first-child { background: var(--surface-hover); } }
.lm-table-scroll .lm-table tbody tr[aria-selected="true"] td:first-child { background: var(--surface-hover); }
@media (width < 720px) {
  .lm-table--cards thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
  .lm-table--cards, .lm-table--cards tbody, .lm-table--cards tr, .lm-table--cards td { display: block; }
  .lm-table--cards tr { padding: var(--space-3) 0; border-bottom: 1px solid var(--line-hairline); }
  .lm-table--cards td { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); height: auto; min-height: 28px; padding: 0 var(--space-3); border: 0; text-align: start; }
  .lm-table--cards td::before { content: attr(data-label); flex: none; color: var(--text-secondary); font: var(--type-label); }
  .lm-table--cards td:first-child { min-height: var(--hit); font-weight: 500; }
  .lm-table--cards td:first-child::before { content: none; }
}

/* ---- Rail ------------------------------------------------------------------------------ */
.lm-rail { width: var(--rail-w); box-sizing: border-box; background: var(--rail-bg); padding: var(--space-4) var(--space-3); display: flex; flex-direction: column; gap: 2px; }
.lm-rail-brand { display: flex; align-items: center; gap: var(--space-2); padding: 0 var(--space-2) var(--space-4); color: var(--rail-text-current); font: var(--type-panel-title); }
.lm-rail-heading { padding: var(--space-4) var(--space-3) var(--space-1); color: var(--rail-heading); font: var(--type-label); }
.lm-rail-item {
  position: relative; display: flex; align-items: center; gap: var(--space-3); min-height: var(--hit);
  padding: 0 var(--space-3); border-radius: var(--radius-control);
  color: var(--rail-text); font: var(--type-dense); text-decoration: none;
}
@media (hover: hover) { .lm-rail-item:hover { color: var(--rail-text-current); background: var(--rail-current-bg); } }
.lm-rail-item:active { color: var(--rail-text-current); background: var(--rail-pressed-bg); }
.lm-rail-item[aria-current="page"] { color: var(--rail-text-current); background: var(--rail-current-bg); font-weight: 600; }
.lm-rail-item[aria-current="page"]::before { content: ""; position: absolute; inset-inline-start: 0; top: 10px; bottom: 10px; width: 3px; border-start-end-radius: var(--radius-bar); border-end-end-radius: var(--radius-bar); background: var(--ember); }
.lm-rail-item svg { width: 18px; height: 18px; flex: none; }
/* Between groups, above a heading. Decorative: the heading names the group. */
.lm-rail-divider { margin: var(--space-2) var(--space-3) 0; border: 0; border-top: 1px solid var(--rail-line); }
.lm-rail-count { margin-inline-start: auto; min-width: 20px; height: 20px; padding: 0 6px; box-sizing: border-box; border-radius: var(--radius-pill); background: var(--rail-text-current); color: var(--rail-bg); font: var(--type-pill); display: flex; align-items: center; justify-content: center; }
.lm-rail-item:focus-visible { outline: 2px solid var(--ember); outline-offset: -2px; }

/* ---- Synthetic data strip -------------------------------------------------------------- */
.lm-strip {
  display: flex; align-items: center; gap: var(--space-2); min-height: var(--strip-h);
  padding: 4px var(--space-5); background: var(--brand-strip); color: var(--on-brand-strip);
  font: var(--type-strip);
}
.lm-strip b { flex: none; font-weight: 600; }
.lm-strip-sep { opacity: .6; }
.lm-strip a { color: var(--on-brand-strip); text-decoration-color: currentColor; }
/* The institution's mark, where it has given one: beside its name in the strip or the top bar. */
.lm-brand-mark { flex: none; width: auto; height: 16px; }

/* ---- Tabs ------------------------------------------------------------------------------ */
.lm-tabs { display: flex; gap: var(--space-6); border-bottom: 1px solid var(--line-hairline); }
.lm-tab {
  display: inline-flex; align-items: center; gap: var(--space-2); min-height: var(--hit);
  margin-bottom: -1px; padding: 0 2px; border: 0; border-bottom: 2px solid transparent; background: none;
  color: var(--text-secondary); font: var(--type-dense); cursor: pointer; text-decoration: none;
}
@media (hover: hover) { .lm-tab:hover:not(:disabled, [aria-disabled="true"]) { color: var(--text-strong); } }
.lm-tab:active:not(:disabled, [aria-disabled="true"]) { color: var(--text-strong); border-bottom-color: var(--line-control); }
.lm-tab:disabled, .lm-tab[aria-disabled="true"] { color: var(--text-disabled); cursor: not-allowed; }
.lm-tab[aria-selected="true"], .lm-tab[aria-current="page"] { color: var(--text-strong); font-weight: 600; border-bottom-color: var(--ember); }

/* ---- Pivot mark ------------------------------------------------------------------------ */
.lm-pivot { display: inline-block; vertical-align: middle; }
.lm-pivot .sq { fill: var(--text-strong); }
.lm-pivot .dm { fill: var(--ember); }
.lm-pivot .ahead { fill: none; stroke: var(--line-control); stroke-width: 1.5; }
.lm-on-ink .lm-pivot .sq { fill: var(--rail-text-current); }
.lm-pivot--anim .dm-g { transform-box: fill-box; transform-origin: center; animation: lm-pivot var(--motion-pivot) var(--ease-pivot) both; }
@keyframes lm-pivot { from { transform: rotate(0deg); } to { transform: rotate(45deg); } }

/* ---- Phase track (the launch's phases) ------------------------------------------------- */
.lm-phases { display: flex; align-items: flex-start; gap: 0; margin: 0; padding: 0; list-style: none; }
.lm-phase { position: relative; flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; gap: var(--space-2); padding: 0; padding-inline-end: var(--space-3); }
.lm-phase-glyph { display: flex; align-items: center; gap: var(--space-2); min-height: 16px; }
.lm-phase-glyph svg { width: 16px; height: 16px; flex: none; }
.lm-phase-glyph::after { content: ""; flex: 1; height: 2px; background: var(--line-strong); border-radius: var(--radius-pill); }
.lm-phase:last-child .lm-phase-glyph::after { display: none; }
.lm-phase--done .lm-phase-glyph::after { background: var(--text-muted); }
.lm-phase-name { font: var(--type-item); color: var(--text-secondary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.lm-phase-meta { font: var(--type-caption); color: var(--text-muted); }
.lm-phase--done .lm-phase-name { color: var(--text-body); }
.lm-phase--done .lm-phase-glyph .sq { fill: var(--text-strong); }
.lm-phase[aria-current="step"] .lm-phase-name, .lm-phase--now .lm-phase-name { color: var(--ember-text); font-weight: 600; }
.lm-phase[aria-current="step"] .lm-phase-glyph .dm, .lm-phase--now .lm-phase-glyph .dm { fill: var(--ember); }
.lm-phase--ahead .lm-phase-glyph .ahead { fill: none; stroke: var(--line-control); stroke-width: 1.5; }
.lm-phase--owed .lm-phase-glyph .owed { fill: var(--unknown-dim); stroke: var(--unknown-line); stroke-width: 1.5; stroke-dasharray: 3 2; }
.lm-phase--owed .lm-phase-name { color: var(--unknown-text); }
.lm-phases--compact .lm-phase { flex-direction: row; align-items: center; gap: var(--space-2); padding: 0; flex: none; }
.lm-phases--compact .lm-phase-glyph::after { display: none; }
.lm-phases--compact .lm-phase-meta { display: none; }
.lm-phases--compact .lm-phase + .lm-phase { margin-inline-start: var(--space-4); }
/* On a phone the full track reads down the page: one phase to a line, glyph then name then date. */
@media (width < 720px) {
  .lm-phases:not(.lm-phases--compact) { flex-direction: column; gap: var(--space-2); }
  .lm-phases:not(.lm-phases--compact) .lm-phase { flex-direction: row; align-items: center; padding: 0; }
  .lm-phases:not(.lm-phases--compact) .lm-phase-glyph::after { display: none; }
  .lm-phases:not(.lm-phases--compact) .lm-phase-meta { margin-inline-start: auto; }
}

/* ---- Popover (the (i)) ----------------------------------------------------------------- */
.lm-info {
  display: inline-flex; align-items: center; justify-content: center; width: 20px; height: 20px; margin: 0 2px;
  border: 1px solid var(--line-control); border-radius: var(--radius-pill); background: var(--surface-panel);
  color: var(--text-secondary); font: var(--type-mark-info); cursor: pointer; vertical-align: middle;
  /* the 20px glyph sits in a 44px inline target: .lm-info-wrap */
}
.lm-info-wrap { position: relative; display: inline-flex; align-items: center; min-height: var(--hit); }
@media (hover: hover) { .lm-info:hover { color: var(--text-strong); border-color: var(--text-strong); } }
.lm-info[aria-expanded="true"] { color: var(--text-strong); border-color: var(--text-strong); }
.lm-info:active { background: var(--surface-pressed); color: var(--text-strong); border-color: var(--text-strong); }
.lm-popover {
  position: absolute; z-index: var(--z-popover); inset-inline-start: 0; top: calc(50% + 14px); width: 300px; max-width: calc(100vw - 2 * var(--space-5));
  padding: var(--space-3) var(--space-4); box-sizing: border-box;
  background: var(--surface-panel); color: var(--text-body); border: 1px solid var(--line-hairline);
  border-radius: var(--radius-panel); box-shadow: var(--shadow-pop);
  font: var(--type-small);
  animation: lm-rise var(--motion-base) var(--ease-out) both;
}
.lm-popover[hidden] { display: none; }
/* Set by the script when there is no room below the trigger. */
.lm-popover--up { top: auto; bottom: calc(50% + 14px); }
.lm-popover-title { margin: 0 0 var(--space-1); font: var(--type-item); font-weight: 600; color: var(--text-strong); }
.lm-popover p { margin: 0; }
.lm-popover p + p { margin-top: var(--space-2); }
.lm-popover a { font-weight: 500; }
.lm-popover--inverse { background: var(--surface-inverse); color: var(--on-inverse); border-color: var(--surface-inverse); }
.lm-popover--inverse .lm-popover-title, .lm-popover--inverse a { color: var(--on-inverse); }
@keyframes lm-rise { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: none; } }

/* ---- Dialog ---------------------------------------------------------------------------- */
.lm-scrim { position: fixed; inset: 0; background: color-mix(in srgb, var(--surface-inverse) 60%, transparent); display: grid; place-items: center; padding: var(--space-5); z-index: var(--z-dialog); }
.lm-scrim[hidden] { display: none; }
.lm-dialog {
  width: 480px; max-width: 100%; padding: var(--space-5); box-sizing: border-box;
  background: var(--surface-panel); color: var(--text-body); border: 1px solid var(--line-hairline);
  border-radius: var(--radius-panel); box-shadow: var(--shadow-pop);
  animation: lm-rise var(--motion-base) var(--ease-out) both;
}
.lm-dialog-title { margin: 0 0 var(--space-2); font: var(--type-heading); letter-spacing: var(--type-heading-tracking); color: var(--text-strong); }
.lm-dialog p { margin: 0 0 var(--space-3); }
.lm-dialog-actions { display: flex; justify-content: flex-end; gap: var(--space-3); margin-top: var(--space-5); }
.lm-dialog-actions .lm-btn--ghost { margin-inline-end: auto; }

/* ---- Toast ----------------------------------------------------------------------------- */
.lm-toasts { position: fixed; left: 50%; bottom: var(--space-6); transform: translateX(-50%); display: flex; flex-direction: column; gap: var(--space-2); width: max-content; max-width: min(560px, calc(100vw - 2 * var(--space-5))); z-index: var(--z-toast); }
/* A toast wraps when its sentence is long; its buttons stay on one line. */
.lm-toast-text { flex: 1 1 auto; min-width: 0; padding: var(--space-2) 0; }
.lm-toast {
  display: flex; align-items: center; gap: var(--space-3); min-height: var(--hit); padding-block: 0; padding-inline: var(--space-4) var(--space-3);
  background: var(--surface-inverse); color: var(--on-inverse); border-radius: var(--radius-control); box-shadow: var(--shadow-pop);
  font: var(--type-dense);
  animation: lm-rise var(--motion-base) var(--ease-out) both;
}
/* A positive or critical toast leads with its status mark (Status mark section). A neutral toast has none. */
.lm-toast--positive::before { background: var(--on-inverse-positive); }
.lm-toast--critical::before { background: var(--on-inverse-critical); }
.lm-toast .lm-btn { color: var(--on-inverse); padding: 0 var(--space-2); }
@media (pointer: fine) { .lm-toast .lm-btn { min-height: 32px; } }
@media (hover: hover) { .lm-toast .lm-btn:hover:not(:disabled) { background: color-mix(in srgb, var(--on-inverse) 12%, transparent); } }
.lm-toast .lm-btn:active:not(:disabled) { background: color-mix(in srgb, var(--on-inverse) 24%, transparent); }
.lm-toast .lm-id, .lm-toast .lm-mono { color: var(--on-inverse); opacity: .8; }

/* ---- Chart (bars and meters) ----------------------------------------------------------- */
.lm-bars { display: grid; grid-template-columns: max-content 1fr max-content; column-gap: var(--space-3); row-gap: var(--space-2); align-items: center; }
.lm-bars-label { font: var(--type-item); font-weight: 400; color: var(--text-body); white-space: nowrap; }
.lm-bars-value { font: var(--type-item); color: var(--text-strong); text-align: end; font-variant-numeric: tabular-nums; }
.lm-bar { height: 12px; border-radius: var(--radius-tag); background: var(--data-track); overflow: hidden; }
.lm-bar > i { display: block; height: 100%; background: var(--data-context-1); border-radius: inherit; }
.lm-bar--focus > i { background: var(--data-focus); }
.lm-bar--context-2 > i { background: var(--data-context-2); }
.lm-bar--context-3 > i { background: var(--data-context-3); background-image: repeating-linear-gradient(135deg, transparent 0 3px, var(--surface-panel) 3px 4px); }
/* A meter is the whole, split by status: its segments add up to 100%, with what is not known as
   the unknown segment, so there is no empty track. Segments are parted by a 2px gap of panel and
   always run critical, caution, positive, unknown, whatever order the markup has them in. */
.lm-meter { display: flex; gap: 2px; height: 8px; border-radius: var(--radius-tag); background: var(--surface-panel); overflow: hidden; }
.lm-meter > i { display: block; height: 100%; }
.lm-meter .critical { order: 1; background: var(--critical); }
.lm-meter .caution { order: 2; background: var(--caution-edge); }
.lm-meter .positive { order: 3; background: var(--positive); }
.lm-meter .unknown { order: 4; background: repeating-linear-gradient(135deg, var(--unknown-line) 0 2px, transparent 2px 5px); }
.lm-legend { display: flex; flex-wrap: wrap; gap: var(--space-4); margin-top: var(--space-2); font: var(--type-caption); color: var(--text-secondary); }
.lm-legend span { display: inline-flex; align-items: center; gap: 6px; }
.lm-legend i { width: 10px; height: 10px; border-radius: var(--radius-bar); }
/* A status legend uses lm-mark in place of the swatch, with the count beside each word. */
.lm-sparkline { width: 120px; height: 28px; }
.lm-sparkline .line { fill: none; stroke: var(--data-context-1); stroke-width: 1.5; }
.lm-sparkline .focus { fill: var(--data-focus); }

/* ---- Choice (select, checkbox, radio) -------------------------------------------------- */
.lm-select {
  appearance: none; -webkit-appearance: none; min-height: var(--hit); width: 100%; box-sizing: border-box;
  padding-block: 0; padding-inline: var(--space-3) var(--space-8); background: var(--surface-field); color: var(--text-strong);
  border: 1px solid var(--line-control); border-radius: var(--radius-control); font: var(--type-field); cursor: pointer;
}
@media (pointer: fine) { .lm-select { min-height: var(--control-h); } }
.lm-select-wrap { position: relative; }
.lm-select-wrap::after { content: ""; position: absolute; inset-inline-end: 14px; top: 50%; width: 8px; height: 8px; margin-top: -6px; border-right: 1.5px solid var(--text-secondary); border-bottom: 1.5px solid var(--text-secondary); transform: rotate(45deg); pointer-events: none; }
@media (hover: hover) { .lm-select:hover:not(:disabled) { border-color: var(--text-secondary); } }
.lm-select:active:not(:disabled) { border-color: var(--text-strong); }
.lm-choice { display: flex; align-items: center; gap: var(--space-3); min-height: var(--hit); font: var(--type-field); color: var(--text-body); cursor: pointer; }
.lm-choice input { appearance: none; -webkit-appearance: none; margin: 0; width: 18px; height: 18px; flex: none; box-sizing: border-box; background: var(--surface-field); border: 1.5px solid var(--line-control); border-radius: var(--radius-inner); cursor: pointer; display: grid; place-content: center; }
.lm-choice input[type="radio"] { border-radius: 50%; }
@media (hover: hover) { .lm-choice input:hover:not(:disabled) { border-color: var(--text-secondary); } }
.lm-choice input:active:not(:disabled) { background: var(--surface-pressed); border-color: var(--text-secondary); }
.lm-choice input:checked { background: var(--action-ink); border-color: var(--action-ink); }
.lm-choice input[type="checkbox"]:checked::after { content: ""; width: 5px; height: 9px; margin-top: -2px; border-right: 2px solid var(--on-action-ink); border-bottom: 2px solid var(--on-action-ink); transform: rotate(45deg); }
/* Mixed: some of what the checkbox stands for is chosen. A dash, in the chosen fill. */
.lm-choice input[type="checkbox"]:indeterminate, .lm-choice input[aria-checked="mixed"] { background: var(--action-ink); border-color: var(--action-ink); }
.lm-choice input[type="checkbox"]:indeterminate::after, .lm-choice input[aria-checked="mixed"]::after { content: ""; width: 8px; height: 2px; margin: 0; border: 0; transform: none; background: var(--on-action-ink); }
/* A group in error: each box takes the 2px critical edge; the sentence and its mark sit under the group (lm-help--error). */
.lm-choice input[aria-invalid="true"] { border-color: var(--critical); box-shadow: inset 0 0 0 1px var(--critical); }
.lm-choice input[type="radio"]:checked::after { content: ""; width: 6px; height: 6px; border-radius: 50%; background: var(--on-action-ink); }
.lm-choice input:disabled { background: var(--surface-sunken); border-color: var(--line-hairline); cursor: not-allowed; }
.lm-choice input:disabled + span { color: var(--text-disabled); }
.lm-choice-help { display: block; font: var(--type-caption); color: var(--text-muted); }

/* ---- Skeleton (loading) ---------------------------------------------------------------- */
/* What stands in for content while it loads. Put aria-busy="true" on the region and one sentence
   for screen readers (lm-sr); the skeleton itself is aria-hidden. It pulses, and holds still
   under reduced motion. */
.lm-skeleton { display: block; height: 12px; border-radius: var(--radius-tag); background: var(--surface-pressed); animation: lm-pulse var(--motion-pulse) var(--ease-out) infinite alternate; }
.lm-skeleton--stat { width: 64px; height: 28px; }
.lm-skeleton--short { width: 40%; }
.lm-skeleton--mid { width: 70%; }
@keyframes lm-pulse { from { opacity: 1; } to { opacity: .45; } }
@media (prefers-reduced-motion: reduce) { .lm-skeleton { animation: none; } }

/* ---- Empty state ----------------------------------------------------------------------- */
.lm-empty {
  display: flex; flex-direction: column; align-items: flex-start; gap: var(--space-2);
  padding: var(--space-6) var(--space-5); background: var(--unknown-dim); border: 1px dashed var(--unknown-line); border-radius: var(--radius-panel);
}
.lm-empty-title { margin: 0; font: var(--type-panel-title); color: var(--text-strong); }
.lm-empty p { margin: 0; max-width: 56ch; color: var(--text-secondary); }
.lm-empty .lm-row { margin-top: var(--space-2); }
.lm-empty--quiet { background: transparent; border-style: solid; border-color: var(--line-hairline); }
.lm-empty--quiet .lm-empty-title { color: var(--text-secondary); font-weight: 500; }

/* ---- Focus on inverse surfaces --------------------------------------------------------- */
/* surface-inverse flips with the theme, so the ring takes on-inverse-ember (3:1 in both). */
.lm-toast :focus-visible, .lm-strip :focus-visible, .lm-popover--inverse :focus-visible { outline-color: var(--on-inverse-ember); }

/* ---- Do and don't (for guidelines) ------------------------------------------------------- */
/* The pair each component's preview ends with: the same thing done right and done wrong, side by
   side, each with one sentence. The word and a tick or a cross carry which is which, in ink: a
   do and a don't are not statuses, so they are never green and red. */
.lm-dodont { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-4); }
@media (width < 720px) { .lm-dodont { grid-template-columns: minmax(0, 1fr); } }
.lm-do, .lm-dont { display: flex; flex-direction: column; gap: var(--space-2); margin: 0; }
.lm-dodont-stage { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3); min-height: 72px; padding: var(--space-4); box-sizing: border-box; background: var(--surface-panel); border: 1px solid var(--line-hairline); border-radius: var(--radius-panel); }
.lm-do figcaption, .lm-dont figcaption { font: var(--type-small); color: var(--text-secondary); }
.lm-do figcaption b, .lm-dont figcaption b { color: var(--text-strong); font-weight: 600; }
.lm-do figcaption b::before { content: "\2713\00a0"; content: "\2713\00a0" / ""; }
.lm-dont figcaption b::before { content: "\2715\00a0"; content: "\2715\00a0" / ""; }

/* ---- Print -------------------------------------------------------------------------------- */
/* A printed screen is a document: the chrome goes, panels lose their shadows, a table shows all
   of itself, and each page carries a head saying what it is and as at when. Print in Light: the
   behaviour script switches a Night page to Light for the print and back.
   lm-print-head is that running head; put it first inside lm-content. It shows only on paper.
   lm-stamp is "Draft, not frozen" and the like: a dashed ink tag, on screen and on paper. */
.lm-print-head { display: none; }
.lm-stamp { display: inline-flex; align-items: center; height: 22px; padding: 0 var(--space-2); box-sizing: border-box; border: 1px dashed var(--text-strong); border-radius: var(--radius-tag); color: var(--text-strong); font: var(--type-pill); white-space: nowrap; }
@media print {
  @page { margin: 16mm 14mm; }
  .lm-root, :where(html:not(:has(.lm-root))) body { background: var(--surface-panel); print-color-adjust: exact; -webkit-print-color-adjust: exact; }
  .lm-shell { display: block; height: auto; }
  .lm-shell > .lm-strip, .lm-rail, .lm-topbar, .lm-filters, .lm-toasts, .lm-scrim, .lm-info, .lm-popover, .lm-pagehead-actions, .lm-skeleton { display: none; }
  /* The content is laid out as a table for print so that the running head can be its header group,
     which a browser repeats at the top of every page. */
  .lm-content { display: table; width: 100%; overflow: visible; padding: 0; }
  .lm-page { max-width: none; gap: var(--space-5); }
  .lm-grid { display: block; }
  .lm-grid > * + * { margin-top: var(--space-5); }
  .lm-panel, .lm-tile, .lm-dialog { box-shadow: none; break-inside: avoid; }
  .lm-pagehead, .lm-panel-head, .lm-table-caption, .lm-table thead { break-after: avoid; }
  .lm-table-scroll { overflow: visible; }
  .lm-table-scroll .lm-table { min-width: 0; }
  .lm-table thead { display: table-header-group; }
  .lm-table tr { break-inside: avoid; }
  .lm-table--sticky thead th, .lm-table-scroll .lm-table th:first-child, .lm-table-scroll .lm-table td:first-child { position: static; }
  .lm-print-head { display: table-header-group; break-inside: avoid; color: var(--text-strong); font: var(--type-label); }
  .lm-print-head > * + * { margin-inline-start: var(--space-4); }
  .lm-print-head .lm-stamp { float: inline-end; }
  .lm-print-head::after { content: ""; display: block; clear: both; margin: var(--space-2) 0 var(--space-5); border-bottom: 1px solid var(--text-strong); }
  /* A link to evidence is no use on paper without its address. */
  .lm-evidence { display: block; }
  .lm-evidence::after { content: attr(href); display: block; color: var(--text-secondary); font: var(--type-id); font-weight: 400; overflow-wrap: anywhere; }
}

/* ---- Forced colours (Windows high contrast) -------------------------------------------- */
/* Backgrounds and box-shadows are dropped there, so place and choice are redrawn as real edges
   in system colours. Transparent borders become visible, so unchosen ones are set to Canvas. */
@media (forced-colors: active) {
  .lm-panel[aria-current="true"], .lm-panel[aria-current="step"], .lm-panel--selected, .lm-panel--current { border-inline-start: 4px solid Highlight; }
  .lm-table tbody tr[aria-selected="true"] td:first-child { border-inline-start: 4px solid Highlight; }
  .lm-rail-item[aria-current="page"]::before { forced-color-adjust: none; background: Highlight; }
  .lm-tab { border-bottom-color: Canvas; margin-bottom: 0; }
  .lm-tab[aria-selected="true"], .lm-tab[aria-current="page"] { border-bottom-color: Highlight; margin-bottom: -1px; }
  .lm-seg button { border-color: Canvas; }
  .lm-seg button[aria-pressed="true"], .lm-chip[aria-pressed="true"] { forced-color-adjust: none; background: Highlight; border-color: Highlight; color: HighlightText; }
  .lm-choice input:checked { forced-color-adjust: none; background: Highlight; border-color: Highlight; }
  .lm-choice input[type="checkbox"]:checked::after { border-color: HighlightText; }
  .lm-choice input[type="radio"]:checked::after { background: HighlightText; }
  .lm-input[aria-invalid="true"], .lm-select[aria-invalid="true"] { border-width: 2px; }
  .lm-toast { border: 1px solid CanvasText; }
  .lm-mark::before, .lm-tile--positive .lm-tile-label::before, .lm-tile--caution .lm-tile-label::before, .lm-tile--critical .lm-tile-label::before, .lm-toast--positive::before, .lm-toast--critical::before { forced-color-adjust: none; background: CanvasText; }
  .lm-mark--unknown::before { background: none; border-color: CanvasText; }
  .lm-help--error::before { forced-color-adjust: none; background: CanvasText; color: Canvas; }
  .lm-choice input[type="checkbox"]:indeterminate, .lm-choice input[aria-checked="mixed"] { forced-color-adjust: none; background: Highlight; border-color: Highlight; }
  .lm-choice input[type="checkbox"]:indeterminate::after, .lm-choice input[aria-checked="mixed"]::after { background: HighlightText; }
  .lm-choice input[aria-invalid="true"] { border-width: 2px; }
  .lm-btn:disabled, .lm-btn[aria-disabled="true"], .lm-chip:disabled, .lm-chip[aria-disabled="true"], .lm-tab:disabled, .lm-tab[aria-disabled="true"], .lm-seg button:disabled { color: GrayText; border-color: GrayText; }
  .lm-input[readonly] { border-style: dashed; }
  .lm-btn[aria-busy="true"]::after { forced-color-adjust: none; background: ButtonText; }
  .lm-skeleton { forced-color-adjust: none; background: GrayText; }
  /* Bars and meters are backgrounds, which forced colours drop: redraw them so the chart is still a chart. */
  .lm-bar, .lm-meter { border: 1px solid CanvasText; }
  .lm-bar > i, .lm-meter > i { forced-color-adjust: none; background: CanvasText; }
  .lm-meter { background: Canvas; }
}

}
