/* ============================================================
   Vetyr Design System — COMPONENTS (core, generic)
   Brand-neutral primitives: console header chrome, buttons,
   fields, badge base. All reference --accent, so overriding the
   accent reskins them. Domain-specific components (severity
   ladders, status systems, the Orbit-absorbed patterns) live in
   patterns.css or the consuming module's own stylesheet.
   Requires core.css.
   ============================================================ */

/* ────────────────────────────────────────────────────────────
   HEADER (.k-* console chrome)
   ──────────────────────────────────────────────────────────── */
.k-header {
  display: flex; align-items: center; gap: 16px;
  padding: 0 16px;
  height: 56px;
  background: var(--panel-2);
  border-bottom: 1px solid var(--rule);
  flex-shrink: 0;
}

/* Block-level/nav anchor: carries the SC 2.5.8 floor through its component class,
   because `a[href]` is deliberately NOT blanket-floored in core.css (the inline
   exception). Measured at 94.2x18.5 before this. */
.k-brand { display: flex; align-items: center; gap: 12px; min-width: 0; min-block-size: var(--target-min); }
/* Vetyr rune mark — NOT a Stein-filled square (Stein never fills).
   Container is transparent; the mark is an inline SVG whose parts are
   coloured by token via the classes below. Rune geometry (viewBox
   0 0 120 120), lifted from the Fargesystem proof, that the template emits:
     Papir stem   <polygon class="stem"  points="52,26.63 68,26.63 68,88 60,100 52,88"/>
     Papir stroke <polyline class="stroke" points="22,30 60,100 98,30"
                    fill="none" stroke-width="14" stroke-linejoin="miter"/>
     Stein head   <polygon class="head"  points="60,10 93.94,43.94 82.63,55.26 60,32.63 37.37,55.26 26.06,43.94"/> */
.k-brand .logo {
  width: 30px; height: 30px;
  display: flex; align-items: center; justify-content: center;
  flex-shrink: 0;
}
.k-brand .logo svg    { width: 26px; height: 26px; display: block; }
.k-brand .logo .stem  { fill: var(--text); }        /* Papir stem  */
.k-brand .logo .stroke{ stroke: var(--text); fill: none; } /* Papir V legs */
.k-brand .logo .head  { fill: var(--accent); }      /* Stein arrowhead */
.k-brand .name h1 {
  font-family: var(--font-display);        /* wordmark = DISPLAY (Familjen) */
  font-size: 16px; font-weight: 700; line-height: 1;
  letter-spacing: -0.01em;                 /* small negative OK on display/wordmark */
  color: var(--text);
}
.k-brand .name p {
  margin: 2px 0 0;
  font-family: var(--font-display);        /* v1.2 MICRO-LABEL (was mono) */
  font-size: 11px;                         /* 11px floor (was 10px) */
  font-weight: 500;
  letter-spacing: var(--tracking-micro);   /* +.04em (was .12em) */
  text-transform: uppercase;
  color: var(--text-2);                    /* ≤11px never --dim */
}
/* The brand is an <a> in every live shell (the management shell AND the kontroll
   console); reset the UA underline — it would otherwise propagate to the wordmark
   <h1>/<p> — and keep a visible keyboard focus ring so the link stays operable.
   SHARED core so BOTH shells inherit it from the ONE cascade every surface links:
   this reset was previously stranded in the kontroll module dialect, so the
   management shell (which links components.css but NOT kontroll.css) never received
   it and its brand rendered UA-underlined. */
.k-brand { text-decoration: none; }
.k-brand:focus-visible { outline: 2px solid var(--ring); outline-offset: 2px; border-radius: var(--radius); }

.k-context {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 7px 12px;
  background: var(--panel);
  border: 1px solid var(--rule);
  color: var(--text);
  font-family: var(--font-sans);           /* Inter — interactive UI chrome (was mono) */
  font-size: 11px;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  font-weight: 600;
  cursor: pointer;
}
.k-context:hover { background: var(--panel-3); border-color: var(--accent-dim); }
.k-context i { width: 13px; height: 13px; color: var(--accent); }
/* The org-switcher disclosure chevron. It MUST carry an explicit box size: the inline
   <svg viewBox> in the summary declares no width/height attribute, so without a CSS
   size it falls back to the replaced-element default (300×150) and balloons the
   .k-context summary far past the .k-header bar. Sized to match the user-menu chevron
   (.k-user .chev, below) so the org context sits within the bar like the other
   header controls (.k-search / .k-user). */
.k-context .chev { color: var(--dim); width: 12px; height: 12px; }
/* Single-org actor: the org context is a STATIC label (no <details>, no chevron, not
   focusable/clickable). It wears the same .k-context chip for visual consistency with
   the switcher, but drops the interactive affordance (pointer cursor + hover shift) so
   it never reads as an empty, clickable dropdown. */
.k-context.is-static { cursor: default; }
.k-context.is-static:hover { background: var(--panel); border-color: var(--rule); }

.k-nav { display: flex; align-items: center; gap: 0; height: 100%; }
.k-nav a {
  display: inline-flex; align-items: center; gap: 7px;
  height: 100%;
  padding: 0 14px;
  color: var(--text-2);                    /* ≤11px never --dim (was --dim) */
  font-family: var(--font-sans);           /* Inter — nav (was mono) */
  font-size: 11px;
  letter-spacing: 0.03em;                  /* was .1em */
  text-transform: uppercase;
  font-weight: 600;
  text-decoration: none;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
}
.k-nav a:hover { color: var(--text); }
.k-nav a.active {
  color: var(--accent);
  border-bottom-color: var(--accent);
}
.k-nav a i { width: 13px; height: 13px; }

.k-spacer { flex: 1; }

.k-tools { display: flex; align-items: center; gap: 10px; }

.k-clock {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 6px 12px;
  background: var(--panel);
  border: 1px solid var(--rule);
  font-family: var(--font-mono);           /* DATA — clock time (keep mono) */
  font-size: 13px;
  font-weight: 600;
  color: var(--text);
  font-variant-numeric: tabular-nums;
  letter-spacing: var(--tracking-data);    /* +.01em data tracking */
}
.k-clock i { width: 12px; height: 12px; color: var(--dim); }
.k-clock .live {
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
  animation: vetyr-pulse 1.6s ease-in-out infinite;
}
@keyframes vetyr-pulse {
  0%, 100% { box-shadow: 0 0 0 3px var(--accent-soft); }
  50%      { box-shadow: 0 0 0 5px rgba(255, 255, 255, 0.04); }
}
/* Motion is progressive enhancement — honour reduced-motion (WCAG 2.2). */
@media (prefers-reduced-motion: reduce) {
  .k-clock .live { animation: none; }
}

.k-user {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 5px 10px 5px 5px;
  background: var(--panel);
  border: 1px solid var(--rule);
  font-size: 12px;
  color: var(--text);
  cursor: pointer;
  font-weight: 600;
}
.k-user:hover { background: var(--panel-3); }
/* Avatar chip — Navy-800 surface with Stein text + Stein outline.
   NOT a solid Stein fill (Stein never fills). */
.k-user .avatar {
  display: inline-flex; align-items: center; justify-content: center;
  width: 24px; height: 24px;
  background: var(--panel-2);
  color: var(--accent);
  border: 1px solid var(--accent-core);
  font-family: var(--font-sans);           /* Inter initials monogram (was mono — not data) */
  font-size: 11px;                         /* 11px floor (was 10px) */
  font-weight: 700;
}
.k-user .role {
  color: var(--text-2);                    /* ≤11px never --dim */
  font-family: var(--font-display);        /* v1.2 MICRO-LABEL (was mono) */
  font-size: 11px;                         /* 11px floor (was 9.5px) */
  letter-spacing: var(--tracking-micro);   /* +.04em */
  text-transform: uppercase;
  padding-left: 8px;
  border-left: 1px solid var(--rule);
  font-weight: 500;
}

.k-darktoggle {
  display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 32px;
  background: var(--panel);
  border: 1px solid var(--rule);
  color: var(--dim);
  cursor: pointer;
}
.k-darktoggle:hover { color: var(--text); border-color: var(--accent-dim); }
.k-darktoggle i { width: 13px; height: 13px; }

/* ────────────────────────────────────────────────────────────
   BUTTONS
   ──────────────────────────────────────────────────────────── */
/* PRIMARY = Papir fill + Navy text. Exactly ONE primary action per view.
   Stein is never a fill, so the primary button is the light Papir surface. */
.btn {
  display: inline-flex; align-items: center; justify-content: center;
  gap: 8px;
  padding: 8px 14px;
  border: 1px solid var(--btn-primary-bg);
  background: var(--btn-primary-bg);
  color: var(--btn-primary-fg);
  font-family: var(--font-sans);
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.02em;
  cursor: pointer;
  text-decoration: none;
  white-space: nowrap;
  border-radius: var(--radius);
  transition: background 0.12s, border-color 0.12s, color 0.12s;
}
.btn:hover  { background: var(--btn-primary-bg-hover);  border-color: var(--btn-primary-bg-hover); }
.btn:active { background: var(--btn-primary-bg-active); border-color: var(--btn-primary-bg-active); }
/* Visible 2px Stein focus ring, offset 2px (WCAG 2.2 focus-visible). */
.btn:focus-visible { outline: 2px solid var(--ring); outline-offset: 2px; }
.btn i, .btn svg { width: 13px; height: 13px; }

