/* Shared design system v0.4.3 concept (graphite, restrained). v0.3.2 rules unchanged above the "v0.4.1 refresh" section at the end. Values come only from tokens.css custom properties.
   Mobile first: base rules target 375px; @media (min-width: 768px) and (min-width: 1280px) step up. */
@layer reset, tokens, base, layout, components, utilities;
@import url("fonts.css");
@import url("tokens.css") layer(tokens);

/* ---------- reset ---------- */
@layer reset {
  *, *::before, *::after { box-sizing: border-box; }
  * { margin: 0; }
  html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }
  a, button, input, select, textarea, label, summary { touch-action: manipulation; }
  img, svg, video, canvas { display: block; max-width: 100%; }
  input, button, textarea, select { font: inherit; color: inherit; letter-spacing: inherit; }
  button { background: none; border: 0; padding: 0; cursor: pointer; }
  table { border-collapse: collapse; }
  fieldset { border: 0; padding: 0; min-width: 0; }
  legend { padding: 0; }
  ul[role], ol[role] { list-style: none; padding: 0; }
  dialog { padding: 0; border: 0; color: inherit; }
  [hidden] { display: none !important; }
}

/* ---------- base ---------- */
@layer base {
  :root {
    --control-h: var(--size-control-lg);      /* 44px touch size below 768px */
    --control-h-sm: var(--size-control-md);
    --item-h: var(--size-control-lg);
    --gutter: var(--space-4);
    --row-h: var(--size-row-normal);
  }
  @media (min-width: 768px) {
    :root { --control-h: var(--size-control-md); --control-h-sm: var(--size-control-sm); --item-h: var(--size-row-condensed); --gutter: var(--space-6); }
  }
  @media (min-width: 1280px) { :root { --gutter: var(--space-8); } }

  html {
    font-family: var(--font-sans);
    background: var(--background);
    color: var(--foreground);
    scroll-padding-top: calc(var(--size-header) + var(--space-4));
    -webkit-font-smoothing: antialiased;
  }
  body { font-size: var(--text-base); line-height: var(--leading-base); letter-spacing: var(--tracking-normal); min-height: 100dvh; }
  /* v0.2: reading measure. v0.4.1: --size-measure is 52ch, which keeps 14px and 16px Geist text at 75 characters a line or less (measured). */
  p, li, dd { max-width: var(--size-measure); }
  ::selection { background: var(--selection); color: var(--foreground); }
  :focus-visible { outline: var(--focus-width) solid var(--ring); outline-offset: var(--focus-offset); }
  h1, h2, h3, h4 { font-weight: var(--font-weight-semibold); text-wrap: balance; }
  h1 { font-size: var(--text-xl); line-height: var(--leading-xl); letter-spacing: var(--tracking-xl); }
  h2 { font-size: var(--text-lg); line-height: var(--leading-lg); }
  h3 { font-size: var(--text-base); line-height: var(--leading-base); }
  h4 { font-size: var(--text-sm); line-height: var(--leading-sm); }
  p { text-wrap: pretty; }
  a { color: var(--link); text-decoration-line: underline; text-decoration-thickness: var(--border-hairline); text-underline-offset: 0.2em; }
  a:hover { text-decoration-thickness: var(--border-strong); }
  code, kbd, samp, pre { font-family: var(--font-mono); font-size: var(--text-sm); }
  small { font-size: var(--text-sm); line-height: var(--leading-sm); }
  strong, b { font-weight: var(--font-weight-semibold); }
  hr { border: 0; border-top: var(--border-hairline) solid var(--border); }
  .icon { width: var(--size-icon-sm); height: var(--size-icon-sm); flex: none; stroke-width: 2; }
  .icon-md { width: var(--size-icon-md); height: var(--size-icon-md); }
  @media (prefers-reduced-motion: reduce) {
    *, *::before, *::after { animation-duration: 1ms !important; animation-iteration-count: 1 !important; transition-duration: 1ms !important; scroll-behavior: auto !important; }
  }
}

/* ---------- layout and app shell ---------- */
@layer layout {
  .skip-link { position: absolute; left: var(--space-2); top: calc(-1 * var(--size-header)); z-index: var(--z-overlay); background: var(--card); color: var(--foreground); padding: var(--space-2) var(--space-3); border: var(--border-hairline) solid var(--border); border-radius: var(--radius-md); }
  .skip-link:focus { top: var(--space-2); }

  .app-header { position: sticky; top: 0; z-index: var(--z-header); height: var(--size-header); background: var(--card); --_header-rule: var(--border); box-shadow: inset 0 calc(-1 * var(--border-hairline)) 0 var(--_header-rule); }
  /* v0.4.2: the bottom rule is an inset shadow, not a border, so the 56px header keeps a 56px content box and 32px
     controls centered in it land on whole pixels (12px above and below). Forced colors drop shadows, so a real border returns there. */
  @media (forced-colors: active) { .app-header { border-bottom: var(--border-hairline) solid CanvasText; } }
  .app-header__inner { height: 100%; max-width: var(--size-wide-max); margin-inline: auto; padding-inline: var(--gutter); display: flex; align-items: center; gap: var(--space-4); }
  .app-mark { display: inline-flex; align-items: center; gap: var(--space-2); color: var(--foreground); text-decoration: none; font-size: var(--text-sm); line-height: var(--leading-sm); font-weight: var(--font-weight-semibold); white-space: nowrap; min-height: var(--size-target-min); }
  .app-mark:hover { text-decoration: none; }
  .app-mark .icon { width: var(--size-icon-md); height: var(--size-icon-md); }
  .app-nav { display: none; align-items: stretch; gap: var(--space-1); height: 100%; }
  .app-nav a { display: inline-flex; align-items: center; padding-inline: var(--space-3); color: var(--muted-foreground); text-decoration: none; font-size: var(--text-sm); line-height: var(--leading-sm); font-weight: var(--font-weight-medium); box-shadow: inset 0 calc(-1 * var(--border-strong)) 0 transparent; }
  .app-nav a:hover { color: var(--foreground); }
  .app-nav a[aria-current="page"] { color: var(--foreground); box-shadow: inset 0 calc(-1 * var(--border-strong)) 0 var(--primary); }
  .app-header__end { margin-left: auto; display: flex; align-items: center; gap: var(--space-2); }
  .app-menu-btn { display: inline-flex; }
  @media (min-width: 768px) { .app-nav { display: flex; } .app-header .app-menu-btn { display: none; } }

  /* v0.3: a hairline strip on the page color with a small Concept tag, not a full-bleed tinted block.
     v0.4.2: the line is an inset shadow, not a border, so the strip is 36px (a multiple of 4) and everything below it stays on the 4px grid. */
  .concept-flag { background: var(--background); color: var(--muted-foreground); box-shadow: inset 0 calc(-1 * var(--border-hairline)) 0 var(--border); font-size: var(--text-sm); line-height: var(--leading-sm); }
  .concept-flag p { max-width: var(--size-measure); } /* v0.4.1: keeps the strip under 75 characters a line, like help text */
  .concept-flag strong { color: var(--foreground); }
  .concept-flag__inner { max-width: var(--size-wide-max); margin-inline: auto; padding: var(--space-2) var(--gutter); display: flex; gap: var(--space-2); align-items: flex-start; }
  .concept-flag .icon { color: var(--warning); margin-block: var(--space-0-5); flex: none; }
  .concept-flag__tag { display: inline-block; margin-right: var(--space-1); padding-inline: var(--space-1); border-radius: var(--radius-sm); background: var(--warning-soft); color: var(--foreground); font-weight: var(--font-weight-semibold); }

  .page { max-width: var(--size-content-max); margin-inline: auto; padding: var(--space-6) var(--gutter) var(--space-16); }
  .page--wide { max-width: var(--size-wide-max); }
  .page--prose { max-width: calc(var(--size-prose-max) + 2 * var(--gutter)); }
  .page-header { display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between; gap: var(--space-4); margin-bottom: var(--space-6); }
  .page-header__text { max-width: var(--size-measure); }
  .page-header p { color: var(--muted-foreground); margin-top: var(--space-1); }
  .page-header__actions { display: flex; flex-wrap: wrap; gap: var(--space-2); }
  .eyebrow { font-size: var(--text-sm); line-height: var(--leading-sm); color: var(--muted-foreground); margin-bottom: var(--space-1); }
  /* v0.4.3 (Testingralph v0.4.3 MF-C): only a shown child after another shown child gets the gap, so hidden siblings
     (the builder's earlier steps) add no space. :where keeps the old specificity of * + *. */
  .stack > :where(:not([hidden]) ~ :not([hidden])) { margin-top: var(--space-4); }
  .stack-lg > :where(:not([hidden]) ~ :not([hidden])) { margin-top: var(--space-8); }
  .cluster { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); }
  .section-title { font-size: var(--text-base); line-height: var(--leading-base); font-weight: var(--font-weight-semibold); margin-bottom: var(--space-3); }

  .grid-2 { display: grid; gap: var(--space-6); }
  @media (min-width: 768px) { .grid-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
  .grid-sidebar { display: grid; gap: var(--space-6); }
  @media (min-width: 1280px) { .grid-sidebar { grid-template-columns: var(--size-sidebar) minmax(0, 1fr); } }

  .app-footer { border-top: var(--border-hairline) solid var(--border); color: var(--muted-foreground); font-size: var(--text-sm); line-height: var(--leading-sm); }
  .app-footer__inner { max-width: var(--size-wide-max); margin-inline: auto; padding: var(--space-6) var(--gutter); display: flex; flex-wrap: wrap; gap: var(--space-3) var(--space-6); }
  .app-footer a { color: var(--muted-foreground); }
  .app-footer nav { display: flex; flex-wrap: wrap; gap: var(--space-1) var(--space-4); }
  /* v0.3: each link is at least a 24px target (WCAG 2.5.8), 44px on touch screens */
  .app-footer nav a { display: inline-flex; align-items: center; min-height: var(--size-target-min); }
  @media (pointer: coarse) { .app-footer nav a { min-height: var(--size-target-touch); } }
}

