/* ============================================================================
   HEARTH — hearth-components.css
   Reusable component classes built from the tokens. Used by the design-system
   preview cards AND the UI kits. Scope everything under .hearth.
   Requires: colors_and_type.css (which imports hearth-tokens.css).
   ============================================================================ */

/* ---- Buttons ------------------------------------------------------------- */
.hearth .btn {
  font-family: var(--sans-ui);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  line-height: 1;
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  border-radius: var(--radius-md);
  padding: var(--space-3) var(--space-4);
  cursor: pointer;
  touch-action: manipulation;
  border: 1px solid transparent;
  white-space: nowrap;
  transition: background var(--duration-fast) var(--ease-standard),
              color var(--duration-fast) var(--ease-standard),
              border-color var(--duration-fast) var(--ease-standard),
              transform var(--duration-fast) var(--ease-standard);
}
.hearth .btn:active { transform: translateY(0.5px); }
.hearth .btn:focus-visible { outline: 2px solid transparent; outline-offset: 1px; box-shadow: var(--focus-ring); } /* transparent outline: survives forced-colours, see colors_and_type.css */
.hearth .btn .ic { width: 16px; height: 16px; }

.hearth .btn-primary { background: var(--accent-solid-bg); color: var(--fg-on-accent); }
.hearth .btn-primary:hover { background: var(--accent-active); }

.hearth .btn-secondary { background: var(--bg2); color: var(--fg1); border-color: var(--hearth-border-strong); }
.hearth .btn-secondary:hover { background: var(--bg-sunken); }

.hearth .btn-ghost { background: transparent; color: var(--accent-text); }
.hearth .btn-ghost:hover { background: var(--accent-subtle-bg); }

.hearth .btn-quiet { background: transparent; color: var(--fg2); }
.hearth .btn-quiet:hover { background: var(--bg-sunken); color: var(--fg1); }

.hearth .btn-danger { background: var(--sev-critical-bg); color: var(--sev-critical-fg); border-color: transparent; }
.hearth .btn-danger:hover { background: color-mix(in srgb, var(--sev-critical-bg) 80%, var(--sev-critical-fg)); }

.hearth .btn-sm { padding: var(--space-2) var(--space-3); font-size: var(--text-xs); }
.hearth .btn-lg { padding: var(--space-4) var(--space-6); font-size: var(--text-base); }
.hearth .btn-icon { padding: var(--space-2); }

/* ---- Badges / chips ------------------------------------------------------ */
.hearth .badge {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: 2px var(--space-3);
  border-radius: var(--radius-full);
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  font-family: var(--sans-ui);
  line-height: 1.5;
}
.hearth .badge .dot { width: 7px; height: 7px; border-radius: var(--radius-full); background: currentColor; flex: none; }

/* severity — never color-alone: dot + label always paired */
.hearth .sev-critical { color: var(--sev-critical-fg); background: var(--sev-critical-bg); }
.hearth .sev-high     { color: var(--sev-high-fg);     background: var(--sev-high-bg); }
.hearth .sev-medium   { color: var(--sev-medium-fg);   background: var(--sev-medium-bg); }
.hearth .sev-low      { color: var(--sev-low-fg);      background: var(--sev-low-bg); }
.hearth .sev-info     { color: var(--sev-info-fg);     background: var(--sev-info-bg); }
.hearth .st-healthy   { color: var(--status-healthy-fg);  background: var(--status-healthy-bg); }
.hearth .st-degraded  { color: var(--status-degraded-fg); background: var(--status-degraded-bg); }
.hearth .st-down      { color: var(--status-down-fg);     background: var(--status-down-bg); }

/* neutral / accent tag */
.hearth .tag {
  display: inline-flex; align-items: center; gap: var(--space-2);
  padding: 2px var(--space-2);
  border-radius: var(--radius-sm);
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
  background: var(--bg-sunken);
  color: var(--fg2);
  border: 1px solid var(--hearth-border);
  font-family: var(--mono-logs);
}
.hearth .tag-accent { background: var(--accent-subtle-bg); color: var(--accent-text); border-color: var(--accent-border); }