.btn-lg { padding: 11px 16px; font-size: 13px; }
.btn-sm { padding: 5px 10px; font-size: 11px; font-weight: 700; letter-spacing: 0.04em; }

/* SECONDARY = Stein OUTLINE (border --accent-core, text --accent).
   .btn-outline is kept as an alias of the same treatment. */
.btn-secondary, .btn-outline {
  background: transparent;
  color: var(--btn-secondary-fg);
  border-color: var(--btn-secondary-border);
}
.btn-secondary:hover, .btn-outline:hover {
  background: var(--btn-secondary-bg-hover);
  border-color: var(--btn-secondary-border-hover);
  color: var(--accent);
}
.btn-secondary:active, .btn-outline:active { background: var(--panel-2); }

/* GHOST = Stein TEXT only. */
.btn-ghost {
  background: transparent;
  color: var(--btn-ghost-fg);
  border-color: transparent;
}
.btn-ghost:hover { background: var(--btn-ghost-bg-hover); color: var(--btn-ghost-fg-hover); border-color: transparent; }

.btn-icon {
  padding: 7px;
  width: 32px; height: 32px;
}
.btn-icon i, .btn-icon svg { width: 14px; height: 14px; }

/* SUCCESS = the OK status colour as a fill. Status hues (green/red/amber)
   MAY fill — that is the Drift layer, and it always carries a shape/label.
   Only the Stein accent is barred from filling. */
.btn-success {
  background: var(--success);
  border-color: var(--success);
  color: var(--navy);
}
.btn-success:hover  { background: color-mix(in oklab, var(--success) 82%, #fff); border-color: color-mix(in oklab, var(--success) 82%, #fff); }

/* ────────────────────────────────────────────────────────────
   FIELDS / INPUTS
   ──────────────────────────────────────────────────────────── */
.field { display: flex; flex-direction: column; gap: 6px; }
.field label {
  font-family: var(--font-display);        /* v1.2 MICRO-LABEL (was mono) */
  font-size: 11px;                         /* 11px floor (was 10px) */
  letter-spacing: var(--tracking-micro);   /* +.04em (was .12em) */
  text-transform: uppercase;
  color: var(--text-2);                    /* ≤11px never --dim */
  font-weight: 500;
  display: flex; align-items: baseline; gap: 6px;
}
.field label .hint {
  font-family: var(--font-sans);           /* Inter — sentence-case hint */
  font-size: 11px;
  font-weight: 500;
  text-transform: none;
  letter-spacing: 0;
  color: var(--text-2);                    /* was --faint; --faint never reading text */
}

.input, .select, .textarea {
  /* Box-model normalization: the declared width INCLUDES padding + the 1px
     border, so a full-width control (width:100%) never renders its padding
     and border OUTSIDE the box and pushes the surface into a horizontal
     scrollbar. Declared once here on the core control rule — modules and the
     platform inherit it from the vendored core and MUST NOT re-declare a
     per-surface box-sizing stopgap. */
  box-sizing: border-box;
  width: 100%;
  padding: 8px 10px;
  background: var(--panel-2);
  border: 1px solid var(--rule);
  color: var(--text);
  font-family: var(--font-sans);
  font-size: 13px;
  outline: none;
  border-radius: 0;
}
/* A placeholder is VISIBLE READING TEXT — WCAG grants it no exemption — so it takes
   `--dim` (4.70:1), not `--faint` (3.15:1). It still reads as a placeholder: `--text`
   input text is 11.32:1, so the weight gap is large and obvious. (Never
   placeholder-as-label — constitution § Accessibility.) */
.input::placeholder, .textarea::placeholder { color: var(--dim); }
.input:focus, .select:focus, .textarea:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 1px var(--accent-soft);
}
.textarea { min-height: 56px; resize: vertical; }

.select {
  appearance: none;
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath fill='%238B96A6' d='M5 6L0 0h10L5 6z'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 10px center;
  padding-right: 28px;
}
.select option { background: var(--panel-2); color: var(--text); }

/* Real form labels are required (placeholder ≠ label). On phones, inputs
   render ≥16px so iOS Safari does not auto-zoom the viewport on focus. */
@media (max-width: 640px) {
  .input, .select, .textarea { font-size: 16px; }
}

/* ────────────────────────────────────────────────────────────
   BADGE — base only. Semantic ramps (priority/status) live in
   patterns.css. Bespoke variants live in the module stylesheet.
   ──────────────────────────────────────────────────────────── */
.b {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 3px 8px;
  font-family: var(--font-sans);           /* Inter — badge (was mono; mono is data-only) */
  font-size: 11px;                         /* 11px floor (was 10px) */
  font-weight: 600;                        /* was 700 */
  letter-spacing: 0.03em;                  /* was .08em */
  text-transform: uppercase;
  white-space: nowrap;
  border-radius: 0;
}
/* Stein badge = tint + Stein text + Stein outline (never a solid Stein fill). */
.b-accent  { background: var(--accent-soft); color: var(--accent); border: 1px solid var(--accent-core); }
.b-outline { background: transparent; color: var(--text-2); border: 1px solid var(--rule); }

/* ────────────────────────────────────────────────────────────
   CARD + generic content primitives
   ──────────────────────────────────────────────────────────── */
.card { background: var(--panel); border: 1px solid var(--rule); padding: var(--space-4); border-radius: var(--radius); }
.card.compact { padding: var(--space-3); }
.section-title {
  font-family: var(--font-display);        /* v1.2 MICRO-LABEL (was mono) */
  font-size: 11px; text-transform: uppercase; letter-spacing: var(--tracking-micro);
  color: var(--text-2); font-weight: 500; margin: 0 0 var(--space-2);
}
.page-head {
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: var(--space-4); padding: 18px 20px 12px;
  border-bottom: 1px solid var(--rule); background: var(--panel);
}
.page-head h1 { font-size: var(--text-xl); font-weight: 700; letter-spacing: -0.01em; }
.page-head .actions { display: flex; gap: var(--space-1_5); align-items: center; }

/* ════════════════════════════════════════════════════════════
   CONTROL-ROOM CONSOLE VOCABULARY — controls + chrome
   (harvested 2026-07-18 from the kontroll module dialect;
   see design.md § "The control-room console — component vocabulary").
   These are the GENERIC operator primitives promoted from
   kontroll.css by PURE RELOCATION — same selectors, same values,
   same tokens — so `personell` and future modules compose from ONE
   visual language. A module keeps only its own layout composition
   (the console shell, the incident-card field grid, the case
   git-graph) and NEVER redefines a class below.

   Appended AFTER `.field label` on purpose: the segmented-control
   and category-tile label rules (`label.seg-opt` / `label.cchoice`)
   win the 0,1,1 tie with `.field label` by SOURCE ORDER, so they
   MUST stay later in the cascade than that rule — hence they live at
   the end of the last core sheet, exactly where the module dialect
   used to sit.
   ════════════════════════════════════════════════════════════ */

/* ── Segmented single-choice control (.seg-opt) ──────────────
   A compact segment strip for a small closed vocabulary (priority
   low/normal/high/urgent, access standard/skjermet). The active
   segment is an accent outline + hue-coded tint + text. Each segment
   is a JS-off radio `<label>` OR a submit `<button>` (submit-on-select),
   so it works with JS off either way. Segment SETS sit in a padded grid
   box (`.prio-seg` in patterns.css, or `.access-seg` / `.kc-segset`). */
.access-seg {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-1);
  padding: var(--space-0_5);
  background: var(--panel-2);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
}
.seg-opt {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-1_5);
  padding: var(--space-1_5) var(--space-1);
  cursor: pointer;
  font-family: var(--font-sans);
  font-size: var(--text-xs);
  font-weight: var(--font-weight-semibold);
  text-transform: uppercase;
  letter-spacing: var(--tracking-micro);
  color: var(--text-2);
  border: 1px solid transparent;
  border-radius: var(--radius);
}
.seg-opt input { position: absolute; opacity: 0; width: 1px; height: 1px; margin: 0; }
.seg-opt svg { width: 1em; height: 1em; flex: none; }
/* A `.seg-opt` is a `<label>` in a create panel and a submit-`<button>` in a
   submit-on-select control. Reset the UA button box chrome so the button reads
   identically to the label segment. NB reset only the box chrome (appearance /
   background) — NOT `font`: a `font: inherit` shorthand re-inherits the body 1rem and
   CLOBBERS the segment's own `--text-xs`. The `.seg-opt` font already wins over the UA
   button font by specificity, so the segment keeps its 11px micro-label size. */
button.seg-opt { appearance: none; background: transparent; width: 100%; }
/* Restore the segment's own inline-flex + centred alignment that the `.field label`
   rule's `display:flex; align-items:baseline` (0,1,1) would otherwise impose when a
   segment is a label-wrapped radio inside a field. Element-qualified (0,1,1), loaded
   after `.field label`, so it wins the tie; also covers the submit-`<button>` segments. */
label.seg-opt, button.seg-opt { display: inline-flex; align-items: center; }
.seg-opt:hover { color: var(--text); }
/* Selected state — keyed on the native radio OR the `data-active` flag a submit-button
   segment carries (when the segment IS the action, there is no separate radio to check). */