/* ---------- components ---------- */
@layer components {
  /* Panel (the only container). Flat, hairline border, no shadow at rest. */
  .panel { background: var(--card); color: var(--card-foreground); border: var(--border-hairline) solid var(--border); border-radius: var(--radius-lg); }
  .panel__header { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--space-3); padding: var(--space-3) var(--space-4); border-bottom: var(--border-hairline) solid var(--border); }
  .panel__title { font-size: var(--text-base); line-height: var(--leading-base); font-weight: var(--font-weight-semibold); }
  .panel__body { padding: var(--space-4); }
  .panel__footer { padding: var(--space-3) var(--space-4); border-top: var(--border-hairline) solid var(--border); display: flex; flex-wrap: wrap; gap: var(--space-2); justify-content: flex-end; }

  /* Button */
  .btn { --_bg: var(--card); --_fg: var(--foreground); --_bd: var(--input); --_bg-hover: var(--accent);
    display: inline-flex; align-items: center; justify-content: center; gap: var(--space-2);
    height: var(--control-h); min-width: var(--size-target-min); padding-inline: var(--space-3);
    border: var(--border-hairline) solid var(--_bd); border-radius: var(--radius-md);
    background: var(--_bg); color: var(--_fg); white-space: nowrap; text-decoration: none;
    font-size: var(--text-sm); line-height: var(--leading-sm); font-weight: var(--font-weight-medium);
    transition: background-color var(--duration-fast) var(--easing-out), transform var(--duration-press) var(--easing-out);
    -webkit-tap-highlight-color: transparent; user-select: none; }
  .btn:hover, .btn.is-hover { background: var(--_bg-hover); text-decoration: none; }
  .btn:active, .btn.is-active { transform: scale(0.98); }
  .btn.is-focus { outline: var(--focus-width) solid var(--ring); outline-offset: var(--focus-offset); }
  .btn--primary { --_bg: var(--primary); --_fg: var(--primary-foreground); --_bd: var(--primary); --_bg-hover: var(--primary-hover); }
  .btn--primary:hover, .btn--primary.is-hover { border-color: var(--primary-hover); }
  .btn--ghost { --_bg: transparent; --_bd: transparent; }
  .btn--destructive { --_fg: var(--destructive); --_bg-hover: var(--destructive-soft); }
  .btn--destructive-solid { --_bg: var(--destructive); --_fg: var(--destructive-foreground); --_bd: var(--destructive); --_bg-hover: var(--destructive); }
  .btn--sm { height: var(--control-h-sm); padding-inline: var(--space-2); }
  .btn--lg { height: var(--size-control-lg); padding-inline: var(--space-4); font-size: var(--text-base); line-height: var(--leading-base); }
  .btn--icon { width: var(--control-h); padding-inline: 0; }
  .btn--icon.btn--sm { width: var(--control-h-sm); }
  .btn[aria-disabled="true"], .btn:disabled { --_bg: var(--muted); --_fg: var(--muted-foreground); --_bd: var(--border); --_bg-hover: var(--muted); cursor: not-allowed; transform: none; }
  .btn[aria-busy="true"] { cursor: progress; }
  .btn[aria-busy="true"] .spinner { color: currentColor; }
  .btn .icon { margin-inline: calc(-1 * var(--space-0-5)); }

  /* Link variants */
  .link-quiet { color: var(--foreground); text-decoration-color: var(--input); }
  .link-quiet:hover { text-decoration-color: currentColor; }
  .link-external .icon { display: inline; vertical-align: -0.125em; width: 0.875em; height: 0.875em; margin-left: var(--space-0-5); }

  /* Form field */
  .field { display: grid; gap: var(--space-2); max-width: var(--size-form-max); }
  .field__label { font-size: var(--text-sm); line-height: var(--leading-sm); font-weight: var(--font-weight-medium); color: var(--foreground); }
  .field__optional { font-weight: var(--font-weight-regular); color: var(--muted-foreground); }
  .field__hint { font-size: var(--text-sm); line-height: var(--leading-sm); color: var(--muted-foreground); margin-top: calc(-1 * var(--space-1)); }
  .field__error { display: flex; gap: var(--space-1); align-items: flex-start; font-size: var(--text-sm); line-height: var(--leading-sm); color: var(--destructive); font-weight: var(--font-weight-medium); }
  .field__error .icon { margin-top: var(--space-0-5); }

  .input, .textarea, .select select { width: 100%; min-height: var(--control-h); padding: 0 var(--space-3);
    background: var(--card); color: var(--foreground);
    border: var(--border-hairline) solid var(--input); border-radius: var(--radius-md);
    font-size: var(--text-base); line-height: var(--leading-base);
    transition: border-color var(--duration-fast) var(--easing-out); }
  @media (min-width: 768px) { .input, .textarea, .select select { font-size: var(--text-sm); line-height: var(--leading-sm); } }
  .input::placeholder, .textarea::placeholder { color: var(--subtle-foreground); opacity: 1; }
  .input:hover, .textarea:hover, .select select:hover, .input.is-hover { border-color: var(--muted-foreground); }
  .input:focus-visible, .textarea:focus-visible, .select select:focus-visible, .input.is-focus { outline: var(--focus-width) solid var(--ring); outline-offset: 0; border-color: var(--ring); border-radius: var(--radius-md); }
  .input:user-invalid, .input[aria-invalid="true"], .textarea[aria-invalid="true"], .select select[aria-invalid="true"] { border-color: var(--destructive); }
  .input:disabled, .textarea:disabled, .select select:disabled { background: var(--muted); color: var(--muted-foreground); border-color: var(--border); cursor: not-allowed; }
  .input[readonly] { background: var(--muted); }
  .input--mono { font-family: var(--font-mono); }
  .input-group { position: relative; display: flex; align-items: center; }
  .input-group > .icon { position: absolute; left: var(--space-3); color: var(--muted-foreground); pointer-events: none; }
  .input-group > .input { padding-left: calc(var(--space-3) + var(--size-icon-sm) + var(--space-2)); }
  .input-group > .kbd { position: absolute; right: var(--space-2); }
  .textarea { padding: var(--space-2) var(--space-3); min-height: calc(5 * var(--leading-sm) + 2 * var(--space-2)); resize: vertical; }
  .textarea--code { font-family: var(--font-mono); font-size: var(--text-sm); line-height: var(--leading-sm); white-space: pre; overflow-wrap: normal; overflow-x: auto; }

  .select { position: relative; display: block; }
  .select select { appearance: none; padding-right: calc(var(--space-3) + var(--size-icon-sm) + var(--space-2)); cursor: pointer; }
  .select > .icon { position: absolute; right: var(--space-3); top: 50%; translate: 0 -50%; pointer-events: none; color: var(--muted-foreground); }
  .select--inline { display: inline-block; width: auto; }
  .select--inline select { width: auto; }

  .kbd { display: inline-flex; align-items: center; height: var(--space-5); padding-inline: var(--space-1); border: var(--border-hairline) solid var(--border); border-radius: var(--radius-sm); background: var(--muted); color: var(--muted-foreground); font-family: var(--font-mono); font-size: var(--text-xs); line-height: var(--leading-xs); }

  /* Checkbox and radio: native inputs, custom drawn. v0.4.2: a 20px box that fills the 20px text line, so no 2px offset. */
  .choice { display: flex; align-items: flex-start; gap: var(--space-2); min-height: var(--size-target-touch); padding-block: calc((var(--size-target-touch) - var(--leading-sm)) / 2); cursor: pointer; font-size: var(--text-sm); line-height: var(--leading-sm); }
  @media (min-width: 768px) { .choice { min-height: var(--size-target-min); padding-block: var(--space-0-5); } }
  /* v0.4.2 note: the 2px block padding above centers a 20px line in the 24px target; it is a target size, not an inset. */
  .choice__hint { display: block; color: var(--muted-foreground); }
  .choice__count { margin-left: auto; color: var(--muted-foreground); font-variant-numeric: tabular-nums; padding-left: var(--space-2); }
  .check, .radio { appearance: none; flex: none; width: var(--size-icon-md); height: var(--size-icon-md); margin: 0; display: grid; place-content: center;
    border: var(--border-hairline) solid var(--input); background: var(--card); cursor: pointer;
    transition: background-color var(--duration-press) var(--easing-out); }
  .check { border-radius: var(--radius-sm); }
  .radio { border-radius: var(--radius-full); }
  .check:hover, .radio:hover, .check.is-hover { border-color: var(--foreground); }
  .check:focus-visible, .radio:focus-visible, .check.is-focus { outline: var(--focus-width) solid var(--ring); outline-offset: var(--focus-offset); }
  .check:checked, .check:indeterminate { background: var(--primary); border-color: var(--primary); }
  .check:checked::before { content: ""; width: var(--size-mark); height: var(--size-mark); background: var(--primary-foreground); clip-path: polygon(14% 44%, 0 59%, 39% 98%, 100% 21%, 86% 7%, 38% 69%); }
  .check:indeterminate::before { content: ""; width: var(--size-mark); height: var(--border-strong); background: var(--primary-foreground); }
  .radio:checked { border-color: var(--primary); }
  .radio:checked::before { content: ""; width: var(--size-dot); height: var(--size-dot); border-radius: var(--radius-full); background: var(--primary); }
  .check:disabled, .radio:disabled { background: var(--muted); border-color: var(--border); cursor: not-allowed; }
  .check:disabled:checked { background: var(--input); border-color: var(--input); }
  .choice:has(:disabled) { color: var(--muted-foreground); cursor: not-allowed; }
  .check[aria-invalid="true"] { border-color: var(--destructive); }

  /* Radio cards (one choice with a description) */
  .choice-card { display: flex; gap: var(--space-3); padding: var(--space-3) var(--space-4); border: var(--border-hairline) solid var(--border); border-radius: var(--radius-md); background: var(--card); cursor: pointer; }
  .choice-card:hover { border-color: var(--input); }
  .choice-card:has(:checked) { border-color: var(--primary); background: var(--primary-soft); box-shadow: inset 0 0 0 var(--border-hairline) var(--primary); }
  .choice-card__title { display: block; font-weight: var(--font-weight-medium); font-size: var(--text-sm); line-height: var(--leading-sm); }
  .choice-card__text { display: block; margin-top: 0; color: var(--muted-foreground); font-size: var(--text-sm); line-height: var(--leading-sm); }

  /* Switch: <button role="switch" aria-checked> */
  .switch { display: inline-flex; align-items: center; gap: var(--space-2); min-height: var(--control-h); font-size: var(--text-sm); line-height: var(--leading-sm); cursor: pointer; }
  .switch__track { position: relative; width: var(--size-switch-width); height: var(--space-5); flex: none; border-radius: var(--radius-full); background: var(--card); border: var(--border-hairline) solid var(--input); transition: background-color var(--duration-fast) var(--easing-out); }
  .switch__track::after { content: ""; position: absolute; top: var(--border-hairline); left: var(--border-hairline); width: var(--size-icon-sm); height: var(--size-icon-sm); border-radius: var(--radius-full); background: var(--input); transition: translate var(--duration-fast) var(--easing-out); }
  .switch[aria-checked="true"] .switch__track { background: var(--primary); border-color: var(--primary); }
  .switch[aria-checked="true"] .switch__track::after { translate: var(--size-icon-sm) 0; background: var(--primary-foreground); }
  .switch:focus-visible { outline: none; }
  .switch:focus-visible .switch__track, .switch.is-focus .switch__track { outline: var(--focus-width) solid var(--ring); outline-offset: var(--focus-offset); }
  .switch:hover .switch__track { border-color: var(--foreground); }
  .switch[aria-checked="true"]:hover .switch__track { border-color: var(--primary-hover); background: var(--primary-hover); }
  .switch[aria-disabled="true"] { color: var(--muted-foreground); cursor: not-allowed; }
  .switch[aria-disabled="true"] .switch__track { background: var(--muted); border-color: var(--border); }
  .switch[aria-disabled="true"] .switch__track::after { background: var(--border); }

  /* File drop zone (behavior per Carbon file uploader) */
  .dropzone { display: grid; gap: var(--space-3); justify-items: start; padding: var(--space-6) var(--space-4); background: var(--card); border: var(--border-hairline) dashed var(--input); border-radius: var(--radius-lg); transition: background-color var(--duration-fast) var(--easing-out); }
  @media (min-width: 768px) { .dropzone { padding: var(--space-8) var(--space-6); } }
  .dropzone__title { font-size: var(--text-base); line-height: var(--leading-base); font-weight: var(--font-weight-semibold); }
  .dropzone__hint { font-size: var(--text-sm); line-height: var(--leading-sm); color: var(--muted-foreground); }
  .dropzone__icon { color: var(--muted-foreground); }
  .dropzone.is-dragover { background: var(--primary-soft); border-style: solid; border-color: var(--primary); box-shadow: inset 0 0 0 var(--border-hairline) var(--primary); }
  .dropzone.is-dragover .dropzone__icon { color: var(--primary); }
  .dropzone.is-invalid { border-color: var(--destructive); border-style: solid; }
  .dropzone[aria-disabled="true"] { background: var(--muted); border-color: var(--border); }
  .dropzone[aria-disabled="true"] .dropzone__title { color: var(--muted-foreground); }
  .file-list { list-style: none; padding: 0; display: grid; gap: var(--space-2); width: 100%; }
  .file-item { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; gap: var(--space-1) var(--space-3); padding: var(--space-2) var(--space-3); border: var(--border-hairline) solid var(--border); border-radius: var(--radius-md); background: var(--card); font-size: var(--text-sm); line-height: var(--leading-sm); }
  .file-item__name { font-weight: var(--font-weight-medium); overflow-wrap: anywhere; }
  .file-item__meta { color: var(--muted-foreground); font-variant-numeric: tabular-nums; }
  .file-item .progress { grid-column: 2 / -1; }
  .file-item__error { grid-column: 2 / -1; color: var(--destructive); }

  /* Tabs */
  .tabs { display: flex; gap: var(--space-1); border-bottom: var(--border-hairline) solid var(--border); overflow-x: auto; scrollbar-width: none; }
  .tab { display: inline-flex; align-items: center; gap: var(--space-2); height: var(--control-h); padding-inline: var(--space-3); white-space: nowrap; color: var(--muted-foreground); font-size: var(--text-sm); line-height: var(--leading-sm); font-weight: var(--font-weight-medium); box-shadow: inset 0 calc(-1 * var(--border-strong)) 0 transparent; text-decoration: none; }
  @media (min-width: 768px) { .tab { height: var(--size-row-normal); } }
  .tab:hover, .tab.is-hover { color: var(--foreground); box-shadow: inset 0 calc(-1 * var(--border-strong)) 0 var(--border); }
  .tab[aria-selected="true"] { color: var(--foreground); box-shadow: inset 0 calc(-1 * var(--border-strong)) 0 var(--primary); }
  .tab:focus-visible, .tab.is-focus { outline-offset: calc(-1 * var(--focus-width)); }
  .tab[aria-disabled="true"] { color: var(--subtle-foreground); cursor: not-allowed; box-shadow: none; }
  .count { display: inline-flex; align-items: center; min-width: var(--space-5); height: var(--space-5); justify-content: center; padding-inline: var(--space-1); border-radius: var(--radius-sm); background: var(--secondary); color: var(--secondary-foreground); font-size: var(--text-xs); line-height: var(--leading-xs); font-weight: var(--font-weight-medium); font-variant-numeric: tabular-nums; }

  /* Segmented control: radio group */
  .seg { display: inline-flex; padding: calc(var(--space-1) - var(--border-hairline)); gap: var(--space-1); background: var(--muted); border: var(--border-hairline) solid var(--border); border-radius: var(--radius-md); max-width: 100%; overflow-x: auto; }
  .seg__item { position: relative; display: inline-flex; }
  .seg__item input { position: absolute; opacity: 0; inset: 0; margin: 0; cursor: pointer; }
  .seg__item span { display: inline-flex; align-items: center; gap: var(--space-1); height: calc(var(--control-h) - 2 * var(--space-1)); padding-inline: var(--space-3); border-radius: var(--radius-sm); color: var(--muted-foreground); font-size: var(--text-sm); line-height: var(--leading-sm); font-weight: var(--font-weight-medium); white-space: nowrap; }
  .seg__item:hover span { color: var(--foreground); }
  .seg__item input:checked + span { background: var(--primary); color: var(--primary-foreground); } /* v0.4.3 (Paperralph v0.4.3 nit 3, Testingralph nit): the selected segment is a filled thumb, no shadow and no second ring inside the --input frame */
  @media (forced-colors: active) { .seg__item input:checked + span { background: Highlight; color: HighlightText; forced-color-adjust: none; } }
  .seg__item input:focus-visible + span { outline: var(--focus-width) solid var(--ring); outline-offset: var(--border-hairline); }
  .seg__item input:disabled + span { color: var(--subtle-foreground); cursor: not-allowed; }

  /* Menu (popover attribute, role="menu") */
  .menu { min-width: var(--size-menu-min); max-width: min(var(--size-overlay-max), calc(100vw - 2 * var(--space-4))); padding: var(--space-1); background: var(--popover); color: var(--popover-foreground); border: var(--border-hairline) solid var(--border); border-radius: var(--radius-lg); box-shadow: var(--shadow-2); }
  .menu[popover] { margin: 0; inset: auto; }
  .menu--static { display: inline-block; }
  .menu__label { padding: var(--space-2) var(--space-2) var(--space-1); font-size: var(--text-xs); line-height: var(--leading-xs); color: var(--muted-foreground); font-weight: var(--font-weight-medium); }
  .menu__item { display: flex; align-items: center; gap: var(--space-2); width: 100%; min-height: var(--item-h); padding-inline: var(--space-2); border-radius: var(--radius-sm); text-align: left; font-size: var(--text-sm); line-height: var(--leading-sm); color: var(--popover-foreground); text-decoration: none; }
  .menu__item:hover, .menu__item:focus-visible, .menu__item.is-hover { background: var(--accent); outline: none; }
  .menu__item:focus-visible { box-shadow: inset 0 0 0 var(--focus-width) var(--ring); }
  .menu__item .icon { color: var(--muted-foreground); }
  .menu__item[aria-checked="true"] .icon--check { color: var(--foreground); }
  .menu__item--destructive { color: var(--destructive); }
  .menu__item--destructive .icon { color: var(--destructive); }
  .menu__item[aria-disabled="true"] { color: var(--subtle-foreground); cursor: not-allowed; background: none; }
  .menu__item kbd, .menu__hint { margin-left: auto; color: var(--muted-foreground); font-size: var(--text-xs); line-height: var(--leading-xs); }
  .menu__sep { height: var(--border-hairline); background: var(--border); margin: var(--space-1) calc(-1 * var(--space-1)); }

  /* Dialog (native <dialog>) and sheet */
  .dialog { width: min(var(--size-dialog-max), calc(100vw - 2 * var(--space-4))); max-height: calc(100dvh - 2 * var(--space-8)); background: var(--popover); color: var(--popover-foreground); border: var(--border-hairline) solid var(--border); border-radius: var(--radius-lg); box-shadow: var(--shadow-3); }
  .dialog::backdrop { background: var(--scrim); }
  .dialog[open] { animation: dialog-in var(--duration-base) var(--easing-out); }
  .dialog__header { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--space-4); padding: var(--space-4) var(--space-4) 0 var(--space-6); }
  .dialog__title { font-size: var(--text-lg); line-height: var(--leading-lg); padding-top: var(--space-2); }
  .dialog__body { padding: var(--space-3) var(--space-6) var(--space-6); color: var(--muted-foreground); }
  .dialog__footer { display: flex; flex-wrap: wrap-reverse; justify-content: flex-end; gap: var(--space-2); padding: var(--space-4) var(--space-6); border-top: var(--border-hairline) solid var(--border); }
  .dialog--static { position: static; display: block; margin: 0; width: 100%; max-width: var(--size-dialog-max); }
  .sheet { margin: auto 0 0; width: 100%; max-width: 100%; max-height: 85dvh; overflow: auto; border-radius: var(--radius-lg) var(--radius-lg) 0 0; }
  .sheet[open] { animation: sheet-in var(--duration-slow) var(--easing-drawer); }
  @keyframes sheet-in { from { transform: translateY(100%); } }
  @keyframes dialog-in { from { opacity: 0; transform: translateY(var(--space-2)) scale(0.98); } }

  /* Tooltip (inverted) and popover */
  .tooltip { display: inline-block; max-width: var(--size-tooltip-max); padding: var(--space-1) var(--space-2); background: var(--foreground); color: var(--background); border-radius: var(--radius-sm); font-size: var(--text-xs); line-height: var(--leading-xs); box-shadow: var(--shadow-2); }
  .tooltip[popover] { margin: 0; border: 0; inset: auto; }
  .tooltip[popover]:not(:popover-open) { display: none; } /* v0.3: .tooltip sets display, which would otherwise override the UA rule that hides a closed popover */
  .popover { max-width: min(var(--size-overlay-max), calc(100vw - 2 * var(--space-4))); padding: var(--space-3) var(--space-4); background: var(--popover); color: var(--popover-foreground); border: var(--border-hairline) solid var(--border); border-radius: var(--radius-lg); box-shadow: var(--shadow-2); font-size: var(--text-sm); line-height: var(--leading-sm); }
  .popover[popover] { margin: 0; inset: auto; }
  .popover--static, .tooltip--static { position: static; }

  /* Toast */
  .toast-region { position: fixed; z-index: var(--z-toast); left: var(--space-4); right: var(--space-4); bottom: var(--space-4); display: grid; gap: var(--space-2); justify-items: end; pointer-events: none; }
  @media (min-width: 768px) { .toast-region { left: auto; right: var(--space-6); bottom: var(--space-6); width: var(--size-toast-max); } }
  .toast-region--static { position: static; width: auto; justify-items: start; }
  /* v0.4.3 round 5 (Testingralph round 4 N1, nit c): the static toasts are a picture, so their Dismiss is inert and looks it:
     out of the tab order and aria-disabled in the markup, and no hover or press here. */
  .toast-region--static .btn { pointer-events: none; }
  .toast { pointer-events: auto; width: 100%; display: grid; grid-template-columns: auto minmax(0, 1fr) auto; gap: var(--space-2) var(--space-3); align-items: start; padding: var(--space-3) var(--space-3) var(--space-3) var(--space-4); background: var(--popover); color: var(--popover-foreground); border: var(--border-hairline) solid var(--border); border-radius: var(--radius-lg); box-shadow: var(--shadow-2); font-size: var(--text-sm); line-height: var(--leading-sm); animation: toast-in var(--duration-base) var(--easing-out); }
  .toast > .icon { margin-top: var(--space-0-5); }
  .toast__title { font-weight: var(--font-weight-medium); }
  .toast__text { color: var(--muted-foreground); }
  .toast__actions { grid-column: 2 / -1; display: flex; gap: var(--space-2); }
  @keyframes toast-in { from { opacity: 0; transform: translateY(var(--space-2)); } }

  /* Alert / banner: soft surface, icon and title. No side stripe. */
  .alert { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: var(--space-1) var(--space-3); padding: var(--space-3) var(--space-4); border-radius: var(--radius-md); background: var(--muted); color: var(--foreground); font-size: var(--text-sm); line-height: var(--leading-sm); }
  .alert > .icon { margin-top: var(--space-0-5); color: var(--muted-foreground); }
  .alert__title { font-weight: var(--font-weight-semibold); }
  .alert__body { grid-column: 2; color: var(--foreground); }
  .alert__body ul { padding-left: var(--space-5); }
  .alert__actions { grid-column: 2; display: flex; flex-wrap: wrap; gap: var(--space-2); margin-top: var(--space-2); }
  /* v0.3: soft tint plus a colored hairline border (light and dark) */
  .alert { border: var(--border-hairline) solid var(--_alert-bd, var(--border)); }
  .alert--error { --_alert-bd: color-mix(in oklab, var(--destructive) 45%, transparent); }
  .alert--warning { --_alert-bd: color-mix(in oklab, var(--warning) 45%, transparent); }
  .alert--success { --_alert-bd: color-mix(in oklab, var(--success) 45%, transparent); }
  .alert--info { --_alert-bd: color-mix(in oklab, var(--info) 45%, transparent); }
  .banner { border-inline: 0; }
  .alert--error { background: var(--destructive-soft); } .alert--error > .icon { color: var(--destructive); }
  .alert--warning { background: var(--warning-soft); } .alert--warning > .icon { color: var(--warning); }
  .alert--success { background: var(--success-soft); } .alert--success > .icon { color: var(--success); }
  .alert--info { background: var(--info-soft); } .alert--info > .icon { color: var(--info); }
  .banner { border-radius: 0; }
  .error-summary { padding: var(--space-4); border: var(--border-strong) solid var(--destructive); border-radius: var(--radius-md); background: var(--card); }
  .error-summary h2 { font-size: var(--text-base); line-height: var(--leading-base); margin-bottom: var(--space-2); }
  .error-summary ul { padding-left: var(--space-5); }
  .error-summary a { color: var(--destructive); font-weight: var(--font-weight-medium); }

  /* Status (icon plus word, no fill) and badge (soft fill) */
  .status { display: inline-flex; align-items: center; gap: var(--space-1); font-size: var(--text-sm); line-height: var(--leading-sm); font-weight: var(--font-weight-medium); white-space: nowrap; color: var(--foreground); }
  .status > .icon { color: var(--muted-foreground); }
  .status--error > .icon { color: var(--destructive); }
  .status--warning > .icon { color: var(--warning); }
  .status--success > .icon { color: var(--success); }
  .status--info > .icon { color: var(--info); }
  .badge { display: inline-flex; align-items: center; gap: var(--space-1); height: var(--space-6); padding-inline: var(--space-2); border-radius: var(--radius-sm); background: var(--secondary); color: var(--secondary-foreground); font-size: var(--text-xs); line-height: var(--leading-xs); font-weight: var(--font-weight-medium); white-space: nowrap; }
  .badge .icon { width: var(--size-icon-xs); height: var(--size-icon-xs); }
  .badge--error { background: var(--destructive-soft); color: var(--foreground); } .badge--error .icon { color: var(--destructive); }
  .badge--warning { background: var(--warning-soft); color: var(--foreground); } .badge--warning .icon { color: var(--warning); }
  .badge--success { background: var(--success-soft); color: var(--foreground); } .badge--success .icon { color: var(--success); }
  .badge--info { background: var(--info-soft); color: var(--foreground); } .badge--info .icon { color: var(--info); }
  .badge--accent { background: var(--primary-soft); color: var(--primary-soft-foreground); }

  /* Summary strip: counts as words, not KPI tiles */
  .result-summary { display: flex; flex-wrap: wrap; gap: var(--space-2) var(--space-6); align-items: center; font-size: var(--text-sm); line-height: var(--leading-sm); }
  .result-summary__verdict { display: flex; align-items: center; gap: var(--space-2); font-size: var(--text-lg); line-height: var(--leading-lg); font-weight: var(--font-weight-semibold); width: 100%; }
  .result-summary__verdict .icon { width: var(--size-icon-md); height: var(--size-icon-md); }
  .result-summary__meta { color: var(--muted-foreground); font-variant-numeric: tabular-nums; }
  .num { font-variant-numeric: tabular-nums; text-align: right; }
  .mono { font-family: var(--font-mono); font-size: var(--text-sm); line-height: var(--leading-sm); }

  /* Toolbar above tables */
  .toolbar { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); padding: var(--space-3) var(--space-4); border-bottom: var(--border-hairline) solid var(--border); }
  .toolbar__search { flex: 1 1 var(--size-sidebar); max-width: var(--size-search-max); }
  .toolbar__end { margin-left: auto; display: flex; gap: var(--space-2); flex-wrap: wrap; }
  .toolbar--batch { background: var(--primary-soft); color: var(--primary-soft-foreground); }
  .chip { display: inline-flex; align-items: center; gap: var(--space-1); height: var(--control-h-sm); min-height: var(--size-target-min); padding-left: var(--space-2); border-radius: var(--radius-sm); background: var(--secondary); color: var(--secondary-foreground); font-size: var(--text-sm); line-height: var(--leading-sm); }
  .chip__remove { display: inline-grid; place-items: center; width: var(--control-h-sm); height: var(--control-h-sm); border-radius: var(--radius-sm); color: var(--muted-foreground); }
  .chip__remove:hover { color: var(--foreground); background: var(--accent); }

  /* Table */
  .table-wrap { position: relative; z-index: var(--z-base); overflow: auto; background: var(--card); overscroll-behavior-x: contain; }
  .table-wrap--scroll { max-height: min(var(--size-scroll-max), calc(100dvh - var(--size-header) - var(--space-16) - var(--space-16) - var(--space-8))); }
  .table { width: 100%; font-size: var(--text-sm); line-height: var(--leading-sm); font-variant-numeric: tabular-nums; }
  .table th, .table td { height: var(--row-h); padding: var(--space-2) var(--space-3); text-align: left; vertical-align: top; border-bottom: var(--border-hairline) solid var(--border); }
  .table thead th { position: sticky; top: 0; z-index: var(--z-sticky); background: var(--muted); color: var(--foreground); font-weight: var(--font-weight-medium); vertical-align: bottom; white-space: nowrap; }
  .table tbody th { font-weight: var(--font-weight-regular); }  /* v0.2: no browser bold (700) on row headers */
  .table tbody tr:hover, .table tbody tr.is-hover { background: var(--muted); }
  .table tbody tr[aria-selected="true"] { background: var(--primary-soft); }
  .table tbody tr:last-child td { border-bottom: 0; }
  .table .num { text-align: right; }
  .table .nowrap { white-space: nowrap; }
  .table .clamp { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; max-width: var(--size-cell-max); }
  .table .wrap-anywhere { overflow-wrap: anywhere; }
  .table .col-select { width: var(--space-10); padding-right: 0; }
  .table .col-actions { width: var(--space-12); text-align: right; padding-block: var(--space-1); }
  .table .pin { position: sticky; left: 0; z-index: var(--z-raised); background: var(--card); box-shadow: inset calc(-1 * var(--border-hairline)) 0 0 var(--border); }
  .table thead .pin { z-index: calc(var(--z-sticky) + 1); background: var(--muted); }
  .table tbody tr:hover .pin { background: var(--muted); }
  .table tbody tr[aria-selected="true"] .pin { background: var(--primary-soft); }
  .table[data-density="condensed"] { --row-h: var(--size-row-condensed); }
  .table[data-density="condensed"] td { padding-block: var(--space-1); }
  .table[data-density="spacious"] { --row-h: var(--size-row-spacious); }
  .table td.is-error { background: var(--destructive-soft); }
  .th-sort { display: inline-flex; align-items: center; gap: var(--space-1); font-weight: inherit; color: inherit; min-height: var(--size-target-min); text-align: left; border-radius: var(--radius-sm); }
  .th-sort .icon { color: var(--subtle-foreground); }
  [aria-sort] .th-sort .icon { color: var(--foreground); }
  @media (hover: hover) {
    th:not([aria-sort]) .th-sort .icon { opacity: 0; transition: opacity var(--duration-fast) var(--easing-out); }
    th:not([aria-sort]) .th-sort:hover .icon, th:not([aria-sort]) .th-sort:focus-visible .icon { opacity: 1; }
  }
  .th-sort:hover { color: var(--foreground); text-decoration: underline; text-underline-offset: 0.2em; }
  .th-count { display: block; font-size: var(--text-xs); line-height: var(--leading-xs); font-weight: var(--font-weight-regular); color: var(--muted-foreground); }
  .not-stated, .nil { color: var(--muted-foreground); }
  .row-link { color: var(--foreground); font-weight: var(--font-weight-medium); text-decoration: none; }
  .row-link:hover { text-decoration: underline; }
  .cell-sub { display: block; color: var(--muted-foreground); }
  @media (max-width: 767.98px) { .table .p3 { display: none; } }
  @media (max-width: 1279.98px) { .table .p4 { display: none; } }

  /* Pagination */
  .pagination { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--space-3); padding: var(--space-3) var(--space-4); border-top: var(--border-hairline) solid var(--border); font-size: var(--text-sm); line-height: var(--leading-sm); color: var(--muted-foreground); }
  .pagination__pages { display: flex; align-items: center; gap: var(--space-2); }
  .pagination__range { font-variant-numeric: tabular-nums; }

  /* Filters / facets */
  .facets { display: grid; gap: var(--space-6); align-content: start; }
  .facet legend { font-size: var(--text-sm); line-height: var(--leading-sm); font-weight: var(--font-weight-semibold); margin-bottom: var(--space-1); }
  .facet__more { margin-top: var(--space-1); }
  .facet-toggle { display: inline-flex; }
  @media (max-width: 1279.98px) { .facets--side { display: none; } }
  @media (min-width: 1280px) { .facet-toggle { display: none; } }

  /* Empty, loading and error states */
  .state { display: grid; justify-items: start; gap: var(--space-2); padding: var(--space-8) var(--space-4); max-width: var(--size-form-max); }
  .state--center { justify-items: center; text-align: center; margin-inline: auto; }
  .state > .icon { width: var(--size-icon-md); height: var(--size-icon-md); color: var(--muted-foreground); margin-bottom: var(--space-1); }
  .state__title { font-size: var(--text-base); line-height: var(--leading-base); font-weight: var(--font-weight-semibold); }
  .state__text { font-size: var(--text-sm); line-height: var(--leading-sm); color: var(--muted-foreground); }
  .state__actions { display: flex; flex-wrap: wrap; gap: var(--space-2); margin-top: var(--space-2); }
  .state--error > .icon { color: var(--destructive); }
  .skeleton { display: block; height: var(--leading-sm); border-radius: var(--radius-sm); background: var(--secondary); animation: pulse var(--duration-pulse) var(--easing-in-out) infinite; }
  .skeleton--text { height: var(--space-3); margin-block: var(--space-1); }
  .skeleton--w25 { width: 25%; } .skeleton--w40 { width: 40%; } .skeleton--w60 { width: 60%; } .skeleton--w80 { width: 80%; }
  @keyframes pulse { 50% { opacity: 0.55; } }
  /* Spinner (v0.4.2, MF10): our own mark, not the stock ring. A 2px comet: a faint full track with a tail that fades into
     a bright head, drawn with a conic gradient and cut to a ring with a mask. currentColor, so it follows the button. */
  /* v0.4.3 round 4 (Paperralph r3 nit 1): the ring and the head turn as pseudo-elements, so the .spinner box itself never
     rotates. Its getBoundingClientRect stays 16 by 16 px at every moment, and the gaps inside a busy button measure equal
     (a turning box reported up to 1 px more on the spinner side). Same drawing as v0.4.2. */
  .spinner { --_w: var(--border-strong); display: inline-block; position: relative; width: var(--size-icon-sm); height: var(--size-icon-sm); flex: none; border-radius: var(--radius-full); color: var(--primary); }
  .spinner::before { content: ""; position: absolute; inset: 0; border-radius: inherit;
    background: conic-gradient(from 0turn, transparent 0turn, color-mix(in oklab, currentColor 12%, transparent) 0.15turn, currentColor 0.9turn, transparent 0.9turn), color-mix(in oklab, currentColor 16%, transparent);
    -webkit-mask: radial-gradient(farthest-side, transparent calc(100% - var(--_w) - var(--border-hairline)), #000 calc(100% - var(--_w))); mask: radial-gradient(farthest-side, transparent calc(100% - var(--_w) - var(--border-hairline)), #000 calc(100% - var(--_w)));
    animation: spin var(--duration-spin) linear infinite; }
  .spinner::after { content: ""; position: absolute; top: 0; left: 50%; width: var(--_w); height: var(--_w); margin-left: calc(-0.5 * var(--_w)); border-radius: var(--radius-full); background: currentColor; rotate: -0.1turn; transform-origin: 50% calc(var(--size-icon-sm) / 2);
    animation: spin-head var(--duration-spin) linear infinite; }
  @keyframes spin { to { rotate: 1turn; } }
  @keyframes spin-head { from { rotate: -0.1turn; } to { rotate: 0.9turn; } }
  @media (prefers-reduced-motion: reduce) { .spinner::before, .spinner::after { animation: none; } .skeleton { animation: none; } }
  @media (forced-colors: active) { .spinner::before { background: CanvasText; } }

  /* Progress */
  .progress { display: grid; gap: var(--space-1); width: 100%; }
  .progress__label { display: flex; justify-content: space-between; gap: var(--space-3); font-size: var(--text-sm); line-height: var(--leading-sm); }
  .progress__value { color: var(--muted-foreground); font-variant-numeric: tabular-nums; }
  .progress__track { height: var(--space-2); border-radius: var(--radius-sm); background: var(--secondary); overflow: hidden; box-shadow: inset 0 0 0 var(--border-hairline) var(--input); }
  /* v0.2: the bar width is set from aria-valuenow by script through the CSSOM (allowed under style-src 'self'); no width classes. */
  .progress__bar { width: 0; height: 100%; background: var(--primary); border-radius: var(--radius-sm); transition: width var(--duration-base) var(--easing-out); }
  .progress--error .progress__bar { background: var(--destructive); }

  /* Stepper */
  .stepper { list-style: none; padding: 0; display: grid; gap: var(--space-1); counter-reset: step; }
  .stepper__item a, .stepper__item > span { display: flex; align-items: center; gap: var(--space-2); min-height: var(--item-h); padding-inline: var(--space-2); border-radius: var(--radius-sm); color: var(--muted-foreground); text-decoration: none; font-size: var(--text-sm); line-height: var(--leading-sm); }
  .stepper__item a:hover { background: var(--accent); color: var(--foreground); }
  .stepper__num { display: inline-grid; place-items: center; width: var(--space-5); height: var(--space-5); flex: none; border-radius: var(--radius-full); border: var(--border-hairline) solid var(--input); font-size: var(--text-xs); line-height: var(--leading-xs); font-variant-numeric: tabular-nums; color: var(--muted-foreground); }
  .stepper__item.is-done .stepper__num { background: var(--primary); border-color: var(--primary); color: var(--primary-foreground); }
  .stepper__item.is-done a { color: var(--foreground); }
  .stepper__item [aria-current="step"] { background: var(--primary-soft); color: var(--primary-soft-foreground); font-weight: var(--font-weight-semibold); }
  .stepper__item [aria-current="step"] .stepper__num { border-color: var(--primary); color: var(--primary-soft-foreground); border-width: var(--border-strong); }
  .stepper__item.is-error a { color: var(--foreground); }
  .stepper__item.is-error .stepper__num { border-color: var(--destructive); color: var(--destructive); }
  .stepper__state { margin-left: auto; font-size: var(--text-xs); line-height: var(--leading-xs); color: var(--muted-foreground); }
  .stepper__item.is-error .stepper__state { color: var(--destructive); }
  .stepper-compact { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); font-size: var(--text-sm); line-height: var(--leading-sm); }
  .step-footer { display: flex; justify-content: space-between; gap: var(--space-2); padding: var(--space-3) var(--space-4); background: var(--card); border-top: var(--border-hairline) solid var(--border); }

  /* Summary list (check your answers) */
  .summary-list { display: grid; font-size: var(--text-sm); line-height: var(--leading-sm); }
  .summary-list__row { display: grid; gap: var(--space-1) var(--space-4); padding-block: var(--space-3); border-bottom: var(--border-hairline) solid var(--border); }
  @media (min-width: 768px) { .summary-list__row { grid-template-columns: var(--size-summary-col) minmax(0, 1fr) auto; } }
  .summary-list dt { font-weight: var(--font-weight-medium); }
  .summary-list dd { margin: 0; }

  /* Code block */
  .code { position: relative; background: var(--muted); border: var(--border-hairline) solid var(--border); border-radius: var(--radius-md); }
  .code pre { margin: 0; padding: var(--space-3) var(--space-4); overflow-x: auto; font-size: var(--text-sm); line-height: var(--leading-sm); tab-size: 2; }
  .code__copy { position: absolute; top: var(--space-1); right: var(--space-1); }
  .code__head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); padding: var(--space-1) var(--space-1) var(--space-1) var(--space-4); border-bottom: var(--border-hairline) solid var(--border); font-size: var(--text-xs); line-height: var(--leading-xs); color: var(--muted-foreground); }
  .tok-keyword { color: var(--syntax-keyword); } .tok-string { color: var(--syntax-string); } .tok-number { color: var(--syntax-number); } .tok-property { color: var(--syntax-property); } .tok-comment { color: var(--syntax-comment); font-style: italic; }
  .tok-punct { color: var(--syntax-comment); }
  .editor__group--end { margin-left: auto; }
  .hl-error { text-decoration: underline wavy var(--destructive); text-decoration-thickness: var(--border-hairline); text-underline-offset: var(--space-0-5); }
  .hl-warning { text-decoration: underline wavy var(--warning); text-decoration-thickness: var(--border-hairline); text-underline-offset: var(--space-0-5); }

  /* CodeMirror 6 theme (class names are CodeMirror's own) */
  .cm-editor { background: var(--card); color: var(--foreground); font-family: var(--font-mono); font-size: var(--text-sm); line-height: var(--leading-sm); height: 100%; }
  .cm-scroller { overflow: auto; font-family: inherit; display: flex; align-items: flex-start; }
  .cm-gutters { background: var(--muted); color: var(--subtle-foreground); border-right: var(--border-hairline) solid var(--border); flex: none; text-align: right; user-select: none; position: sticky; left: 0; z-index: var(--z-raised); padding: var(--space-2) 0; }
  .cm-gutterElement { padding: 0 var(--space-2) 0 var(--space-3); min-width: var(--space-10); display: flex; align-items: center; justify-content: flex-end; gap: var(--space-1); height: var(--leading-sm); }
  .cm-gutterElement .icon { width: var(--size-icon-xs); height: var(--size-icon-xs); }
  .cm-gutterElement.is-error .icon { color: var(--destructive); }
  .cm-gutterElement.is-warning .icon { color: var(--warning); }
  .cm-content { padding: var(--space-2) 0; white-space: pre; flex: 1 0 auto; caret-color: var(--foreground); }
  .cm-line { padding: 0 var(--space-4) 0 var(--space-3); height: var(--leading-sm); }
  .cm-activeLine { background: var(--muted); }
  .cm-activeLineGutter { color: var(--foreground); }
  .cm-selectionBackground { background: var(--selection); }
  .cm-editor.cm-focused { outline: var(--focus-width) solid var(--ring); outline-offset: calc(-1 * var(--focus-width)); }

  /* ProseMirror document (Policy Hub editor) */
  /* v0.4.2: the frame is a control edge, so it takes --input (3:1 or more on card and page), not the decorative hairline. */
  .editor { background: var(--card); border: var(--border-hairline) solid var(--input); border-radius: var(--radius-lg); }
  /* v0.2: the toolbar never clips (no overflow: hidden). Below 768px it is not sticky, so it cannot cover the focused item (2.4.11). */
  .editor__toolbar { display: flex; flex-wrap: nowrap; align-items: center; gap: var(--space-1); padding: var(--space-1) var(--space-2); background: var(--card); border-bottom: var(--border-hairline) solid var(--border); }
  @media (min-width: 768px) { .editor__toolbar { position: sticky; top: var(--size-header); z-index: var(--z-sticky); } }
  .editor__toolbar .btn[aria-pressed="true"] { background: var(--secondary); }
  .editor__group { display: flex; gap: var(--space-1); }
  .editor__divider { width: var(--border-hairline); align-self: stretch; margin: var(--space-1) var(--space-1); background: var(--border); }
  .editor__toolbar .p3 { display: none; }
  @media (min-width: 768px) { .editor__toolbar .p3 { display: flex; } }
  .editor__toolbar .more { margin-left: auto; }
  .ProseMirror { max-width: var(--size-prose-max); margin-inline: auto; padding: var(--space-6) var(--space-4) var(--space-12); font-size: var(--text-base); line-height: var(--leading-prose); color: var(--foreground); white-space: pre-wrap; word-wrap: break-word; }
  @media (min-width: 768px) { .ProseMirror { padding-inline: var(--space-8); } }
  .ProseMirror:focus { outline: none; }
  .ProseMirror:focus-visible { outline: var(--focus-width) solid var(--ring); outline-offset: calc(-1 * var(--focus-width)); }
  .ProseMirror h1 { font-size: var(--text-xl); line-height: var(--leading-xl); margin-bottom: var(--space-4); }
  .ProseMirror h2 { font-size: var(--text-lg); line-height: var(--leading-lg); margin-top: var(--space-8); margin-bottom: var(--space-2); }
  .ProseMirror h3 { font-size: var(--text-base); line-height: var(--leading-base); margin-top: var(--space-6); margin-bottom: var(--space-1); }
  .ProseMirror p + p, .ProseMirror ul, .ProseMirror ol { margin-top: var(--space-3); }
  .ProseMirror ul, .ProseMirror ol { padding-left: var(--space-6); }
  .ProseMirror li + li { margin-top: var(--space-1); }
  .ProseMirror blockquote { margin-top: var(--space-4); padding-left: var(--space-4); color: var(--muted-foreground); box-shadow: inset var(--border-strong) 0 0 var(--border); }
  .ProseMirror code { background: var(--muted); border-radius: var(--radius-sm); padding: 0 var(--space-1); }
  .ProseMirror .is-empty::before { content: attr(data-placeholder); color: var(--subtle-foreground); pointer-events: none; float: left; height: 0; }
  .ProseMirror-selectednode { outline: var(--focus-width) solid var(--ring); }
  .ProseMirror .is-filled { background: var(--primary-soft); color: var(--primary-soft-foreground); border-radius: var(--radius-sm); padding: 0 var(--space-0-5); }
  .editor__status { display: flex; flex-wrap: wrap; gap: var(--space-1) var(--space-4); padding: var(--space-2) var(--space-4); border-top: var(--border-hairline) solid var(--border); font-size: var(--text-xs); line-height: var(--leading-xs); color: var(--muted-foreground); }

  /* Two-pane workspace */
  .workspace { display: grid; grid-template-rows: auto minmax(0, 1fr) auto; height: calc(100dvh - var(--size-header) - 2 * var(--space-4)); min-height: var(--size-pane-min); background: var(--card); border: var(--border-hairline) solid var(--border); border-radius: var(--radius-lg); overflow: hidden; }
  .workspace__bar { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); padding: var(--space-2) var(--space-3); border-bottom: var(--border-hairline) solid var(--border); }
  .workspace__bar .tabs { border-bottom: 0; }
  .workspace__panes { display: grid; min-height: 0; }
  .workspace__pane { min-height: 0; min-width: 0; overflow: auto; display: flex; flex-direction: column; }
  .workspace__pane-head { position: sticky; top: 0; z-index: var(--z-sticky); display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); min-height: var(--size-row-normal); padding: var(--space-1) var(--space-3); background: var(--muted); border-bottom: var(--border-hairline) solid var(--border); font-size: var(--text-sm); line-height: var(--leading-sm); font-weight: var(--font-weight-medium); }
  .workspace__pane + .workspace__pane { border-top: var(--border-hairline) solid var(--border); }
  .workspace__pane[data-hidden-below-lg] { display: none; }
  .workspace__switch { display: flex; }
  @media (min-width: 1280px) {
    .workspace__panes { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
    .workspace__pane + .workspace__pane { border-top: 0; border-left: var(--border-hairline) solid var(--border); }
    .workspace__pane[data-hidden-below-lg] { display: flex; }
    .workspace__switch { display: none; }
  }
  .workspace__status { display: flex; flex-wrap: wrap; gap: var(--space-1) var(--space-4); padding: var(--space-1) var(--space-3); border-top: var(--border-hairline) solid var(--border); background: var(--muted); font-size: var(--text-xs); line-height: var(--leading-xs); color: var(--muted-foreground); }

  /* Problems list */
  .problems { list-style: none; padding: 0; }
  .problem { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; gap: var(--space-1) var(--space-3); padding: var(--space-3); border-bottom: var(--border-hairline) solid var(--border); font-size: var(--text-sm); line-height: var(--leading-sm); }
  .problem:hover { background: var(--muted); }
  .problem > .icon { margin-top: var(--space-0-5); }
  .problem--error > .icon { color: var(--destructive); }
  .problem--warning > .icon { color: var(--warning); }
  .problem--note > .icon { color: var(--muted-foreground); }
  .problem__loc { font-family: var(--font-mono); font-size: var(--text-sm); line-height: var(--leading-sm); color: var(--muted-foreground); white-space: nowrap; }
  .problem__fix { grid-column: 2 / -1; color: var(--muted-foreground); }
  .problem__msg { font-weight: var(--font-weight-medium); }

  /* Charts (static SVG built by Observable Plot in apps) */
  .chart { display: grid; gap: var(--space-2); }
  .chart svg { width: 100%; height: auto; overflow: visible; font-family: var(--font-sans); font-variant-numeric: tabular-nums; }
  .chart__title { font-size: var(--text-sm); line-height: var(--leading-sm); font-weight: var(--font-weight-semibold); }
  .chart__note { font-size: var(--text-sm); line-height: var(--leading-sm); color: var(--muted-foreground); }
  .chart .axis text, .chart .label { fill: var(--muted-foreground); font-size: var(--text-xs); }
  .chart .label-strong { fill: var(--foreground); font-size: var(--text-xs); font-weight: var(--font-weight-medium); }
  .chart .grid line { stroke: var(--border); }
  .chart .baseline { stroke: var(--input); }
  .chart .mark-gap { stroke: var(--card); stroke-width: var(--border-strong); }
  .fill-chart-1 { fill: var(--chart-1); } .fill-chart-2 { fill: var(--chart-2); } .fill-chart-3 { fill: var(--chart-3); } .fill-chart-4 { fill: var(--chart-4); } .fill-chart-5 { fill: var(--chart-5); }
  .stroke-chart-1 { stroke: var(--chart-1); } .stroke-chart-2 { stroke: var(--chart-2); }
  .legend { display: flex; flex-wrap: wrap; gap: var(--space-1) var(--space-4); list-style: none; padding: 0; font-size: var(--text-xs); line-height: var(--leading-xs); color: var(--muted-foreground); }
  .legend li { display: inline-flex; align-items: center; gap: var(--space-1); }
  .legend .swatch { width: var(--size-mark); height: var(--size-mark); border-radius: var(--radius-sm); }
  .bg-chart-1 { background: var(--chart-1); } .bg-chart-2 { background: var(--chart-2); } .bg-chart-3 { background: var(--chart-3); } .bg-chart-4 { background: var(--chart-4); } .bg-chart-5 { background: var(--chart-5); }

  /* Description list for row detail */
  .detail { display: grid; gap: var(--space-3); font-size: var(--text-sm); line-height: var(--leading-sm); }
  .detail dt { color: var(--muted-foreground); }
  .detail dd { margin: 0; overflow-wrap: anywhere; }
  @media (min-width: 768px) { .detail { grid-template-columns: var(--size-label-col) minmax(0, 1fr); } }
}