/* ---- Cards / surfaces ---------------------------------------------------- */
.hearth .card {
  background: var(--bg2);
  border: 1px solid var(--hearth-border);
  border-radius: var(--radius-xl);
  padding: var(--space-6);
  box-shadow: var(--shadow-md);
}
.hearth .card-flat { box-shadow: none; }
.hearth .panel {
  background: var(--bg2);
  border: 1px solid var(--hearth-border);
  border-radius: var(--radius-lg);
}
.hearth .well {
  background: var(--bg-sunken);
  border: 1px solid var(--hearth-border-subtle);
  border-radius: var(--radius-md);
}

/* ---- Inputs -------------------------------------------------------------- */
.hearth .input, .hearth .select, .hearth .textarea {
  font-family: var(--sans-ui);
  font-size: var(--text-sm);
  color: var(--fg1);
  background: var(--bg-raised);
  border: 1px solid var(--hearth-border-input);   /* 3:1 control edge, WCAG 1.4.11 (B6-D5) */
  border-radius: var(--radius-md);
  padding: var(--space-3) var(--space-3);
  width: 100%;
  transition: border-color var(--duration-fast) var(--ease-standard),
              box-shadow var(--duration-fast) var(--ease-standard);
}
.hearth .input::placeholder { color: var(--fg4); }
.hearth .input:focus, .hearth .select:focus, .hearth .textarea:focus {
  outline: 2px solid transparent; border-color: var(--accent-border); box-shadow: var(--focus-ring); /* forced-colours keeps focus visible */
}
.hearth .field-label {
  display: block; font-size: var(--text-xs); font-weight: var(--weight-semibold);
  color: var(--fg2); margin-bottom: var(--space-2);
  text-transform: uppercase; letter-spacing: var(--tracking-wide);
}

/* search field with leading icon */
.hearth .search { position: relative; display: flex; align-items: center; }
.hearth .search .ic { position: absolute; inset-inline-start: var(--space-3); width: 16px; height: 16px; color: var(--fg3); pointer-events: none; }
.hearth .search .input { padding-inline-start: calc(var(--space-3) * 2 + 16px); }

/* ---- Toggle / segmented control ------------------------------------------ */
.hearth .segmented {
  display: inline-flex;
  background: var(--bg-sunken);
  border: 1px solid var(--hearth-border);
  border-radius: var(--radius-full);
  padding: 3px;
  gap: 2px;
}
.hearth .segmented button {
  border: 0; background: transparent; color: var(--fg3);
  font: inherit; font-size: var(--text-sm); font-weight: var(--weight-medium);
  padding: var(--space-2) var(--space-4); border-radius: var(--radius-full); cursor: pointer;
  touch-action: manipulation;
  transition: background var(--duration-fast) var(--ease-standard), color var(--duration-fast) var(--ease-standard);
}
.hearth .segmented button[aria-pressed="true"], .hearth .segmented button.active {
  background: var(--bg-raised); color: var(--fg1); box-shadow: var(--shadow-sm);
}

/* ---- Metric scorecard ---------------------------------------------------- */
.hearth .metric {
  font-family: var(--serif-display);
  font-size: var(--text-3xl);
  font-weight: var(--font-display-weight, 400);
  font-variant-numeric: tabular-nums;
  letter-spacing: var(--tracking-tight);
  line-height: 1.1;
  color: var(--fg1);
}
.hearth .metric small {
  font-family: var(--sans-ui); font-size: var(--text-sm);
  font-weight: var(--weight-regular); color: var(--fg3);
}
.hearth .delta-up   { color: var(--status-healthy-fg); font-size: var(--text-sm); font-weight: var(--weight-medium); }
.hearth .delta-down { color: var(--sev-critical-fg);   font-size: var(--text-sm); font-weight: var(--weight-medium); }