.seg-opt:has(input:checked),
.seg-opt[data-active="true"] { background: var(--accent-soft); color: var(--accent); border-color: var(--accent-core); }
.seg-opt:has(input:focus-visible) { outline: 2px solid var(--ring); outline-offset: 2px; }
/* Access segments hue-code the CHECKED state per level: standard → neutral grey,
   skjermet → accent tint. Higher specificity than the generic accent checked-state above. */
.seg-opt[data-acc="standard"]:has(input:checked) { background: var(--panel-3); color: var(--text); border-color: var(--rule); }
.seg-opt[data-acc="skjermet"]:has(input:checked) { background: color-mix(in oklab, var(--accent) 16%, transparent); color: var(--accent); border-color: var(--accent-core); }
/* Priority segments hue-code the CHECKED segment per priority: low = green, normal =
   neutral, high = amber, urgent = red — from the `--priority-*` tokens; the hue is
   REDUNDANT with the segment's text label (never colour alone). Higher specificity via
   the `[data-prio]` attribute, so it wins the generic accent checked-state above. */
.seg-opt[data-prio="low"]:has(input:checked),
.seg-opt[data-prio="low"][data-active="true"] {
  background: color-mix(in oklab, var(--priority-low) 16%, transparent);
  color: var(--priority-low);
  border-color: color-mix(in oklab, var(--priority-low) 40%, transparent);
}
.seg-opt[data-prio="normal"]:has(input:checked),
.seg-opt[data-prio="normal"][data-active="true"] {
  background: var(--panel-3);
  color: var(--text);
  border-color: var(--rule);
}
.seg-opt[data-prio="high"]:has(input:checked),
.seg-opt[data-prio="high"][data-active="true"] {
  background: color-mix(in oklab, var(--priority-high) 16%, transparent);
  color: var(--priority-high);
  border-color: color-mix(in oklab, var(--priority-high) 40%, transparent);
}
.seg-opt[data-prio="urgent"]:has(input:checked),
.seg-opt[data-prio="urgent"][data-active="true"] {
  background: color-mix(in oklab, var(--priority-urgent) 16%, transparent);
  color: var(--priority-urgent);
  border-color: color-mix(in oklab, var(--priority-urgent) 45%, transparent);
}
/* A disabled «kommer» segment (a deferred choice shown but not selectable). */
/* The «coming» segment is DE-EMPHASISED, not EXEMPTED. `--faint` is below the body
   floor (3.15:1) and this node renders READING TEXT, so it takes `--dim` (4.70:1).
   WCAG 1.4.3 does exempt "text that is part of an INACTIVE user interface
   component" — it does not reach here: this is a roleless `<span>` with no input,
   no tabindex and no widget role (its `aria-disabled` therefore conveys nothing),
   and by its template's own words a "NON-submitting placeholder ... shown for
   orientation". It is not an inactive COMPONENT; it is informational text about a
   feature that does not exist yet, and reading it IS its entire purpose.
   The affordance is NOT lost: enabled segments are `--text-2` (6.01:1), so the
   weight difference survives at 6.01 vs 4.70 — and inertness is carried by the
   padlock glyph, `cursor: not-allowed` and the `title`, never by contrast alone
   (Hard Rule 8). See specs/design.md § "Disabled is not exempt". */
.seg-opt.seg-soon { color: var(--dim); cursor: not-allowed; }
.seg-opt .seg-soon-tag {
  font-family: var(--font-sans);
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: var(--tracking-micro);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  padding: 0 var(--space-1);
}
/* A 4-up segment-SET box (mirrors the `.prio-seg` geometry) for hosting submit-`<button>`
   segments in a container OTHER than `.prio-seg`, so the `.prio-seg button` solid-fill
   rule (patterns.css) never overrides the `.seg-opt` tint. */
.kc-segset {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--space-1);
  padding: var(--space-0_5);
  background: var(--panel-2);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
}

/* ── Category icon tile as a JS-off radio (.cchoice) ─────────
   Extends the `.cat-tile` preset (patterns.css) with checked/focus
   affordances keyed on a native radio (JS-off): checked = an inset
   accent box-shadow; a sensitive category shows an auto-Skjermet
   corner padlock on the glyph so all tiles keep equal height. */
.cchoice { text-align: center; position: relative; gap: var(--space-1_5); }
/* A `.cat-tile.cchoice` is a `<label>` inside a field, so `.field label` (0,1,1) would
   otherwise UPPERCASE the sentence-case category labels and knock the glyph/label
   off-centre. Re-assert the tile's own look with an element-qualified selector (0,1,1)
   that loads AFTER `.field label`, so it wins the tie (column direction stays inherited
   from `.cat-tile`; here we only undo the axes the field-label rule overrode). */
label.cchoice { text-transform: none; align-items: center; letter-spacing: normal; }
.cchoice:has(input:checked) { box-shadow: inset 0 0 0 2px var(--accent); color: var(--text); background: var(--panel-2); }
.cchoice:has(input:focus-visible) { outline: 2px solid var(--ring); outline-offset: 2px; }
.cchoice input {
  /* The native radio stays operable (JS-off) but visually collapses into the tile —
     the tile itself is the checked affordance (box-shadow) + the icon/label. */
  position: absolute;
  opacity: 0;
  width: 1px;
  height: 1px;
  margin: 0;
}
/* The glyph is the positioning context for the auto-Skjermet corner padlock. Centred on
   BOTH axes so the lucide glyph sits dead-centre above the label. */
.cchoice .kc-tileicon { color: var(--text-2); display: inline-flex; align-items: center; justify-content: center; margin-inline: auto; position: relative; }
.cchoice:has(input:checked) .kc-tileicon { color: var(--accent); }
.cchoice .kc-tileicon .kc-ic { width: 1.7em; height: 1.7em; display: block; }
.cchoice .kc-tile-label {
  font-size: var(--text-xs);
  font-weight: var(--font-weight-medium);
  color: inherit;
}
/* The sensitive-category auto-Skjermet mark — a tiny padlock overlapping the glyph's
   top-right corner, NO word, so every tile keeps the SAME height. Redundant emphasis
   (the screened meaning is carried in TEXT elsewhere), so this shape may be aria-hidden. */
.cchoice .lockmark {
  position: absolute;
  top: calc(-1 * var(--space-1));
  right: calc(-1 * var(--space-2));
  display: inline-flex;
  color: var(--accent);
}
.cchoice .lockmark svg { width: 1em; height: 1em; }

/* ── Count-carrying filter chip (.qf) ───────────────────────
   One chip that is BOTH a live count AND the filter link — a mono
   tabular `.cnt` + an uppercase `.lbl`, hyperlinked as a plain
   query-param GET (round-trips JS-off). Active = accent outline +
   accent label (`aria-current`), never colour alone. */
.qfilters { display: flex; flex-wrap: wrap; gap: var(--space-1_5); }
.qf {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-1_5) var(--space-2_5);
  background: var(--panel);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  text-decoration: none;
  cursor: pointer;
}
.qf:hover { border-color: var(--accent-dim); }
.qf:focus-visible { outline: 2px solid var(--ring); outline-offset: 2px; }
.qf[aria-current="true"],
.qf[aria-pressed="true"] { border-color: var(--accent); background: var(--accent-soft); }
.qf .cnt {
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  font-weight: var(--font-weight-bold);
  color: var(--text);
  line-height: 1;
  font-variant-numeric: tabular-nums;
  letter-spacing: var(--tracking-data);
}
.qf .lbl {
  font-family: var(--font-sans);
  font-size: var(--text-xs);
  font-weight: var(--font-weight-semibold);
  text-transform: uppercase;
  letter-spacing: var(--tracking-micro);
  color: var(--text-2);
}
.qf[aria-current="true"] .lbl,
/* The pressed chip fills with `--accent-soft` — a 12% tint OF THE ACCENT — so an
   `--accent` label sits on a background tinted toward itself and measured 4.12:1,
   below the 4.5 body floor. The ACCENT stays as the OUTLINE signal (border-color
   above, the sanctioned accent role); the LABEL takes `--text`. Fixing the pairing
   is preferred to lifting `--accent`, which is themeable and used platform-wide as
   link/focus/live-dot ink — a far wider blast radius for the same leg. */
.qf[aria-pressed="true"] .lbl { color: var(--text); }
/* Non-colour count accent for the two urgent chips when non-empty; the LABEL still
   carries the meaning, so this is redundant emphasis. */
.qf.critaccent[data-nz="true"] .cnt { color: var(--crit); }
.qf.warnaccent[data-nz="true"] .cnt { color: var(--watch); }

/* ── Labelled key/value record cell (.ff / .k / .v) ─────────
   A generic record cell: an uppercase micro-label `.k` over a value
   `.v`. Composed into a fixed field grid by the consuming module
   (e.g. kontroll's `.kc-fields` / `.focus-grid`). */