/* ---------- v0.2 additions ---------- */
@layer components {
  /* Missing value with a tooltip. The words are the label; the title adds the reason. */
  button.not-stated { font: inherit; line-height: inherit; background: none; border: 0; padding: 0; margin: 0; color: var(--muted-foreground); text-align: inherit; border-radius: var(--radius-sm); }
  .not-stated[data-tip], .not-stated[title] { cursor: help; text-decoration-line: underline; text-decoration-style: dotted; text-decoration-color: var(--subtle-foreground); text-underline-offset: 0.2em; }

  /* Popover menus are placed next to their button by script (CSSOM, allowed under style-src 'self') */
  .menu[popover], .popover[popover] { position: fixed; }
  /* v0.3: app.js caps max-height to the space left in the viewport; the popover then scrolls inside. */
  .menu[popover], .popover[popover] { overflow-y: auto; overscroll-behavior: contain; }
  .menu .choice { padding-inline: var(--space-2); border-radius: var(--radius-sm); }
  .menu .choice:hover { background: var(--accent); }
  .menu__item[role="menuitemradio"] .icon--check { visibility: hidden; }
  .menu__item[role="menuitemradio"][aria-checked="true"] .icon--check { visibility: visible; color: var(--foreground); }
  .menu-btn .icon:last-child { color: var(--muted-foreground); }

  /* Batch selection bar: replaces nothing, appears under the toolbar while rows are selected */
  .toolbar--batch { gap: var(--space-2) var(--space-4); }
  .toolbar__count { font-size: var(--text-sm); line-height: var(--leading-sm); font-weight: var(--font-weight-medium); }
  .table tbody tr[aria-selected="true"]:hover { background: var(--primary-soft); }
  .table .col-select .check { margin-top: 0; }

  /* Editor: file row, then a separate formatting toolbar */
  .editor__files { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2) var(--space-3); padding: var(--space-2) var(--space-3); border-bottom: var(--border-hairline) solid var(--border); }
  .editor__files .tabs { border-bottom: 0; flex: 1 1 auto; min-width: 0; display: none; }
  .editor__files .file-select { flex: 1 1 auto; }
  @media (min-width: 768px) { .editor__files .tabs { display: flex; } .editor__files .file-select { display: none; } }
  .editor__actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); margin-left: auto; }
  .select--sm select { min-height: var(--control-h-sm); font-size: var(--text-sm); line-height: var(--leading-sm); }
  .editor__toolbar .select--sm select { padding-left: var(--space-2); }
  .doc-preview[contenteditable="true"]:focus-visible, .doc-edit:focus-visible { outline: var(--focus-width) solid var(--ring); outline-offset: calc(-1 * var(--focus-width)); }
  .ProseMirror .task-list { list-style: none; padding-left: 0; }
  .ProseMirror .task-list li { display: flex; gap: var(--space-2); align-items: flex-start; }
  .ProseMirror .task-list .check { margin-top: var(--space-1); }

  /* Statement and preview boxes */
  .preview-box { padding: var(--space-4); background: var(--muted); border: var(--border-hairline) solid var(--border); border-radius: var(--radius-md); font-size: var(--text-base); line-height: var(--leading-base); }

  /* Problems list with jump to line */
  .problem__loc a { color: inherit; }
  .problem.is-current { background: var(--accent); }
  .cm-line.is-target { background: var(--selection); }
  .cm-gutterElement.is-target { color: var(--foreground); }
  .problems__more { padding: var(--space-3); font-size: var(--text-sm); line-height: var(--leading-sm); color: var(--muted-foreground); }

  /* Facets in a bottom sheet below 1280px */
  .sheet .facets { padding: 0 var(--space-6) var(--space-6); }
  .sheet .dialog__header { position: sticky; top: 0; background: var(--popover); }

  /* Visible label for a region that scrolls on its own */
  .scroll-note { font-size: var(--text-sm); line-height: var(--leading-sm); color: var(--muted-foreground); }

  /* One list of definitions in a resumable job */
  .job { display: grid; gap: var(--space-3); }
}