/* ---- Divider / hairline -------------------------------------------------- */
.hearth .hr { height: 1px; background: var(--hearth-border-subtle); border: 0; width: 100%; }
.hearth .vr { width: 1px; align-self: stretch; background: var(--hearth-border); }

/* ---- Avatar -------------------------------------------------------------- */
.hearth .avatar {
  width: 32px; height: 32px; border-radius: var(--radius-full);
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--accent-subtle-bg); color: var(--accent-text);
  font-size: var(--text-xs); font-weight: var(--weight-semibold);
  font-family: var(--sans-ui); flex: none;
}

/* ---- Brand lockup -------------------------------------------------------- */
.hearth .brand { display: inline-flex; align-items: center; gap: var(--space-3); }
.hearth .brand .mote {
  width: 14px; height: 14px; border-radius: var(--radius-full);
  background: var(--accent); box-shadow: 0 0 0 4px var(--accent-subtle-bg);
  flex: none;
}
.hearth .brand b {
  font-family: var(--font-wordmark); font-weight: var(--weight-bold);
  letter-spacing: 0.06em; font-size: var(--text-lg);
}

/* ---- Handwritten annotation (Architects Daughter) — sparing margin notes -- */
.hearth .annot {
  font-family: var(--font-hand); color: var(--accent-text);
  font-size: var(--text-base); line-height: 1.2; font-weight: 400;
}

/* ---- Utility ------------------------------------------------------------- */
.hearth .row { display: flex; gap: var(--space-3); align-items: center; }
.hearth .col { display: flex; flex-direction: column; }
.hearth .wrap { flex-wrap: wrap; }
.hearth .grow { flex: 1; }
.hearth .icon { width: 18px; height: 18px; stroke-width: 1.75; }

/* ---- EventLake wordmark (brand Phase A) --------------------------------
   The mark's identity is its two signal accents, not its letterforms: a dotless
   i carrying a precision dot (the "i-Mote"), and a reticle replacing the o in
   Counter (the "o-Target"). Both are decorative and aria-hidden; the container
   carries the accessible name so a screen reader reads "EventLake" once.
   Type is the canon UI face (var(--font-sans) — Hanken Grotesk under P2A) at 700.
   It named Plus Jakarta Sans literally until 2026-10-17, so the P2A face change
   (2026-10-04) never reached it; a token cannot be left behind that way. The
   brand board specified Inter, which check.sh guard #3 bans and which is not
   vendored. The two accents take --signal-emphasis, the ONE themed signal colour
   (P2A blue on paper, P2C warm on ink): they named --sig-500, which only the
   public-site plates define, so everywhere else the literal #3A6A8C fallback
   rendered — the same blue on the dark theme as on the light.

   Deliberately GLOBAL, not `.hearth`-scoped, unlike every other rule above:
   this file's convention (line 4) is "scope everything under .hearth", but
   two of the eight shipping kits — concord/ and verichain/ — never wrap their
   markup in a `.hearth` container and don't even link hearth-components.css
   today (verified 2026-07-26: grep for class="hearth across every kit's
   index.html finds it in portal/worldline/beacon/chronicle/notary/console
   only — deliberately NOT spelling out the two-level ui_kits glob here as a
   literal pattern: doing so once put the closing comment-delimiter's two
   characters back to back in the middle of this sentence, which ends a CSS
   comment wherever it appears, no escaping possible. That silently dropped
   the whole .hx-wordmark rule below in every browser — a 2026-07-26 Task 5
   session hit exactly that bug while verifying this file and fixed it by
   rewording this comment; keep prose here, never that literal pattern).
   Concord
   and Verichain are exactly where Task 5 wires the wordmark in first (the
   mobile app + the MFA surfaces), so scoping these rules under `.hearth`
   would make the wordmark silently render unstyled the moment it lands
   there. Keep `.hx-*` global until/unless those kits adopt the `.hearth`
   wrapper. */