.ff { display: flex; flex-direction: column; gap: var(--space-0_5); min-width: 0; }
.ff .k {
  font-family: var(--font-display);
  font-size: var(--text-xs);
  font-weight: var(--font-weight-medium);
  text-transform: uppercase;
  letter-spacing: var(--tracking-micro);
  color: var(--text-2);
}
.ff .v {
  font-size: var(--text-sm);
  font-weight: var(--font-weight-medium);
  color: var(--text);
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.ff .v.muted { color: var(--text-2); }
@media (max-width: 640px) {
  .ff .v { white-space: normal; }
}

/* ── Read-access padlock (list .kc-lock · focus .lockchip) ──
   The access affordance is ALWAYS an explicit padlock. In a list, a
   compact padlock marks an effective-Skjermet row. In a focus pane, a
   native <details>/<summary> chip shows a three-state read-access
   (Standard / Utvidet / Skjermet) as a padlock SHAPE + a text state
   label, expanding JS-off to the «who can read this» reader panel. */
.kc-lock { color: var(--accent); display: inline-flex; flex: none; }
.kc-lock .kc-ic { width: 1em; height: 1em; display: block; }
/* De-boxed: the wrap is a plain <details> block (full-column so the OPEN reader panel
   spans the column); the compact chip below carries the border. */
.lockchip-wrap { display: block; }
.lockchip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1_5);
  padding: var(--space-1) var(--space-2);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  cursor: pointer;
  font-family: var(--font-sans);
  font-size: var(--text-xs);
  font-weight: var(--font-weight-semibold);
  text-transform: uppercase;
  letter-spacing: var(--tracking-micro);
  color: var(--text-2);
  list-style: none;
}
.lockchip::-webkit-details-marker { display: none; }
.lockchip svg { width: 1em; height: 1em; flex: none; }
/* A Skjermet record's closed chip is ACCENT-tinted — the read-access state carries its
   own subtle colour, not the neutral grey of a Standard/Extended chip. */
.lockchip.is-skjermet { border-color: var(--accent-core); background: var(--accent-soft); color: var(--accent); }
.lockchip:focus-visible { outline: 2px solid var(--ring); outline-offset: 2px; }
/* The expanded «who can read this» reader panel — a bordered region below the chip. */
.lock-pop {
  margin-top: var(--space-2);
  padding: var(--space-2_5);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--panel);
}

/* ── Live-clock connection-state dot (.kc-conn-dot) ─────────
   The SSE connection state FOLDED onto the single live clock's one dot
   (`.k-clock .live`, above): online = success, reconnecting = warning,
   offline = dim. A consumer stamps `[data-conn-state]` on the clock;
   JS-off there is no state value, so the core accent dot shows and
   correctness never rides it. Loaded after `.k-clock .live` so the
   equal-specificity recolour wins by source order. */
[data-conn-state="online"] .kc-conn-dot { background: var(--success); }
[data-conn-state="reconnecting"] .kc-conn-dot { background: var(--warning); }
[data-conn-state="offline"] .kc-conn-dot { background: var(--dim); }

/* ── Single «type-or-pick» person/entity combo (.combo) ─────
   One free-text line up front, with structured `<select>`s tucked into
   a native <details> «choose from list» disclosure as the JS-off
   fallback (a collapsed select still submits, so every slot round-trips).
   The group heading + placeholder + hint are the visible cue; each
   control keeps an sr-only associated label. An `is-inline` mode flexes
   it beside an action button. */
.combo {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}
.combo-title {
  font-family: var(--font-display);
  font-size: var(--text-xs);
  font-weight: var(--font-weight-medium);
  text-transform: uppercase;
  letter-spacing: var(--tracking-micro);
  color: var(--text-2);
}
.combo-input { width: 100%; }
.combo-lbl {
  font-family: var(--font-display);
  font-size: var(--text-xs);
  font-weight: var(--font-weight-medium);
  text-transform: uppercase;
  letter-spacing: var(--tracking-micro);
  color: var(--text-2);
}
/* Each control keeps a programmatically-associated <label for> for AT, but it is
   visually hidden — the group heading + placeholder + hint are the visible cue. */
.combo-lbl-sr {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}
/* The JS-off «choose from list» fallback — a native <details> holding the structured
   SELECTS. Its <summary> reads as a tiny faint inline affordance (not a persistent
   full-width accent line), so the combo reads as one input line with a small grey
   «choose from list» link tucked under it. */
.combo-more { display: flex; flex-direction: column; gap: var(--space-1); }
.combo-more-sum {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  width: max-content;
  min-height: var(--target-min);   /* ≥24px pointer/touch target (WCAG 2.2 SC 2.5.8) */
  cursor: pointer;
  font-family: var(--font-sans);
  font-size: var(--text-xs);
  font-weight: var(--font-weight-medium);
  /* An 11px INTERACTIVE disclosure label. `--faint` left it legible only on hover,
     which is the wrong way round; `--dim` meets the body floor at rest. */
  color: var(--dim);
  list-style: none;
}
.combo-more-sum:hover { color: var(--text-2); }
.combo-more-sum::-webkit-details-marker { display: none; }
.combo-more-sum::before {
  content: "";
  width: 0;
  height: 0;
  border-inline: 4px solid transparent;
  border-top: 5px solid currentColor;
  transition: transform 0.12s;
}
.combo-more[open] .combo-more-sum::before { transform: rotate(180deg); }
.combo-more-sum:focus-visible { outline: 2px solid var(--ring); outline-offset: 2px; }
.combo-more-body { display: flex; flex-direction: column; gap: var(--space-1); }
.combo-native { width: 100%; }
/* 11px hint text is READING TEXT: `--dim`, never `--faint`. */
.combo-hint { font-size: var(--text-xs); font-weight: var(--font-weight-medium); color: var(--dim); }
.combo.is-inline { gap: var(--space-0_5); }

/* ── Creatable combobox — the ENHANCED overlay listbox layer ─
   (.combo-enh / .combo-listwrap / .combo-list / .combo-opt / .combo-add)
   The progressive-enhancement FRONT for the `.combo` above: a WAI-ARIA
   `role="combobox"` input driving an htmx active-search into an OVERLAY
   `role="listbox"` popup, with DOM focus staying on the input while the
   active row is tracked by `aria-activedescendant` (combobox.js stamps
   `aria-selected="true"` on that row + `aria-expanded` on the input). The
   enhanced front is `hidden` until the JS reveals it, so JS-off the native
   `.combo-more` fallback is the whole picker (the native `<select>` /
   free-text path is untouched). Every value composes from the core tokens
   above — no colour / type / space / radius / elevation literal. */

/* The enhanced front is the ANCHORING context for the absolute dropdown.
   `hidden` (the JS-off floor + the collapsed state) always wins over the
   flow display, so the popup can never show without the runtime. */
.combo-enh { position: relative; display: flex; flex-direction: column; gap: var(--space-1); }
.combo-enh[hidden] { display: none; }

/* The popup is an OVERLAY anchored under the input — lifted out of flow so it
   never pushes the sibling fields down; stacked above in-flow content but
   below the fixed detail drawer (patterns.css `.mf-drawer`, z-index 80).
   `hidden` is the collapse toggle combobox.js drives in lockstep with the
   input's `aria-expanded`. */
.combo-listwrap {
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  z-index: 30;
  margin-top: var(--space-1);
}
.combo-listwrap[hidden] { display: none; }
/* Belt for the collapsed state: a combobox reporting `aria-expanded="false"`
   keeps its popup hidden even if the `hidden` attribute lags a frame behind. */
.combo-enh [role="combobox"][aria-expanded="false"] ~ .combo-listwrap { display: none; }

/* The popup surface (`role="listbox"`) — a raised, bordered card carrying the
   overlay elevation token; scrolls once it outgrows a few rows. */
.combo-list {
  margin: 0;
  padding: var(--space-1);
  list-style: none;
  max-height: calc(var(--space-8) * 6);
  overflow-y: auto;
  background: var(--popover);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  box-shadow: var(--shadow-md);
}

/* An option row (`role="option"`) — the `display_handle` up front with its
   `kind` («Person» / «Rolle») as a trailing `.combo-hint` text sub-label
   (never colour alone). A ≥24px min target (WCAG 2.2 SC 2.5.8). */
.combo-opt {
  display: flex;
  align-items: baseline;
  gap: var(--space-2);
  min-height: var(--target-min);
  padding: var(--space-1_5) var(--space-2);
  border-radius: var(--radius);
  color: var(--text);
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  cursor: pointer;
}
.combo-opt .combo-hint { margin-left: auto; }
/* Pointer hover — a raised surface tint. */
.combo-opt:hover { background: var(--panel-3); }
/* Keyboard-active (the arrow-walked row combobox.js marks `aria-selected`):
   emphasis on THREE channels — a Stein tint + a Stein inset left-edge bar +
   a heavier weight — so the active row never rests on hue alone (WCAG). Placed
   after `:hover` so the active row wins when the pointer is also over it. */
.combo-opt[aria-selected="true"] {
  background: var(--accent-soft);
  box-shadow: inset var(--space-0_5) 0 0 0 var(--accent);
  font-weight: var(--font-weight-semibold);
}

/* The «＋ Opprett «…»» CREATE row — appended as the LAST option when the query
   matches nothing. Distinct as an ACTION by a top divider rule + the ＋ glyph
   (carried in the text) + Stein action text — never a tint alone; still a row
   (it walks with the arrows + highlights like any option). Its label rides a
   NON-interactive inner `<span>` (a `role="option"` must not contain an
   interactive control); the wrapper option's delegated handler reveals the
   create form JS-on, so DOM focus stays on the input (ac-3). */
.combo-add { padding: 0; margin-top: var(--space-1); border-top: 1px solid var(--rule); }
.combo-add:first-child { margin-top: 0; border-top: 0; }
.combo-add span {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  width: 100%;
  min-height: var(--target-min);
  padding: var(--space-1_5) var(--space-2);
  background: transparent;
  border: 0;
  border-radius: var(--radius);
  color: var(--accent);
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  font-weight: var(--font-weight-semibold);
  text-align: left;
  cursor: pointer;
}
.combo-add span:focus-visible { outline: 2px solid var(--ring); outline-offset: -2px; }