@layer components {
  /* v0.2 additions, part 2 */
  .th-sort .icon--sort-asc, .th-sort .icon--sort-desc { display: none; }
  [aria-sort="ascending"] .th-sort .icon--sort-asc, [aria-sort="descending"] .th-sort .icon--sort-desc { display: inline-block; }
  [aria-sort="ascending"] .th-sort .icon--sort-none, [aria-sort="descending"] .th-sort .icon--sort-none { display: none; }
  .sheet .facets--side { display: grid; }
  button.row-link { text-align: left; font: inherit; background: none; border: 0; padding: 0; color: inherit; cursor: pointer; }
  button.row-link:hover { text-decoration: underline; text-underline-offset: 0.2em; }
  /* v0.3 A5: in-table buttons get a 24px target (WCAG 2.5.8) without changing the 40px row. */
  button.not-stated, button.row-link { display: inline-flex; align-items: center; min-height: 24px; vertical-align: middle; }
  .menu__item .icon--check { margin-left: auto; }
  .cm-line { scroll-margin-block: var(--space-16); }
  .cm-line:target { background: var(--selection); }
  @media (max-width: 1279.98px) {
    .workspace[data-show="problems"] .workspace__pane:not([data-hidden-below-lg]) { display: none; }
    .workspace[data-show="problems"] .workspace__pane[data-hidden-below-lg] { display: flex; }
  }
  .workspace--fit { height: min(var(--size-scroll-max), 80dvh); }
  .field--inline { display: flex; align-items: center; gap: var(--space-2); }
  .preview-source { white-space: pre-wrap; max-width: var(--size-measure); margin: 0; }
  .prose { max-width: var(--size-measure); }
  .not-stated { white-space: nowrap; }
  @media (min-width: 1280px) { .table tbody .pin { min-width: var(--size-summary-col); } }
}
@layer components {
  /* v0.3: Base UI ScrollArea viewport. With CSPProvider disableStyleElements, Base UI no longer injects
     its own style element, but still puts this class on the viewport, so the native scrollbar has to be
     hidden here (same rules Base UI 1.9.0 ships in utils/styles.js). */
  .base-ui-disable-scrollbar { scrollbar-width: none; }
  .base-ui-disable-scrollbar::-webkit-scrollbar { display: none; }
}
@layer components {
  /* v0.3 layout polish (Testingralph should-fix 5) */
  @media (min-width: 768px) { .grid-2__sticky { position: sticky; top: calc(var(--size-header) + var(--space-4)); } }
  .ProseMirror > :first-child { margin-top: 0; }
  .problems > li { max-width: none; }
  /* Long V2 lines scroll sideways; a short fade at the pane edge keeps text off the divider. */
  .workspace__pane .cm-scroller { mask-image: linear-gradient(to left, transparent, #000 var(--space-4)); }
  /* v0.3 nits: a modal dialog locks the page scroll; on phones long tables grow with the page instead of nesting a second vertical scroll. */
  html:has(dialog:modal) { overflow: hidden; scrollbar-gutter: stable; }
  @media (max-width: 767.98px) { .table-wrap--scroll { max-height: none; } }
}
/* ---------- utilities ---------- */
@layer utilities {
  @media (min-width: 768px) { .app-menu-btn { display: none; } }
  .not-mono { font-family: var(--font-sans); font-weight: var(--font-weight-regular); color: var(--muted-foreground); }
  .sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0; }
  .muted { color: var(--muted-foreground); }
  .text-sm { font-size: var(--text-sm); line-height: var(--leading-sm); }
  .text-xs { font-size: var(--text-xs); line-height: var(--leading-xs); }
  .mb-4 { margin-bottom: var(--space-4); } .mt-2 { margin-top: var(--space-2); } .mt-4 { margin-top: var(--space-4); } .mt-6 { margin-top: var(--space-6); } .mt-8 { margin-top: var(--space-8); }
  .w-full { width: 100%; }
  .hide-sm { display: none; }
  @media (min-width: 768px) { .hide-sm { display: revert; } .show-sm-only { display: none; } }
}

/* =====================================================================
   v0.4.1 refresh (graphite, restrained). Visual only: same classes, same
   markup, same behavior as v0.3.2. Hierarchy comes from type, spacing and
   contrast. Cards are flat with a hairline; only floating layers cast a
   shadow. Full pills only on status, badges, tab counts, switch and radio.
   Every value is a token. Reasoning: ../../direction.md.
   ===================================================================== */
@layer base {
  html { font-optical-sizing: auto; text-rendering: optimizeLegibility; -moz-osx-font-smoothing: grayscale; }
  h1, h2, h3, h4 { font-weight: var(--font-weight-semibold); color: var(--foreground); }
  h1 { font-size: var(--text-xl); line-height: var(--leading-xl); letter-spacing: var(--tracking-xl); }
  @media (min-width: 768px) { h1 { font-size: var(--text-2xl); line-height: var(--leading-2xl); letter-spacing: var(--tracking-2xl); } }
  h2 { letter-spacing: var(--tracking-lg); }
  h3 { letter-spacing: var(--tracking-lg); }
  .num, .result-summary__meta, .file-item__meta, .count { font-variant-numeric: tabular-nums; }

  /* At 768px and up the editor toolbar is sticky under the header (28px buttons, 4px padding each side, two hairlines).
     While the document has focus, the caret line scrolls in below the toolbar, not only below the header. */
  :root { --editor-toolbar-h: calc(var(--size-control-sm) + 2 * var(--space-1) + 2 * var(--border-hairline)); }
  @media (min-width: 768px) {
    html:has(.editor [contenteditable="true"]:focus) { scroll-padding-top: calc(var(--size-header) + var(--editor-toolbar-h) + var(--space-4)); }
  }
}

@layer layout {
  /* Header: the page background, slightly translucent with a light blur; solid where transparency is reduced or unsupported. */
  .app-header { background: var(--header-background); -webkit-backdrop-filter: blur(var(--blur-header)); backdrop-filter: blur(var(--blur-header)); }
  @supports not ((backdrop-filter: none) or (-webkit-backdrop-filter: none)) { .app-header { background: var(--background); } }
  @media (prefers-reduced-transparency: reduce) { .app-header { background: var(--background); -webkit-backdrop-filter: none; backdrop-filter: none; } }
  .app-mark .icon { width: var(--size-icon-sm); height: var(--size-icon-sm); }
  /* Current page: 2px accent bar drawn as a box, so forced colors can repaint it (box-shadow is dropped there). */
  .app-nav a { position: relative; box-shadow: none; }
  .app-nav a[aria-current="page"] { box-shadow: none; }
  .app-nav a[aria-current="page"]::after { content: ""; position: absolute; left: var(--space-3); right: var(--space-3); bottom: 0; height: var(--border-strong); background: var(--primary); }

  .page { padding-top: var(--space-8); }
  @media (min-width: 768px) { .page { padding-top: var(--space-10); } }
  .page-header { margin-bottom: var(--space-8); }
  .page-header p { margin-top: var(--space-2); }
  .eyebrow { margin-bottom: var(--space-2); font-weight: var(--font-weight-medium); }
}

@layer components {
  /* Buttons: the v0.3.2 rules apply unchanged. Flat, no shadow, no gradient; solid accent primary;
     secondary keeps the input-colored 1px edge (3:1, project rule). Only the tokens behind them changed. */

  /* Drop zone: muted well, plain icon. */
  .dropzone { background: var(--muted); }
  .dropzone:hover { background: var(--secondary); }

  /* Tabs: same accent bar as the nav, as a box so forced colors can repaint it. Counts are pills. */
  .tab { position: relative; }
  .tab[aria-selected="true"] { box-shadow: none; }
  .tab[aria-selected="true"]::after { content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: var(--border-strong); background: var(--primary); }
  .count { border-radius: var(--radius-full); padding-inline: var(--space-2); }
  .tab[aria-selected="true"] .count { background: var(--foreground); color: var(--background); }

  /* Overlays: solid surface, hairline, one subtle elevation; overlays take the large radius. */
  .menu, .popover, .toast { border-radius: var(--radius-xl); }
  .dialog { border-radius: var(--radius-xl); box-shadow: var(--shadow-2); }

  /* Status and badges: tinted pills that keep icon plus word. */
  .status { padding: 0 var(--space-2); height: var(--space-6); border-radius: var(--radius-full); background: var(--secondary); font-size: var(--text-xs); line-height: var(--leading-xs); }
  .status--error { background: var(--destructive-soft); }
  .status--warning { background: var(--warning-soft); }
  .status--success { background: var(--success-soft); }
  .status--info { background: var(--info-soft); }
  .status > .icon { width: var(--size-icon-xs); height: var(--size-icon-xs); }
  .badge { border-radius: var(--radius-full); }

  /* Summary: the verdict is the loudest line on the page; the icon is plain, in the status color. */
  .result-summary { gap: var(--space-2) var(--space-3); }
  .result-summary__verdict { font-size: var(--text-xl); line-height: var(--leading-xl); letter-spacing: var(--tracking-xl); margin-bottom: var(--space-1); }
  .result-summary__verdict .icon.status--error { color: var(--destructive); }
  .result-summary__verdict .icon.status--warning { color: var(--warning); }
  .result-summary__verdict .icon.status--success { color: var(--success); }
  .result-summary__verdict .icon.status--info { color: var(--info); }

  /* Table: quiet header labels on the muted band, roomier outer gutters. */
  .table thead th { color: var(--muted-foreground); font-size: var(--text-xs); line-height: var(--leading-xs); }
  .table th:first-child, .table td:first-child { padding-left: var(--space-4); }
  .table th:last-child, .table td:last-child { padding-right: var(--space-4); }
  .table tbody tr:hover, .table tbody tr.is-hover { background: var(--muted); }
  .table tbody tr:hover .pin { background: var(--muted); }
  .table td.mono:first-child { font-weight: var(--font-weight-medium); }
}

@layer components {
  /* Lines (v0.4.2). One 1px hairline token (--border) for every frame and divider: panels, the table frame and its
     rows, the header bottom, toolbars. Control edges (inputs, selects, the editor frame) use --input.
     v0.4.1's second hairline (--border-subtle for rows) is merged into --border.
     Where two boxes meet, only one of them draws the line. */
  .table { border-collapse: separate; border-spacing: 0; }
  .panel .table tbody tr:last-child > *,
  .problems > .problem:last-child { border-bottom: 0; }
  /* Pills in table cells sit on the top of the line box, so rows stay on whole pixels (no blurry half pixel lines). */
  .table .status, .table .badge, .table .count, .table .th-sort, .table .not-stated { vertical-align: top; }
  /* Tabs that sit in a toolbar or bar use its bottom line: no second rule, the selected bar lands on the frame line. */
  .toolbar:has(> .tabs) { padding-block: 0; }
  .toolbar > .tabs, .panel__header > .tabs { border-bottom: 0; align-self: stretch; }
  .toolbar > .tabs .tab, .panel__header > .tabs .tab { height: 100%; min-height: var(--control-h); }
  /* Nested radius: a box inside a padded box takes the parent radius minus nothing larger than its own step. */
  .panel .alert, .panel .preview-box, .panel .code { border-radius: var(--radius-md); }
}

@layer components {
  /* EmptyState. v0.4.2 (Testingralph v0.4.1 MF3, MF6, MF7): every size sits top left with 24px padding, like the table
     cells and text around it. Nothing is centered, so nothing lands on a half pixel, and the box is sized to its content. */
  .panel > .state { padding: var(--space-6); max-width: none; }
  .state--success > .icon { color: var(--success); }
  .table td.empty-cell { padding: 0; white-space: normal; }
  .table tbody tr:has(> .empty-cell):hover { background: transparent; }
  .state--inline { padding: var(--space-6) var(--space-4); max-width: none; justify-items: start; text-align: start; }
  .state--inline > .icon { width: var(--size-icon-sm); height: var(--size-icon-sm); }

  /* Loading (v0.4.1). The busy label replaces the button text; the width is reserved by the script before the first click. */
  .btn[aria-busy="true"] { pointer-events: none; }
  .btn__busy { white-space: nowrap; }
  .btn--probe { position: absolute; visibility: hidden; pointer-events: none; }
  .load-error:not([hidden]) { display: block; padding: var(--space-3) var(--space-4); }
  .demo-net { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2) var(--space-4); margin-bottom: var(--space-4); }
  .lazy { display: grid; }
  .lazy .skeleton { opacity: 0; }
  .lazy.is-waiting .skeleton { opacity: 1; transition: opacity var(--duration-fast) var(--easing-out); }
  @media (prefers-reduced-motion: reduce) { .lazy.is-waiting .skeleton { transition: none; } }
}