.hx-wordmark{
  display:inline-flex; align-items:baseline; white-space:nowrap;
  font-family:var(--font-wordmark, var(--font-sans, system-ui, sans-serif));
  font-weight:700; letter-spacing:-.02em; color:var(--hearth-text);
}
.hx-wordmark--lg{ font-size:clamp(40px,7vw,76px); }

/* i-Mote — the dot is positioned, so the glyph must be the DOTLESS i (U+0131). */
.hx-imote{ position:relative; display:inline-block; line-height:1; }
.hx-imote .hx-dot{
  position:absolute; left:50%; bottom:.9em; transform:translateX(-50%);
  width:.16em; height:.16em; border-radius:50%; background:var(--signal-emphasis, #27506B);
}

/* o-Target — a reticle sized to the surrounding type, so it scales with it. */
.hx-otarget{
  display:inline-block; position:relative; top:.06em;
  width:.72em; height:.72em; margin:0 .01em;
}
.hx-otarget svg{ width:100%; height:100%; display:block; }
.hx-otarget svg *{ stroke:var(--signal-emphasis, #27506B); }

/* ---- coalesce + arrive — the live-list verbs (2026-09-30co; ui_kits/hearth-coalesce.js) ----------------
   motion-graphics-scope.md §5.2. ARRIVE: a row that enters a list below ~4/s rises 8px and wears a clay
   ink that decays. COALESCE: above that rate rows are held and only this bar's count moves.
   Never-blank: the rise animates FROM hidden and only under no-preference, so reduced motion, print and a
   frozen first frame all show the row. The ink is information ("this row is new"): under reduced motion it
   is a static tint for the same span (the JS removes the attribute), never a fade. */
[data-hc-arrive] { animation: hcInk calc(var(--duration-slower) * 3) var(--ease-standard); }
@media (prefers-reduced-motion: no-preference) {
  [data-hc-arrive] { animation: hcRise var(--duration-base) var(--ease-standard), hcInk calc(var(--duration-slower) * 3) var(--ease-standard); }
}
@media (prefers-reduced-motion: reduce) {
  [data-hc-arrive] { animation: none; background-color: var(--accent-subtle-bg); }
}
@keyframes hcRise { from { transform: translateY(var(--motion-rise)); opacity: 0; } }
@keyframes hcInk  { from { background-color: var(--accent-subtle-bg); } }

/* The bar: a sentence and a button — never colour alone. The count is tabular so it ticks without the
   sentence jittering; it is NOT a live region (hearth-announce.js speaks for it, throttled). */
.hc-bar { display: flex; align-items: center; gap: var(--space-3); padding: var(--space-2) var(--space-4);
  border-bottom: 1px solid var(--accent-border); background: var(--accent-subtle-bg); color: var(--hearth-text);
  font-size: var(--text-sm); }
.hc-bar[hidden] { display: none; }
.hc-bar__t { flex: 1; min-width: 0; }
.hc-bar__n { font-variant-numeric: tabular-nums; font-weight: 700; }
.hc-bar__go { flex: none; font: inherit; font-weight: 600; padding: 4px 12px; border-radius: var(--radius-sm);
  border: 1px solid var(--accent-border); background: var(--hearth-surface); color: var(--accent-text); cursor: pointer;
  touch-action: manipulation; }
.hc-bar__go:hover { background: var(--hearth-sunken); }
.hc-bar__go:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* ---- The absence grammar — five components, one shape each (§13 row 112) -----------------------------
   Board: `ui_kits/Brand-And-Surfaces-Handoff/Absence Grammar.dc.html` (§6a-xxxviii), frame 1e "the contract
   · five classes, no new tokens". Every colour below is an existing token; the only custom properties are
   COMPONENT-LOCAL (`--abs-ink`/`--abs-tint`, plus `--fraction`, a per-instance value the caller sets — the
   board's "--fraction bar" is a parameter, not a palette entry).

     .absence        ○  nobody has looked          dotted 1px --hearth-border-strong (1.5px on dark)
     .refusal        ⊘  ordered, not enforced      solid 1px --sev-high-fg @ 40%
     .partial        ◐  counted N of M             solid + a --fraction bar
     .measured-zero  ●  swept, found nothing       solid 1px --hearth-border-subtle (the ONE calm state)
     .denied         ✕  known, not by you          4px hatch over the sunken ground
     .fixable        →  CODE-ADDED, PENDING DESIGN — §13 row 77's fourth portal kind ("yours, and fixable",
                        `→ ONE STEP AWAY`). The board predates it; it sits on the ACCENT ramp (the colour of
                        things you can press — never clay, never amber) and is never drawn without its step.

   Anatomy (panel density, the board's 1b): the frame holds `.glyph` (30px disc) + a body of `.eyebrow`
   (mono 12/.12em) · `.said` (14/1.4 — what is not known) · `.why` (12/1.6 — why) · `.next` (≥44px — the
   ONE affordance that ends the absence). The glyph is the identifier; colour only reinforces it.
   ⚠ One deliberate departure from the board: its `.absence` disc is clay-700. Clay means FAILURE only
   (palette direction 2026-10-04, which postdates the board), and "nobody has looked" is not a failure, so
   the disc takes neutral ink on the sunken ground. The dotted frame and the hollow ○ carry it.

   CHIP density (`.abs-chip` + a component class) is the inline form the portal's one shared renderer
   (`absentKind`, ui_kits/portal/portal.js) draws in table cells and panel rows. ⛔ A CHIP CARRIES THE
   FRAME, NEVER THE TINT: neutral ink on a neutral ground, so no absence can be read as healthy/degraded/
   down (`portal-absence.test.js` guards it). The fixable chip is the one exception and takes accent, not a
   status token. The portal's four kinds fold onto it BY SHAPE (the glyph and words stay the kind's own):
     unserved  ◌ → .absence        dotted  — the board wants it, no door carries it
     cannot    ▨ → .denied         dashed, sunken — the board's own 1d draws "dark, not reporting" here
     design    ◼ → .measured-zero  solid, calm — nothing to fix
     yours     → → .fixable        solid accent + a printed step (`.abs-step`)
   Refusal and partial have no chip density: the board draws them only at panel scale.
   Selectors stay scoped (`.hearth .absence …` / `:is(…) .glyph`), never a bare `.hearth .glyph`: public-
   site and specimen pages already use `class="glyph"` / `class="why"` for unrelated things. */
.hearth :is(.absence, .refusal, .partial, .measured-zero, .denied, .fixable) {
  --abs-ink: var(--hearth-text-secondary);
  --abs-tint: var(--hearth-sunken);
  display: flex; align-items: flex-start; gap: 13px;
  padding: 16px 17px;
  border: 1px solid var(--hearth-border-subtle);
  border-radius: 11px;
  background: var(--hearth-surface);
  color: var(--hearth-text);
  font-family: var(--sans-ui);
}
.hearth .absence       { border: 1px dotted var(--hearth-border-strong); }
.hearth .refusal       { border-color: color-mix(in srgb, var(--sev-high-fg) 40%, transparent);
                         --abs-ink: var(--sev-high-fg); --abs-tint: var(--sev-high-bg); }
.hearth .partial       { border-color: color-mix(in srgb, var(--status-degraded-fg) 40%, transparent);
                         --abs-ink: var(--status-degraded-fg); --abs-tint: var(--status-degraded-bg); }
.hearth .measured-zero { border-color: var(--hearth-border-subtle);
                         --abs-ink: var(--status-healthy-fg); --abs-tint: var(--status-healthy-bg); }
.hearth .denied        { border-color: color-mix(in srgb, var(--sev-info-fg) 30%, transparent);
                         background: repeating-linear-gradient(45deg, var(--hearth-sunken) 0 4px, var(--hearth-surface) 4px 8px);
                         --abs-ink: var(--sev-info-fg); --abs-tint: var(--sev-info-bg); }
.hearth .fixable       { border-color: var(--accent-border); background: var(--accent-subtle-bg);
                         --abs-ink: var(--accent-text); --abs-tint: var(--hearth-surface); }
/* A 1px dotted hairline on the dark ground reads as a rendering artefact, not an edge (board 1c). */
:root[data-theme="dark"] .hearth .absence:not(.abs-chip) { border-width: 1.5px; }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .hearth .absence:not(.abs-chip) { border-width: 1.5px; } }

.hearth :is(.absence, .refusal, .partial, .measured-zero, .denied, .fixable) .glyph {
  width: 30px; height: 30px; flex: none; display: grid; place-items: center;
  border-radius: var(--radius-full); background: var(--abs-tint); color: var(--abs-ink);
  font: 700 14px/1 var(--mono-logs);
}
.hearth .fixable .glyph { box-shadow: inset 0 0 0 1px var(--accent-border); }
/* The body beside the disc: what is not known → why → what would make it known (the board's sentence order). */
.hearth :is(.absence, .refusal, .partial, .measured-zero, .denied, .fixable):not(.abs-chip) > :not(.glyph) {
  flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 7px;
}
.hearth :is(.absence, .refusal, .partial, .measured-zero, .denied, .fixable) .eyebrow {
  display: inline-block; align-self: flex-start; padding: 5px 7px; border-radius: 4px;
  background: var(--abs-tint); color: var(--abs-ink);
  font: 700 12px/1 var(--mono-logs); letter-spacing: .12em; text-transform: uppercase;
}
.hearth :is(.absence, .refusal, .partial, .measured-zero, .denied, .fixable) .said {
  font: 600 14px/1.4 var(--sans-ui); color: var(--hearth-text);
}
.hearth :is(.absence, .refusal, .partial, .measured-zero, .denied, .fixable) .why {
  font: 400 12px/1.6 var(--sans-ui); color: var(--hearth-text-secondary);
}
/* The ONE affordance. ≥44px (WCAG 2.5.5 target), a 3:1 control edge (1.4.11), the canon focus ring. */
.hearth :is(.absence, .refusal, .partial, .measured-zero, .denied, .fixable) .next {
  display: inline-flex; align-items: center; min-height: 44px; padding: 9px 12px;
  border: 1px solid var(--hearth-border-input); border-radius: 7px;
  background: var(--hearth-surface); color: var(--accent-text);
  font: 600 12px/1 var(--sans-ui); text-decoration: none; cursor: pointer;
  touch-action: manipulation;
}
.hearth :is(.absence, .refusal, .partial, .measured-zero, .denied, .fixable) .next:hover { background: var(--hearth-sunken); }
.hearth :is(.absence, .refusal, .partial, .measured-zero, .denied, .fixable) .next:focus-visible {
  outline: 2px solid transparent; outline-offset: 1px; box-shadow: var(--focus-ring);
}
/* The fraction bar: counted ÷ total. Decorative (aria-hidden) — the eyebrow carries "COUNTED N OF M" in
   words, so the denominator survives a screenshot, a print and a screen reader without the bar. */
.hearth .partial .fraction {
  height: 4px; border-radius: var(--radius-full); background: var(--hearth-sunken); overflow: hidden;
}
.hearth .partial .fraction::before {
  content: ""; display: block; height: 100%;
  width: calc(clamp(0, var(--fraction, 0), 1) * 100%); background: var(--status-degraded-fg);
}

/* Chip density — the frame, not the tint. Same specificity as the panel rule above and declared after
   it, so every property the panel sets is reset here; the per-kind border is one class more specific. */
.hearth .abs-chip {
  display: inline-flex; align-items: center; gap: 5px; vertical-align: baseline;
  padding: 1px 7px;
  border: 1px solid var(--hearth-text-muted);
  border-radius: 5px;
  background: var(--hearth-surface);
  color: var(--hearth-text-secondary);
  font-family: var(--mono-logs); font-size: .75rem; font-weight: 700; letter-spacing: .03em; font-style: normal;
}
.hearth .abs-chip.absence       { border-style: dotted; }
.hearth .abs-chip.denied        { border-style: dashed; background: var(--hearth-sunken); font-style: italic; }
.hearth .abs-chip.measured-zero { border-style: solid; }
.hearth .abs-chip.fixable       { border: 1px solid var(--accent-border); background: var(--accent-subtle-bg); color: var(--accent-text); }
.hearth .abs-chip .glyph {
  width: auto; height: auto; display: inline; border-radius: 0; background: none; box-shadow: none;
  color: inherit; font-size: .75rem; line-height: 1;
}
/* The step a fixable chip MUST print — text, or a real button pressing the screen's own control. */
.hearth .abs-step {
  display: inline-block; margin-inline-start: 6px;
  font-family: var(--mono-logs); font-size: .75rem; font-weight: 700; color: var(--accent-text);
}
.hearth button.abs-step {
  background: none; border: 0; padding: 0; cursor: pointer;
  touch-action: manipulation;
  text-decoration: underline; text-underline-offset: 2px;
}
.hearth button.abs-step:focus-visible { outline: 2px solid transparent; outline-offset: 1px; box-shadow: var(--focus-ring); }

/* The UNCLASSIFIED chip (`PX.absent`, the §9ap default until a site is decided) — was an inline style in
   portal.js. ⛔ Deliberately NOT an `.abs-chip`: guards that ask "is this a classified absence?" test for
   that class, and the default must never pass for one. Dashed, neutral ink, no tint — like every chip. */
.hearth .abs-unclassified {
  display: inline-block; padding: 1px 7px;
  border: 1px dashed var(--hearth-text-muted); border-radius: 5px;
  font-family: var(--mono-logs); font-size: .75rem; font-weight: 700; letter-spacing: .03em;
  color: var(--hearth-text-secondary);
}
/* Panel-density parts the portal's `absencePanel` prints (§13 row 112): the measured zero's count and the
   sweep that earned it — a real `0`, in tabular figures, never the unmeasured shape — and the printed
   "What to do" line when the affordance is words rather than a control. */
.hearth .measured-zero .abs-meta {
  font: 400 12px/1.5 var(--mono-logs); color: var(--hearth-text-secondary);
}
.hearth .measured-zero .abs-count { font-variant-numeric: tabular-nums; color: var(--hearth-text); }
.hearth :is(.absence, .refusal, .partial, .measured-zero, .denied) .abs-next b { color: var(--hearth-text); }

/* The "what this board cannot tell you yet" list: one row per absence — title + chip, then why. */
.hearth .abs-list { display: flex; flex-direction: column; gap: 10px; }
.hearth .abs-list__row { padding: 8px 0; border-bottom: 1px solid var(--hearth-border); }
.hearth .abs-list__title { font-family: var(--mono-logs); font-weight: 700; font-size: .82rem; }
.hearth .abs-list__why { margin-top: 2px; }

/* Key labels and inline code are LEFT-TO-RIGHT tokens in every language (W11, 2026-10-18d): in an rtl
   page the bidi algorithm otherwise reorders a neutral run like "⌘K" into "K⌘". Isolated, so the
   surrounding sentence still flows right-to-left around it. */
kbd, code, samp { unicode-bidi: isolate; direction: ltr; }

/* ---- Touch / coarse-pointer target floor (WCAG 2.5.5 — 44×44px) ------------ */
@media (pointer: coarse) {
  .hc-bar button,
  .hc-bar__go,
  .hc-copy,
  .hearth .btn,
  .hearth .segmented button,
  .hearth button.abs-step {
    min-height: 44px;
    min-width: 44px;
  }
}