/* JS-on belt for the retired JS-off create fallback. The native `<details>` create
   disclosure's `.combo-more-sum` summary declares an explicit `display`, which would
   out-cascade the UA `[hidden]` rule — so `summary.hidden = true` alone would not hide
   it. combobox.js sets `hidden` on those summaries (and the quick-add section heading,
   a plain `<p>` the UA rule already handles) once it reveals the enhanced combobox, so
   the panel foot is clean and the «＋ Opprett» row is the only create trigger. JS-off
   (the runtime never runs) the summaries stay visible as the fallback create path. */
.combo-more-sum[hidden] { display: none; }

/* ════════════════════════════════════════════════════════════
   THE OVERLAY-POPOVER SURFACE (.popover) — consumer-neutral primitive
   spec: specs/design.md § "The overlay-popover surface — one primitive,
         a native disclosure underneath" (ruling committed 9c3412f)
   task: krc-043-popover-primitive-promotion  (contributes-to ac-1 / ac-28;
         second consumer: operator-access-override ac-34's readership panel)
   Exercised in specs/design/styleguide.html #popover.

   A JS-ANCHORED overlay surface: a raised, bordered, rounded card that is
   lifted out of flow and given its top/left/width by MEASURED GEOMETRY —
   never by a design-system literal. Every visual value here is a core token;
   `position`, `overflow`, `box-sizing` and the stacking ordinal are structural.
   `box-sizing: border-box` is part of the anchoring CONTRACT, not taste: the
   caller stamps `width` from the trigger's rect, so the border must sit inside
   that width. The viewport-relative `max-height` + `overflow:auto` keep the card
   bounded and scrollable, and the caller FLIPS it above the trigger when
   anchoring below would overflow the fold — together that is why a popover's
   primary action is ALWAYS reachable on a short viewport.

   THE THREE-LAYER FLOOR (design.md): the component is a native
   `<details>`/`<summary>` disclosure IN FLOW carrying its FULL content; this
   class is the JS-on LIFT (positioning only) applied to the SAME element, never
   reparented, so anything inside it that submits or serialises keeps working.
   Absent scripting, the in-flow disclosure is the whole component. (This is a
   CLASS named `popover`; the HTML `popover` attribute is not used — the floor
   is the native disclosure.)

   POPOVER-SHAPED SURFACES IN CORE — THE FULL ENUMERATION, so a third consumer
   does not have to re-derive it. Classified by the QUESTION each answers:
     1. "Where do I float, given a trigger I must MEASURE?"  → THIS primitive
        (`position:fixed`, JS geometry, viewport-relative clamp, flip-above).
        Consumer today: the creatable combobox's create-confirm (below).
     2. "Where do I hang off my trigger in NORMAL FLOW?" → the CSS-anchored
        dropdowns: `.combo-listwrap`/`.combo-list` (z 30, content-relative
        six-row clamp) and `.org-switch-menu`/`.user-menu-list` (z 100, dropped
        below a `<details>` summary). CSS alone answers it; no geometry, no
        flip. These are NOT compositions of this primitive and folding them in
        would CHANGE what they render — see the pin below.
     3. "How do I cover a viewport EDGE?" → `patterns.css .mf-drawer` (z 80).
        A sheet, not a trigger-anchored overlay. Not a popover at all.
     4. "What does the expanded content look like IN FLOW?" → `.lock-pop`
        (above, :667) — the read-access reader panel. Despite the `-pop` name
        it is a FLOOR, not a popover: an in-flow bordered region below its
        chip. It stays exactly that (it IS the JS-off component), and under
        `operator-access-override` ac-34 the SAME element additionally composes
        `.popover` when scripting is present. Floor and lift are two classes on
        one element, not one class doing both.
   Classes 2, 3 and 4 share this card's *look* and answer a different question;
   shape is not the classifier. Per design.md the standing constraint still
   binds: no module may author a second popover surface of its own — a class-1
   need composes `.popover`; a class-2 need composes the dropdown it matches.

   WHY THE LIFT ZEROES MARGIN. A lift is applied ON TOP of an element that is
   already styled for flow (class 4 is exactly that), so any in-flow margin it
   carries would offset the box from the geometry the caller stamped — and
   would not be counted in the `offsetHeight` the flip-above decision measures,
   so the flip would be short by that margin too. Neutralising it is part of
   the lift's contract, not a fix for one consumer. This is a NO-OP for the
   live consumer, which is how it stays inside the pin: nothing in core sets a
   margin on the create-confirm `<form>` (`.field` is a gap-based flex column,
   `.combo-more` likewise) and `<form>` carries no UA margin in the rendering
   target the constitution mandates.

   THE PIN — what a promotion may and may not change. A promotion moves WHERE a
   declaration lives; it never changes what a LIVE consumer looks like. So the
   invariant is the RENDERED RESULT, not this sheet's text (freezing the text
   would freeze the very thing being rewritten). Held here by construction: the
   block below carries every declaration of the `.combo-reveal-pop` block it
   replaces, unchanged and in the same order, AND sits at the same point in the
   cascade — so no rule's precedence over it moves either. It adds exactly one
   declaration, `margin: 0`, argued above to be a no-op for the live consumer.
   THE CHECKABLE FORM of the pin: the create-confirm's computed surface —
   background, border, radius, elevation, padding, clamp, overflow, stacking —
   resolves identically before and after. That is what to assert; do NOT assert
   this file's bytes.

   Stacking: above the listbox popup (z 30), below the detail drawer (z 80) and
   the banner pop-outs (z 100). NOTE — design.md says the stacking ordinal
   "resolves from core tokens"; core.css declares no `--z-*` token and every
   other stacking ordinal in core is a literal. The literal here follows the
   shipped convention; reconciling the two is a spec question, not this block's.
   ════════════════════════════════════════════════════════════ */
/* `.combo-reveal-pop` is the FIRST consumer's spelling — the creatable
   combobox's create-confirm `<form>`, anchored under the picker input where the
   «＋ Opprett» row that opened it lives, instead of stranded at the panel foot
   (its JS-off, in-flow `<details>` position). Retained as a pure
   ALIAS — one declaration block, two names, no duplicated declarations. It is
   NOT a second surface and NOT a composition, and this selector list DOES NOT
   GROW: a new consumer puts `.popover` in its markup. Retained rather than
   renamed away because the alias makes the landing ORDER safe — the canonical
   sheet is vendored into four build copies by a separate task
   (specs/tasks/login-issuance/074-…, whose write-path is the whole core tree),
   so the new bytes can reach a running build BEFORE krc-043's implementer half
   rewires `combobox.js`. Under a clean rename that window renders the live
   create-confirm unstyled; under the alias every order is safe.
   RETIREMENT: when combobox.js applies `.popover` instead (a class-name swap at
   its two sites — `positionReveal` adds it, `clearReveal` removes it; no
   template references this class), the alias line is deleted and nothing else
   changes. Until then it stays — a retained alias is a recorded retraction, not
   an accident. */
.popover,
.combo-reveal-pop {
  position: fixed;
  z-index: 40;
  box-sizing: border-box;
  margin: 0;
  max-height: calc(100svh - var(--space-8));
  overflow: auto;
  padding: var(--space-3);
  background: var(--popover);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  box-shadow: var(--shadow-md);
}

/* ════════════════════════════════════════════════════════════
   MANAGEMENT-SHELL VOCABULARY — chrome + sub-pattern components
   spec: specs/features/management-surface-framework.md
   task: msf-001-ds-components
   Promoted (TOKENS-ONLY) from the LOCKED management-shell mock (v1)
   so every module and `personell` reuse ONE admin look (ac-16), and
   nothing downstream hardcodes a colour/size/font (ac-14). These are
   the cross-cutting classes the shell (msf-005) and the sub-patterns
   (msf-006–msf-009) COMPOSE from. NEW class blocks only — no existing
   token or class is redefined; the banner .k-* console chrome, .btn*,
   .field/.input/.select, .card, .section-title, .b and the .kbd hint
   (core.css) are reused as-is, not re-declared. The «Deaktivert»
   hollow-ring status shape + the disabled-action treatment are
   SEMANTICS and live in patterns.css (msf-002), NOT here.
   ════════════════════════════════════════════════════════════ */

/* ── Banner: global search / ⌘K affordance (.k-search) ───────
   Sits in the shell banner beside the .k-* console chrome (above);
   the ⌘K `.kbd` hint it wraps already lives in core.css. */
.k-search {
  display: inline-flex; align-items: center; gap: var(--space-2);
  padding: 6px var(--space-2_5);
  background: var(--panel);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  color: var(--text-2);
  font-size: var(--text-sm);
  cursor: pointer;
  min-height: 32px;
}
.k-search:hover { border-color: var(--accent-dim); color: var(--text); }
.k-search svg { width: 14px; height: 14px; color: var(--dim); }
.k-search .lbl { font-weight: 500; }

/* ── Banner: management-shell entry («Administrasjon») (.k-manage) ───────
   A LINK to the management-shell root, rendered in a MODULE surface's top-bar (e.g. the
   kontroll console) ONLY when the actor has ≥1 visible management area — so an org-admin
   operator can reach /manage without leaving the console. Absent on the management shell
   itself (they are already there). Styled as a header control, consistent with
   .k-search. */