@layer layout {
  /* Alignment (v0.4.1). Boxes in one row share top and bottom. --equal stretches both columns and lets the main box in
     each grow; --follow lets the left column set the height and the right panel scrolls inside it. */
  .grid-2--equal { align-items: stretch; }
  .grid-2--equal > * { display: flex; flex-direction: column; }
  .grid-2--equal > .stack > :first-child, .grid-2--equal > * > .panel__body, .grid-2--equal > .code > .cm-editor,
  .grid-2--equal > .editor > .doc-preview, .grid-2--equal > * > .panel__body > .preview-box { flex: 1 1 auto; }
  .grid-2--equal > * > .panel__body { display: flex; flex-direction: column; }
  .grid-2--equal .code { display: flex; flex-direction: column; }
  .grid-2--equal .code > .cm-editor { flex: 1 1 auto; }
  .grid-2--grow-last > .stack > :first-child { flex: 0 0 auto; }
  .grid-2--grow-last > .stack > :last-child { flex: 1 1 auto; }
  .grid-2--follow { align-items: stretch; }
  @media (min-width: 768px) {
    .grid-2--follow > :last-child { height: 0; min-height: 100%; display: flex; flex-direction: column; }
    .grid-2--follow > :last-child > .panel__body { flex: 1 1 auto; min-height: 0; overflow: auto; }
  }
}