.k-manage {
  display: inline-flex; align-items: center; gap: var(--space-2);
  padding: 6px var(--space-2_5);
  background: var(--panel);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  color: var(--text-2);
  font-size: var(--text-sm);
  text-decoration: none;
  min-height: 32px;
}
.k-manage:hover { border-color: var(--accent-dim); color: var(--text); }
.k-manage:focus-visible { outline: 2px solid var(--ring); outline-offset: 2px; }
.k-manage svg { width: 14px; height: 14px; color: var(--dim); }
.k-manage .lbl { font-weight: 500; }

/* The user-menu disclosure chevron on the banner .k-user chip (above). */
.k-user .chev { color: var(--dim); width: 12px; height: 12px; }

/* ── Banner <details> disclosures (.org-switcher · .user-menu) ───────
   Native <details> so both work JS-off. The <summary> already wears the chrome
   (.k-context / .k-user, above), so these wrappers only anchor the pop-out list and
   drop the UA disclosure marker. SHARED core so EVERY shell composes the same banner
   disclosures from one source — the management shell's org-switcher + tier user-menu
   AND the kontroll console's (the console links components.css but NOT the platform
   dialect where these were previously stranded). */
.org-switcher,
.user-menu {
  position: relative;           /* the containing block for the absolute pop-out list */
  display: inline-flex;
}
.org-switcher > summary,
.user-menu > summary {
  list-style: none;
}
.org-switcher > summary::-webkit-details-marker,
.user-menu > summary::-webkit-details-marker {
  display: none;
}

/* The pop-out list — a bordered panel dropped below the summary, right-aligned,
   layered above the shell. Rendered only while the <details> is open. */
.org-switch-menu,
.user-menu-list {
  position: absolute;
  top: calc(100% + var(--space-1));
  right: 0;
  z-index: 100;                 /* above the nav/content (layering ordinal) */
  min-width: 100%;
  margin: 0;
  padding: var(--space-1);
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  background: var(--panel-2);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  box-shadow: var(--shadow-md);
}
.org-switch-menu li,
.user-menu-list li {
  display: flex;
}
/* Each row's CSRF form + its submit button (org-switch / sign-out) fills the row. */
.org-switch-menu form,
.user-menu-list form {
  display: flex;
  width: 100%;
}
.org-switch-menu button,
.user-menu-list button {
  flex: 1;
  justify-content: flex-start;
}

/* The OPTIONAL per-area banner context slot — an inline holder, empty by default. */
.banner-context {
  display: inline-flex;
  align-items: center;
}

/* ── Left topic-nav (.adm-nav) — persistent, permission-filtered ──
   The active row is a Stein LEFT-BAR (shape) + tint + accent text +
   heavier weight (pairs with aria-current="page") — never hue alone. */
.adm-nav {
  background: var(--panel);
  border-right: 1px solid var(--rule);
  padding: var(--space-4) var(--space-2_5);
  display: flex; flex-direction: column; gap: var(--space-6);
}
.adm-group { display: flex; flex-direction: column; gap: var(--space-0_5); }
.adm-group-label {
  font-family: var(--font-display);
  font-size: var(--text-xs);
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: var(--tracking-micro);
  color: var(--text-2);
  padding: 0 var(--space-2) var(--space-1_5);
}
.adm-nav a {
  display: flex; align-items: center; gap: var(--space-2_5);
  min-height: 38px;
  padding: var(--space-2) var(--space-2_5);
  color: var(--text-2);
  font-size: var(--text-sm);
  font-weight: 500;
  text-decoration: none;
  border-radius: var(--radius);
  border-left: 3px solid transparent;
}
.adm-nav a svg { width: 16px; height: 16px; flex: none; color: var(--dim); }
.adm-nav a:hover { background: var(--accent-soft); color: var(--text); }
.adm-nav a:hover svg { color: var(--text-2); }
.adm-nav a[aria-current="page"] {
  background: var(--accent-soft);
  border-left-color: var(--accent);
  color: var(--text);
  font-weight: var(--font-weight-semibold);
}
.adm-nav a[aria-current="page"] svg { color: var(--accent); }
.adm-nav a[aria-current="page"] .lbl { color: var(--accent); }

/* ── Content-header (.content-head) — breadcrumbs + h1 + action slot ── */
.content-head {
  padding: var(--space-6) var(--space-6) var(--space-4);
  border-bottom: 1px solid var(--rule);
  background: var(--panel);
}
.crumbs {
  display: flex; align-items: center; gap: var(--space-1_5); flex-wrap: wrap;
  font-size: var(--text-xs);
  color: var(--text-2);
  margin-bottom: var(--space-2);
}
.crumbs a { color: var(--text-2); text-decoration: none; }
.crumbs a:hover { color: var(--text); text-decoration: underline; }
/* KEPT `--faint` DELIBERATELY: a breadcrumb separator glyph is PURE DECORATION —
   it carries no information the adjacent links do not, so 1.4.3 exempts it. This is
   what `--faint` exists for, and it is the only surviving core use. */
.crumbs .sep { color: var(--faint); }
.crumbs [aria-current="page"] { color: var(--text); font-weight: 500; }
.head-row {
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: var(--space-4); flex-wrap: wrap;
}
.head-row h1 { font-size: var(--text-xl); font-weight: 700; letter-spacing: -0.01em; }
.head-row .sub { font-size: var(--text-sm); color: var(--text-2); margin-top: 2px; }
.head-actions { display: flex; align-items: center; gap: var(--space-2); }

/* ── Records toolbar (.rec-tools) — search field + filter selects ── */
.rec-tools {
  display: flex; align-items: center; gap: var(--space-2_5); flex-wrap: wrap;
  margin-bottom: var(--space-4);
}
.search-field { position: relative; flex: 1 1 220px; min-width: 180px; }
.search-field svg {
  position: absolute; left: var(--space-2_5); top: 50%; transform: translateY(-50%);
  width: 15px; height: 15px; color: var(--dim); pointer-events: none;
}
.search-field input { padding-left: 32px; }
.rec-tools .filters {
  display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; flex: 2 1 360px;
}

/* ── Records table (.tbl / .tbl-wrap) — the semantic records grid.
   Status cells compose the Drift .st-shape/.st-badge from patterns.css. */
.tbl-wrap {
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  overflow-x: auto;
  background: var(--panel);
}
table.tbl { width: 100%; border-collapse: collapse; font-size: var(--text-sm); min-width: 640px; }
.tbl thead th {
  text-align: left;
  padding: var(--space-2_5) var(--space-3);
  background: var(--panel-2);
  border-bottom: 1px solid var(--rule);
  font-family: var(--font-display);
  font-size: var(--text-xs);
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: var(--tracking-micro);
  color: var(--text-2);
  white-space: nowrap;
}
.tbl tbody td { padding: var(--space-2_5) var(--space-3); border-bottom: 1px solid var(--rule-2); vertical-align: middle; }
.tbl tbody tr:last-child td { border-bottom: 0; }
.tbl tbody tr:hover { background: var(--accent-soft); }
.tbl .col-check { width: 38px; text-align: center; }
.tbl .col-act { width: 44px; text-align: right; }
.tbl .nm { color: var(--text); font-weight: 500; }
.tbl .area { color: var(--text-2); }
.tbl a.nm { text-decoration: none; }
.tbl a.nm:hover { text-decoration: underline; }
.row-act {
  display: inline-flex; align-items: center; justify-content: center;
  width: 28px; height: 28px;
  background: transparent;
  border: 1px solid transparent;
  border-radius: var(--radius);
  color: var(--dim);
  cursor: pointer;
}
.row-act:hover { background: var(--panel-3); color: var(--text); border-color: var(--rule); }
.row-act svg { width: 16px; height: 16px; }

/* ── Pagination (.pager) + record foot / count ── */
.pager { display: flex; align-items: center; gap: var(--space-1); margin-top: var(--space-4); justify-content: flex-end; }
.pager a, .pager span.pg {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 32px; height: 32px;
  padding: 0 var(--space-2);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  color: var(--text-2);
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  text-decoration: none;
  font-variant-numeric: tabular-nums;
  background: var(--panel);
}
.pager a:hover { border-color: var(--accent-dim); color: var(--text); }
.pager [aria-current="page"] { border-color: var(--accent); background: var(--accent-soft); color: var(--accent); }
.pager .edge { color: var(--dim); }
.rec-foot { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); flex-wrap: wrap; }
.rec-count { font-size: var(--text-xs); color: var(--text-2); font-family: var(--font-mono); letter-spacing: var(--tracking-data); }

/* ── Form composition (.form-grid / .form-actions) ──
   Fields compose the core .field/.input/.select (above). */
.form-grid { display: flex; flex-direction: column; gap: var(--space-3); }
.form-actions { display: flex; align-items: center; gap: var(--space-2); margin-top: var(--space-1); }

/* ── Card sub-parts (.c-head / .c-body / .c-actions) ──
   Compose inside .card (above). The destructive-confirm wrapper and
   its danger icon are msf-008, not core. */
.c-head { display: flex; align-items: center; gap: var(--space-2_5); margin-bottom: var(--space-2_5); }
.c-body { font-size: var(--text-sm); color: var(--text-2); margin: 0 0 var(--space-4); line-height: var(--leading-normal); }
.c-body strong { color: var(--text); font-weight: 600; }
.c-actions { display: flex; align-items: center; justify-content: flex-end; gap: var(--space-2); }