@layer utilities {
  /* v0.4: .hide-sm used revert, which made header buttons display block and lost vertical centering */
  @media (min-width: 768px) { .btn.hide-sm { display: inline-flex; } }
  /* Forced colors: repaint the current-page and selected-tab bars in the system text color. */
  @media (forced-colors: active) {
    .app-nav a[aria-current="page"]::after, .tab[aria-selected="true"]::after { background: CanvasText; }
  }
}

@layer components {
  /* Two-line rows (v0.4.2). Every row of a list that can show a skeleton holds exactly two text lines, so skeleton
     rows and loaded rows are the same height at every width (57px with the row line). List items in a cell keep to
     one line each; the summary is already clamped to two. */
  .table--two-line { --row-h: calc(2 * var(--leading-sm) + 2 * var(--space-2)); }
  .table--two-line .cell-list li { white-space: nowrap; }
  /* Skeleton table (v0.4.2): the real header row and the real cell classes, one 20px bar per text line, so the
     columns, header height and row height match the loaded table. It never takes hover or selection. */
  .table--skeleton tbody tr:hover, .table--skeleton tbody tr:hover .pin { background: var(--card); }
  .table--skeleton .skeleton--text + .skeleton--text { margin-top: var(--space-2); }
  .table--skeleton .th-sort { cursor: default; }
  .table--skeleton .th-sort:hover { text-decoration: none; }

  /* Top progress line (v0.4.2). One 2px primary line on the top edge of the window for a page level load that no
     single button owns (a list or a block loading). It follows the loading timing: hidden for 300ms, then shown at
     least 600ms, eases toward 90 percent and fills on arrival. Decorative: aria-hidden, the region being loaded has
     aria-busy and the page status region says what is loading. Reduced motion: a still, full line. */
  .top-progress { position: fixed; inset: 0 0 auto; z-index: calc(var(--z-header) + 1); height: var(--border-strong); pointer-events: none; opacity: 0; transition: opacity var(--duration-base) var(--easing-out); }
  .top-progress.is-active { opacity: 1; }
  .top-progress__bar { display: block; height: 100%; background: var(--primary); transform-origin: left center; transform: scaleX(0); transition: transform var(--duration-slow) var(--easing-out); }
  /* Logo loader (v0.4.2): while the top line shows, the product mark in the header breathes. Reduced motion: still. */
  .app-header.is-loading .app-mark__tile { animation: pulse var(--duration-pulse) var(--easing-in-out) infinite; }
  @media (prefers-reduced-motion: reduce) {
    .top-progress, .top-progress__bar { transition: none; }
    .app-header.is-loading .app-mark__tile { animation: none; }
  }
  @media (forced-colors: active) { .top-progress__bar { background: Highlight; } }

  /* Breadcrumbs (v0.4.2). Deeper pages only (help, templates, docs, a dataset); never in the editor. It takes the
     eyebrow's place above the page title, so the header keeps its height. */
  .breadcrumbs ol { display: flex; flex-wrap: wrap; align-items: center; gap: 0 var(--space-2); font-size: var(--text-sm); line-height: var(--leading-sm); color: var(--muted-foreground); }
  .breadcrumbs li { display: inline-flex; align-items: center; gap: var(--space-2); min-height: var(--size-target-min); }
  .breadcrumbs li + li::before { content: "/" / ""; color: var(--subtle-foreground); }
  .breadcrumbs a { display: inline-flex; align-items: center; min-height: var(--size-target-min); color: var(--muted-foreground); text-decoration: none; }
  .breadcrumbs a:hover { color: var(--foreground); text-decoration: underline; text-underline-offset: 0.2em; }
  .breadcrumbs [aria-current="page"] { color: var(--foreground); font-weight: var(--font-weight-medium); }
  .page-header .breadcrumbs { margin-bottom: var(--space-1); }
  @media (pointer: coarse) { .breadcrumbs li, .breadcrumbs a { min-height: var(--size-target-touch); } }

  /* Blank document (v0.4.2). When the open file has no text, an inline EmptyState sits under the first line with one
     action, Start from a template. Typing hides it. */
  .doc-empty { max-width: var(--size-prose-max); margin-inline: auto; padding: 0 var(--space-4) var(--space-12); }
  @media (min-width: 768px) { .doc-empty { padding-inline: var(--space-8); } }
  .doc-empty > .state { padding: 0; }
  .doc-preview.is-blank > .ProseMirror { padding-bottom: var(--space-4); }
}

@layer components {
  /* ---------- v0.4.2 (Testingralph v0.4.1 review, FIX 68/78) ---------- */
  /* MF14: our own product marks. A 24px tile in the foreground ink with the mark knocked out in the page color. */
  .app-mark__tile { display: inline-grid; place-items: center; flex: none; width: var(--size-target-min); height: var(--size-target-min); border-radius: var(--radius-md); background: var(--foreground); color: var(--background); }
  .app-mark__glyph { width: var(--size-icon-sm); height: var(--size-icon-sm); }

  /* MF15 (v0.4.2) gave panels a resting --shadow-1. v0.4.3 (Testingralph v0.4.2 SF-B) takes it out again: panels are
     flat with a hairline (spec G7, R1, T2); shadows are only for floating layers (menus, popovers, dialogs, toasts). */
  /* Quieter chrome: the header has no rule; its glass and the page color separate it. A rule fades in once the page scrolls under it. */
  .app-header { --_header-rule: transparent; transition: box-shadow var(--duration-fast) var(--easing-out); }
  html.is-scrolled .app-header { --_header-rule: var(--border); }

  /* MF1: editor frames are control edges, 3:1 or more on card and page. */
  .code:has(.cm-editor) { border-color: var(--input); }

  /* MF13: a file button is a label around a hidden input; it shows the ring when its input has keyboard focus. */
  .btn:has(> input:focus-visible) { outline: var(--focus-width) solid var(--ring); outline-offset: var(--focus-offset); }

  /* MF4, MF5: the drop zone is a full width row at 768px and up (icon, words, actions), so it never sits beside a box
     of another height. Icon and actions center on the 44px of title and hint: (44 - 20) / 2 and (44 - 32) / 2, whole pixels. */
  @media (min-width: 768px) {
    .dropzone--row { grid-template-columns: auto minmax(0, 1fr) auto; grid-template-rows: auto auto; column-gap: var(--space-4); row-gap: 0; align-items: start; padding: var(--space-6); }
    .dropzone--row > .dropzone__icon { grid-row: 1 / span 2; align-self: center; }
    .dropzone--row > .dropzone__title { grid-column: 2; }
    .dropzone--row > .dropzone__hint { grid-column: 2; }
    .dropzone--row > .cluster { grid-column: 3; grid-row: 1 / span 2; align-self: center; flex-wrap: nowrap; }
  }
  /* One panel holds the summary and the table it summarizes; the toolbar line separates them. */
  .panel > .panel__body + .toolbar, .panel > .panel__body + .table-wrap { border-top: var(--border-hairline) solid var(--border); }

  /* MF7: job and loading bodies use the same 24px padding as the states beside them. */
  .panel__body--state { padding: var(--space-6); }

  /* MF6: the statement and its preview live in one panel. The form sets the height; the statement column is sized to
     its text and stays in view while you scroll the form. */
  .statement { display: grid; align-content: start; } /* v0.4.3: when data-snap4 adds up to 3 px, it goes under the rows, not half into each row */
  .statement__form { padding: var(--space-4); border-bottom: var(--border-hairline) solid var(--border); }
  .statement__out { display: grid; gap: var(--space-3); align-content: start; padding: var(--space-4); }
  .statement__head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); }
  @media (min-width: 768px) {
    .statement { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); align-items: start; }
    .statement__form { border-bottom: 0; border-right: var(--border-hairline) solid var(--border); }
    .statement__out { position: sticky; top: calc(var(--size-header) + var(--space-4)); }
  }

  /* SF2: a lazy region that failed keeps the height it had (locked by the script), and its error sits at the top. */
  .lazy.is-failed > [data-lazy-slot] { align-self: start; }
}

@layer components {
  /* v0.4.2 (SF2, MF3): a lazy chart and its skeleton take a whole number of 4px steps of height for their width, so
     the box, its skeleton and its error are the same size and every edge below lands on a whole pixel. */
  .lazy .chart { container-type: inline-size; }
  .lazy .chart > svg, .lazy .skeleton.skeleton--chart-bar { height: round(down, calc(100cqi * 150 / 560), var(--space-1)); aspect-ratio: auto; }
}

@layer components {
  /* v0.4.2: a file row spans its list like the drop zone above it (li elements otherwise keep to the 75 character measure). */
  .file-list > .file-item { max-width: none; }
  /* MF6: a job or loading card is a state with a bar: the same 24px padding and 8px steps, so it is no taller than the states beside it. */
  .panel__body--state.stack > * + * { margin-top: var(--space-2); }
  .panel__body--state.stack > .cluster { margin-top: var(--space-4); }
}