/* ── Empty state (.empty / .e-ic) ── */
.empty {
  text-align: center;
  padding: var(--space-8) var(--space-4);
  display: flex; flex-direction: column; align-items: center; gap: var(--space-2_5);
}
.empty .e-ic {
  display: inline-flex; align-items: center; justify-content: center;
  width: 52px; height: 52px;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  color: var(--dim);
  background: var(--panel);
}
.empty .e-ic svg { width: 24px; height: 24px; }
.empty h3 { font-size: var(--text-lg); color: var(--text); }
.empty p { font-size: var(--text-sm); color: var(--text-2); margin: 0; max-width: 34ch; }

/* ── Bulk-selection toolbar (.bulkbar) — replaces the filter bar ──
   The .blk count glyph is a small Stein indicator (redundant with the
   count text), not a surface fill. */
.bulkbar {
  display: flex; align-items: center; gap: var(--space-3); flex-wrap: wrap;
  padding: var(--space-2) var(--space-3);
  background: var(--accent-soft);
  border: 1px solid var(--accent-core);
  border-radius: var(--radius);
}
.bulkbar .count { display: inline-flex; align-items: center; gap: var(--space-2); color: var(--accent); font-weight: 600; font-size: var(--text-sm); }
.bulkbar .count .blk { width: 12px; height: 12px; background: var(--accent); flex: none; }
.bulkbar .bulk-actions { display: flex; align-items: center; gap: var(--space-2); margin-left: auto; }
.bulkbar .clear {
  display: inline-flex; align-items: center; justify-content: center;
  width: 28px; height: 28px;
  background: transparent;
  border: 1px solid transparent;
  border-radius: var(--radius);
  color: var(--text-2);
  cursor: pointer;
}
.bulkbar .clear:hover { background: var(--panel-3); color: var(--text); }
.bulkbar .clear svg { width: 15px; height: 15px; }

/* ── Operator read-only note (.ro-note) ── */
.ro-note {
  display: inline-flex; align-items: center; gap: var(--space-1_5);
  font-size: var(--text-xs); color: var(--text-2);
  margin-top: var(--space-2);
}
.ro-note svg { width: 13px; height: 13px; color: var(--dim); }

/* ── Danger-OUTLINE button (.btn-danger-outline) — the LOCKED
   destructive treatment: an OUTLINE, never a fill (msf-008 composes
   it). A status hue (Critical) always paired with a text label, so it
   is never colour-alone. Sits alongside .btn / .btn-outline / .btn-sm. */
.btn-danger-outline { background: transparent; color: var(--danger); border-color: var(--danger); }
.btn-danger-outline:hover { background: var(--danger-soft); border-color: var(--danger); color: var(--danger); }
.btn-danger-outline:active { background: var(--danger-soft); border-color: var(--danger); color: var(--danger); }

/* ════════════════════════════════════════════════════════════
   GROUPED CHECKBOX MULTI-SELECT (.checkgroup)
   spec: specs/features/org-custom-group-editor.md
   task: ocg-013-checkgroup-design-primitive
   The platform's FIRST multi-choice grouped control (Decision 9): a
   <fieldset> per group (e.g. a permission MODULE) headed by a <legend>,
   holding one NATIVE <input type="checkbox"> + a real <label for> per
   option. Every grouped control promoted above it is SINGLE-choice — the
   segmented control (.seg-opt), the category tile (.cchoice), the single
   «type-or-pick» .combo — so a grouped MULTI-select is genuinely net-new;
   the org-custom-group editor's permission matrix (ocg-014) renders from
   it, one fieldset per entitled module. Native checkboxes, so the ticked
   set round-trips as a plain form field and is keyboard-operable with JS
   OFF; the checked state is the checkbox's own SHAPE (a tick) + accent
   fill — never colour alone. Each option keeps a real programmatic
   <label for> (never placeholder-as-label); a field-level error renders as
   role="alert" text (the consuming template composes the shared .ro-note).
   TOKENS-ONLY — every colour/size/font/spacing/radius resolves from a
   var(--…) token.

   Appended AFTER `.field label` on purpose (like .seg-opt / .cchoice): the
   element-qualified `label.checkgroup-opt-label` below wins that rule's
   0,1,1 specificity tie by SOURCE ORDER, so an option label stays
   sentence-case (the `.field label` rule would otherwise UPPERCASE it)
   even when the matrix sits inside a `.field`.
   ════════════════════════════════════════════════════════════ */
.checkgroup { display: flex; flex-direction: column; gap: var(--space-3); }

/* A per-group <fieldset> — its own bordered panel so the groups read as
   distinct sets. `min-width: 0` lets a native <fieldset> shrink inside a
   flex / grid column (a <fieldset> defaults to min-content width). */
.checkgroup-fieldset {
  min-width: 0;
  margin: 0;
  padding: var(--space-2) var(--space-3) var(--space-3);
  background: var(--panel-2);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
}
/* The group heading — an uppercase micro-label (the .field label / .combo-title
   vocabulary), carrying the group's name (a permission module's name). */
.checkgroup-legend {
  padding: 0 var(--space-1);
  font-family: var(--font-display);
  font-size: var(--text-xs);
  font-weight: var(--font-weight-medium);
  text-transform: uppercase;
  letter-spacing: var(--tracking-micro);
  color: var(--text-2);
}
/* One option row: a native checkbox beside its real <label for>. The row is
   ≥24px tall (WCAG 2.2 SC 2.5.8 target size); the label toggles the associated
   input, so the label text extends the pointer target. */
.checkgroup-opt {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  min-height: var(--target-min);
  padding: var(--space-0_5) 0;
}
.checkgroup-opt-input {
  flex: none;
  width: var(--space-4);
  height: var(--space-4);
  margin: 0;
  accent-color: var(--accent);   /* the checked fill is the Stein accent (a token, not a literal) */
  cursor: pointer;
}
.checkgroup-opt-input:focus-visible { outline: 2px solid var(--ring); outline-offset: 2px; }
/* Element-qualified (0,1,1), loaded after `.field label`, so it wins the tie and
   keeps the option label sentence-case — the same idiom as `label.seg-opt` /
   `label.cchoice` above. */
label.checkgroup-opt-label {
  display: inline;
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  font-weight: var(--font-weight-medium);
  text-transform: none;
  letter-spacing: normal;
  color: var(--text);
  cursor: pointer;
  line-height: var(--leading-normal);
}

/* ════════════════════════════════════════════════════════════
   CROSS-GROUP PERMISSION MATRIX (.permmatrix)
   spec: specs/features/org-custom-group-editor.md
   task: ocg-029-permmatrix-design-primitive
   The editable permission GRID ADR 0019's "matrix editor" intended
   (Decision 9, rewritten 2026-07-24): ROWS = permissions grouped by
   entitled module, COLUMNS = the org's groups. An ORG-CUSTOM column is
   EDITABLE (a native checkbox per cell = a DIRECT grant); a MODULE-role
   column is a READ-ONLY ● / ○ indicator for comparison; a permission a
   group INHERITS via nesting shows DIMMED + LOCKED (a disabled checkbox).
   A semantic <table> with a STICKY <thead> and a STICKY first column, so
   the group headers and the permission names stay in view while the grid
   scrolls. Cell meaning is carried by SHAPE (a checkbox tick, a filled ●
   vs a hollow ○, the disabled dim) plus a programmatic accessible name —
   NEVER colour alone. TOKENS-ONLY: every colour/size/font/spacing/radius
   resolves from a var(--…) token. Sits alongside the records table (.tbl)
   and the grouped checkbox (.checkgroup) above.
   ════════════════════════════════════════════════════════════ */
.permmatrix-wrap {
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  overflow: auto;
  max-height: 70vh;
  background: var(--panel);
}
table.permmatrix {
  border-collapse: separate;
  border-spacing: 0;
  width: 100%;
  font-size: var(--text-sm);
}
/* The grid's accessible name — a top micro-label (the .tbl thead vocabulary). */
.permmatrix-caption {
  caption-side: top;
  text-align: left;
  padding: var(--space-2) var(--space-3);
  font-family: var(--font-display);
  font-size: var(--text-xs);
  font-weight: var(--font-weight-medium);
  text-transform: uppercase;
  letter-spacing: var(--tracking-micro);
  color: var(--text-2);
}
/* The group column headers — sticky to the top edge as the grid scrolls. */
.permmatrix thead th {
  position: sticky;
  top: 0;
  z-index: 2;
  background: var(--panel-2);
  border-bottom: 1px solid var(--rule);
  padding: var(--space-2) var(--space-3);
  vertical-align: bottom;
  text-align: center;
  white-space: nowrap;
}
.permmatrix-colhead { min-width: var(--space-8); }
/* A read-only MODULE-role column reads a touch fainter than an editable one — a
   background cue REDUNDANT with the «Modul» kind text below (never colour alone). */
.permmatrix-colhead--readonly { background: var(--panel-3); }
.permmatrix-colname {
  display: block;
  font-family: var(--font-display);
  font-size: var(--text-xs);
  font-weight: var(--font-weight-medium);
  color: var(--text);
}
.permmatrix-colkind {
  display: block;
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: var(--tracking-micro);
  color: var(--text-2);
}
/* The top-left corner — sticky on BOTH axes (over the row headers + column headers). */
.permmatrix-corner {
  left: 0;
  z-index: 3;
  text-align: left;
  font-family: var(--font-display);
  font-size: var(--text-xs);
  font-weight: var(--font-weight-medium);
  text-transform: uppercase;
  letter-spacing: var(--tracking-micro);
  color: var(--text-2);
}
/* A module SECTION header row (<th scope="colgroup">) — an uppercase micro-label band
   introducing that module's permission rows (the .checkgroup-legend vocabulary). */
.permmatrix-sechead {
  position: sticky;
  left: 0;
  text-align: left;
  padding: var(--space-2) var(--space-3);
  background: var(--panel-2);
  border-bottom: 1px solid var(--rule);
  border-top: 1px solid var(--rule);
  font-family: var(--font-display);
  font-size: var(--text-xs);
  font-weight: var(--font-weight-medium);
  text-transform: uppercase;
  letter-spacing: var(--tracking-micro);
  color: var(--text-2);
}
/* The permission row header (left column) — sticky to the left edge as the grid
   scrolls horizontally, so the permission name always labels its cells. */
.permmatrix-rowhead {
  position: sticky;
  left: 0;
  z-index: 1;
  background: var(--panel);
  border-bottom: 1px solid var(--rule-2);
  padding: var(--space-2_5) var(--space-3);
  text-align: left;
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  font-weight: var(--font-weight-medium);
  color: var(--text);
  white-space: nowrap;
}
.permmatrix-cell {
  border-bottom: 1px solid var(--rule-2);
  padding: var(--space-2) var(--space-3);
  text-align: center;
  vertical-align: middle;
}
.permmatrix tbody tr:hover .permmatrix-cell,
.permmatrix tbody tr:hover .permmatrix-rowhead { background: var(--accent-soft); }
/* One editable cell — a native checkbox ≥24px target (WCAG 2.2 SC 2.5.8); the checked
   fill is the Stein accent (a token); the tick SHAPE carries meaning, not colour. */
.permmatrix-check {
  width: var(--space-4);
  height: var(--space-4);
  margin: 0;
  accent-color: var(--accent);
  cursor: pointer;
}
.permmatrix-check:focus-visible { outline: 2px solid var(--ring); outline-offset: 2px; }
/* A cell the group INHERITS via nesting — a DISABLED, dimmed, checked checkbox: present
   (the picture is honest) but LOCKED (never a submittable direct toggle). The dim +
   the disabled state carry the meaning alongside the accessible name (never colour
   alone). */
.permmatrix-check--inherited {
  accent-color: var(--dim);
  opacity: 0.55;
  cursor: not-allowed;
}
/* A read-only MODULE-role indicator — a filled ● (granted) vs a hollow ○ (not): the
   SHAPE is the signal; the hue only reinforces it. */
.permmatrix-ind {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: var(--target-min);
  min-height: var(--target-min);
  font-size: var(--text-base);
  line-height: var(--leading-normal);
}
.permmatrix-ind--on { color: var(--accent); }
.permmatrix-ind--off { color: var(--dim); }

/* ────────────────────────────────────────────────────────────
   CONTENT CLASSES — what the STRING is, not what carries it
   Added 2026-07-29 under `root-login-membership` ac-30, from a
   MEASURED defect on the shipped org picker.
   ──────────────────────────────────────────────────────────── */
/* THE CONFLATION THIS CORRECTS. `.btn` declares `white-space: nowrap` (:216) and
   that is RIGHT for a button — but it is right for a reason that has nothing to
   do with buttons: a button's label is normally PLATFORM COPY, a catalogue
   string whose length the platform controls in every locale, and a wrapping
   «Lagre» is a defect. The rule was written on the ELEMENT, so it also caught
   every string a button merely HAPPENS to carry. Measured consequence: an org
   picker option labelled with a 60-character tenant org name kept its box (the
   `--measure-form` bound held — 358px ≤ 416px) and spilled its INK 428px across
   a 356px content box, putting a horizontal scrollbar on the page at 390px
   (scrollWidth 445 > clientWidth 390). The box was bounded; only the ink escaped.

   CLASSIFY BY THE QUESTION THE STRING ANSWERS, NEVER BY THE ELEMENT THAT CARRIES
   IT. There are three answers, and all three are live in this product today —
   enumerated because a corrected rule reads as audited, and the third case is
   the one that would otherwise inherit confidence nobody earned:

     1. "WHAT WILL THIS DO?" — PLATFORM COPY: an action name, a column header, a
        micro-label. Authored in the i18n catalogue, so its length is under the
        platform's control in both locales, and a wrap is a layout defect.
        → must NOT wrap. This is `.btn`'s default, and it stays exactly as it is.
     2. "WHICH ONE IS THIS?" — ACTOR-AUTHORED CONTENT: an org name, an Area or
        Arrangement name, a person's name, an incident title. Shown verbatim,
        never translated (ADR 0007), of UNBOUNDED length — the platform can never
        promise it fits. → must never widen or escape its box. Where the surface
        must show it WHOLE, that is `.text-verbatim` below.
     3. "WHAT IS THE VALUE?" — a MACHINE-FORMATTED DATUM: an `ID-` / `GRP-`
        record id, a timestamp, a count, an age. Bounded by its FORMAT, and
        breaking it changes the reading: `ID-427` split over two lines reads as
        two ids. → must NOT wrap, and for a STRONGER reason than (1) — (1) is
        typographic, (3) is correctness. It is live: kontroll's un-merge control
        is a `.btn` whose label ends in a mono `ID-<n>`. THIS IS WHY DELETING
        `nowrap` FROM `.btn` IS NOT THE FIX — it would take the guarantee away
        from (3) as well as from (1).

   A LABEL THAT MIXES (1) AND (2) IS (2) ENTIRELY — «Slett "<navn>"» is unbounded
   because the tenant's fragment is. Classify by the widest class the string
   contains, not by the words that open it.

   (3) HAS NO BREAKING GUARANTEE OF ITS OWN TODAY, and this is left as found:
   `.mono` (core.css) marks the data ROLE (face + tabular figures) but declares
   no `white-space`, so the `ID-<n>` case above is protected only by the `.btn`
   it happens to sit inside. That is INHERITED, not stated. Recorded rather than
   fixed — stating it would change (3)'s contract on every surface `.mono`
   reaches, which is a ruling nobody has asked for. */
.text-verbatim {
  /* This box renders its string WHOLE: it wraps rather than overflowing, and it
     breaks a word wider than the box rather than escaping it. Both declarations
     are load-bearing.

     `white-space: normal` re-enables wrapping. It must be DECLARED, not assumed:
     the class is applied on top of components that set `nowrap`.

     `overflow-wrap: anywhere` — and NOT `break-word`, which is the near-miss:
     the two break identically ON SCREEN and differ only in that `anywhere` also
     shrinks the box's MIN-CONTENT size. That difference is the whole criterion
     here. Every consumer carries the string inside a flex container (a `.btn` is
     `inline-flex`, so its label is an anonymous flex item with `min-width: auto`,
     whose automatic minimum size is a FLOOR on the box). Under `break-word` an
     unbreakable 60-character name still forces the box wider than its parent and
     the defect returns unchanged — it just needs a name with no spaces in it.
     ac-30 quantifies over tenant names of UNBOUNDED length, so the treatment has
     to hold for the unbreakable one, not only for the fixture.

     NO TOKEN IS OWED (ac-53): neither value is a length, colour, size, spacing or
     radius — they name a BEHAVIOUR. There is nothing here for a token to carry,
     and inventing one would be a token that answers no question.

     NOT DECLARED, DELIBERATELY:
     * `hyphens: auto` — it inserts a character the author never wrote into a
       string that is shown verbatim.
     * `text-overflow: ellipsis` — it renders a DIFFERENT name. On a surface whose
       whole job is telling two tenants apart, it can render two of them
       identically even with the full string intact in the accessible name.
       A surface that deliberately clamps actor text to one line is a real and
       DIFFERENT case (kontroll's `.kc-primary-t` console-card title, where the
       full string is one click away) — it does not take this class.
     * `min-width: 0` — unnecessary once `anywhere` has shrunk min-content to a
       single character. A declaration that changes nothing does not belong here.

     PRE-WRAP IS A DIFFERENT CASE AND THIS CLASS WOULD DESTROY IT. A box that must
     keep the line breaks its author typed (a note body) needs
     `white-space: pre-wrap`; `normal` COLLAPSES them, which loses content rather
     than re-flowing it. Such a box wants `pre-wrap` + `overflow-wrap: anywhere`,
     never this class. No such box exists in core today (`.kc-tl-text` already
     collapses), so the hazard is NAMED, not solved.

     THE SPELLING IS `white-space`, not the more precise `text-wrap-mode` — which
     would flip wrapping without touching collapsing and so would not carry the
     pre-wrap hazard at all. It is not used because it would set a browser-support
     baseline this repo has never stated. Revisit it WITH that baseline, not
     instead of it.

     PLACEMENT IS LOAD-BEARING. `.text-verbatim` is (0,1,0) — the same weight as
     the `.btn` it overrides — so it wins on SOURCE ORDER and must stay BELOW the
     component classes in this file. A component declared under it, or any (0,2,0)
     descendant rule setting `white-space` on the same element, silently takes the
     guarantee back. This is not left to vigilance: ac-30's gate measures RENDERED
     ink against the RENDERED box, so a cascade regression returns red rather than
     quiet. */
  white-space: normal;
  overflow-wrap: anywhere;
}