@layer components {
  /* v0.4.2 (MF3): static charts take a whole number of 4px steps of height for their width (the two viewBox shapes the
     reference uses), so nothing below a chart lands on a half pixel. The drawing keeps its aspect and centers in the box. */
  .chart { container-type: inline-size; }
  .chart > svg[viewBox="0 0 560 150"] { height: round(down, calc(100cqi * 150 / 560), var(--space-1)); }
  .chart > svg[viewBox="0 0 560 72"] { height: round(down, calc(100cqi * 72 / 560), var(--space-1)); }
  /* The last problem in a pane has no bottom rule; the status bar line closes the pane (no doubled line). */
  .workspace__pane > .problems > .problem:last-child { border-bottom: 0; }
}

@layer utilities {
  /* v0.4.2 (MF3): .hide-sm reverted a flex group to block at 768px and up, which made the editor toolbar 29px and put
     every control on a half pixel (#blk at y.5). Groups stay flex. */
  @media (min-width: 768px) { .editor__group.hide-sm { display: flex; } }
  /* A Not stated button inside running text sits on the top of its 24px line, not the middle (no 0.77px taller lines). */
  p > button.not-stated, li > button.not-stated { vertical-align: top; }
}
@layer components {
  /* v0.4.2: key combinations stay on one line, so stacked keys never put two borders 1px apart at 375px. */
  .table th:has(> .kbd) { white-space: nowrap; }
}

@layer components {
  /* v0.4.2 (SF2): a lazy region's error sits inside the panel body, which already has the padding, and its sentence fits
     one line at 375px, so the error (icon, title, sentence, Retry: 128px) fits the smallest skeleton box (136px) and
     nothing below it moves at any width. */
  .lazy.is-failed .state--inline { padding: 0; }
}

@layer components {
  /* v0.4.2: the verdict is a p, so it took the 75 character measure; at 1280 the meta then sat beside it and the
     warning count wrapped alone. The verdict line spans the summary, and the meta and counts share the next line. */
  .result-summary > .result-summary__verdict { max-width: none; }
}

@layer components {
  /* v0.4.2 (MF6): the statement column was half empty under its text. Now the panel is one two column grid: tool,
     uses and parts on the left; checker and the statement on the right. Each column stacks on its own (no shared row
     to leave a gap under the shorter field), and neither column has a blank band. The statement keeps its measure. DOM, reading and tab order are unchanged. */
  @media (min-width: 768px) {
    .statement { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); grid-template-rows: auto 1fr; grid-auto-flow: row; gap: var(--space-4) var(--space-6); padding: var(--space-4); align-items: start; }
    .statement__form { display: contents; }
    .statement__form > .statement__col:first-child { grid-column: 1; grid-row: 1 / span 2; }
    .statement__form > .statement__col:last-child { grid-column: 2; grid-row: 1; }
    .statement__form.stack > * + * { margin-top: 0; }
    .statement__out { grid-column: 2; grid-row: 2; position: static; padding: 0; }
  }
}
@layer components {
  /* v0.4.2: the FSH problem list is full width now (the health #states row is one stack), so a long message capped to
     the reading measure, like other text; the line number stays at the right edge of the row. */
  .problem__msg { max-width: var(--size-measure); }
}
@layer components {
  /* v0.4.2 app feedback (Buildralph). */
  /* Breadcrumbs: no browser list indent or bullets, so the trail starts on the page edge like the h1 under it. */
  .breadcrumbs ol { margin: 0; padding: 0; list-style: none; }
  /* Keycaps on whole pixels in any mono font: the width is the text in ch plus padding and border, rounded up to a
     4px step and the text centered. One character by default; .kbd--2, .kbd--3, .kbd--4 for longer keys (Esc is 3,
     Ctrl is 4). Browsers without round() keep the content width with a 20px minimum. */
  .kbd { --_n: 1; justify-content: center; min-width: var(--space-5); white-space: nowrap;
    width: round(up, calc(var(--_n) * 1ch + 2 * var(--space-1) + 2 * var(--border-hairline)), var(--space-1)); }
  .kbd--2 { --_n: 2; }
  .kbd--3 { --_n: 3; }
  .kbd--4 { --_n: 4; }
  /* v0.4.3: .kbd--5 for five character keys (Enter, Shift). 48px in Geist Mono. */
  .kbd--5 { --_n: 5; }
  /* Blank editor: the empty line and the EmptyState under it are one unit. The focus ring goes round the whole
     document area, never as a thin box round the empty line above the state. */
  .doc-preview.is-blank > .ProseMirror:focus-visible { outline: none; }
  .doc-preview.is-blank:has(> .ProseMirror:focus-visible) { outline: var(--focus-width) solid var(--ring); outline-offset: calc(-1 * var(--focus-width)); }
}

@layer components {
  /* ---------- v0.4.3 (Paperralph v0.4.2 click test, Testingralph v0.4.2 review) ---------- */
  /* Ghost skeleton (SF3): the loaded rows sit under the bars with their text hidden, so columns and rows match the
     loaded table exactly. Scoped to .table--ghost so plain skeleton tables keep their bars. Rows after the visible ones only size the columns. */
  /* v0.4.3 (Testingralph v0.4.3 nit): the cell text sits in .skel-src and is visibility hidden, so it cannot be
     selected or found with find in page, and axe no longer meets transparent text. */
  .table--ghost { user-select: none; }
  .table--ghost tbody :is(th, td):not(.pin) { position: relative; }
  .table--ghost tbody :is(th, td) > :not(.skel-cell) { visibility: hidden; }
  .table--ghost .skel-cell { position: absolute; inset: var(--space-2) var(--space-3); }
  .table--ghost tr.skel-ghost { visibility: collapse; }
  /* .zip menu item (Paperralph v0.4.3 must-fix): a second line names the blank files left out. The two lines are
     20px and 16px with a 4px pad above and below, so the item is 44px tall, on the 4px grid. */
  .menu__text { display: grid; }
  .menu__sub { font-size: var(--text-xs); line-height: var(--leading-xs); color: var(--muted-foreground); }
  .menu__item:has(.menu__sub:not([hidden])) { padding-block: var(--space-1); }
  /* Cancel stands in the busy button's slot at the same size (SF2); its width comes from the busy button. */
  .btn--cancel { justify-content: center; }
  /* v0.4.3 (Paperralph v0.4.3 nit 2): the busy label is visible beside the spinner, muted, and Cancel follows after a
     hairline divider. The resting button already reserves this width (lock in 15-lazy.js), so nothing moves. */
  .btn--cancel .btn__busy { color: var(--muted-foreground); font-weight: var(--font-weight-regular); }
  .btn__stop { padding-inline-start: var(--space-2); border-inline-start: var(--border-hairline) solid var(--border); }
  /* Builder panel headers (MF-A): the two panels side by side have the same header height, a control plus the
     header padding and rule (57px from 768px, 69px below), so their bottom rules line up. */
  [data-builder] .grid-2 .panel > .panel__header { min-block-size: calc(var(--control-h) + 2 * var(--space-3) + var(--border-hairline)); }
  /* Blank file (MF-B and the blank editor nit): the editor's status region is always in the page and takes no room
     while it is empty; the Preview shows its own empty state. */
  .doc-empty:empty { padding: 0; }
  .preview-empty > .state { padding: 0; }
  /* v0.4.3 (Testingralph v0.4.3 nit): while Preview shows its empty state the panel keeps its content height instead
     of stretching to the step panel, so no tall empty card is left under the state. Its top and header still line up. */
  .grid-2--follow > .panel:has([data-preview-empty]:not([hidden])) { align-self: start; height: auto; min-height: 0; }
  /* Dataset rows (SF-D): a "Not stated" button in a summary row keeps its 24px target but takes only the 20px line,
     so the row is the same height as the others and its text sits on the label's baseline. */
  .summary-list dd > button.not-stated { vertical-align: baseline; margin-block: calc((var(--leading-sm) - var(--size-target-min)) / 2); }
  /* Segmented control frame (nit): a control edge, so --input (3:1 or more on card and page), like the editor frame. */
  .seg { border-color: var(--input); }
  /* Text selection (nit): the primary fill with its own foreground, 3:1 or more against the page in both themes.
     --selection stays for target lines in code blocks. */
  ::selection { background: var(--primary); color: var(--primary-foreground); }
  /* Top progress line: eases toward 90 percent while waiting, fills on arrival. */
  .top-progress.is-active .top-progress__bar { transform: scaleX(.9); transition-duration: calc(5 * var(--duration-pulse)); }
  .top-progress.is-done .top-progress__bar { transform: scaleX(1); transition-duration: var(--duration-fast); }
  /* Reduced motion (Testingralph v0.4.3 nit): no growth, so a still line must not read as done. While loading it is a
     dashed line (8px on, 8px off) across the width; it turns solid only for the short done state. */
  @media (prefers-reduced-motion: reduce) {
    .top-progress.is-active .top-progress__bar { transform: scaleX(1); background: repeating-linear-gradient(90deg, var(--primary) 0 var(--space-2), transparent var(--space-2) var(--space-4)); }
    .top-progress.is-done .top-progress__bar { background: var(--primary); }
  }
}
/* v0.4.3 round 3 (Testingralph r2 SF-1, SF-2, N3; Paperralph r2 nits) */
@layer components {
  /* Toast kinds: the icon carries the kind in its status color. Success (circle-check, --success), warning for an
     action that did nothing (circle-alert, --warning) and error (octagon-alert, --destructive). */
  .toast > .icon.status--success { color: var(--success); }
  .toast > .icon.status--warning { color: var(--warning); }
  .toast > .icon.status--error { color: var(--destructive); }
  /* Busy note: the visible busy label, outside the button flow, so the busy button keeps its resting size. */
  .busy-note { color: var(--muted-foreground); font-size: var(--text-sm); line-height: var(--leading-sm); white-space: nowrap; pointer-events: none; }
  [data-busy-note="side"] { position: relative; }
  .busy-note--side { position: absolute; inset-inline-end: calc(100% + var(--space-2)); inset-block-start: 50%; transform: translateY(-50%); text-align: end; }
  /* v0.4.3 round 4 (Testingralph r3 SF-B): the labels are short enough for one line at 375 ("Making Word..." 90 px in 103 px);
     below that (320) every label wraps the same way and keeps the same size as the one line note. */
  .busy-note--wrap { white-space: normal; inline-size: min-content; }
  [data-busy-status].is-busy-host { position: relative; visibility: hidden; }
  .busy-note--status { position: absolute; inset-inline-start: 0; inset-block-start: 0; visibility: visible; font-size: inherit; line-height: inherit; }
  .busy-note--after { align-self: center; }
  /* Cancel on a primary button: the spinner arc takes the button text color, as on the busy button itself. */
  .btn--primary.btn--cancel .spinner { color: currentColor; }
  /* Zip note: no single word left on its own line. */
  .menu__sub { text-wrap: pretty; }
}
@layer components {
  /* Snapped card grid (policy states): the grid box takes the 4px step, the cards keep their own height. */
  .grid-cards[data-snap4] { align-content: start; }
}
@layer components {
  /* v0.4.3 round 5 (Testingralph v0.4.3 round 4 SF-2): a state card's outer height is a multiple of 4 px on every page.
     Its content is built from 4 px steps (24 px padding, 20 and 24 px lines, 20 px icon with a 4 px gap, 36 px
     buttons), and the 1 px border on each side made every card 2 px off (182, 190, 202, 214, 238). One more hairline
     of padding at the top and bottom puts the outer box back on the grid (184, 192, 204, 216, 240), on every page and
     in the apps, with no script. .grid-cards keeps grid-auto-rows: 1fr, so the cards of a grid share that height. */
  .panel:has(> .state, > .panel__body--state) { padding-block: var(--border-hairline); }
  /* Round 5 nit b: a progress card carries a status icon in the same slot as the other state cards, so the titles
     of cards side by side start at the same height. */
  .panel__body--state > .icon:first-child { display: block; width: var(--size-icon-md); height: var(--size-icon-md); color: var(--muted-foreground); }
  .panel__body--state.stack > .icon:first-child + * { margin-top: calc(var(--space-1) + var(--space-2)); }
  /* Round 5 nit a: a section, main or heading that takes focus from script after a same-page jump (tabindex -1, not a
     control) shows no ring; the jump itself shows where you are. Controls keep their :focus-visible ring. */
  :is(main, section, article, aside, form, div, h1, h2, h3, h4, h5, h6)[tabindex="-1"]:not([role]):focus { outline: none; }
}
