/* ===== components/components.css ===== */
/* Prism · component style manifest (imported by root styles.css) */
/* ===== components/core/core.css ===== */
/* ============================================================
   Prism · Core component styles
   Button · IconButton · Badge · Tag · Avatar · Card · Spinner
   States (hover / focus-visible / active / disabled) are all
   explicit and high-contrast — this is a deliberate Prism rule.
   ============================================================ */

/* ---------------- Button ---------------- */
.prism-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  font-family: var(--label-font);
  font-weight: var(--weight-semibold);
  font-size: var(--text-sm);
  line-height: 1;
  white-space: nowrap;
  text-decoration: none; /* LinkButton renders it on an <a> */
  border: var(--border-width) solid transparent;
  border-radius: var(--radius-control);
  height: var(--control-height);
  padding-inline: var(--pad-control-x);
  min-width: var(--size-touch);
  cursor: pointer;
  user-select: none;
  transition: var(--transition-colors), transform var(--duration-instant) var(--ease-standard);
}
.prism-btn:focus-visible {
  outline: var(--focus-ring-width) solid var(--focus-ring);
  outline-offset: var(--focus-ring-offset-width);
}
.prism-btn:active { transform: translateY(0.5px) scale(0.985); }
/* Subtle 3D: filled buttons get a sheen + beveled edge; press pushes in */
.prism-btn:not([data-variant="quiet"]) { background-image: var(--sheen); box-shadow: var(--bevel), var(--shadow-xs); }
.prism-btn:not([data-variant="quiet"]):hover:not([disabled]) { box-shadow: var(--bevel), var(--shadow-sm); }
.prism-btn:not([data-variant="quiet"]):active:not([disabled]) { background-image: none; box-shadow: var(--press); }
.prism-btn[disabled],
.prism-btn[aria-disabled="true"] {
  cursor: not-allowed;
  opacity: 0.45;
  transform: none;
}
.prism-btn > svg { width: var(--icon-sm); height: var(--icon-sm); flex: none; }

/* sizes */
.prism-btn[data-size="sm"] { height: var(--control-sm); font-size: var(--text-xs); padding-inline: var(--space-3); }
.prism-btn[data-size="lg"] { height: var(--control-lg); font-size: var(--text-base); padding-inline: var(--space-5); }
.prism-btn[data-size="xl"] { height: var(--control-xl); font-size: var(--text-lg); padding-inline: var(--space-6); }

/* variants — accent (primary) */
.prism-btn[data-variant="accent"] { background: var(--accent); color: var(--accent-on); }
.prism-btn[data-variant="accent"]:hover:not([disabled]) { background: var(--accent-hover); }
.prism-btn[data-variant="accent"]:active:not([disabled]) { background: var(--accent-active); }

/* neutral (secondary, bordered) */
.prism-btn[data-variant="neutral"] { background: var(--surface-card); color: var(--text-primary); border-color: var(--border-strong); }
.prism-btn[data-variant="neutral"]:hover:not([disabled]) { background: var(--fill-subtle); border-color: var(--gray-400); }
.prism-btn[data-variant="neutral"]:active:not([disabled]) { background: var(--fill-subtle-hover); }

/* quiet (ghost) */
.prism-btn[data-variant="quiet"] { background: transparent; color: var(--text-primary); }
.prism-btn[data-variant="quiet"]:hover:not([disabled]) { background: var(--fill-subtle); }
.prism-btn[data-variant="quiet"]:active:not([disabled]) { background: var(--fill-subtle-hover); }

/* negative (destructive) */
.prism-btn[data-variant="negative"] { background: var(--negative); color: var(--negative-on); }
.prism-btn[data-variant="negative"]:hover:not([disabled]) { background: var(--negative-hover); }

/* outline-accent */
.prism-btn[data-variant="outline"] { background: transparent; color: var(--accent-text); border-color: var(--accent-border); }
.prism-btn[data-variant="outline"]:hover:not([disabled]) { background: var(--accent-subtle); }

/* prompt — an opener that looks like the field it opens ("What's on your
   mind?"): full width, start-aligned, input surface, muted sentence-case text,
   no button sheen. */
.prism-btn[data-variant="prompt"] {
  inline-size: 100%; justify-content: flex-start; text-align: start;
  font-family: var(--body-font); font-size: var(--text-base); font-weight: var(--weight-regular);
  background: var(--surface-card); background-image: none; color: var(--text-tertiary);
  border-color: var(--border-strong); box-shadow: none;
}
.prism-btn[data-variant="prompt"]:hover:not([disabled]) { background: var(--fill-subtle); border-color: var(--border-strong); box-shadow: none; color: var(--text-secondary); }
.prism-btn[data-variant="prompt"]:active:not([disabled]) { transform: none; box-shadow: none; }
.prism-btn[data-variant="prompt"] > span { overflow: hidden; text-overflow: ellipsis; }

/* negative-outline — a destructive action that isn't the final step (it opens
   the confirmation; the filled `negative` is kept for the confirm itself) */
.prism-btn[data-variant="negative-outline"] { background: transparent; color: var(--negative-text); border-color: var(--negative-border); }
.prism-btn[data-variant="negative-outline"]:hover:not([disabled]) { background: var(--negative-subtle); }

/* semantic fills — confirm / caution (destructive `negative` is above) */
.prism-btn[data-variant="positive"] { background: var(--positive); color: var(--positive-on); }
.prism-btn[data-variant="positive"]:hover:not([disabled]) { background: color-mix(in oklch, var(--positive) 90%, black); }
.prism-btn[data-variant="notice"] { background: var(--notice); color: var(--notice-on); }
.prism-btn[data-variant="notice"]:hover:not([disabled]) { background: color-mix(in oklch, var(--notice) 90%, black); }

.prism-btn[data-full="true"] { width: 100%; }
/* isTruncated: the button can shrink below its label, which ellipsises */
.prism-btn[data-truncate="true"] { max-inline-size: 100%; min-inline-size: 0; justify-content: flex-start; }
.prism-btn[data-truncate="true"] > span:not(.prism-btn-spinner) { min-inline-size: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* in-button spinner (isLoading) — inherits the label colour */
.prism-btn-spinner {
  width: var(--icon-sm); height: var(--icon-sm); flex: none;
  border-radius: 50%; border: 2px solid currentColor; border-top-color: transparent;
  opacity: 0.9; animation: prism-spin 0.7s linear infinite;
}
.prism-btn[data-size="lg"] .prism-btn-spinner,
.prism-btn[data-size="xl"] .prism-btn-spinner { width: var(--icon-md); height: var(--icon-md); }

/* ---------------- ButtonGroup (segmented) ---------------- */
.prism-btn-group { display: inline-flex; }
.prism-btn-group[data-orientation="vertical"] { flex-direction: column; }
.prism-btn-group > .prism-btn,
.prism-btn-group > .prism-icon-btn { border-radius: 0; box-shadow: none; background-image: none; position: relative; }
.prism-btn-group[data-orientation="horizontal"] > :not(:first-child) { margin-inline-start: calc(var(--border-width) * -1); }
.prism-btn-group[data-orientation="vertical"]   > :not(:first-child) { margin-block-start: calc(var(--border-width) * -1); }
.prism-btn-group[data-orientation="horizontal"] > :first-child { border-start-start-radius: var(--radius-control); border-end-start-radius: var(--radius-control); }
.prism-btn-group[data-orientation="horizontal"] > :last-child  { border-start-end-radius: var(--radius-control); border-end-end-radius: var(--radius-control); }
.prism-btn-group[data-orientation="vertical"]   > :first-child { border-start-start-radius: var(--radius-control); border-start-end-radius: var(--radius-control); }
.prism-btn-group[data-orientation="vertical"]   > :last-child  { border-end-start-radius: var(--radius-control); border-end-end-radius: var(--radius-control); }
/* active segment (toggle / pagination) reads from ARIA, not a variant */
.prism-btn-group > .prism-btn[aria-pressed="true"],
.prism-btn-group > .prism-btn[aria-current="page"] { background: var(--accent-subtle); color: var(--accent-text); border-color: var(--accent-border); z-index: 1; }
.prism-btn-group > :focus-visible { z-index: 2; }

/* ---------------- IconButton ---------------- */
.prism-icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--control-height);
  height: var(--control-height);
  border-radius: var(--radius-control);
  border: var(--border-width) solid transparent;
  background: transparent;
  color: var(--text-secondary);
  cursor: pointer;
  transition: var(--transition-colors), transform var(--duration-instant) var(--ease-standard);
}
.prism-icon-btn:hover:not([disabled]) { background: var(--fill-subtle); color: var(--text-primary); }
.prism-icon-btn:active:not([disabled]) { background: var(--fill-subtle-hover); transform: scale(0.94); }
.prism-icon-btn:focus-visible { outline: var(--focus-ring-width) solid var(--focus-ring); outline-offset: var(--focus-ring-offset-width); }
.prism-icon-btn[disabled] { opacity: 0.45; cursor: not-allowed; }
.prism-icon-btn[data-size="sm"] { width: var(--control-sm); height: var(--control-sm); }
.prism-icon-btn[data-size="lg"] { width: var(--control-lg); height: var(--control-lg); }
.prism-icon-btn[data-variant="accent"] { background: var(--accent); color: var(--accent-on); }
.prism-icon-btn[data-variant="accent"]:hover:not([disabled]) { background: var(--accent-hover); color: var(--accent-on); }
/* Destructive icon buttons, so delete/remove never look harmless:
   negative-quiet (red icon, no fill — rows of "remove" buttons) and
   negative (red fill — the one destructive action in a toolbar). */
.prism-icon-btn[data-variant="negative-quiet"] { color: var(--negative-text); }
.prism-icon-btn[data-variant="negative-quiet"]:hover:not([disabled]) { background: var(--negative-subtle); color: var(--negative-text); }
.prism-icon-btn[data-variant="negative-quiet"]:active:not([disabled]) { background: var(--negative-subtle); }
.prism-icon-btn[data-variant="negative"] { background: var(--negative); color: var(--negative-on); background-image: var(--sheen); box-shadow: var(--bevel), var(--shadow-xs); }
.prism-icon-btn[data-variant="negative"]:hover:not([disabled]) { background-color: var(--negative-hover); color: var(--negative-on); }
.prism-icon-btn[data-variant="negative"]:active:not([disabled]) { background-image: none; box-shadow: var(--press); }
.prism-icon-btn > svg { width: var(--icon-md); height: var(--icon-md); }
.prism-icon-btn[data-variant="accent"] { background-image: var(--sheen); box-shadow: var(--bevel), var(--shadow-xs); }

/* ---------- Action bar — full-bleed footer of equal-width buttons ----------
   Drop as the LAST child of a card or dialog: it bleeds to the container edges
   (cancelling the container's padding via --actionbar-inset, default
   --pad-card), splits the width evenly, and divides the buttons with a
   hairline. The primary action keeps its accent fill; buttons go edge-to-edge
   and flat-cornered, rounding only into the container's bottom corners.
   Override --actionbar-inset on the bar if the container's padding differs. */
.prism-actionbar {
  /* follows the card's published padding by default (so an override of
     --card-pad propagates); set --actionbar-inset explicitly for non-card
     containers (e.g. a dialog) whose padding differs. */
  --actionbar-inset: var(--card-pad, var(--pad-card));
  display: flex;
  align-items: stretch;
  margin: var(--actionbar-inset) calc(-1 * var(--actionbar-inset)) calc(-1 * var(--actionbar-inset));
  border-block-start: var(--border-width) solid var(--border-default);
  border-end-start-radius: inherit;
  border-end-end-radius: inherit;
  overflow: hidden;
}
/* NB: children are an EQUAL split (flex: 1 1 0) and .prism-btn does not shrink or
   wrap — every label must fit half the card (a third for three buttons), or it
   overflows. min-inline-size:0 does NOT rescue it: the binding constraint is the
   button's intrinsic width. Use short, verb-first labels; for a long explanation
   use .prism-cardfoot with its note slot instead. */
.prism-actionbar > * { flex: 1 1 0; min-inline-size: 0; }
.prism-actionbar > * + * { border-inline-start: var(--border-width) solid var(--border-default); }
.prism-actionbar :is(.prism-btn, button, a) {
  inline-size: 100%;
  min-block-size: var(--control-lg);
  padding-inline: var(--space-4);
  border: 0;
  border-radius: 0;
  justify-content: center;
}

/* ---------- Card footer — the INSET action row (context: on-page dialogs) ----------
   Companion to .prism-actionbar; the two are chosen by CONTEXT, not container:

     • .prism-actionbar — a FLUSH edge-to-edge bar that TERMINATES a contained
       surface (a modal, or a card that is the whole surface). The bar is where
       the surface ends and there is nothing beyond it.
     • .prism-cardfoot   — an INSET footer for a card sitting IN PAGE FLOW (an
       "on-page dialog": sign-in, KYC, settings). Buttons at their natural width,
       right-aligned, padded off the card edge, so the footer reads as PART of the
       card rather than the card's edge.

   data-rule="true" adds a full-bleed top divider — the rule spans the card while
   the buttons stay inset, which is what makes it read as a footer rather than a
   loose row of buttons. Buttons WRAP instead of clipping long / localised labels.
   A leading .prism-cardfoot-note is pushed to the opposite side as a caption slot
   (e.g. a short button captioned "Opens DigiLocker in a new tab."). */
.prism-cardfoot {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  align-items: center;
  gap: var(--gap-inline);
  padding-block-start: var(--space-5);
}
.prism-cardfoot[data-rule="true"] {
  /* cancel the card's OWN padding (published as --card-pad), so the divider goes
     edge-to-edge whatever padding the card uses; --pad-card is the fallback when
     the footer isn't inside a .prism-card. */
  margin-inline: calc(-1 * var(--card-pad, var(--pad-card)));
  padding-inline: var(--card-pad, var(--pad-card));
  border-block-start: var(--border-width) solid var(--border-default);
}
.prism-cardfoot-note {
  flex: 0 1 auto;
  margin-inline-end: auto;
  font-size: var(--fs-caption);
  color: var(--text-secondary);
}
.prism-icon-btn[data-variant="accent"]:active:not([disabled]) { background-image: none; box-shadow: var(--press); }
.prism-icon-btn[data-shape="round"] { border-radius: var(--radius-pill); }

/* ---------------- Fab (floating action button) ---------------- */
.prism-fab {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--space-2);
  height: 56px; min-width: 56px; padding: 0; flex: none;
  border: var(--border-width) solid transparent; border-radius: var(--radius-pill);
  font-family: var(--label-font); font-weight: var(--weight-semibold); font-size: var(--text-sm); white-space: nowrap;
  background: var(--accent); color: var(--accent-on); background-image: var(--sheen);
  box-shadow: var(--bevel), var(--shadow-lg); cursor: pointer; user-select: none;
  transition: var(--transition-colors), transform var(--duration-instant) var(--ease-standard), box-shadow var(--duration-fast) var(--ease-standard);
}
.prism-fab > svg { width: var(--icon-md); height: var(--icon-md); flex: none; }
.prism-fab[data-extended="true"] { padding-inline: var(--space-5); }
.prism-fab[data-size="sm"] { height: 44px; min-width: 44px; }
.prism-fab[data-size="sm"] > svg { width: var(--icon-sm); height: var(--icon-sm); }
.prism-fab[data-size="lg"] { height: 64px; min-width: 64px; }
.prism-fab[data-size="lg"] > svg { width: var(--icon-lg); height: var(--icon-lg); }
.prism-fab:hover:not([disabled]) { background: var(--accent-hover); box-shadow: var(--bevel), var(--shadow-xl, var(--shadow-lg)); }
.prism-fab:active:not([disabled]) { background: var(--accent-active); background-image: none; transform: translateY(0.5px) scale(0.97); box-shadow: var(--press); }
.prism-fab:focus-visible { outline: var(--focus-ring-width) solid var(--focus-ring); outline-offset: var(--focus-ring-offset-width); }
.prism-fab[disabled] { opacity: 0.45; cursor: not-allowed; }
.prism-fab[data-variant="neutral"] { background: var(--surface-card); color: var(--text-primary); border-color: var(--border-strong); }
.prism-fab[data-variant="neutral"]:hover:not([disabled]) { background: var(--fill-subtle); }
.prism-fab[data-variant="positive"] { background: var(--positive); color: var(--positive-on); }
.prism-fab[data-variant="negative"] { background: var(--negative); color: var(--negative-on); }

/* ---------------- NavButton (toolbar / tab-bar destination) ---------------- */
.prism-navbtn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--space-1);
  border: 0; background: transparent; cursor: pointer; user-select: none; position: relative;
  color: var(--text-secondary); font-family: var(--label-font); font-weight: var(--weight-medium);
  border-radius: var(--radius-md); padding: var(--space-2) var(--space-3);
  transition: var(--transition-colors);
}
.prism-navbtn[data-orientation="vertical"] { flex-direction: column; min-width: 64px; font-size: var(--text-xs); }
.prism-navbtn[data-orientation="horizontal"] { flex-direction: row; gap: var(--space-3); font-size: var(--text-sm); justify-content: flex-start; min-height: var(--size-touch); }
.prism-navbtn-icon { position: relative; display: inline-flex; }
.prism-navbtn-icon > svg { width: var(--icon-md); height: var(--icon-md); display: block; }
.prism-navbtn-label { line-height: 1; }
.prism-navbtn:hover { color: var(--text-primary); background: var(--fill-subtle); }
.prism-navbtn:focus-visible { outline: var(--focus-ring-width) solid var(--focus-ring); outline-offset: var(--focus-ring-offset-width); }
.prism-navbtn[data-active="true"] { color: var(--accent-text); }
.prism-navbtn[data-active="true"] .prism-navbtn-icon > svg { color: var(--accent); }
.prism-navbtn[data-active="true"][data-orientation="horizontal"] { background: var(--accent-subtle); }
.prism-navbtn-badge {
  position: absolute; inset-block-start: -5px; inset-inline-end: -7px;
  min-width: 16px; height: 16px; padding: 0 var(--space-1); border-radius: var(--radius-pill);
  background: var(--negative); color: var(--negative-on);
  font-size: var(--fs-caption); font-weight: var(--weight-bold); line-height: 16px; text-align: center;
  box-shadow: 0 0 0 2px var(--surface-card);
}
.prism-navbtn-badge[data-dot="true"] { min-width: 9px; width: 9px; height: 9px; padding: 0; inset-block-start: -2px; inset-inline-end: -3px; }

/* ---------------- Badge ---------------- */
.prism-badge {
  display: inline-flex;
  /* Never wider than its content: as a stretch flex/grid item (a column card
     body, a sidebar cell) it would otherwise fill the line. A definite inline
     size also cancels align-items:stretch. fit-content still clamps to the
     container, so a long label can't overflow. */
  inline-size: fit-content;
  align-items: center;
  gap: var(--space-1);
  font-family: var(--label-font);
  font-weight: var(--weight-medium);
  font-size: var(--text-xs);
  /* A long label wraps between its words inside the badge; a word never
     splits ("WAL" / "K IN"), so in a table the badge's longest word sets the
     column's minimum. Line-height 1.2 keeps wrapped lines legible; the extra
     0.2em comes back out of the vertical padding, so a one-line badge is
     exactly as tall as before. */
  line-height: 1.2;
  max-inline-size: 100%;
  overflow-wrap: normal; word-break: keep-all;
  padding: calc(var(--space-1) - 0.1em) var(--space-2);
  border-radius: var(--radius-sm);
  border: var(--border-width) solid transparent;
}
.prism-badge > svg { width: var(--icon-xs); height: var(--icon-xs); flex: none; }
/* leading status dot (Helios-style) */
.prism-badge-dot { width: 7px; height: 7px; border-radius: 50%; background: currentColor; flex: none; }
.prism-badge[data-tone="neutral"]  { background: var(--fill-subtle);     color: var(--text-secondary); border-color: var(--border-default); }
.prism-badge[data-tone="accent"]   { background: var(--accent-subtle);   color: var(--accent-text);   border-color: var(--accent-border);   }
.prism-badge[data-tone="positive"] { background: var(--positive-subtle); color: var(--positive-text); border-color: var(--positive-border); }
.prism-badge[data-tone="notice"]   { background: var(--notice-subtle);   color: var(--notice-text);   border-color: var(--notice-border);   }
.prism-badge[data-tone="negative"] { background: var(--negative-subtle); color: var(--negative-text); border-color: var(--negative-border); }
.prism-badge[data-tone="info"]     { background: var(--info-subtle);     color: var(--info-text);     border-color: var(--info-border);     }
/* solid variant */
.prism-badge[data-variant="solid"][data-tone="accent"]   { background: var(--accent);   color: var(--accent-on); }
.prism-badge[data-variant="solid"][data-tone="positive"] { background: var(--positive); color: var(--positive-on); }
.prism-badge[data-variant="solid"][data-tone="notice"]   { background: var(--notice);   color: var(--notice-on); }
.prism-badge[data-variant="solid"][data-tone="negative"] { background: var(--negative); color: var(--negative-on); }

/* ---------------- Tag (removable chip) ---------------- */
.prism-tag {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-family: var(--label-font);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  color: var(--text-primary);
  background: var(--fill-subtle);
  border: var(--border-width) solid var(--border-default);
  border-radius: var(--radius-pill);
  padding: 0.3em 0.55em 0.3em 0.8em;
  /* a minimum, not a fixed height: long content wraps and the chip grows
     instead of overflowing its pill on a phone */
  min-height: var(--control-sm);
  max-inline-size: 100%;
  line-height: var(--leading-snug);
  text-align: start;
}
.prism-tag > span:first-child { min-inline-size: 0; overflow-wrap: anywhere; }
/* data-selected = a filter chip REFLECTING state; aria-pressed = a control that
   TOGGLES it (a <button class="prism-tag">). Same look for both. */
.prism-tag[data-selected="true"],
.prism-tag[aria-pressed="true"] { background: var(--accent-subtle); border-color: var(--accent-border); color: var(--accent-text); }
/* A pressable tag (<button>): keep .prism-tag's own font (a `font: inherit`
   here used to outrank it), even padding (no × to make room for), and a hover. */
.prism-tag:is(button, a) { cursor: pointer; padding-inline: 0.8em; }
.prism-tag:is(button, a):hover:not(:disabled):not([aria-disabled="true"]) { border-color: var(--border-strong); }
.prism-tag:is(button, a):is([aria-pressed="true"], [data-selected="true"]):hover:not(:disabled):not([aria-disabled="true"]) { border-color: var(--accent); }
.prism-tag:is(button, a):focus-visible { outline: var(--focus-ring-width) solid var(--focus-ring); outline-offset: var(--focus-ring-offset-width); }
/* A link tag (href): a filter chip that changes the URL. It looks like the
   chip, never like link text — element-qualified so an app's global
   a:visited / a:hover rules can't recolour or underline it. The current
   filter (isSelected → aria-current) keeps the selected look. */
a.prism-tag, a.prism-tag:is(:link, :visited, :hover) { color: var(--text-primary); text-decoration: none; }
a.prism-tag[data-selected="true"], a.prism-tag[data-selected="true"]:is(:link, :visited, :hover) { color: var(--accent-text); }
a.prism-tag[aria-disabled="true"] { cursor: not-allowed; }
/* hue — a categorical tint; selected, the chip fills with the hue */
.prism-tag[data-hue],
a.prism-tag[data-hue]:is(:link, :visited, :hover) { background: var(--hue-surface); color: var(--hue-text); border-color: var(--hue-border); }
.prism-tag[data-hue]:is([data-selected="true"], [aria-pressed="true"]),
a.prism-tag[data-hue][data-selected="true"]:is(:link, :visited, :hover) { background: var(--hue); color: var(--hue-on); border-color: var(--hue); }
/* variant="chip": a read-only label — smaller, quieter, no control look */
.prism-tag[data-variant="chip"] {
  min-height: 0; gap: var(--space-1);
  padding: 0.2em 0.65em; font-size: var(--text-xs); line-height: var(--leading-snug);
}
.prism-tag[data-variant="chip"]:not([data-hue]) { background: var(--fill-subtle); border-color: var(--border-subtle); color: var(--text-secondary); }
.prism-tag:disabled,
.prism-tag[aria-disabled="true"] { opacity: 0.45; cursor: not-allowed; }
.prism-tag-remove {
  display: inline-flex; align-items: center; justify-content: center;
  width: 20px; height: 20px; border: 0; border-radius: var(--radius-pill);
  background: transparent; color: inherit; cursor: pointer; opacity: 0.7;
  transition: var(--transition-colors);
}
.prism-tag-remove:hover { background: var(--fill-muted); opacity: 1; }
.prism-tag-remove:focus-visible { outline: var(--focus-ring-width) solid var(--focus-ring); outline-offset: 1px; }
.prism-tag-remove > svg { width: 14px; height: 14px; }

/* ---------------- Avatar ---------------- */
.prism-avatar {
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: var(--radius-pill);
  background: var(--accent-subtle);
  color: var(--accent-text);
  font-family: var(--label-font);
  font-weight: var(--weight-semibold);
  overflow: hidden;
  flex: none;
  user-select: none;
  box-shadow: inset 0 0 0 1px oklch(0.22 0.02 60 / 0.06);
}
/* the ring's gap colour — zero specificity, so any rule or inline style on the
   avatar overrides it when it sits on a non-card surface */
:where(.prism-avatar) { --avatar-ring-gap: var(--surface-card); }
.prism-avatar img { width: 100%; height: 100%; object-fit: cover; display: block; }
.prism-avatar[data-size="sm"] { width: 28px; height: 28px; font-size: var(--text-xs); }
.prism-avatar[data-size="md"] { width: 40px; height: 40px; font-size: var(--text-sm); }
.prism-avatar[data-size="lg"] { width: 56px; height: 56px; font-size: var(--text-lg); }
.prism-avatar[data-size="xl"] { width: 64px; height: 64px; font-size: var(--text-xl); }
.prism-avatar[data-size="2xl"] { width: 80px; height: 80px; font-size: var(--text-2xl); }
/* tones — the default is the accent tint, which data-hue re-points */
.prism-avatar[data-tone="neutral"] { background: var(--surface-sunken); color: var(--text-secondary); }
.prism-avatar[data-tone="inverse"] { background: var(--surface-inverse); color: var(--text-on-inverse); box-shadow: none; }
/* ring — status / online / selected. A gap in the surface colour, then the
   ring; box-shadow, so it never shifts layout and isn't clipped by the
   avatar's own overflow. --avatar-ring-gap: set it on a non-card surface. */
.prism-avatar[data-ring] { box-shadow: 0 0 0 2px var(--avatar-ring-gap, var(--surface-card)), 0 0 0 4px var(--avatar-ring, var(--accent)); }
.prism-avatar[data-ring="accent"]   { --avatar-ring: var(--accent); }
.prism-avatar[data-ring="positive"] { --avatar-ring: var(--positive); }
.prism-avatar[data-ring="notice"]   { --avatar-ring: var(--notice); }
.prism-avatar[data-ring="negative"] { --avatar-ring: var(--negative); }
.prism-avatar[data-ring="neutral"]  { --avatar-ring: var(--border-strong); }

/* ---------------- Divider ---------------- */
/* An <hr> brings browser margins, borders and a height; clear them with zero
   specificity so any layout class still wins. Space it with the parent's gap. */
:where(hr.prism-divider) { margin: 0; border: 0; block-size: 0; color: inherit; overflow: visible; }
.prism-divider { border-block-start: var(--border-width) solid var(--border-default); }
.prism-divider[data-labelled="true"] {
  display: flex; align-items: center; gap: var(--space-3);
  border: 0; color: var(--text-tertiary); font-size: var(--fs-small); line-height: var(--leading-snug);
}
.prism-divider[data-labelled="true"]::before,
.prism-divider[data-labelled="true"]::after { content: ""; flex: 1 1 0; border-block-start: var(--border-width) solid var(--border-default); }
.prism-divider-label { flex: none; max-inline-size: 80%; text-align: center; }
/* variant="accent": a brand hairline — the secondary brand colour (--sig-2)
   when set, else the accent. Detail only: it stays one border wide. */
.prism-divider[data-variant="accent"],
.prism-divider[data-variant="accent"][data-labelled="true"]::before,
.prism-divider[data-variant="accent"][data-labelled="true"]::after { border-color: var(--sig-2-line, var(--accent)); }
.prism-divider[data-orientation="vertical"] {
  border: 0; border-inline-start: var(--border-width) solid var(--border-default);
  inline-size: 0; align-self: stretch; min-block-size: 1em;
}

/* ---------------- Card ---------------- */
.prism-card {
  /* The card PUBLISHES its inner padding as --card-pad so full-bleed children
     (cardfoot rule, actionbar) can cancel exactly that value. To use a custom
     padding, override --card-pad — never `padding` directly — so the bleed
     stays in sync instead of overshooting by the difference. */
  --card-pad: var(--pad-card);
  background: var(--surface-card);
  border: var(--border-width) solid var(--border-subtle);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-sm), var(--bevel-soft);
}
.prism-card[data-padded="true"] { padding: var(--card-pad); }
/* Card can render any element (as="fieldset" | "li" | "form", or a link via
   href): clear the browser defaults those bring. Zero specificity via :where(),
   so they beat only the browser — any class (a layout's display: flex, a
   utility) still wins, whatever order the sheets load in. */
:where(.prism-card) { margin: 0; min-inline-size: 0; list-style: none; color: inherit; text-decoration: none; }
:where(a.prism-card) { display: block; }
:where(.prism-card[data-padded="false"]) { padding: 0; }
.prism-card[data-interactive="true"] {
  cursor: pointer;
  transition: box-shadow var(--duration-fast) var(--ease-standard),
              border-color var(--duration-fast) var(--ease-standard),
              transform var(--duration-fast) var(--ease-standard);
}
.prism-card[data-interactive="true"]:not([data-disabled="true"]):hover { box-shadow: var(--shadow-md), var(--bevel-soft); border-color: var(--border-default); }
.prism-card[data-interactive="true"]:not([data-disabled="true"]):active { transform: translateY(1px); }
.prism-card[data-interactive="true"]:focus-visible { outline: var(--focus-ring-width) solid var(--focus-ring); outline-offset: var(--focus-ring-offset-width); }
/* A linked card (href) is a surface, not a run of link text: body text keeps
   its normal colour and is never underlined, even against an app's global
   `a` / `a:hover` rules (element-qualified, so it outranks a bare `a`). The
   hover affordance is the lift + border above. */
a.prism-card, a.prism-card:visited, a.prism-card:hover { color: inherit; text-decoration: none; }

/* Choice card (isSelected): an accent ring plus a check mark, so the state
   isn't carried by colour alone. The ring is a shadow, so selecting never
   shifts layout; it holds on hover too. */
.prism-card[data-selected="true"],
.prism-card[data-selected="true"]:hover {
  position: relative;
  border-color: var(--accent);
  box-shadow: 0 0 0 1px var(--accent), var(--shadow-sm), var(--bevel-soft);
}
.prism-card[data-selected="true"]::after {
  content: ""; position: absolute; inset-block-start: var(--space-2); inset-inline-end: var(--space-2);
  inline-size: var(--icon-md); block-size: var(--icon-md);
  background: var(--accent);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%23000' d='M12 1a11 11 0 1 0 0 22 11 11 0 0 0 0-22Zm-1.4 15.3-4.3-4.3 1.4-1.4 2.9 2.9 6.2-6.2 1.4 1.4-7.6 7.6Z'/%3E%3C/svg%3E") center / contain no-repeat;
          mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%23000' d='M12 1a11 11 0 1 0 0 22 11 11 0 0 0 0-22Zm-1.4 15.3-4.3-4.3 1.4-1.4 2.9 2.9 6.2-6.2 1.4 1.4-7.6 7.6Z'/%3E%3C/svg%3E") center / contain no-repeat;
}

/* Tone edge: an intent bar on the inline-start side (flips in RTL). */
.prism-card[data-tone] { border-inline-start: 4px solid var(--card-tone); }
.prism-card[data-tone="accent"]   { --card-tone: var(--accent); }
.prism-card[data-tone="info"]     { --card-tone: var(--info); }
.prism-card[data-tone="positive"] { --card-tone: var(--positive); }
.prism-card[data-tone="notice"]   { --card-tone: var(--notice); }
.prism-card[data-tone="negative"] { --card-tone: var(--negative); }
/* Hue: a categorical identity band across the top. data-hue also re-points
   the accent inside the card, so its buttons, links and icons follow. */
.prism-card[data-hue]:not(.pc-tile) { border-block-start: 4px solid var(--hue); }

/* Just arrived (isHighlighted): a short accent glow that settles. With reduced
   motion it's a steady accent ring instead, so the cue is never lost. */
@keyframes prism-card-arrive {
  0%, 30% { box-shadow: 0 0 0 3px var(--accent-border), 0 0 24px 2px var(--accent-subtle), var(--shadow-sm); background-color: var(--accent-subtle); }
  100%    { box-shadow: var(--shadow-sm), var(--bevel-soft); background-color: var(--surface-card); }
}
.prism-card[data-highlighted="true"] { animation: prism-card-arrive 2.4s var(--ease-standard) 1; }
@media (prefers-reduced-motion: reduce) {
  .prism-card[data-highlighted="true"] { animation: none; box-shadow: 0 0 0 2px var(--accent-border), var(--shadow-sm); }
}

/* Inset (variant="inset"): a card inside a card — tighter padding (through the
   published --card-pad knob), a sunken surface and no lift, so it reads as a
   region of its parent rather than another floating card. */
.prism-card[data-variant="inset"] {
  --card-pad: var(--space-4);
  background: var(--surface-sunken);
  border-color: var(--border-subtle);
  border-radius: var(--radius-control);
  box-shadow: none;
}

/* Clickable card via CardAction: the action (a real <button> or link, usually
   the title text inside its heading) stretches its hit area over the whole
   card with ::after, so headings keep their semantics. Other controls in the
   card are lifted above that area (zero-specificity, so a component's own
   positioning still wins) and stay clickable. */
.prism-card:has(.prism-card-action) { position: relative; cursor: pointer; transition: box-shadow var(--duration-fast) var(--ease-standard), border-color var(--duration-fast) var(--ease-standard); }
.prism-card:has(.prism-card-action):not(:has(.prism-card-action[data-disabled="true"])):hover { box-shadow: var(--shadow-md), var(--bevel-soft); border-color: var(--border-default); }
.prism-card:has(.prism-card-action:focus-visible) { outline: var(--focus-ring-width) solid var(--focus-ring); outline-offset: var(--focus-ring-offset-width); }
/* isLifted: a linked card rises slightly on hover (and when its link has
   keyboard focus), with a deeper shadow. Pointer devices only; no movement
   under prefers-reduced-motion (the shadow still deepens). */
.prism-card[data-lift="true"] {
  transition: box-shadow var(--duration-fast) var(--ease-standard),
              border-color var(--duration-fast) var(--ease-standard),
              transform var(--duration-fast) var(--ease-standard);
}
@media (hover: hover) {
  .prism-card[data-lift="true"]:not([data-disabled="true"]):not(:has(.prism-card-action[data-disabled="true"])):hover {
    transform: translateY(-3px); box-shadow: var(--shadow-lg), var(--bevel-soft); border-color: var(--border-default);
  }
}
.prism-card[data-lift="true"]:not([data-disabled="true"]):is(:focus-visible, :has(.prism-card-action:focus-visible)) {
  transform: translateY(-3px); box-shadow: var(--shadow-lg), var(--bevel-soft);
}
.prism-card[data-lift="true"]:not([data-disabled="true"]):active { transform: translateY(-1px); }
@media (prefers-reduced-motion: reduce) {
  .prism-card[data-lift="true"], .prism-card[data-lift="true"]:is(:hover, :focus-visible, :focus-within, :active) { transform: none; }
}
.prism-card-action {
  appearance: none; margin: 0; padding: 0; border: 0; background: none;
  font: inherit; color: inherit; letter-spacing: inherit; text-align: inherit; text-decoration: none; cursor: pointer;
}
.prism-card-action:focus-visible { outline: none; } /* the ring is drawn on the card */
.prism-card-action::after { content: ""; position: absolute; inset: 0; z-index: 1; border-radius: inherit; }
:where(.prism-card:has(.prism-card-action)) :where(a[href], button, input, select, textarea, label, summary, [tabindex]):not(.prism-card-action) { position: relative; z-index: 2; }

/* Disabled (isDisabled on Card or CardAction): an unavailable option. Greyed,
   no lift or press (the hover/active rules above skip it), not-allowed cursor.
   The reason belongs in the card, referenced by aria-describedby. */
.prism-card[data-disabled="true"],
.prism-card:has(.prism-card-action[data-disabled="true"]) { cursor: not-allowed; opacity: 0.55; }
.prism-card-action[data-disabled="true"] { cursor: not-allowed; }

/* ---------------- Spinner ---------------- */
.prism-spinner {
  display: inline-block;
  border-radius: 50%;
  border: 2px solid var(--fill-muted);
  border-top-color: var(--accent);
  width: var(--icon-md); height: var(--icon-md);
  animation: prism-spin 0.7s linear infinite;
}
.prism-spinner[data-size="sm"] { width: var(--icon-sm); height: var(--icon-sm); }
.prism-spinner[data-size="lg"] { width: var(--icon-xl); height: var(--icon-xl); border-width: 3px; }
@keyframes prism-spin { to { transform: rotate(360deg); } }

/* ---------------- Toolbar ---------------- */
.prism-toolbar {
  display: inline-flex; align-items: center; gap: var(--space-1);
  padding: var(--space-1);
  background: var(--surface-card);
  border: var(--border-width) solid var(--border-default);
  border-radius: var(--radius-control);
  box-shadow: var(--bevel-soft), var(--shadow-xs);
}
.prism-toolbar[data-orientation="vertical"] { flex-direction: column; }
.prism-toolbar-sep { width: 1px; align-self: stretch; background: var(--border-subtle); margin: var(--space-0-5) var(--space-1); flex: none; }
.prism-toolbar[data-orientation="vertical"] .prism-toolbar-sep { width: auto; height: 1px; margin: var(--space-1) var(--space-0-5); }

/* ---------------- Print ----------------
   A card is a screen surface; on paper it flattens to its content — no
   border, shadow, radius or inner padding (--card-pad drives the padding and
   the full-bleed children that cancel it, so it goes to 0). A choice ring,
   tone edge or highlight glow means nothing on paper either. Badges keep
   their tone colours (browsers drop backgrounds in print by default). */
@media print {
  .prism-card { --card-pad: 0; border: 0; border-radius: 0; box-shadow: none; background: transparent; }
  .prism-card::before, .prism-card::after { box-shadow: none; }
  .prism-badge, .prism-tag[data-hue] { print-color-adjust: exact; -webkit-print-color-adjust: exact; }
}

/* ===== components/forms/forms.css ===== */
/* ============================================================
   Prism · Form component styles
   TextField · Select · Checkbox · Radio · Switch
   Labels are always visible; description + error are wired for
   screen readers in the JSX. Inputs show clear hover, focus and
   invalid states; controls meet the 44px touch target.
   ============================================================ */

/* ---------------- Field scaffold (label / description / error) ---------------- */
.prism-field { display: flex; flex-direction: column; gap: var(--space-2); }
/* width: a maximum on the whole field — label, description and error follow
   the control — never a fixed width, so it still shrinks on a phone or in a
   narrow FormRow column (the column is the upper bound). */
.prism-field[data-width] { inline-size: 100%; }
.prism-field[data-width="xs"] { max-inline-size: var(--field-width-xs); }
.prism-field[data-width="sm"] { max-inline-size: var(--field-width-sm); }
.prism-field[data-width="md"] { max-inline-size: var(--field-width-md); }
.prism-field[data-width="lg"] { max-inline-size: var(--field-width-lg); }
/* On a phone every field fills the screen, whatever its width. */
@media (max-width: 639.98px) { .prism-field[data-width] { max-inline-size: none; } }
.prism-field-label {
  font-family: var(--label-font);
  font-weight: var(--weight-semibold);
  font-size: var(--text-sm);
  color: var(--text-primary);
  display: inline-flex; align-items: center; gap: var(--space-1);
}
/* "Required" as a word in the label's own tone — a red asterisk was the one
   colour-only signal in the system, and the input already carries aria-required. */
.prism-field-required { color: var(--text-tertiary); font-weight: var(--weight-regular); font-size: var(--fs-caption); margin-inline-start: var(--space-1-5); }
.prism-field-desc { font-size: var(--text-xs); color: var(--text-secondary); }
/* Label + an end-aligned hint (TextField `hint`, e.g. a character counter) */
.prism-field-labelrow { display: flex; align-items: baseline; gap: var(--space-3); min-inline-size: 0; }
.prism-field-labelrow > .prism-field-label { min-inline-size: 0; }
.prism-field-hint { margin-inline-start: auto; flex: none; font-size: var(--text-xs); color: var(--text-secondary); font-variant-numeric: tabular-nums; white-space: nowrap; }
/* TextField `mono`: URLs, JSON, reference codes */
.prism-input[data-mono="true"] { font-family: var(--font-mono); font-variant-numeric: tabular-nums slashed-zero; }
.prism-field-error {
  font-size: var(--text-xs);
  color: var(--negative-text);
  font-weight: var(--weight-medium);
  display: inline-flex; align-items: center; gap: var(--space-1);
}
.prism-field-error > svg { width: var(--icon-xs); height: var(--icon-xs); flex: none; }

/* ---------------- Input / Textarea / Select ---------------- */
.prism-input {
  font-family: var(--body-font);
  font-size: var(--text-base);
  color: var(--text-primary);
  background: var(--surface-card);
  border: var(--border-width) solid var(--border-strong);
  border-radius: var(--radius-control);
  height: var(--control-height);
  padding-inline: var(--space-3);
  width: 100%;
  box-shadow: var(--well);
  transition: var(--transition-colors);
}
.prism-input::placeholder { color: var(--text-placeholder); }
.prism-input:hover:not(:disabled) { border-color: var(--gray-400); }
.prism-input:focus-visible,
.prism-input:focus {
  outline: var(--focus-ring-width) solid var(--focus-ring);
  outline-offset: 0;
  border-color: var(--accent);
}
.prism-input:disabled { background: var(--fill-subtle); color: var(--text-disabled); cursor: not-allowed; box-shadow: none; }
.prism-input[aria-invalid="true"] { border-color: var(--negative); }
.prism-input[aria-invalid="true"]:focus-visible { outline-color: var(--negative); }
textarea.prism-input { height: auto; min-height: calc(var(--control-height) * 2); padding-block: var(--space-2); resize: vertical; line-height: var(--leading-normal); }
/* size="sm" — the compact control for table cells (TextField, Select trigger):
   the small control height and a tighter type and inset. */
.prism-input[data-size="sm"] { --control-height: var(--control-sm); font-size: var(--text-sm); padding-inline: var(--space-2); }

/* Select uses a wrapper for the chevron */
.prism-select-wrap { position: relative; display: block; }
select.prism-input { appearance: none; padding-inline-end: var(--space-10); cursor: pointer; }
/* Custom non-searchable picker trigger — a button wearing the input's skin, so
   it inherits the theme's field/well treatment; the styled options live in
   .prism-listbox (shared with ComboBox). */
.prism-select {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-2);
  inline-size: 100%; text-align: start; cursor: pointer;
  padding-inline-end: var(--space-10); font: inherit;
}
.prism-select:disabled { cursor: not-allowed; }
.prism-select-placeholder { color: var(--text-placeholder); }
.prism-select-chevron {
  position: absolute;
  inset-inline-end: var(--space-3);
  inset-block-start: 50%;
  transform: translateY(-50%);
  pointer-events: none;
  color: var(--text-secondary);
  width: var(--icon-md); height: var(--icon-md);
  transition: transform var(--duration-fast) var(--ease-standard);
}
.prism-select-wrap[data-open="true"] .prism-select-chevron { transform: translateY(-50%) rotate(180deg); }
/* size="sm": keep room for a smaller chevron (the compact inset above would otherwise eat it) */
.prism-select-wrap[data-size="sm"] .prism-select { padding-inline-end: var(--space-8); }
.prism-select-wrap[data-size="sm"] .prism-select-chevron { inset-inline-end: var(--space-2); width: var(--icon-sm); height: var(--icon-sm); }
/* A disabled option (Select item isDisabled): visible but greyed out, never highlighted */
.prism-option[aria-disabled="true"],
.prism-option[aria-disabled="true"]:hover,
.prism-option[aria-disabled="true"][data-focused="true"] { color: var(--text-disabled); background: transparent; cursor: not-allowed; }

/* Input with leading/trailing slot */
.prism-input-group { position: relative; display: flex; align-items: center; }
.prism-input-group .prism-input { padding-inline-start: var(--space-10); }
.prism-input-affix {
  position: absolute; inset-inline-start: var(--space-3);
  color: var(--text-tertiary); display: inline-flex; pointer-events: none;
}
.prism-input-affix > svg { width: var(--icon-md); height: var(--icon-md); }
/* TextField isCopyable: a Copy button inside the end of the field. Without a
   leading icon the start padding stays the plain input's. */
.prism-input-group[data-copyable="true"]:not([data-icon]) .prism-input { padding-inline-start: var(--space-3); }
.prism-input-group[data-copyable="true"] .prism-input { padding-inline-end: 6.75rem; text-overflow: ellipsis; }
.prism-input-copy {
  position: absolute; inset-inline-end: var(--space-1); inset-block: var(--space-1);
  display: inline-flex; align-items: center; gap: var(--space-1); padding-inline: var(--space-2);
  border: 0; border-radius: calc(var(--radius-control) - 2px); background: var(--fill-subtle); cursor: pointer;
  font-family: var(--label-font); font-size: var(--fs-small); font-weight: var(--weight-semibold); color: var(--text-secondary);
  transition: var(--transition-colors);
}
.prism-input-copy > svg { width: var(--icon-sm); height: var(--icon-sm); flex: none; }
.prism-input-copy:hover:not(:disabled) { background: var(--fill-muted); color: var(--text-primary); }
.prism-input-copy:focus-visible { outline: var(--focus-ring-width) solid var(--focus-ring); outline-offset: 1px; }
.prism-input-copy:disabled { opacity: 0.45; cursor: not-allowed; }
.prism-input-copy[data-copied="true"] { color: var(--positive-text); background: var(--positive-subtle); }
/* read-only: still a field (focusable, selectable) but visibly not editable */
:is(input, textarea).prism-input:read-only:not(:disabled) { background: var(--fill-subtle); box-shadow: none; }

/* ---------------- Checkbox ---------------- */
.prism-checkbox { display: inline-flex; align-items: flex-start; gap: var(--space-3); cursor: pointer; font-family: var(--body-font); font-size: var(--text-base); color: var(--text-primary); }
.prism-checkbox[data-disabled="true"] { cursor: not-allowed; color: var(--text-disabled); }
.prism-checkbox-box {
  flex: none;
  width: 22px; height: 22px;
  border-radius: var(--radius-sm);
  border: var(--border-width-strong) solid var(--border-strong);
  background: var(--surface-card);
  box-shadow: var(--well);
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--accent-on);
  transition: var(--transition-colors);
  margin-block-start: 1px;
}
.prism-checkbox-box > svg { width: 15px; height: 15px; opacity: 0; transform: scale(0.6); transition: opacity var(--duration-fast) var(--ease-standard), transform var(--duration-fast) var(--ease-emphasized); }
.prism-checkbox:hover .prism-checkbox-box { border-color: var(--accent); }
/* Checked state: the data-checked attribute (React keeps it in sync) OR the
   native input itself being checked, so server-rendered forms (prismds,
   plain HTML) tick visibly without JavaScript. The :where() keeps the
   specificity exactly what it was. */
:is(.prism-checkbox[data-checked="true"], .prism-checkbox:where(:has(> input:checked))) .prism-checkbox-box,
.prism-checkbox[data-indeterminate="true"] .prism-checkbox-box { background: var(--accent); background-image: var(--sheen); border-color: var(--accent); box-shadow: var(--bevel); }
:is(.prism-checkbox[data-checked="true"], .prism-checkbox:where(:has(> input:checked))) .prism-checkbox-box > svg,
.prism-checkbox[data-indeterminate="true"] .prism-checkbox-box > svg { opacity: 1; transform: scale(1); }
.prism-checkbox input:focus-visible + .prism-checkbox-box { outline: var(--focus-ring-width) solid var(--focus-ring); outline-offset: var(--focus-ring-offset-width); }

/* ---------------- Radio ---------------- */
.prism-radio-group { display: flex; flex-direction: column; gap: var(--space-3); }
/* horizontal: a row of options that wraps on a narrow screen */
.prism-radio-group[data-orientation="horizontal"] { flex-direction: row; flex-wrap: wrap; gap: var(--space-3) var(--space-6); }
/* the label side: a block column, so a title + a line of terms stack without a consumer wrapper */
.prism-radio-text { display: flex; flex-direction: column; gap: var(--space-0-5); min-inline-size: 0; }
.prism-radio-label { line-height: var(--leading-snug); }
.prism-radio-desc { font-size: var(--fs-small); color: var(--text-secondary); }
.prism-radio[data-disabled="true"] .prism-radio-desc,
.prism-checkbox[data-disabled="true"] .prism-radio-desc { color: var(--text-disabled); }
.prism-radio { display: inline-flex; align-items: flex-start; gap: var(--space-3); cursor: pointer; font-family: var(--body-font); font-size: var(--text-base); color: var(--text-primary); }
.prism-radio[data-disabled="true"] { cursor: not-allowed; color: var(--text-disabled); }
.prism-radio-dot {
  flex: none;
  width: 22px; height: 22px; border-radius: 50%;
  border: var(--border-width-strong) solid var(--border-strong);
  background: var(--surface-card);
  box-shadow: var(--well);
  display: inline-flex; align-items: center; justify-content: center;
  transition: var(--transition-colors);
  margin-block-start: 1px;
}
.prism-radio-dot::after { content: ""; width: 10px; height: 10px; border-radius: 50%; background: var(--accent-on); transform: scale(0); transition: transform var(--duration-fast) var(--ease-emphasized); }
.prism-radio:hover .prism-radio-dot { border-color: var(--accent); }
[data-invalid="true"] > .prism-radio-group .prism-radio:not([data-checked="true"]):not(:where(:has(> input:checked))) .prism-radio-dot { border-color: var(--negative); }
:is(.prism-radio[data-checked="true"], .prism-radio:where(:has(> input:checked))) .prism-radio-dot { background: var(--accent); background-image: var(--sheen); border-color: var(--accent); box-shadow: var(--bevel); }
:is(.prism-radio[data-checked="true"], .prism-radio:where(:has(> input:checked))) .prism-radio-dot::after { transform: scale(1); }
.prism-radio input:focus-visible + .prism-radio-dot { outline: var(--focus-ring-width) solid var(--focus-ring); outline-offset: var(--focus-ring-offset-width); }

/* ---------------- Switch ---------------- */
.prism-switch { display: inline-flex; align-items: center; gap: var(--space-3); cursor: pointer; font-family: var(--body-font); font-size: var(--text-base); color: var(--text-primary); }
.prism-switch[data-disabled="true"] { cursor: not-allowed; color: var(--text-disabled); }
.prism-switch-track {
  flex: none;
  width: 46px; height: 28px;
  border-radius: var(--radius-pill);
  background: var(--gray-300);
  box-shadow: var(--well);
  padding: var(--space-0-5);
  transition: background-color var(--duration-normal) var(--ease-standard);
}
.prism-switch-thumb {
  width: 24px; height: 24px; border-radius: 50%;
  background: oklch(1 0 0);
  box-shadow: 0 1px 2px oklch(0 0 0 / 0.3), var(--bevel-soft);
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--text-tertiary);
  transition: transform var(--duration-normal) var(--ease-emphasized), color var(--duration-fast) var(--ease-standard);
}
.prism-switch-thumb > svg { width: 13px; height: 13px; }
:is(.prism-switch[data-checked="true"], .prism-switch:where(:has(> input:checked))) .prism-switch-track { background: var(--accent); }
:is(.prism-switch[data-checked="true"], .prism-switch:where(:has(> input:checked))) .prism-switch-thumb { transform: translateX(18px); color: var(--accent-text); }
[dir="rtl"] :is(.prism-switch[data-checked="true"], .prism-switch:where(:has(> input:checked))) .prism-switch-thumb { transform: translateX(-18px); }
.prism-switch input:focus-visible + .prism-switch-track { outline: var(--focus-ring-width) solid var(--focus-ring); outline-offset: var(--focus-ring-offset-width); }

/* Hidden native input that keeps a11y semantics.
   It's absolutely positioned, so its wrapper MUST be its containing block:
   with no positioned ancestor it is placed against the page, so inside a
   scroll box or wide table cell it escapes the scroller and widens the page
   (a roster stretched to 7,047px at 390px), and focusing it scrolls the page.
   Every wrapper that holds one is position: relative (zero specificity, so a
   layout class still wins), and the input sits on the wrapper's corner. */
.prism-native-control {
  position: absolute; inset-block-start: 0; inset-inline-start: 0;
  opacity: 0; width: 1px; height: 1px; margin: 0; padding: 0; overflow: hidden;
}
:where(.prism-checkbox, .prism-radio, .prism-switch, .prism-dropzone, .prism-filetrigger),
:where(:has(> .prism-native-control)) { position: relative; }

/* FileTrigger with isRequired / showFileName: the trigger plus the chosen
   file name(s), inline */
.prism-filetrigger-slot { display: contents; }
.prism-filetrigger { display: inline-flex; align-items: center; gap: var(--space-3); min-inline-size: 0; max-inline-size: 100%; }
.prism-filetrigger-name { font-size: var(--fs-small); color: var(--text-secondary); min-inline-size: 0; overflow-wrap: anywhere; }
.prism-filetrigger-name:empty { display: none; }

/* ---------------- NumberField (stepper) ---------------- */
.prism-numberfield { display: flex; align-items: stretch; }
.prism-numberfield .prism-input { border-radius: 0; text-align: end; font-family: var(--font-mono); }
.prism-numberfield .prism-input { border-inline: 0; }
.prism-num-step {
  display: inline-flex; align-items: center; justify-content: center;
  width: var(--control-height); flex: none;
  border: var(--border-width) solid var(--border-strong);
  background: var(--surface-card); color: var(--text-secondary);
  cursor: pointer; transition: var(--transition-colors);
}
.prism-num-step:first-child { border-start-start-radius: var(--radius-control); border-end-start-radius: var(--radius-control); }
.prism-num-step:last-child { border-start-end-radius: var(--radius-control); border-end-end-radius: var(--radius-control); }
.prism-num-step:hover:not(:disabled) { background: var(--fill-subtle); color: var(--text-primary); }
.prism-num-step:focus-visible { outline: var(--focus-ring-width) solid var(--focus-ring); outline-offset: -1px; z-index: 1; }
.prism-num-step:disabled { opacity: 0.45; cursor: not-allowed; }
.prism-num-step > svg { width: var(--icon-sm); height: var(--icon-sm); }

/* Trailing stacked stepper (default): both keys sit on the end edge, up over
   down, so the pair reads as one control and the value never moves between
   two hit targets. The split layout stays available as data-stepper="split"
   for wide numeric tables where the keys need separating. */
.prism-numberfield[data-stepper="end"] .prism-input {
  text-align: start;
  border-inline-start: var(--border-width) solid var(--border-strong);
  border-start-start-radius: var(--radius-control);
  border-end-start-radius: var(--radius-control);
}
.prism-num-steps { display: flex; flex-direction: column; flex: none; inline-size: var(--control-height); }
.prism-num-steps .prism-num-step {
  inline-size: 100%; flex: 1 1 0; min-block-size: 0;
  border-inline-start: 0; border-radius: 0;
}
.prism-num-steps .prism-num-step:first-child { border-block-end: 0; border-start-end-radius: var(--radius-control); }
.prism-num-steps .prism-num-step:last-child { border-end-end-radius: var(--radius-control); }
.prism-num-steps .prism-num-step > svg { inline-size: 13px; block-size: 13px; }

/* ---------------- SearchField ---------------- */
.prism-searchfield { position: relative; display: flex; align-items: center; }
/* Search bar (SearchField with `actions`): the box keeps its width cap and
   the buttons sit beside it; the bar itself isn't capped. On a phone the box
   takes the whole line and the buttons wrap under it. */
.prism-searchbar[data-width] { max-inline-size: none; }
.prism-searchbar-row { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); }
.prism-searchbar-row > .prism-searchfield { flex: 1 1 16rem; min-inline-size: 0; }
.prism-searchbar[data-width="xs"] .prism-searchbar-row > .prism-searchfield { max-inline-size: var(--field-width-xs); }
.prism-searchbar[data-width="sm"] .prism-searchbar-row > .prism-searchfield { max-inline-size: var(--field-width-sm); }
.prism-searchbar[data-width="md"] .prism-searchbar-row > .prism-searchfield { max-inline-size: var(--field-width-md); }
.prism-searchbar[data-width="lg"] .prism-searchbar-row > .prism-searchfield { max-inline-size: var(--field-width-lg); }
.prism-searchbar-actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); flex: none; }
:where(form.prism-searchbar) { margin: 0; }
@media (max-width: 639.98px) {
  .prism-searchbar-row > .prism-searchfield { flex-basis: 100%; max-inline-size: none !important; }
}
.prism-searchfield .prism-input { padding-inline: var(--space-10); }
.prism-searchfield-icon { position: absolute; inset-inline-start: var(--space-3); color: var(--text-tertiary); display: inline-flex; pointer-events: none; }
.prism-searchfield-icon > svg { width: var(--icon-md); height: var(--icon-md); }
/* type="search" makes Chromium/Safari draw their own cancel (×) and search
   decoration next to Prism's clear button — hide the native ones. */
.prism-searchfield .prism-input::-webkit-search-cancel-button,
.prism-searchfield .prism-input::-webkit-search-decoration { -webkit-appearance: none; appearance: none; display: none; }
.prism-searchfield-clear {
  position: absolute; inset-inline-end: var(--space-2);
  display: inline-flex; align-items: center; justify-content: center;
  width: 28px; height: 28px; border: 0; border-radius: var(--radius-pill);
  background: transparent; color: var(--text-secondary); cursor: pointer;
}
.prism-searchfield-clear:hover { background: var(--fill-subtle); color: var(--text-primary); }
.prism-searchfield-clear:focus-visible { outline: var(--focus-ring-width) solid var(--focus-ring); outline-offset: 1px; }
.prism-searchfield-clear > svg { width: var(--icon-sm); height: var(--icon-sm); }

/* ---------------- Slider ---------------- */
.prism-slider { display: flex; flex-direction: column; gap: var(--space-3); }
.prism-slider-head { display: flex; justify-content: space-between; align-items: baseline; }
.prism-slider-value { font-family: var(--font-mono); font-size: var(--fs-small); color: var(--text-secondary); }
.prism-slider-track {
  position: relative; height: 6px; border-radius: var(--radius-pill);
  background: var(--fill-muted); cursor: pointer; touch-action: none;
  margin: var(--space-2) 0;
}
.prism-slider-fill { position: absolute; height: 100%; border-radius: inherit; background: var(--accent); inset-inline-start: 0; overflow: hidden; }
/* Brightens with its value — see the value-ramp note in controls.css. The ramp
   is sized to the whole track and clipped by the fill, so a low value shows
   only its dark end. */
.prism-slider-fill::before {
  content: ""; position: absolute; inset-block: 0; inset-inline-start: 0;
  inline-size: calc(100% * 100 / var(--span, 100));
  background-image: var(--value-ramp);
}
.prism-slider-thumb {
  position: absolute; top: 50%; width: 22px; height: 22px; border-radius: 50%;
  background: var(--surface-card); border: 2px solid var(--accent);
  box-shadow: var(--shadow-sm); transform: translate(-50%, -50%);
  transition: box-shadow var(--duration-fast) var(--ease-standard), transform var(--duration-instant) var(--ease-standard);
}
[dir="rtl"] .prism-slider-thumb { transform: translate(50%, -50%); }
.prism-slider-thumb:focus-visible { outline: var(--focus-ring-width) solid var(--focus-ring); outline-offset: 2px; }
/* Unset (value={null}): no value yet. Hollow, muted thumb at the start, no
   fill, and the value reads "Not set" — the word carries it, not colour. */
.prism-slider[data-unset="true"] .prism-slider-fill { visibility: hidden; }
.prism-slider[data-unset="true"] .prism-slider-thumb { border-style: dashed; border-color: var(--border-strong); box-shadow: none; }
.prism-slider[data-unset="true"] .prism-slider-value { font-family: var(--body-font); font-style: italic; color: var(--text-tertiary); }
/* Optional snap detents (present only when `snap` is set): engraved marks the
   thumb clicks to. Passed ones light up. */
.prism-slider-ticks { position: absolute; inset: 0; pointer-events: none; }
.prism-slider-tick {
  position: absolute; inset-block-start: 50%; inline-size: 2px; block-size: 8px;
  transform: translate(-50%, -50%); border-radius: var(--radius-pill);
  background: var(--border-strong);
}
.prism-slider-tick[data-on="true"] { background: var(--accent); }
.prism-slider-thumb:active { transform: translate(-50%, -50%) scale(1.1); }
[dir="rtl"] .prism-slider-thumb:active { transform: translate(50%, -50%) scale(1.1); }

/* ---------------- SegmentedControl (ToggleButtonGroup) ---------------- */
.prism-segmented {
  display: inline-flex; background: var(--fill-subtle); border-radius: var(--radius-control); padding: var(--space-0-5); gap: var(--space-0-5);
  /* Too many options for the width: scroll sideways rather than overlap or
     widen the page (ToggleButtonGroup keeps the selected option in view). */
  max-inline-size: 100%; overflow-x: auto; overflow-y: hidden; flex-wrap: nowrap;
  scrollbar-width: none; -webkit-overflow-scrolling: touch;
}
.prism-segmented::-webkit-scrollbar { display: none; }
.prism-segmented > .prism-segmented-btn { flex: none; }
/* wrap: options flow onto more lines instead of scrolling */
.prism-segmented[data-wrap="true"] { flex-wrap: wrap; overflow: visible; }
.prism-segmented-btn {
  border: var(--border-width) solid transparent; background: transparent; cursor: pointer;
  font-family: var(--label-font); font-weight: var(--weight-semibold); font-size: var(--fs-small);
  color: var(--text-secondary); padding: 0 var(--space-3);
  height: calc(var(--control-height) - 6px); min-width: 36px; white-space: nowrap;
  border-radius: calc(var(--radius-control) - 1px);
  display: inline-flex; align-items: center; justify-content: center; gap: var(--space-1-5);
  transition: var(--transition-colors);
}
.prism-segmented-btn > svg { width: var(--icon-sm); height: var(--icon-sm); }
.prism-segmented-btn:hover { color: var(--text-primary); }
.prism-segmented-btn:focus-visible { outline: var(--focus-ring-width) solid var(--focus-ring); outline-offset: 1px; }
.prism-segmented-btn[aria-pressed="true"] { background: var(--surface-card); background-image: var(--sheen); color: var(--text-primary); border-color: var(--border-default); box-shadow: var(--shadow-sm), var(--bevel-soft); }
.prism-segmented-btn[disabled] { opacity: 0.45; cursor: not-allowed; }
/* selectedVariant="accent": the selected segment fills with the accent. The
   fill is far darker (light theme) / lighter (dark) than the well, so the
   state reads by lightness as well as hue. */
.prism-segmented[data-selected-variant="accent"] .prism-segmented-btn[aria-pressed="true"] {
  background: var(--accent); color: var(--accent-on); border-color: transparent;
  box-shadow: var(--shadow-sm);
}
.prism-segmented[data-selected-variant="accent"] .prism-segmented-btn[aria-pressed="true"]:hover { background: var(--accent-hover); color: var(--accent-on); }
/* Dark: white ink on the dark theme's lighter accent is only ~3.4:1, so the
   selected segment inverts — the light accent text colour as the fill, the
   page colour as ink (≥ 4.5:1, and far from the dark well). */
[data-theme="dark"] .prism-segmented[data-selected-variant="accent"] .prism-segmented-btn[aria-pressed="true"] { background: var(--accent-text); color: var(--surface-page); }
[data-theme="dark"] .prism-segmented[data-selected-variant="accent"] .prism-segmented-btn[aria-pressed="true"]:hover { background: color-mix(in oklab, var(--accent-text) 88%, var(--surface-page)); color: var(--surface-page); }
@media (prefers-color-scheme: dark) {
  [data-theme="system"] .prism-segmented[data-selected-variant="accent"] .prism-segmented-btn[aria-pressed="true"] { background: var(--accent-text); color: var(--surface-page); }
  [data-theme="system"] .prism-segmented[data-selected-variant="accent"] .prism-segmented-btn[aria-pressed="true"]:hover { background: color-mix(in oklab, var(--accent-text) 88%, var(--surface-page)); color: var(--surface-page); }
}

/* ---------------- ComboBox ---------------- */
.prism-combobox { position: relative; }
.prism-combobox-input { position: relative; display: flex; align-items: center; }
.prism-combobox-input .prism-input { padding-inline-end: var(--space-10); }
.prism-combobox-toggle {
  position: absolute; inset-inline-end: var(--space-2);
  display: inline-flex; align-items: center; justify-content: center;
  width: 28px; height: 28px; border: 0; border-radius: var(--radius-control);
  background: transparent; color: var(--text-secondary); cursor: pointer;
}
.prism-combobox-toggle:hover { background: var(--fill-subtle); color: var(--text-primary); }
.prism-combobox-toggle > svg { width: var(--icon-md); height: var(--icon-md); transition: transform var(--duration-fast) var(--ease-standard); }
.prism-combobox[data-open="true"] .prism-combobox-toggle > svg { transform: rotate(180deg); }
.prism-listbox {
  /* It's a <ul>: without margin 0 the browser's 1em list margin pushed the
     popup ~17px below the field (Select, ComboBox). */
  margin: 0; list-style: none;
  position: absolute; top: calc(100% + 4px); inset-inline: 0;
  background: var(--surface-overlay);
  border: var(--border-width) solid var(--border-default);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-lg);
  padding: var(--space-1); max-height: 260px; overflow-y: auto;
  z-index: var(--z-dropdown);
  animation: prism-pop var(--duration-fast) var(--ease-standard);
}
/* Portalled variant (Select) — positioned via inline fixed coords on <body>, so
   it escapes card overflow/stacking and clears modals. Reset the absolute
   defaults so the inline left/top/width/bottom win. */
.prism-listbox[data-portal="true"] {
  position: fixed;
  inset-inline: auto;
  top: auto;
  z-index: var(--z-tooltip);
}
.prism-option {
  display: flex; align-items: center; gap: var(--space-2);
  padding: var(--space-2) var(--space-3); border-radius: var(--radius-control);
  font-size: var(--fs-small); color: var(--text-primary); cursor: pointer;
}
.prism-option[data-focused="true"], .prism-option:hover { background: var(--fill-subtle); }
.prism-option[aria-selected="true"] { color: var(--accent-text); font-weight: var(--weight-semibold); }
.prism-option .prism-option-check { margin-inline-start: auto; color: var(--accent-text); display: inline-flex; }
.prism-option .prism-option-check > svg { width: var(--icon-sm); height: var(--icon-sm); }
.prism-combobox-empty { padding: var(--space-3); color: var(--text-tertiary); font-size: var(--fs-small); }
/* A second line per option (ComboBoxItem.description): dose, stock, an email… */
.prism-option-text { display: flex; flex-direction: column; gap: var(--space-0-5); min-inline-size: 0; }
.prism-option-desc { font-size: var(--fs-caption); font-weight: var(--weight-regular); color: var(--text-tertiary); }
.prism-combobox[data-invalid="true"] .prism-combobox-multi { border-color: var(--negative); }
/* footer: a note pinned under the options ("Showing 60 of 616 — type to search") */
.prism-listbox-footer {
  position: sticky; inset-block-end: calc(-1 * var(--space-1)); margin: var(--space-1) calc(-1 * var(--space-1)) calc(-1 * var(--space-1));
  padding: var(--space-2) var(--space-3); background: var(--surface-overlay);
  border-block-start: var(--border-width) solid var(--border-subtle);
  font-size: var(--fs-caption); color: var(--text-tertiary);
}
/* Sections: { section, items } entries group options under a heading */
.prism-listbox-section { list-style: none; }
.prism-listbox-section + .prism-listbox-section, .prism-option + .prism-listbox-section { margin-block-start: var(--space-1); padding-block-start: var(--space-1); border-block-start: var(--border-width) solid var(--border-subtle); }
.prism-listbox-heading {
  padding: var(--space-2) var(--space-3) var(--space-1);
  font-size: var(--fs-caption); font-weight: var(--weight-semibold); color: var(--text-tertiary);
}
/* the nested option list is a <ul>: no browser list margin/padding */
.prism-listbox-group { margin: 0; padding: 0; list-style: none; }
/* leadingIcon: reuse the input affix; pad the field so text clears it */
.prism-combobox-input[data-icon="true"] .prism-input { padding-inline-start: var(--space-10); }
.prism-combobox-input[data-icon="true"] .prism-input-affix { z-index: 1; }
/* renderSelected: the chosen item's detail, under the field */
.prism-combobox-selected { margin-block-start: var(--space-2); }
/* isLoading: sits just inside the toggle while a search runs */
.prism-combobox-spinner { position: absolute; inset-inline-end: calc(var(--space-2) + 32px); pointer-events: none; }
/* multiple-selection combobox */
.prism-combobox-multi { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-1-5); height: auto; min-height: var(--control-height); padding: var(--space-1) var(--space-10) var(--space-1) var(--space-2); cursor: text; }
.prism-combobox-multi .prism-tag { height: 24px; }
.prism-combobox-multi-input { border: 0; outline: 0; background: transparent; flex: 1; min-width: 80px; font: inherit; font-size: var(--text-base); color: var(--text-primary); padding: var(--space-0-5); }
.prism-combobox-multi-input::placeholder { color: var(--text-placeholder); }

/* ---------------- DropZone ---------------- */
.prism-dropzone {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: var(--space-2); text-align: center;
  padding: var(--space-8) var(--space-6);
  border: var(--border-width-strong) dashed var(--border-strong);
  border-radius: var(--radius-card);
  background: var(--surface-card); color: var(--text-secondary);
  cursor: pointer; transition: var(--transition-colors);
}
.prism-dropzone:hover { border-color: var(--accent-border); background: var(--accent-subtle); }
.prism-dropzone[data-dragging="true"] { border-color: var(--accent); background: var(--accent-subtle); color: var(--accent-text); }
.prism-dropzone:focus-visible { outline: var(--focus-ring-width) solid var(--focus-ring); outline-offset: var(--focus-ring-offset-width); }
.prism-dropzone[data-disabled="true"] { opacity: 0.5; cursor: not-allowed; }
.prism-dropzone-icon { color: var(--text-tertiary); display: inline-flex; }
.prism-dropzone-icon > svg { width: 36px; height: 36px; }
.prism-dropzone[data-dragging="true"] .prism-dropzone-icon { color: var(--accent); }
.prism-dropzone-title { font-family: var(--label-font); font-weight: var(--weight-semibold); font-size: var(--fs-body); color: var(--text-primary); }
.prism-dropzone[data-dragging="true"] .prism-dropzone-title { color: var(--accent-text); }
.prism-dropzone-hint { font-size: var(--text-xs); color: var(--text-tertiary); }
.prism-dropzone-link { color: var(--text-link); text-decoration: underline; text-underline-offset: 0.15em; }

/* ============================================================
   FORM ORCHESTRATION — sections · rows · error summary · actions
   · autosave · multi-step
   ============================================================ */

/* Form container + section */
.prism-form { display: flex; flex-direction: column; gap: var(--gap-section); }
.prism-formsection { border: 0; margin: 0; padding: 0; min-inline-size: 0; display: flex; flex-direction: column; gap: var(--space-4); }
/* measure: a readable single-column form on a wide page */
.prism-formsection[data-measure="true"] { inline-size: 100%; max-inline-size: var(--form-measure); }
.prism-formsection-head { display: flex; flex-direction: column; gap: var(--space-1); }
.prism-formsection-legend { padding: 0; font-family: var(--font-display); font-weight: var(--weight-semibold); font-size: var(--fs-h4); color: var(--text-primary); }
/* size — the same steps as SectionHeader (h5 / h4 / h3) */
.prism-formsection[data-size="sm"] .prism-formsection-legend { font-size: var(--fs-h5); }
.prism-formsection[data-size="lg"] .prism-formsection-legend { font-size: var(--fs-h3); }
/* xs: a label-style legend for a group nested inside a card — clearly below a
   card title (sm = --fs-h5, the same role card titles use). Mirrors
   SectionHeader size="xs". */
.prism-formsection[data-size="xs"] .prism-formsection-legend {
  font-family: var(--label-font); font-size: var(--fs-caption); font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-caps); text-transform: uppercase; color: var(--text-secondary);
}
.prism-formsection-desc { margin: 0; font-size: var(--fs-body-sm); color: var(--text-secondary); text-wrap: pretty; }
.prism-formsection[data-card="true"] { background: var(--surface-card); border: var(--border-width) solid var(--border-subtle); border-radius: var(--radius-card); padding: var(--pad-card); }

/* Responsive field grid row */
.prism-formrow { display: grid; gap: var(--space-4); grid-template-columns: repeat(2, minmax(0, 1fr)); }
.prism-formrow[data-cols="1"] { grid-template-columns: 1fr; }
.prism-formrow[data-cols="3"] { grid-template-columns: repeat(3, minmax(0, 1fr)); }
/* data-span on a field component lands on its native control, so a field
   holding a spanned control spans too */
.prism-formrow > [data-span="2"], .prism-formrow > :has([data-span="2"]) { grid-column: span 2; }
.prism-formrow > [data-span="full"], .prism-formrow > :has([data-span="full"]) { grid-column: 1 / -1; }
@media (max-width: 639.98px) { .prism-formrow, .prism-formrow[data-cols] { grid-template-columns: 1fr; } .prism-formrow > * { grid-column: auto !important; } }

/* Aligned tracks. Every field in a FormRow is a row subgrid over 7 rows that
   the whole line shares: 1 label row, 2 description, 3 control, 4-6 whatever
   follows (a description placed below, the error, a counter, a detail card),
   7 the space before the next line. So controls line up however long a
   neighbour's description is. Spacing is margins, not row-gap, so rows a line
   doesn't use collapse to nothing. A field wrapped in one element (to carry
   data-span) is aligned too; anything else spans the line, top-aligned.
   Without subgrid support it's the plain grid above. */
@supports (grid-template-rows: subgrid) {
  .prism-formrow { row-gap: 0; margin-block-end: calc(-1 * var(--space-4)); }
  .prism-formrow > * { grid-row: span 7; align-self: start; margin-block-end: var(--space-4); }
  .prism-formrow > :is(.prism-field, .prism-slider),
  .prism-formrow > :has(> :is(.prism-field, .prism-slider):only-child),
  .prism-formrow > * > :is(.prism-field, .prism-slider):only-child {
    display: grid; grid-template-rows: subgrid; grid-template-columns: minmax(0, 1fr);
    row-gap: 0; align-self: stretch; align-content: start; margin-block-end: 0;
  }
  .prism-formrow > * > :is(.prism-field, .prism-slider):only-child { grid-row: 1 / -1; }
  :is(.prism-formrow > :is(.prism-field, .prism-slider), .prism-formrow > * > :is(.prism-field, .prism-slider):only-child) > * {
    margin-block-start: var(--space-2); min-inline-size: 0;
  }
  :is(.prism-formrow > :is(.prism-field, .prism-slider), .prism-formrow > * > :is(.prism-field, .prism-slider):only-child) > :is(.prism-field-label, .prism-field-labelrow, .prism-slider-head) {
    grid-row: 1; grid-column: 1; margin-block-start: 0;
  }
  :is(.prism-formrow > :is(.prism-field, .prism-slider), .prism-formrow > * > :is(.prism-field, .prism-slider):only-child) > :is(.prism-field-label, .prism-field-labelrow, .prism-slider-head) + .prism-field-desc,
  :is(.prism-formrow > :is(.prism-field, .prism-slider), .prism-formrow > * > :is(.prism-field, .prism-slider):only-child) > .prism-field-desc:first-child {
    grid-row: 2; grid-column: 1;
  }
  /* placeholders: rows 1-2 are always taken, so the control lands in row 3
     even without a label or description; row 7 holds the line spacing */
  :is(.prism-formrow > :is(.prism-field, .prism-slider), .prism-formrow > * > :is(.prism-field, .prism-slider):only-child)::before {
    content: ""; grid-row: 1 / 3; grid-column: 1;
  }
  :is(.prism-formrow > :is(.prism-field, .prism-slider), .prism-formrow > * > :is(.prism-field, .prism-slider):only-child)::after {
    content: ""; grid-row: -2 / -1; grid-column: 1; block-size: var(--space-4);
  }
}

/* Error summary (a11y: links jump to each invalid field) */
.prism-errorsummary {
  border: var(--border-width) solid var(--negative-border);
  border-inline-start-width: 3px; border-inline-start-color: var(--negative);
  background: var(--negative-subtle); border-radius: var(--radius-md);
  padding: var(--space-4); display: flex; flex-direction: column; gap: var(--space-2);
}
.prism-errorsummary-title { display: inline-flex; align-items: center; gap: var(--space-2); font-family: var(--label-font); font-weight: var(--weight-semibold); font-size: var(--fs-body-sm); color: var(--negative-text); }
.prism-errorsummary-title > svg { width: var(--icon-md); height: var(--icon-md); flex: none; }
.prism-errorsummary-list { margin: 0; padding-inline-start: var(--space-5); display: flex; flex-direction: column; gap: var(--space-1); }
.prism-errorsummary-list a { color: var(--negative-text); font-size: var(--fs-body-sm); text-decoration: underline; text-underline-offset: 0.15em; }
.prism-errorsummary-list a:hover { text-decoration-thickness: 2px; }

/* Form actions bar */
.prism-formactions {
  display: flex; align-items: center; gap: var(--space-3); flex-wrap: wrap;
  padding-block-start: var(--space-4); border-top: var(--border-width) solid var(--border-subtle);
}
.prism-formactions[data-align="end"] { justify-content: flex-end; }
.prism-formactions[data-align="between"] { justify-content: space-between; }
.prism-formactions-status { font-size: var(--text-xs); color: var(--text-secondary); margin-inline-end: auto; }
.prism-formactions-group { display: flex; align-items: center; justify-content: flex-end; gap: var(--space-3); flex-wrap: wrap; min-inline-size: 0; }
/* On a phone the buttons stack full-width; column-reverse keeps the primary
   (last in source, at the end of the row on wide screens) on top, nearest the
   thumb, and the status line above them. */
@media (max-width: 639.98px) {
  .prism-formactions-group { flex: 1 1 100%; flex-direction: column-reverse; align-items: stretch; }
  .prism-formactions-group > * { inline-size: 100%; }
}
.prism-formactions[data-sticky="true"] {
  position: sticky; inset-block-end: 0; z-index: 5;
  background: var(--surface-card); margin-block-start: var(--space-2);
  padding: var(--space-3) var(--pad-card); border-radius: var(--radius-card) var(--radius-card) 0 0;
  box-shadow: 0 -8px 16px -12px rgb(0 0 0 / 0.18);
}

/* Autosave indicator */
.prism-autosave { display: inline-flex; align-items: center; gap: var(--space-1-5); font-size: var(--text-xs); color: var(--text-tertiary); }
.prism-autosave-dot { width: 7px; height: 7px; border-radius: var(--radius-pill); flex: none; background: var(--text-tertiary); }
.prism-autosave[data-state="saving"] .prism-autosave-dot { background: var(--notice); animation: prism-pulse 1s var(--ease-standard) infinite; }
.prism-autosave[data-state="saved"] { color: var(--positive-text); }
.prism-autosave[data-state="saved"] .prism-autosave-dot { background: var(--positive); }
.prism-autosave[data-state="error"] { color: var(--negative-text); }
.prism-autosave[data-state="error"] .prism-autosave-dot { background: var(--negative); }
.prism-autosave[data-state="unsaved"] .prism-autosave-dot { background: var(--notice); }
.prism-autosave > svg { width: var(--icon-sm); height: var(--icon-sm); }
@keyframes prism-pulse { 50% { opacity: 0.35; } }

/* Multi-step form scaffold */
.prism-multistep { display: flex; flex-direction: column; gap: var(--gap-section); }
.prism-multistep[data-layout="side"] { display: grid; grid-template-columns: minmax(180px, 240px) 1fr; gap: var(--gap-section); align-items: start; }
@media (max-width: 1023.98px) { .prism-multistep[data-layout="side"] { grid-template-columns: 1fr; } }
.prism-multistep-body { display: flex; flex-direction: column; gap: var(--space-5); min-width: 0; }
.prism-multistep-stephead { display: flex; flex-direction: column; gap: var(--space-1); }
.prism-multistep-stepcount { font-family: var(--font-mono); font-size: var(--fs-caption); color: var(--text-tertiary); }
.prism-multistep-steptitle { font-family: var(--font-display); font-weight: var(--weight-semibold); font-size: var(--fs-h3); color: var(--text-primary); margin: 0; }
.prism-multistep-stepdesc { margin: 0; font-size: var(--fs-body); color: var(--text-secondary); text-wrap: pretty; }


/* ============================================================
   MOTION · state changes move like parts, not like paint
   ------------------------------------------------------------
   A click or a key SETTLES a thumb to its new position (--duration-settle,
   --ease-settle, no overshoot); a drag follows the pointer with no easing,
   which is why the settle transition is gated on data-settling — the
   component sets it on click and key and drops it on the first drag move.
   Everything here collapses under prefers-reduced-motion.
   ============================================================ */
@media (prefers-reduced-motion: no-preference) {
  .prism-slider[data-settling="true"] .prism-slider-fill { transition: width var(--duration-settle) var(--ease-settle); }
  .prism-slider[data-settling="true"] .prism-slider-thumb {
    transition: inset-inline-start var(--duration-settle) var(--ease-settle),
                box-shadow var(--duration-fast) var(--ease-standard),
                transform var(--duration-instant) var(--ease-standard);
  }
  .prism-segmented-btn { transition: color var(--duration-fast) var(--ease-standard), background-color var(--duration-fast) var(--ease-standard), box-shadow var(--duration-fast) var(--ease-standard); }
  .prism-checkbox-box, .prism-radio-dot {
    transition: background-color var(--duration-fast) var(--ease-standard), border-color var(--duration-fast) var(--ease-standard), box-shadow var(--duration-fast) var(--ease-standard);
  }
}

/* ============================================================
   RichTextEditor — toolbar + contentEditable area in one framed
   field. The frame takes the input's border, well and focus ring
   (via :focus-within), so it reads as one control.
   ============================================================ */
.prism-rte-frame {
  display: flex; flex-direction: column;
  background: var(--surface-card);
  border: var(--border-width) solid var(--border-strong);
  border-radius: var(--radius-control);
  box-shadow: var(--well);
  transition: var(--transition-colors);
  min-inline-size: 0;
}
.prism-rte-frame:hover { border-color: var(--gray-400); }
.prism-rte-frame:focus-within { outline: var(--focus-ring-width) solid var(--focus-ring); outline-offset: 0; border-color: var(--accent); }
.prism-rte[data-invalid="true"] .prism-rte-frame { border-color: var(--negative); }
.prism-rte[data-invalid="true"] .prism-rte-frame:focus-within { outline-color: var(--negative); }
.prism-rte[data-disabled="true"] .prism-rte-frame { background: var(--fill-subtle); box-shadow: none; }
.prism-rte-toolbar {
  display: flex; flex-wrap: wrap; gap: var(--space-0-5);
  padding: var(--space-1);
  border-block-end: var(--border-width) solid var(--border-subtle);
}
.prism-rte-tool {
  display: inline-flex; align-items: center; justify-content: center;
  inline-size: var(--control-sm); block-size: var(--control-sm);
  border: 0; border-radius: var(--radius-sm); background: transparent;
  color: var(--text-secondary); cursor: pointer;
  transition: var(--transition-colors);
}
.prism-rte-tool > svg { inline-size: var(--icon-sm); block-size: var(--icon-sm); }
.prism-rte-tool:hover:not(:disabled) { background: var(--fill-subtle); color: var(--text-primary); }
.prism-rte-tool[aria-pressed="true"] { background: var(--accent-subtle); color: var(--accent-text); }
.prism-rte-tool:focus-visible { outline: var(--focus-ring-width) solid var(--focus-ring); outline-offset: 1px; }
.prism-rte-tool:disabled { color: var(--text-disabled); cursor: not-allowed; }
.prism-rte-linkbar {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2);
  padding: var(--space-2);
  border-block-end: var(--border-width) solid var(--border-subtle);
  background: var(--fill-subtle);
}
.prism-rte-linkbar > .prism-input { flex: 1 1 12rem; min-inline-size: 0; inline-size: auto; }
.prism-rte-linkerror { flex-basis: 100%; font-size: var(--text-xs); color: var(--negative-text); }
.prism-rte-editor {
  min-block-size: calc(var(--control-height) * 3);
  padding: var(--space-2) var(--space-3);
  font-family: var(--body-font); font-size: var(--text-base); line-height: var(--leading-normal);
  color: var(--text-primary);
  overflow-wrap: anywhere;
  position: relative;
  outline: none; /* the frame shows the focus ring */
}
.prism-rte[data-disabled="true"] .prism-rte-editor { color: var(--text-disabled); cursor: not-allowed; }
.prism-rte-editor[data-empty="true"]::before {
  content: attr(data-placeholder); color: var(--text-placeholder); pointer-events: none;
  position: absolute;
}
.prism-rte-editor :where(p, ul, ol) { margin: 0 0 var(--space-2); }
.prism-rte-editor :where(p, ul, ol):last-child { margin-block-end: 0; }
.prism-rte-editor :where(ul, ol) { padding-inline-start: var(--space-6); }
.prism-rte-editor a { color: var(--text-link); text-decoration: underline; }
.prism-rte-count { font-size: var(--text-xs); color: var(--text-tertiary); align-self: flex-end; font-variant-numeric: tabular-nums; }
.prism-rte-count[data-over="true"] { color: var(--negative-text); font-weight: var(--weight-semibold); }

/* ===== components/feedback/feedback.css ===== */
/* ============================================================
   Prism · Feedback & navigation component styles
   Alert · ProgressBar · Tabs · Breadcrumbs
   ============================================================ */

/* ---------------- Alert (inline banner) ---------------- */
.prism-alert {
  display: flex;
  gap: var(--space-3);
  padding: var(--space-4);
  border-radius: var(--radius-md);
  border: var(--border-width) solid transparent;
  border-inline-start-width: 3px;
  font-size: var(--text-sm);
  color: var(--text-primary);
}
.prism-alert-icon { flex: none; margin-block-start: 1px; }
.prism-alert-icon > svg { width: var(--icon-md); height: var(--icon-md); }
.prism-alert-body { display: flex; flex-direction: column; gap: var(--space-1); }
/* With actions: message and actions share the text column; actions wrap
   under the message (aligned to the text, not the icon) when narrow. */
.prism-alert-main { flex: 1 1 auto; min-inline-size: 0; display: flex; flex-wrap: wrap; align-items: flex-start; gap: var(--space-3); }
.prism-alert-main > .prism-alert-body { flex: 1 1 16rem; min-inline-size: 0; }
.prism-alert-actions { flex: 0 1 auto; display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); }
.prism-alert-title { font-family: var(--label-font); font-weight: var(--weight-semibold); font-size: var(--text-sm); }
.prism-alert-text { color: var(--text-secondary); }
/* One emphasis device: the tint and the left bar. A coloured frame on top read as
   three signals for one message. */
.prism-alert[data-tone="info"]     { background: var(--info-subtle);     border-color: var(--border-subtle); border-inline-start-color: var(--info); }
.prism-alert[data-tone="info"] .prism-alert-icon { color: var(--info-text); }
.prism-alert[data-tone="positive"] { background: var(--positive-subtle); border-color: var(--border-subtle); border-inline-start-color: var(--positive); }
.prism-alert[data-tone="positive"] .prism-alert-icon { color: var(--positive-text); }
.prism-alert[data-tone="notice"]   { background: var(--notice-subtle);   border-color: var(--border-subtle); border-inline-start-color: var(--notice); }
.prism-alert[data-tone="notice"] .prism-alert-icon { color: var(--notice-text); }
.prism-alert[data-tone="negative"] { background: var(--negative-subtle); border-color: var(--border-subtle); border-inline-start-color: var(--negative); }
.prism-alert[data-tone="negative"] .prism-alert-icon { color: var(--negative-text); }

/* ---------------- ProgressBar / Meter ---------------- */
.prism-progress { display: flex; flex-direction: column; gap: var(--space-2); }
.prism-progress-head { display: flex; justify-content: space-between; gap: var(--space-3); font-size: var(--text-xs); color: var(--text-secondary); }
.prism-progress-label { font-weight: var(--weight-semibold); color: var(--text-primary); white-space: nowrap; }
.prism-progress-track {
  height: 8px; border-radius: var(--radius-pill);
  background: var(--fill-muted); overflow: hidden;
}
.prism-progress-fill {
  height: 100%; border-radius: inherit;
  background: var(--accent);
  transition: width var(--duration-slow) var(--ease-standard);
}
.prism-progress[data-tone="positive"] .prism-progress-fill { background: var(--positive); }
.prism-progress[data-tone="notice"]   .prism-progress-fill { background: var(--notice); }
.prism-progress[data-tone="negative"] .prism-progress-fill { background: var(--negative); }
/* ---------------- Meter ---------------- */
/* A measured amount (role="meter") — ProgressBar's shape, its own name, so the
   two can diverge without either breaking the other. */
.prism-meter { display: flex; flex-direction: column; gap: var(--space-2); min-inline-size: 0; }
.prism-meter-head { display: flex; justify-content: space-between; align-items: baseline; gap: var(--space-3); font-size: var(--text-xs); color: var(--text-secondary); }
.prism-meter-label { font-weight: var(--weight-semibold); color: var(--text-primary); min-inline-size: 0; overflow-wrap: anywhere; }
.prism-meter-value { font-variant-numeric: tabular-nums; white-space: nowrap; }
.prism-meter-track { block-size: 8px; border-radius: var(--radius-pill); background: var(--fill-muted); overflow: hidden; }
.prism-meter-fill { block-size: 100%; border-radius: inherit; background: var(--accent); }
.prism-meter[data-tone="positive"] .prism-meter-fill { background: var(--positive); }
.prism-meter[data-tone="notice"]   .prism-meter-fill { background: var(--notice); }
.prism-meter[data-tone="negative"] .prism-meter-fill { background: var(--negative); }
.prism-meter[data-tone="neutral"]  .prism-meter-fill { background: var(--text-tertiary); }

.prism-progress[data-indeterminate="true"] .prism-progress-fill {
  width: 35% !important;
  animation: prism-progress-slide 1.2s var(--ease-standard) infinite;
}
@keyframes prism-progress-slide {
  0%   { margin-inline-start: -35%; }
  100% { margin-inline-start: 100%; }
}

/* ---------------- Tabs ---------------- */
.prism-tabs { display: flex; flex-direction: column; gap: var(--space-4);
  /* A grid/flex item's minimum width is its content's by default; the tab row
     is a nowrap scroller, so without this the tabs widened their column (and
     the page) instead of scrolling. */
  min-inline-size: 0; max-inline-size: 100%; }
.prism-tablist {
  display: flex; gap: var(--space-1);
  /* The rule is drawn inside the box (not a border): the scrolling list clips
     everything outside its padding box, and the selected underline must still
     sit on top of the rule. */
  box-shadow: inset 0 calc(-1 * var(--border-width)) 0 var(--border-default);
  /* Too many tabs for the width: scroll sideways (Tabs keeps the selected one
     in view) rather than widening the page. No wrapping, no visible scrollbar. */
  flex-wrap: nowrap; overflow-x: auto; overflow-y: hidden;
  scrollbar-width: none; -webkit-overflow-scrolling: touch;
}
.prism-tablist::-webkit-scrollbar { display: none; }
/* Tabs wraps the list in a frame that carries the rule, so the list itself can
   be masked: when tabs are scrolled out of view, the edge with more fades out
   (Tabs sets data-fade-start / -end from the scroll position). The rule stays
   full width on the frame, under the selected underline. */
.prism-tablist-frame { position: relative; min-inline-size: 0; }
.prism-tablist-frame::after {
  content: ""; position: absolute; inset-inline: 0; inset-block-end: 0;
  block-size: var(--border-width); background: var(--border-default); pointer-events: none;
}
.prism-tablist-frame > .prism-tablist { box-shadow: none; position: relative; z-index: 1; --fade: var(--space-8); }
.prism-tablist-frame[data-fade-start="true"] > .prism-tablist { -webkit-mask-image: linear-gradient(to right, transparent, black var(--fade)); mask-image: linear-gradient(to right, transparent, black var(--fade)); }
.prism-tablist-frame[data-fade-end="true"] > .prism-tablist { -webkit-mask-image: linear-gradient(to left, transparent, black var(--fade)); mask-image: linear-gradient(to left, transparent, black var(--fade)); }
.prism-tablist-frame[data-fade-start="true"][data-fade-end="true"] > .prism-tablist {
  -webkit-mask-image: linear-gradient(to right, transparent, black var(--fade), black calc(100% - var(--fade)), transparent);
  mask-image: linear-gradient(to right, transparent, black var(--fade), black calc(100% - var(--fade)), transparent);
}
/* RTL: the start edge is on the right */
[dir="rtl"] .prism-tablist-frame[data-fade-start="true"]:not([data-fade-end="true"]) > .prism-tablist { -webkit-mask-image: linear-gradient(to left, transparent, black var(--fade)); mask-image: linear-gradient(to left, transparent, black var(--fade)); }
[dir="rtl"] .prism-tablist-frame[data-fade-end="true"]:not([data-fade-start="true"]) > .prism-tablist { -webkit-mask-image: linear-gradient(to right, transparent, black var(--fade)); mask-image: linear-gradient(to right, transparent, black var(--fade)); }
.prism-tablist > .prism-tab { flex: none; white-space: nowrap; }
.prism-tab {
  appearance: none; border: 0; background: transparent; text-decoration: none; /* href tabs render an <a> */
  font-family: var(--label-font); font-weight: var(--weight-semibold);
  font-size: var(--text-sm); color: var(--text-secondary);
  padding: var(--space-3) var(--space-4);
  cursor: pointer;
  position: relative;
  border-radius: var(--radius-sm) var(--radius-sm) 0 0;
  transition: var(--transition-colors);
  display: inline-flex; align-items: center; gap: var(--space-2);
}
.prism-tab > svg { width: var(--icon-sm); height: var(--icon-sm); }
.prism-tab::after {
  content: ""; position: absolute;
  inset-inline: var(--space-2); bottom: 0; height: 2.5px;
  border-radius: var(--radius-pill); background: transparent;
  transition: background-color var(--duration-fast) var(--ease-standard);
}
.prism-tab:hover { color: var(--text-primary); background: var(--fill-subtle); }
.prism-tab:focus-visible { outline: var(--focus-ring-width) solid var(--focus-ring); outline-offset: -2px; }
.prism-tab[aria-selected="true"] { color: var(--accent-text); }
.prism-tab[aria-selected="true"]::after { background: var(--accent); }
.prism-tab[disabled] { opacity: 0.45; cursor: not-allowed; }

/* ---------------- Breadcrumbs ---------------- */
.prism-breadcrumbs { display: flex; align-items: center; flex-wrap: wrap; gap: var(--space-1); font-size: var(--text-sm); }
.prism-crumb { display: inline-flex; align-items: center; gap: var(--space-1); }
.prism-crumb a, .prism-crumb span { color: var(--text-secondary); text-decoration: none; padding: var(--space-0-5) var(--space-1); border-radius: var(--radius-xs); }
.prism-crumb a:hover { color: var(--text-link); background: var(--fill-subtle); }
.prism-crumb a:focus-visible { outline: var(--focus-ring-width) solid var(--focus-ring); outline-offset: 1px; }
.prism-crumb[aria-current="page"] span { color: var(--text-primary); font-weight: var(--weight-semibold); }
.prism-crumb-sep { color: var(--text-tertiary); display: inline-flex; }
.prism-crumb-sep > svg { width: var(--icon-sm); height: var(--icon-sm); }
[dir="rtl"] .prism-crumb-sep > svg { transform: scaleX(-1); }

/* ---------------- Pagination ---------------- */
.prism-pagination { font-size: var(--text-sm); }
.prism-pagination-list { list-style: none; margin: 0; padding: 0; display: flex; align-items: center; flex-wrap: wrap; gap: var(--space-1); }
.prism-pagination-page,
.prism-pagination-step {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--space-1);
  min-inline-size: var(--control-sm); min-block-size: var(--control-sm); padding-inline: var(--space-2);
  border-radius: var(--radius-control); color: var(--text-secondary); text-decoration: none;
  font-weight: var(--weight-medium); font-variant-numeric: tabular-nums;
  transition: var(--transition-colors);
}
.prism-pagination-step > svg { inline-size: var(--icon-sm); block-size: var(--icon-sm); flex: none; }
[dir="rtl"] .prism-pagination-step > svg { transform: scaleX(-1); }
:is(a, button).prism-pagination-page:hover, :is(a, button).prism-pagination-step:not(:disabled):hover { background: var(--fill-subtle); color: var(--text-primary); }
:is(a, button):is(.prism-pagination-page, .prism-pagination-step):focus-visible { outline: var(--focus-ring-width) solid var(--focus-ring); outline-offset: 1px; }
/* the current page: filled, so it isn't carried by colour alone */
:is(a, button).prism-pagination-page[aria-current="page"],
:is(a, button).prism-pagination-page[aria-current="page"]:hover { background: var(--accent); color: var(--accent-on); font-weight: var(--weight-semibold); }
.prism-pagination-step:is([aria-disabled="true"], :disabled) { color: var(--text-disabled); cursor: default; }
/* onChange mode renders buttons: clear the browser's button chrome */
button:is(.prism-pagination-page, .prism-pagination-step) { appearance: none; border: 0; background: transparent; font: inherit; cursor: pointer; }
.prism-pagination-gap { min-inline-size: var(--control-sm); text-align: center; color: var(--text-tertiary); }
/* "Page X of Y": read on every screen, shown only when the numbers collapse */
.prism-pagination-status {
  position: absolute; inline-size: 1px; block-size: 1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap;
}
@media (max-width: 639.98px) {
  .prism-pagination-list { flex-wrap: nowrap; justify-content: space-between; }
  .prism-pagination-num, .prism-pagination-gap { display: none; }
  .prism-pagination-status { position: static; inline-size: auto; block-size: auto; overflow: visible; clip-path: none; color: var(--text-secondary); font-variant-numeric: tabular-nums; }
}

/* ---------------- Stepper (process nav) ---------------- */
.prism-stepper { display: flex; align-items: center; padding: var(--space-2); overflow-x: auto; }
.prism-stepper[data-orientation="vertical"] { flex-direction: column; align-items: stretch; overflow-x: visible; }
/* Steps may shrink (and their text wrap) so a horizontal stepper fits its
   column instead of overflowing; with room to spare nothing changes. */
.prism-step { display: flex; align-items: center; flex: 0 1 auto; min-width: 0; }
.prism-step-button {
  display: flex; align-items: center; gap: var(--space-3);
  background: transparent; border: 0; padding: var(--space-0-5); font: inherit; color: inherit;
  border-radius: var(--radius-control); text-align: start; cursor: default;
}
.prism-step[data-interactive="true"] .prism-step-button { cursor: pointer; }
.prism-step[data-interactive="true"] .prism-step-button:hover .prism-step-title { color: var(--text-primary); }
.prism-step-button:focus-visible { outline: var(--focus-ring-width) solid var(--focus-ring); outline-offset: 1px; }
.prism-step-marker {
  width: 32px; height: 32px; border-radius: 50%; flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  font-family: var(--font-display); font-weight: var(--weight-semibold); font-size: var(--fs-small);
  border: var(--border-width-strong) solid var(--border-strong); color: var(--text-tertiary);
  background: var(--surface-card); box-shadow: var(--well);
  transition: var(--transition-colors), box-shadow var(--duration-fast) var(--ease-standard);
}
.prism-step-marker > svg { width: 16px; height: 16px; }
.prism-step-text { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.prism-step-title { font-family: var(--label-font); font-weight: var(--weight-semibold); font-size: var(--fs-small); color: var(--text-secondary); }
.prism-step-desc { font-size: var(--text-xs); color: var(--text-tertiary); }
.prism-step-line { flex: 1 1 auto; height: 2px; min-width: 20px; margin: 0 var(--space-3); border-radius: var(--radius-pill); background: var(--border-default); }
.prism-stepper[data-orientation="vertical"] .prism-step { align-items: flex-start; }
.prism-stepper[data-orientation="vertical"] .prism-step-line { width: 2px; height: auto; min-height: 22px; min-width: 0; flex: none; border-radius: 0; align-self: flex-start; margin: var(--space-1) 0 var(--space-1) var(--space-4); }
.prism-stepper[data-orientation="vertical"] .prism-step-row { display: flex; align-items: center; gap: var(--space-3); }
.prism-stepper[data-orientation="vertical"] .prism-step-text { padding-block: var(--space-1); }
/* states */
.prism-step[data-state="current"] .prism-step-marker { border-color: var(--accent); color: var(--accent-text); box-shadow: 0 0 0 4px var(--accent-subtle); }
.prism-step[data-state="current"] .prism-step-title { color: var(--text-primary); }
.prism-step[data-state="complete"] .prism-step-marker { background: var(--accent); background-image: var(--sheen); border-color: var(--accent); color: var(--accent-on); box-shadow: var(--bevel); }
.prism-step[data-state="complete"] .prism-step-title { color: var(--text-primary); }
.prism-step[data-state="error"] .prism-step-marker { border-color: var(--negative); color: var(--negative-text); box-shadow: 0 0 0 4px var(--negative-subtle); }
.prism-step[data-state="error"] .prism-step-title { color: var(--negative-text); }
.prism-step-line[data-reached="true"] { background: var(--accent); }

/* orientation="responsive" — follows its column, not the viewport. */
.prism-stepper-frame { container: prism-stepper / inline-size; }
@container prism-stepper (max-width: 44rem) {
  .prism-stepper[data-orientation="responsive"] .prism-step-desc { display: none; }
}
@container prism-stepper (max-width: 30rem) {
  .prism-stepper[data-orientation="responsive"] { flex-direction: column; align-items: stretch; overflow-x: visible; }
  .prism-stepper[data-orientation="responsive"] .prism-step { align-items: flex-start; }
  .prism-stepper[data-orientation="responsive"] .prism-step-desc { display: block; }
  .prism-stepper[data-orientation="responsive"] .prism-step-text { padding-block: var(--space-1); }
  .prism-stepper[data-orientation="responsive"] .prism-step-line { width: 2px; height: auto; min-height: 22px; min-width: 0; flex: none; border-radius: 0; align-self: flex-start; margin: var(--space-1) 0 var(--space-1) var(--space-4); }
  .prism-stepper[data-orientation="responsive"][data-marker="end"] .prism-step { align-items: stretch; }
  .prism-stepper[data-orientation="responsive"][data-marker="end"] .prism-step-button { width: 100%; }
  .prism-stepper[data-orientation="responsive"][data-marker="end"] .prism-step-text { flex: 1 1 auto; text-align: end; }
  .prism-stepper[data-orientation="responsive"][data-marker="end"] .prism-step-line { align-self: flex-end; margin: var(--space-1) var(--space-4) var(--space-1) 0; }
}

/* ---- marker-after-label variants (data-marker="end") ---- */
.prism-stepper[data-marker="end"] .prism-step-button { flex-direction: row-reverse; }
/* horizontal: label reads first, marker sits to its right */
.prism-stepper[data-orientation="horizontal"][data-marker="end"] .prism-step-text { text-align: end; }
/* vertical: text on the left, marker on the right, connector under the marker */
.prism-stepper[data-orientation="vertical"][data-marker="end"] .prism-step { align-items: stretch; }
.prism-stepper[data-orientation="vertical"][data-marker="end"] .prism-step-button { width: 100%; }
.prism-stepper[data-orientation="vertical"][data-marker="end"] .prism-step-text { flex: 1 1 auto; text-align: end; }
.prism-stepper[data-orientation="vertical"][data-marker="end"] .prism-step-line { align-self: flex-end; margin: var(--space-1) var(--space-4) var(--space-1) 0; }

/* ---------------- Accordion (Disclosure group) ---------------- */
.prism-accordion { border: var(--border-width) solid var(--border-subtle); border-radius: var(--radius-card); overflow: hidden; background: var(--surface-card); }
.prism-accordion-item + .prism-accordion-item { border-top: var(--border-width) solid var(--border-subtle); }
.prism-accordion-trigger {
  width: 100%; display: flex; align-items: center; justify-content: space-between; gap: var(--space-3);
  background: transparent; border: 0; cursor: pointer; text-align: start;
  padding: var(--space-4);
  font-family: var(--label-font); font-weight: var(--weight-semibold); font-size: var(--fs-body); color: var(--text-primary);
  transition: var(--transition-colors);
}
.prism-accordion-trigger:hover { background: var(--fill-subtle); }
.prism-accordion-trigger:focus-visible { outline: var(--focus-ring-width) solid var(--focus-ring); outline-offset: -2px; }
.prism-accordion-chevron { flex: none; color: var(--text-secondary); transition: transform var(--duration-fast) var(--ease-standard); }
.prism-accordion-chevron > svg { width: var(--icon-md); height: var(--icon-md); display: block; }
.prism-accordion-trigger[aria-expanded="true"] .prism-accordion-chevron { transform: rotate(180deg); }
.prism-accordion-panel { padding: 0 var(--space-4) var(--space-4); color: var(--text-secondary); font-size: var(--fs-small); line-height: var(--leading-normal); }
.prism-accordion-panel[hidden] { display: none; }
/* Header row: the disclosure button fills it; item actions sit beside it. */
.prism-accordion-head { display: flex; align-items: center; min-inline-size: 0; }
.prism-accordion-heading { flex: 1 1 auto; min-inline-size: 0; margin: 0; font: inherit; }
.prism-accordion-actions { flex: none; display: flex; align-items: center; gap: var(--space-1); padding-inline-end: var(--space-3); }

/* ---------------- Toast ---------------- */
.prism-toast-region {
  position: fixed; inset-block-end: var(--space-5); inset-inline-end: var(--space-5);
  display: flex; flex-direction: column; gap: var(--space-3);
  z-index: var(--z-toast); pointer-events: none;
}
.prism-toast {
  display: flex; align-items: flex-start; gap: var(--space-3);
  background: var(--surface-overlay); color: var(--text-primary);
  padding: var(--space-3) var(--space-4); border-radius: var(--radius-card);
  border: var(--border-width) solid var(--border-subtle);
  border-inline-start: 4px solid var(--info);
  box-shadow: var(--shadow-lg), var(--bevel-soft); min-width: 300px; max-width: 400px;
  pointer-events: auto;
  animation: prism-toast-in var(--duration-normal) var(--ease-emphasized);
}
@keyframes prism-toast-in { from { opacity: 0; transform: translateY(12px); } }
.prism-toast-icon { flex: none; margin-block-start: 1px; color: var(--info-text); }
.prism-toast-icon > svg { width: var(--icon-md); height: var(--icon-md); }
.prism-toast[data-tone="positive"] { border-inline-start-color: var(--positive); }
.prism-toast[data-tone="positive"] .prism-toast-icon { color: var(--positive-text); }
.prism-toast[data-tone="negative"] { border-inline-start-color: var(--negative); }
.prism-toast[data-tone="negative"] .prism-toast-icon { color: var(--negative-text); }
.prism-toast[data-tone="notice"] { border-inline-start-color: var(--notice); }
.prism-toast[data-tone="notice"] .prism-toast-icon { color: var(--notice-text); }
.prism-toast[data-tone="info"] { border-inline-start-color: var(--info); }
.prism-toast[data-tone="info"] .prism-toast-icon { color: var(--info-text); }
.prism-toast-body { flex: 1; display: flex; flex-direction: column; gap: var(--space-0-5); }
.prism-toast-title { font-family: var(--label-font); font-weight: var(--weight-semibold); font-size: var(--fs-small); color: var(--text-primary); }
.prism-toast-text { font-size: var(--text-xs); color: var(--text-secondary); }
.prism-toast-close {
  flex: none; border: 0; background: transparent; color: var(--text-tertiary); opacity: 0.8;
  cursor: pointer; border-radius: var(--radius-control); width: 24px; height: 24px;
  display: inline-flex; align-items: center; justify-content: center;
}
.prism-toast-close:hover { opacity: 1; background: var(--fill-subtle); color: var(--text-primary); }
.prism-toast-close:focus-visible { outline: var(--focus-ring-width) solid var(--focus-ring); outline-offset: 1px; }
.prism-toast-close > svg { width: var(--icon-sm); height: var(--icon-sm); }


/* ============================================================
   MOTION · progress fills travel, tab indicators arrive, steps light
   ============================================================ */
@media (prefers-reduced-motion: no-preference) {
  .prism-progress:not([data-indeterminate="true"]) .prism-progress-fill { transition: width var(--duration-slow) var(--ease-standard); }
  .prism-tab[aria-selected="true"]::after { animation: prism-indicator-in var(--duration-normal) var(--ease-emphasized); }
  @keyframes prism-indicator-in { from { transform: scaleX(0.35); opacity: 0; } }
  .prism-step-marker { transition: background-color var(--duration-normal) var(--ease-standard), border-color var(--duration-normal) var(--ease-standard), box-shadow var(--duration-normal) var(--ease-standard), color var(--duration-normal) var(--ease-standard); }
  .prism-step-line { transition: background-color var(--duration-normal) var(--ease-standard); }
}

/* ---------------- Print ----------------
   Toasts are transient screen messages: never printed. */
@media print {
  .prism-toast-region { display: none !important; }
}

/* ===== components/overlays/overlays.css ===== */
/* ============================================================
   Prism · Overlay component styles
   Dialog / Modal · Menu · Tooltip · Popover
   ============================================================ */

/* ---------------- Modal / Dialog ---------------- */
.prism-modal-scrim {
  position: fixed; inset: 0;
  background: var(--surface-scrim);
  display: flex; align-items: center; justify-content: center;
  padding: var(--space-4);
  z-index: var(--z-modal);
  animation: prism-fade var(--duration-fast) var(--ease-standard);
}
.prism-dialog {
  background: var(--surface-overlay);
  border: var(--border-width) solid var(--border-subtle);
  border-radius: var(--radius-surface);
  box-shadow: var(--shadow-xl);
  width: 100%;
  max-width: 480px;
  max-height: calc(100vh - var(--space-8));
  display: flex; flex-direction: column;
  animation: prism-pop var(--duration-normal) var(--ease-emphasized);
}
.prism-dialog[data-size="lg"] { max-width: 720px; }
.prism-dialog[data-size="sm"] { max-width: 380px; }
.prism-dialog[data-size="xs"] { max-width: 320px; }
.prism-dialog-head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--space-4); padding: var(--pad-card) var(--pad-card) var(--space-3); }
.prism-dialog-title { font-family: var(--heading-font); font-size: var(--fs-h3); font-weight: var(--weight-semibold); margin: 0; display: flex; align-items: center; gap: var(--space-2); }
.prism-dialog-warn { display: inline-flex; flex: none; color: var(--negative); }
.prism-dialog-warn > svg { width: var(--icon-md); height: var(--icon-md); }
.prism-dialog-body { padding: 0 var(--pad-card); overflow-y: auto; color: var(--text-secondary); font-size: var(--fs-body); line-height: var(--leading-normal); }
/* with no footer the body is the last child and closes the dialog itself */
.prism-dialog-body:last-child { padding-block-end: var(--pad-card); }
/* ConfirmDialog: the message under the title */
/* An alert dialog asks one short question: body face at a lead size, so
   "Leave without saving?" sits on one line in a ~380px dialog instead of
   wrapping in the display face. */
[role="alertdialog"] .prism-dialog-title { font-family: var(--body-font); font-size: var(--fs-body-lg); line-height: var(--leading-snug); letter-spacing: normal; text-wrap: balance; }
.prism-confirm-desc { margin: 0; color: var(--text-secondary); text-wrap: pretty; }
.prism-confirm-desc > :where(p) { margin: 0; }
.prism-confirm-desc > * + * { margin-block-start: var(--space-2); }
.prism-dialog-foot { display: flex; justify-content: flex-end; gap: var(--gap-inline); padding: var(--pad-card); margin-top: var(--space-2); }
@keyframes prism-fade { from { opacity: 0; } }
@keyframes prism-pop { from { opacity: 0; transform: translateY(8px) scale(0.98); } }

/* Title kept for screen readers only: the head holds just the close button. */
.prism-dialog-head[data-title-hidden="true"] { justify-content: flex-end; padding-block-end: 0; }

/* size="full" — fills the viewport (lightbox, media viewer). */
.prism-dialog[data-size="full"] { max-width: none; width: 100%; height: 100%; max-height: none; }
.prism-dialog[data-size="full"] .prism-dialog-body { flex: 1; }

/* backdrop="dark" — a near-black backdrop for media (overrides a theme's
   light veil too). */
.prism-modal-scrim[data-backdrop="dark"] { background: color-mix(in oklab, var(--gray-950) 88%, transparent); }

/* placement="end" — a side sheet from the inline-end edge: full height, the
   footer pinned to the bottom, the body scrolling between. Sizes set its
   width; below the tablet tier it takes the whole width. */
.prism-modal-scrim[data-placement="end"] { justify-content: flex-end; align-items: stretch; padding: 0; }
.prism-dialog[data-placement="end"] {
  height: 100%; max-height: none;
  border-radius: 0; border-block: 0; border-inline-end: 0;
  border-start-start-radius: var(--radius-surface); border-end-start-radius: var(--radius-surface);
  animation: prism-sheet-in var(--duration-normal) var(--ease-emphasized);
}
.prism-dialog[data-placement="end"] .prism-dialog-body { flex: 1; }
.prism-dialog[data-placement="end"] .prism-dialog-foot { border-block-start: var(--border-width) solid var(--border-subtle); margin-top: 0; }
[dir="rtl"] .prism-dialog[data-placement="end"] { animation-name: prism-sheet-in-rtl; }
@media (max-width: 639.98px) {
  .prism-dialog[data-placement="end"] { max-width: none; border-radius: 0; }
}
@keyframes prism-sheet-in { from { transform: translateX(100%); } }
@keyframes prism-sheet-in-rtl { from { transform: translateX(-100%); } }

/* ---------------- Menu ---------------- */
.prism-menu {
  margin: 0; list-style: none; /* sometimes a <ul> (AppHeader's More menu) */
  background: var(--surface-overlay);
  border: var(--border-width) solid var(--border-default);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-lg);
  padding: var(--space-1);
  min-width: 200px;
  z-index: var(--z-dropdown);
  animation: prism-pop var(--duration-fast) var(--ease-standard);
}
/* Menu component: a popover="manual" in the top layer, placed by script against
   the viewport, so a Dialog body or card overflow never clips it. These lines
   undo the browser's [popover] defaults. */
.prism-menu[data-anchored="true"] {
  position: fixed; inset: auto; top: 0; left: 0; color: var(--text-primary);
  max-inline-size: calc(100vw - 2 * var(--space-2)); overflow: auto; box-sizing: border-box;
}
.prism-menu-item {
  display: flex; align-items: center; gap: var(--space-3);
  width: 100%; border: 0; background: transparent; cursor: pointer;
  padding: var(--space-2) var(--space-3); height: var(--size-touch);
  border-radius: var(--radius-control);
  font-family: var(--body-font); font-size: var(--fs-small); color: var(--text-primary);
  text-align: start; transition: var(--transition-colors);
  text-decoration: none; box-sizing: border-box; /* link items (href) render an <a> */
}
.prism-menu-item > svg { width: var(--icon-sm); height: var(--icon-sm); flex: none; color: var(--text-secondary); }
.prism-menu-item .prism-menu-shortcut { margin-inline-start: auto; font-family: var(--font-mono); font-size: var(--text-xs); color: var(--text-tertiary); }
.prism-menu-item:hover, .prism-menu-item[data-focused="true"] { background: var(--fill-subtle); }
.prism-menu-item:focus-visible { outline: var(--focus-ring-width) solid var(--focus-ring); outline-offset: -2px; }
.prism-menu-item[data-tone="negative"] { color: var(--negative-text); }
.prism-menu-item[data-tone="negative"] > svg { color: var(--negative-text); }
.prism-menu-sep { height: 1px; background: var(--border-subtle); margin: var(--space-1) 0; }
.prism-menu-label { padding: var(--space-2) var(--space-3) var(--space-1); font-size: var(--text-xs); font-weight: var(--weight-semibold); color: var(--text-tertiary); }
/* header slot — e.g. the signed-in user above the account menu; not an item */
.prism-menu-header {
  padding: var(--space-2) var(--space-3) var(--space-3); margin-block-end: var(--space-1);
  border-block-end: var(--border-width) solid var(--border-subtle);
  font-size: var(--fs-small); color: var(--text-secondary);
}

/* ---------------- Tooltip ---------------- */
.prism-tooltip {
  background: var(--surface-inverse);
  color: var(--text-on-inverse);
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-control);
  box-shadow: var(--shadow-md);
  max-width: 240px;
  z-index: var(--z-tooltip);
  animation: prism-fade var(--duration-fast) var(--ease-standard);
}
.prism-tooltip-wrap { position: relative; display: inline-flex; }
/* A popover="manual" in the top layer, placed by script against the viewport
   (above the trigger, flipped below near the top), so a Dialog body or card
   overflow never clips it. These lines undo the browser's [popover] defaults. */
.prism-tooltip-pop {
  position: fixed; inset: auto; top: 0; left: 0; margin: 0; padding: 0;
  border: 0; background: transparent; overflow: visible; color: inherit;
  pointer-events: none; inline-size: max-content; max-inline-size: calc(100vw - 2 * var(--space-2));
}
.prism-tooltip-pop[hidden] { display: none; }
.prism-tooltip-pop .prism-tooltip { display: block; overflow-wrap: break-word; }

/* ===== components/data/data.css ===== */
/* ============================================================
   Prism · Data component styles
   Table
   ============================================================ */

.prism-table-wrap { width: 100%; overflow-x: auto; border: var(--border-width) solid var(--border-subtle); border-radius: var(--radius-card); }
.prism-table { width: 100%; border-collapse: collapse; font-size: var(--fs-small); }
.prism-table caption { text-align: start; padding: var(--space-3) var(--pad-card); font-weight: var(--weight-semibold); color: var(--text-primary); }
.prism-table th {
  text-align: start; font-weight: var(--weight-semibold);
  color: var(--text-secondary); font-size: var(--fs-caption);
  padding: var(--space-3) var(--pad-card);
  border-bottom: var(--border-width) solid var(--border-default);
  background: var(--surface-card);
  position: sticky; top: 0;
  white-space: nowrap;
}
.prism-table th[aria-sort] { cursor: pointer; user-select: none; }
.prism-th-sort {
  display: inline-flex; align-items: center; gap: var(--space-1-5);
  background: transparent; border: 0; cursor: pointer; padding: 0;
  font: inherit; color: inherit; letter-spacing: inherit; text-transform: inherit;
}
.prism-th-sort:focus-visible { outline: var(--focus-ring-width) solid var(--focus-ring); outline-offset: 2px; border-radius: var(--radius-xs); }
.prism-th-sort:hover { color: var(--text-primary); }
.prism-table th .prism-sort-icon { display: inline-flex; vertical-align: middle; opacity: 0; transition: opacity var(--duration-fast) var(--ease-standard); }
.prism-th-sort:hover .prism-sort-icon { opacity: 0.5; }
.prism-table th .prism-sort-icon[data-active="true"] { opacity: 1; color: var(--accent-text); }
/* selection checkbox column */
.prism-table-checkcol { width: 1%; white-space: nowrap; }
.prism-table-checkcol .prism-checkbox { gap: 0; }
.prism-table-checkcol .prism-checkbox-box { width: 18px; height: 18px; margin: 0; }
.prism-table-checkcol .prism-checkbox-box > svg { width: 13px; height: 13px; }
.prism-table td { padding: var(--space-3) var(--pad-card); border-bottom: var(--border-width) solid var(--border-subtle); color: var(--text-primary); }
.prism-table tbody tr:last-child td { border-bottom: 0; }
.prism-table tbody tr { transition: background-color var(--duration-fast) var(--ease-standard); }
/* subtle zebra striping — on by default, disable with data-striped="false".
   An expandable table stripes by DATA row (data-alt), since detail rows
   would throw nth-of-type off; a detail row carries its row's stripe.
   Zero specificity (:where), so hover, tone and selection always show over it. */
:where(.prism-table:not([data-striped="false"]):not([data-expandable="true"]) tbody tr:nth-of-type(even)),
:where(.prism-table:not([data-striped="false"])[data-expandable="true"] tbody tr[data-alt="true"]) { background: var(--surface-stripe); }
.prism-table[data-hoverable="true"] tbody tr:not(.prism-table-detail):not([data-disabled="true"]):hover { background: var(--fill-subtle); }
/* Row tone: a tint, plus a leading edge bar whose SHAPE differs by tone
   (solid / dashed / thin), so colour is never the only cue. */
.prism-table tbody tr[data-tone="negative"] { --row-tint: var(--negative-subtle); }
.prism-table tbody tr[data-tone="notice"] { --row-tint: var(--notice-subtle); }
.prism-table tbody tr[data-tone="positive"] { --row-tint: var(--positive-subtle); }
.prism-table tbody tr[data-tone] { background: var(--row-tint); }
.prism-table[data-hoverable="true"] tbody tr[data-tone]:not(.prism-table-detail):hover {
  background: color-mix(in oklab, var(--row-tint) 65%, var(--fill-subtle)); /* hover keeps the tint */
}
.prism-table tbody tr[data-tone]:not(.prism-table-detail) > :first-child { position: relative; }
.prism-table tbody tr[data-tone]:not(.prism-table-detail) > :first-child::before {
  content: ""; position: absolute; inset-block: 0; inset-inline-start: 0; inline-size: 4px;
}
.prism-table tbody tr[data-tone="negative"]:not(.prism-table-detail) > :first-child::before { background: var(--negative); }
.prism-table tbody tr[data-tone="notice"]:not(.prism-table-detail) > :first-child::before {
  background: repeating-linear-gradient(to bottom, var(--notice) 0 5px, transparent 5px 8px);
}
.prism-table tbody tr[data-tone="positive"]:not(.prism-table-detail) > :first-child::before { background: var(--positive); inline-size: 2px; }
.prism-table tbody tr[aria-selected="true"] { background: var(--accent-subtle); }
.prism-table tbody tr:focus-visible { outline: var(--focus-ring-width) solid var(--focus-ring); outline-offset: -2px; }
/* Row actions (onRowAction). The row stays a table row; its action is a real
   <button> in the first column cell, visually hidden so the row looks the same.
   Keyboard focus on that button rings the whole row; a pointer click anywhere
   on the row runs the same action (handled in Table.jsx). */
.prism-table-rowaction {
  position: absolute; inline-size: 1px; block-size: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.prism-table tbody tr[data-actionable="true"] { cursor: pointer; }
.prism-table tbody tr:has(> td > .prism-table-rowaction:focus-visible) { outline: var(--focus-ring-width) solid var(--focus-ring); outline-offset: -2px; }
/* Disabled rows: muted, no hover, not-allowed. The action is aria-disabled, so
   it stays focusable and is announced as unavailable. */
.prism-table tbody tr[data-disabled="true"] { cursor: not-allowed; }
.prism-table tbody tr[data-disabled="true"] > td { color: var(--text-disabled); }

/* Grouped headers (headerGroups): a band row above the column headers.
   Ungrouped columns span both rows and sit on the bottom line with the rest. */
.prism-table th.prism-table-band {
  text-align: center; color: var(--text-primary);
  border-bottom: var(--border-width) solid var(--border-subtle);
  border-inline: var(--border-width) solid var(--border-subtle);
}
.prism-table[data-grouped="true"] th[rowspan] { vertical-align: bottom; }
/* Two header rows can't both stick at top: 0, so the whole head sticks. */
.prism-table[data-grouped="true"] thead { position: sticky; top: 0; z-index: 1; }
.prism-table[data-grouped="true"] th { position: static; }
/* align: "end" right-aligns the header and cells; only body cells take the
   monospace figures (a header is a label, not a number). */
.prism-table .prism-num { text-align: end; }
.prism-table td.prism-num { font-family: var(--font-mono); }
/* Vertical alignment: middle by default; "top" (table-wide or per column) for
   cells that hold a field plus a caption, so neighbours line up at the top. */
.prism-table[data-valign="top"] td, .prism-table td[data-valign="top"] { vertical-align: top; }
.prism-table td[data-valign="middle"] { vertical-align: middle; }
.prism-table .prism-mono { font-family: var(--font-mono); }
/* Column sizing: nowrap keeps dates/codes on one line; truncate cuts at the
   column's width with an ellipsis (full text in the cell's title). */
/* Cell wrapping. Words never split by default: text wraps at its spaces
   (break-word only splits a word wider than the whole column, and unlike
   `anywhere` it doesn't lower min-content, so an auto-layout column never
   shrinks a name to one letter per line). Mono columns hold codes and ids
   (INV-00004), which stay on one line. A column of long references (payment
   refs, URLs) opts in with wrap: "anywhere" — it may break between any two
   characters, but never narrower than 10ch. What still doesn't fit scrolls
   inside the table's own wrapper, never past the card. */
.prism-table td { overflow-wrap: break-word; }
.prism-table td.prism-mono:not([data-wrap]) { white-space: nowrap; }
.prism-table td[data-wrap="words"] { white-space: normal; overflow-wrap: break-word; }
.prism-table td[data-wrap="anywhere"] { white-space: normal; overflow-wrap: anywhere; min-inline-size: 10ch; }
.prism-table td[data-wrap="none"] { white-space: nowrap; }
.prism-table td.prism-num { overflow-wrap: normal; }
/* A text cell keeps a 12ch minimum, so when a table runs out of room it
   scrolls in its frame before prose stacks one word per line ("Term / 1, /
   2026–"). Figures, mono and one-line columns already hold their width; the
   checkbox and expand columns are exempt. Override per column with minWidth. */
.prism-table td:not(.prism-num, .prism-mono, [data-nowrap="true"], [data-wrap="none"], .prism-table-checkcol, .prism-table-expandcol) { min-inline-size: 12ch; }
/* Column gaps: the card's gutter sits at the table's two outer edges (so text
   lines up with the card), and inner cells split it — one gutter between
   columns rather than two, which leaves the width to the content. */
.prism-table :is(th, td):not(:first-child) { padding-inline-start: calc(var(--pad-card) / 2); }
.prism-table :is(th, td):not(:last-child) { padding-inline-end: calc(var(--pad-card) / 2); }
.prism-table[data-density="compact"] :is(th, td):not(:first-child) { padding-inline-start: calc(var(--space-3) / 2); }
.prism-table[data-density="compact"] :is(th, td):not(:last-child) { padding-inline-end: calc(var(--space-3) / 2); }
/* the expand toggle hugs the next column, as before */
.prism-table :is(th, td).prism-table-expandcol { padding-inline-end: 0; }
/* Headers stay on one line, except on a phone, where a header that wraps at
   its spaces beats a table that scrolls sideways. */
@media (max-width: 639.98px) { .prism-table th:not([data-nowrap="true"]) { white-space: normal; } }
.prism-table :is(th, td)[data-nowrap="true"] { white-space: nowrap; }
.prism-table td[data-truncate="true"] { overflow: hidden; text-overflow: ellipsis; }
/* Expandable rows */
.prism-table .prism-table-expandcol { width: 1%; white-space: nowrap; padding-inline-end: 0; }
.prism-table-expand {
  display: inline-flex; align-items: center; justify-content: center;
  inline-size: var(--control-sm); block-size: var(--control-sm);
  border: 0; border-radius: var(--radius-control); background: transparent;
  color: var(--text-secondary); cursor: pointer;
}
.prism-table-expand:hover { background: var(--fill-subtle); color: var(--text-primary); }
.prism-table-expand:focus-visible { outline: var(--focus-ring-width) solid var(--focus-ring); outline-offset: 1px; }
.prism-table-expand > svg { inline-size: var(--icon-sm); block-size: var(--icon-sm); transition: transform var(--duration-fast) var(--ease-standard); }
.prism-table-expand[aria-expanded="true"] > svg { transform: rotate(90deg); }
[dir="rtl"] .prism-table-expand[aria-expanded="false"] > svg { transform: rotate(180deg); }
.prism-table tbody tr[data-expanded="true"] > td { border-bottom: 0; } /* the row and its detail read as one */
.prism-table tbody tr.prism-table-detail > td { padding-block: var(--space-2) var(--space-4); }
/* Footer row (column footers, e.g. totals) */
.prism-table tfoot td {
  padding: var(--space-3) var(--pad-card);
  border-top: var(--border-width) solid var(--border-default);
  background: var(--surface-card);
  font-weight: var(--weight-semibold); color: var(--text-primary);
}
.prism-table[data-density="compact"] th,
.prism-table[data-density="compact"] td { padding: var(--space-2) var(--space-3); }

/* ============================================================
   DataGrid — toolbar · filters · saved views · pin · inline edit
   ============================================================ */
.prism-datagrid {
  display: flex; flex-direction: column;
  border: var(--border-width) solid var(--border-subtle);
  border-radius: var(--radius-card);
  background: var(--surface-card);
  overflow: hidden;
}

/* toolbar */
.prism-dg-toolbar {
  display: flex; align-items: center; gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  border-bottom: var(--border-width) solid var(--border-subtle);
  flex-wrap: wrap;
}
.prism-dg-toolbar-start { display: flex; align-items: center; gap: var(--space-2); flex: 1 1 auto; min-width: 0; flex-wrap: wrap; }
.prism-dg-toolbar-end { display: flex; align-items: center; gap: var(--space-2); flex: none; }
.prism-dg-search { position: relative; display: inline-flex; align-items: center; min-width: 200px; }
.prism-dg-search > svg { position: absolute; inset-inline-start: 10px; width: var(--icon-sm); height: var(--icon-sm); color: var(--text-tertiary); pointer-events: none; }
.prism-dg-search input {
  height: var(--control-sm, 32px); width: 100%;
  padding: 0 var(--space-3) 0 calc(var(--space-3) + var(--icon-sm) + var(--space-1-5));
  border: var(--border-width) solid var(--border-default); border-radius: var(--radius-control);
  background: var(--surface-card); color: var(--text-primary); font: inherit; font-size: var(--text-sm);
}
.prism-dg-search input:focus-visible { outline: var(--focus-ring-width) solid var(--focus-ring); outline-offset: 1px; border-color: var(--accent); }

/* a small ghost toolbar button (filters / columns / views) */
.prism-dg-tool {
  display: inline-flex; align-items: center; gap: var(--space-1-5);
  height: var(--control-sm, 32px); padding: 0 var(--space-3);
  border: var(--border-width) solid var(--border-default); border-radius: var(--radius-control);
  background: var(--surface-card); color: var(--text-secondary);
  font: inherit; font-size: var(--text-sm); font-weight: var(--weight-medium); cursor: pointer;
  white-space: nowrap; transition: var(--transition-colors);
}
.prism-dg-tool:hover { background: var(--fill-subtle); color: var(--text-primary); }
.prism-dg-tool:focus-visible { outline: var(--focus-ring-width) solid var(--focus-ring); outline-offset: 1px; }
.prism-dg-tool[aria-expanded="true"], .prism-dg-tool[data-active="true"] { border-color: var(--accent); color: var(--accent-text); background: var(--accent-subtle); }
.prism-dg-tool > svg { width: var(--icon-sm); height: var(--icon-sm); }
.prism-dg-tool .prism-dg-count {
  font-family: var(--font-mono); font-size: var(--fs-caption); line-height: 1;
  background: var(--accent); color: var(--accent-on); border-radius: var(--radius-pill);
  padding: var(--space-0-5) var(--space-1-5); margin-inline-start: var(--space-0-5);
}

/* popover panels */
.prism-dg-pop-wrap { position: relative; }
.prism-dg-pop {
  position: absolute; inset-block-start: calc(100% + 4px); inset-inline-end: 0; z-index: var(--z-popover, 50);
  min-width: 240px; max-width: 320px;
  background: var(--surface-overlay); border: var(--border-width) solid var(--border-subtle);
  border-radius: var(--radius-card); box-shadow: var(--shadow-lg); padding: var(--space-3);
  display: flex; flex-direction: column; gap: var(--space-2);
}
.prism-dg-pop-title { font-size: var(--fs-caption); color: var(--text-tertiary); font-weight: var(--weight-semibold); padding: 0 var(--space-0-5); }
.prism-dg-pop-row { display: flex; align-items: center; gap: var(--space-2); padding: var(--space-1) var(--space-0-5); font-size: var(--text-sm); color: var(--text-primary); cursor: pointer; border-radius: var(--radius-sm); }
.prism-dg-pop-row:hover { background: var(--fill-subtle); }
.prism-dg-pop-row .prism-dg-pop-grow { flex: 1 1 auto; min-width: 0; }
.prism-dg-pop-foot { display: flex; justify-content: space-between; gap: var(--space-2); padding-top: var(--space-2); border-top: var(--border-width) solid var(--border-subtle); }
.prism-dg-linkbtn { background: transparent; border: 0; color: var(--text-link); font: inherit; font-size: var(--text-sm); font-weight: var(--weight-medium); cursor: pointer; padding: var(--space-0-5); }
.prism-dg-linkbtn:hover { text-decoration: underline; }
.prism-dg-linkbtn:disabled { color: var(--text-tertiary); cursor: not-allowed; text-decoration: none; }

/* active-filter chips */
.prism-dg-chips { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); padding: var(--space-2) var(--space-4); border-bottom: var(--border-width) solid var(--border-subtle); background: var(--surface-sunken); }
.prism-dg-chip {
  display: inline-flex; align-items: center; gap: var(--space-1-5);
  height: 26px; padding: 0 var(--space-1-5) 0 var(--space-2); border-radius: var(--radius-pill);
  background: var(--surface-card); border: var(--border-width) solid var(--border-default);
  font-size: var(--text-xs); color: var(--text-secondary);
}
.prism-dg-chip b { color: var(--text-primary); font-weight: var(--weight-semibold); }
.prism-dg-chip-x { display: inline-flex; border: 0; background: transparent; color: var(--text-tertiary); cursor: pointer; border-radius: var(--radius-pill); padding: var(--space-0-5); }
.prism-dg-chip-x:hover { background: var(--fill-muted); color: var(--text-primary); }
.prism-dg-chip-x > svg { width: 13px; height: 13px; }

/* scroll region + table */
.prism-dg-scroll { overflow: auto; max-height: var(--dg-max-h, 460px); }
.prism-dg-table { width: 100%; border-collapse: separate; border-spacing: 0; font-size: var(--fs-small); }
.prism-dg-table th, .prism-dg-table td {
  padding: var(--space-3) var(--pad-card); text-align: start;
  border-bottom: var(--border-width) solid var(--border-subtle);
  white-space: nowrap; background: var(--surface-card);
}
.prism-dg-table thead th {
  position: sticky; top: 0; z-index: 2;
  font-size: var(--fs-caption);
  font-weight: var(--weight-semibold); color: var(--text-secondary);
  border-bottom: var(--border-width) solid var(--border-default);
}
.prism-dg-table:not([data-striped="false"]) tbody tr:nth-of-type(even) td { background: var(--surface-stripe); }
.prism-dg-table tbody tr:hover td { background: var(--fill-subtle); }
.prism-dg-table tbody tr[aria-selected="true"] td { background: var(--accent-subtle); }
.prism-dg-table .prism-num { text-align: end; font-family: var(--font-mono); }
.prism-dg-table .prism-mono { font-family: var(--font-mono); }
.prism-dg-table[data-density="compact"] th, .prism-dg-table[data-density="compact"] td { padding: var(--space-2) var(--space-3); }

/* pinned columns (sticky start) — header pin sits above body pin */
/* A sticky cell must be OPAQUE — the columns it pins against scroll underneath
   it. The row states above paint a TINT (--accent-subtle is ~13% alpha) as the
   whole background, which replaces the opaque colour rather than sitting on it.
   So pinned cells take an opaque base and the state tint as a background-image
   layered over it; this holds whether or not a theme's tint carries alpha. */
.prism-dg-table .prism-dg-pinned { position: sticky; z-index: 1; background-color: var(--surface-card); }
.prism-dg-table:not([data-striped="false"]) tbody tr:nth-of-type(even) .prism-dg-pinned { background-image: linear-gradient(var(--surface-stripe), var(--surface-stripe)); }
.prism-dg-table tbody tr:hover .prism-dg-pinned { background-image: linear-gradient(var(--fill-subtle), var(--fill-subtle)); }
.prism-dg-table tbody tr[aria-selected="true"] .prism-dg-pinned { background-image: linear-gradient(var(--accent-subtle), var(--accent-subtle)); }
.prism-dg-table thead .prism-dg-pinned { z-index: 3; }
.prism-dg-table .prism-dg-pinned[data-last-pinned="true"] { box-shadow: 1px 0 0 var(--border-default), 6px 0 12px -8px rgb(0 0 0 / 0.18); }
[dir="rtl"] .prism-dg-table .prism-dg-pinned[data-last-pinned="true"] { box-shadow: -1px 0 0 var(--border-default), -6px 0 12px -8px rgb(0 0 0 / 0.18); }

.prism-dg-table .prism-table-checkcol { width: 1%; }
.prism-dg-th-sort { display: inline-flex; align-items: center; gap: var(--space-1-5); background: transparent; border: 0; cursor: pointer; padding: 0; font: inherit; color: inherit; letter-spacing: inherit; text-transform: inherit; }
.prism-dg-th-sort:focus-visible { outline: var(--focus-ring-width) solid var(--focus-ring); outline-offset: 2px; border-radius: var(--radius-xs); }
.prism-dg-th-sort:hover { color: var(--text-primary); }
.prism-dg-table th .prism-sort-icon { display: inline-flex; vertical-align: middle; opacity: 0; transition: opacity var(--duration-fast) var(--ease-standard); }
.prism-dg-th-sort:hover .prism-sort-icon { opacity: 0.5; }
.prism-dg-table th .prism-sort-icon[data-active="true"] { opacity: 1; color: var(--accent-text); }

/* inline edit */
.prism-dg-cell-edit { display: inline-flex; align-items: center; gap: var(--space-1-5); width: 100%; }
.prism-dg-table td[data-editable="true"] { cursor: text; }
.prism-dg-table td[data-editable="true"]:hover { box-shadow: inset 0 0 0 1px var(--border-default); }
.prism-dg-edit-pencil { opacity: 0; color: var(--text-tertiary); flex: none; transition: opacity var(--duration-fast) var(--ease-standard); }
.prism-dg-table td[data-editable="true"]:hover .prism-dg-edit-pencil { opacity: 0.6; }
.prism-dg-edit-pencil > svg { width: 13px; height: 13px; }
.prism-dg-input {
  width: 100%; min-width: 80px; box-sizing: border-box;
  height: 28px; padding: 0 var(--space-2); font: inherit; font-size: var(--fs-small);
  border: var(--border-width) solid var(--accent); border-radius: var(--radius-sm);
  background: var(--surface-card); color: var(--text-primary);
}
.prism-dg-input:focus-visible { outline: var(--focus-ring-width) solid var(--focus-ring); outline-offset: 1px; }

/* footer summary */
.prism-dg-footer {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-3);
  padding: var(--space-2) var(--space-4); border-top: var(--border-width) solid var(--border-subtle);
  font-size: var(--text-xs); color: var(--text-secondary); background: var(--surface-card);
}
.prism-dg-footer b { color: var(--text-primary); font-weight: var(--weight-semibold); }
.prism-dg-footer-sel { color: var(--accent-text); }

/* empty region inside the grid body */
.prism-dg-empty-cell { padding: 0 !important; background: var(--surface-card) !important; }

/* ---------------- Tree ---------------- */
.prism-tree { font-size: var(--fs-small); color: var(--text-primary); }
.prism-tree[role="tree"] { padding: var(--space-1); }
.prism-tree-row {
  display: flex; align-items: center; gap: var(--space-1-5);
  height: 32px; padding-inline-end: var(--space-2);
  border-radius: var(--radius-control); cursor: pointer;
  transition: var(--transition-colors); user-select: none;
}
.prism-tree-row:hover { background: var(--fill-subtle); }
.prism-tree-row:focus-visible { outline: var(--focus-ring-width) solid var(--focus-ring); outline-offset: -2px; }
.prism-tree-row[aria-selected="true"] { background: var(--accent-subtle); color: var(--accent-text); }
.prism-tree-toggle {
  width: 20px; height: 20px; flex: none; border: 0; background: transparent; cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center; color: var(--text-secondary);
  border-radius: var(--radius-xs);
}
.prism-tree-toggle > svg { width: 16px; height: 16px; transition: transform var(--duration-fast) var(--ease-standard); }
.prism-tree-row[data-expanded="true"] .prism-tree-toggle > svg { transform: rotate(90deg); }
[dir="rtl"] .prism-tree-row[data-expanded="true"] .prism-tree-toggle > svg { transform: rotate(-90deg); }
.prism-tree-spacer { width: 20px; flex: none; }
.prism-tree-icon { color: var(--text-tertiary); display: inline-flex; flex: none; }
.prism-tree-row[aria-selected="true"] .prism-tree-icon { color: var(--accent-text); }
.prism-tree-icon > svg { width: var(--icon-sm); height: var(--icon-sm); }
.prism-tree-label { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* ============================================================
   Cell renderers — DeltaValue · MiniBar · StatusDot · AvatarStack
   Deliberately matte, including under Industry: these repeat on
   every row, which makes them chrome. The lit-gel material is a
   signal reserved for the one real chart on the screen.
   ============================================================ */

/* ---------------- DeltaValue ---------------- */
.prism-delta { display: inline-flex; align-items: baseline; gap: var(--space-2); }
.prism-delta-val { color: var(--text-primary); font-variant-numeric: tabular-nums; }
.prism-delta[data-size="sm"] { font-size: var(--text-xs); }
.prism-delta[data-size="md"] .prism-delta-val { font-size: var(--fs-small); }
.prism-delta[data-size="lg"] .prism-delta-val { font-size: var(--text-2xl); font-weight: var(--weight-semibold); font-family: var(--heading-font); }
.prism-delta-chg {
  display: inline-flex; align-items: center; gap: var(--space-0-5);
  font-family: var(--font-mono); font-size: var(--text-xs);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.prism-delta-chg > svg { width: 12px; height: 12px; flex: none; }
.prism-delta[data-size="lg"] .prism-delta-chg { font-size: var(--text-sm); }
.prism-delta[data-size="lg"] .prism-delta-chg > svg { width: 14px; height: 14px; }
.prism-delta-chg[data-tone="positive"] { color: var(--led-positive, var(--positive)); }
.prism-delta-chg[data-tone="negative"] { color: var(--led-negative, var(--negative)); }
.prism-delta-chg[data-tone="neutral"]  { color: var(--text-tertiary); }
/* flat gets a shorter bar so the glyph itself still distinguishes it */
.prism-delta-chg[data-dir="flat"] > svg { width: 10px; }

/* ---------------- MiniBar ---------------- */
.prism-minibar { display: inline-flex; align-items: center; gap: var(--space-2); }
.prism-minibar-track {
  display: block; inline-size: var(--minibar-w, 72px); block-size: 6px; flex: none;
  border-radius: var(--radius-pill); background: var(--fill-subtle);
  box-shadow: var(--shadow-inset, none); overflow: hidden;
}
.prism-minibar-fill { display: block; block-size: 100%; border-radius: var(--radius-pill); background: var(--accent); }
.prism-minibar-fill[data-tone="positive"] { background: var(--positive); }
.prism-minibar-fill[data-tone="notice"]   { background: var(--notice); }
.prism-minibar-fill[data-tone="negative"] { background: var(--negative); }
.prism-minibar-fill[data-tone="neutral"]  { background: var(--text-tertiary); }
.prism-minibar-val { font-family: var(--font-mono); font-size: var(--text-xs); font-variant-numeric: tabular-nums; color: var(--text-secondary); }

/* ---------------- BarList ---------------- */
/* A share-of-total breakdown; matte like MiniBar (a reading aid, not a hero chart). */
.prism-barlist { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--space-3); }
.prism-barlist-row { display: flex; flex-direction: column; gap: var(--space-1); min-inline-size: 0; }
.prism-barlist-head { display: flex; justify-content: space-between; align-items: baseline; gap: var(--space-3); font-size: var(--fs-small); }
.prism-barlist-label { color: var(--text-primary); min-inline-size: 0; overflow-wrap: anywhere; }
.prism-barlist-value { display: inline-flex; align-items: baseline; gap: var(--space-2); white-space: nowrap; font-variant-numeric: tabular-nums; color: var(--text-primary); font-weight: var(--weight-semibold); }
.prism-barlist-share { font-family: var(--font-mono); font-size: var(--text-xs); font-weight: var(--weight-regular); color: var(--text-tertiary); }
.prism-barlist-track { display: block; block-size: 6px; border-radius: var(--radius-pill); background: var(--fill-subtle); box-shadow: var(--shadow-inset, none); overflow: hidden; }
.prism-barlist-fill { display: block; block-size: 100%; border-radius: var(--radius-pill); background: var(--accent); }
.prism-barlist-fill[data-tone="positive"] { background: var(--positive); }
.prism-barlist-fill[data-tone="notice"]   { background: var(--notice); }
.prism-barlist-fill[data-tone="negative"] { background: var(--negative); }
.prism-barlist-fill[data-tone="neutral"]  { background: var(--text-tertiary); }
.prism-barlist-fill[data-hue] { background: var(--hue); }

/* ---------------- StatusDot ---------------- */
.prism-statusdot { display: inline-flex; align-items: center; gap: var(--space-2); font-size: var(--fs-small); color: var(--text-primary); white-space: nowrap; }
.prism-statusdot[data-size="sm"] { font-size: var(--text-xs); }
.prism-statusdot-led { inline-size: 8px; block-size: 8px; border-radius: 50%; flex: none; background: var(--text-tertiary); }
.prism-statusdot[data-size="sm"] .prism-statusdot-led { inline-size: 7px; block-size: 7px; }
.prism-statusdot[data-tone="positive"] .prism-statusdot-led { background: var(--led-positive, var(--positive)); box-shadow: var(--led-glow-positive, none); }
.prism-statusdot[data-tone="notice"]   .prism-statusdot-led { background: var(--led-notice, var(--notice)); box-shadow: var(--led-glow-notice, none); }
.prism-statusdot[data-tone="negative"] .prism-statusdot-led { background: var(--led-negative, var(--negative)); box-shadow: var(--led-glow-negative, none); }
.prism-statusdot[data-tone="accent"]   .prism-statusdot-led { background: var(--led, var(--accent)); box-shadow: var(--led-glow-soft, none); }
.prism-statusdot[data-tone="dim"]      .prism-statusdot-led { background: var(--led-dim, var(--text-disabled)); box-shadow: none; }
.prism-statusdot[data-tone="dim"] .prism-statusdot-label { color: var(--text-tertiary); }
@keyframes prism-statusdot-breathe { 0%, 100% { opacity: 1; } 50% { opacity: 0.42; } }
.prism-statusdot[data-pulse="true"] .prism-statusdot-led { animation: prism-statusdot-breathe 2s var(--ease-standard, ease-in-out) infinite; }
@media (prefers-reduced-motion: reduce) { .prism-statusdot[data-pulse="true"] .prism-statusdot-led { animation: none; } }

/* ---------------- AvatarStack ---------------- */
.prism-avatar-stack { display: inline-flex; align-items: center; }
.prism-avatar-stack > * + * { margin-inline-start: calc(-1 * var(--space-2)); }
.prism-avatar-stack .prism-avatar { box-shadow: 0 0 0 2px var(--surface-card); }
.prism-avatar-stack[data-size="xs"] .prism-avatar,
.prism-avatar-stack .prism-avatar[data-size="xs"] { inline-size: 22px; block-size: 22px; font-size: var(--fs-caption); }
.prism-avatar-stack[data-size="xs"] > * + * { margin-inline-start: calc(-1 * var(--space-1-5)); }
.prism-avatar-stack-more {
  display: inline-flex; align-items: center; justify-content: center;
  inline-size: 28px; block-size: 28px; border-radius: var(--radius-pill);
  background: var(--fill-subtle); color: var(--text-secondary);
  font-family: var(--font-mono); font-size: var(--fs-caption); font-variant-numeric: tabular-nums;
  box-shadow: 0 0 0 2px var(--surface-card);
}
.prism-avatar-stack-more[data-size="xs"] { inline-size: 22px; block-size: 22px; font-size: var(--fs-caption); }
.prism-avatar-stack-more[data-size="md"] { inline-size: 40px; block-size: 40px; font-size: var(--text-xs); }

/* ============================================================
   DataGrid — grouping, aggregation footer, bulk action bar
   ============================================================ */
.prism-dg-group-row > td {
  background: var(--surface-stripe, var(--fill-subtle));
  border-block-end: var(--border-width) solid var(--border-default);
  padding: var(--space-2) var(--pad-card);
  position: sticky; inset-inline-start: 0;
}
.prism-dg-group-btn {
  display: inline-flex; align-items: center; gap: var(--space-2);
  background: transparent; border: 0; padding: 0; font: inherit; cursor: pointer;
  color: var(--text-primary); font-weight: var(--weight-semibold); font-size: var(--fs-caption);
}
.prism-dg-group-btn:focus-visible { outline: var(--focus-ring-width) solid var(--focus-ring); outline-offset: 2px; border-radius: var(--radius-xs); }
.prism-dg-group-btn > svg { width: 13px; height: 13px; transition: transform var(--duration-fast) var(--ease-standard); }
.prism-dg-group-btn[aria-expanded="false"] > svg { transform: rotate(-90deg); }
.prism-dg-group-count { color: var(--text-tertiary); font-weight: var(--weight-regular); }
.prism-dg-group-agg { color: var(--text-secondary); font-family: var(--font-mono); font-weight: var(--weight-regular); text-transform: none; letter-spacing: 0; }
/* aggregation row — sticky to the bottom of the scroll box so totals stay visible */
.prism-dg-table tfoot td {
  position: sticky; inset-block-end: 0; z-index: 2;
  background: var(--surface-card);
  border-block-start: var(--border-width) solid var(--border-strong);
  padding: var(--space-3) var(--pad-card);
  font-family: var(--font-mono); font-variant-numeric: tabular-nums;
  color: var(--text-primary); font-weight: var(--weight-semibold);
}
.prism-dg-table tfoot .prism-dg-agg-label { font-family: var(--body-font); font-weight: var(--weight-semibold); font-size: var(--text-xs); color: var(--text-tertiary); }
/* bulk action bar */
.prism-dg-bulk {
  position: sticky; inset-block-end: var(--space-3); z-index: 5;
  --dg-bulk-lift: 44px; /* the bar's own height; lifts the sticky bar over the last row */
  margin: calc(var(--space-3) * -1 - var(--dg-bulk-lift)) auto var(--space-3);
  inline-size: fit-content; max-inline-size: 100%;
  display: flex; align-items: center; gap: var(--space-3);
  padding: var(--space-2) var(--space-2) var(--space-2) var(--space-4);
  border-radius: var(--radius-pill);
  background: var(--surface-overlay); color: var(--text-primary);
  border: var(--border-width) solid var(--border-strong);
  box-shadow: var(--shadow-lg);
  font-size: var(--fs-small);
}
.prism-dg-bulk-count { font-variant-numeric: tabular-nums; white-space: nowrap; }
.prism-dg-bulk-count b { font-family: var(--font-mono); }
.prism-dg-bulk-sep { inline-size: 1px; block-size: 20px; background: var(--border-strong); flex: none; }
.prism-dg-bulk-actions { display: flex; align-items: center; gap: var(--space-2); }
.prism-dg-bulk-btn {
  display: inline-flex; align-items: center; gap: var(--space-1-5); height: 30px; padding: 0 var(--space-3);
  border-radius: var(--radius-pill); border: var(--border-width) solid var(--border-strong);
  background: var(--surface-raised); color: var(--text-primary);
  font: inherit; font-size: var(--text-xs); cursor: pointer;
  transition: var(--transition-colors);
}
.prism-dg-bulk-btn:hover { background: var(--fill-subtle); }
.prism-dg-bulk-btn:focus-visible { outline: var(--focus-ring-width) solid var(--focus-ring); outline-offset: 2px; }
.prism-dg-bulk-btn > svg { width: 14px; height: 14px; }
.prism-dg-bulk-btn[data-tone="negative"] { color: var(--negative); border-color: color-mix(in oklch, var(--negative) 40%, transparent); }
.prism-dg-bulk-btn[data-tone="negative"]:hover { background: color-mix(in oklch, var(--negative) 14%, transparent); }
.prism-dg-bulk-btn[data-tone="accent"] { background: var(--accent); color: var(--accent-on); border-color: transparent; }
.prism-dg-bulk-btn[data-tone="accent"]:hover { background: var(--accent-hover); }
.prism-dg-bulk-x { display: inline-flex; align-items: center; justify-content: center; inline-size: 30px; block-size: 30px; border-radius: var(--radius-pill); border: 0; background: transparent; color: var(--text-tertiary); cursor: pointer; }
.prism-dg-bulk-x:hover { background: var(--fill-subtle); color: var(--text-primary); }
.prism-dg-bulk-x:focus-visible { outline: var(--focus-ring-width) solid var(--focus-ring); outline-offset: 2px; }

/* ---------------- Print ----------------
   On paper the scroll wrapper must not clip: the table takes the page width,
   wraps its cells, repeats its header row on every page and keeps each row
   whole. No hover tint or wrapper chrome. */
@media print {
  .prism-table-wrap { overflow: visible; border: 0; border-radius: 0; }
  .prism-table { width: 100%; }
  .prism-table thead { display: table-header-group; }
  .prism-table tfoot { display: table-footer-group; }
  .prism-table tr { break-inside: avoid; }
  .prism-table :is(th, td)[data-truncate="true"] { white-space: normal; overflow: visible; text-overflow: clip; }
  .prism-statusdot { print-color-adjust: exact; -webkit-print-color-adjust: exact; }
}

/* ===== components/navigation/appheader.css ===== */
/* ============================================================
   Prism · AppHeader (Carbon UI-shell style)
   A top app bar: hamburger (mobile) · brand · primary nav ·
   actions · optional collapsible side nav. Responsive: the
   inline nav collapses into the side panel below --bp.
   ============================================================ */
.prism-appheader {
  display: flex; align-items: stretch;
  /* Constrain to the container regardless of placement: as a flex/grid ITEM the
     default min-width:auto would let the header size to its content and overflow,
     so priority-plus (which measures the header's own width) would decide off a
     wrong, over-grown width and never fold links into "More". min-inline-size:0
     + width caps make the measured width always the AVAILABLE width. */
  inline-size: 100%; min-inline-size: 0; max-inline-size: 100%;
  height: var(--topbar-height);
  background: var(--surface-inverse);
  color: var(--text-on-inverse);
  border-bottom: 1px solid var(--border-inverse);
  font-family: var(--label-font);
  /* A UI-shell top bar stays put: sticky by default (it already claims the
     --z-sticky layer). sticky (not fixed) keeps it in flow so it reserves its
     space — no content jump — and the overlay drawer, being fixed, stays pinned
     regardless. Consumers who want it to scroll away override position:static. */
  position: sticky; inset-block-start: 0; z-index: var(--z-sticky);
}
/* Inverse token context (default bar). The bar is the inverse surface — dark on
   a light page, light on a dark one — so components placed in `actions` (an
   outline or quiet Button, accent text, a Select) would read the PAGE's tokens
   and vanish against it. Re-point the semantic tokens they read to values
   derived from the inverse pair, which flip with the page theme. Not under the
   instrument themes: they re-pin the inverse pair TO the page tokens
   (themes/industry.css), so remapping back would be circular. */
.prism-appheader:not([data-appearance]):not(:is([data-theme="industry"], [data-theme="laboratory"]) *) {
  --text-primary:     var(--text-on-inverse);
  --text-secondary:   color-mix(in oklab, var(--text-on-inverse) 78%, var(--surface-inverse));
  --text-tertiary:    color-mix(in oklab, var(--text-on-inverse) 62%, var(--surface-inverse));
  --text-placeholder: color-mix(in oklab, var(--text-on-inverse) 55%, var(--surface-inverse));
  --text-disabled:    color-mix(in oklab, var(--text-on-inverse) 42%, var(--surface-inverse));
  --surface-card:     var(--surface-inverse);
  --surface-raised:   var(--surface-inverse);
  --surface-sunken:   color-mix(in oklab, var(--text-on-inverse) 8%, var(--surface-inverse));
  --surface-overlay:  color-mix(in oklab, var(--text-on-inverse) 6%, var(--surface-inverse));
  --border-subtle:    color-mix(in oklab, var(--text-on-inverse) 14%, var(--surface-inverse));
  --border-default:   var(--border-inverse);
  --border-strong:    color-mix(in oklab, var(--text-on-inverse) 45%, var(--surface-inverse));
  --fill-subtle:      color-mix(in oklab, var(--text-on-inverse) 10%, transparent);
  --fill-muted:       color-mix(in oklab, var(--text-on-inverse) 16%, transparent);
  --accent-text:      color-mix(in oklab, var(--accent) 55%, var(--text-on-inverse));
  --accent-border:    color-mix(in oklab, var(--accent) 65%, var(--text-on-inverse));
  --accent-subtle:    color-mix(in oklab, var(--accent) 24%, transparent);
  --text-link:        var(--accent-text);
  --focus-ring:       var(--text-on-inverse);
  /* secondary brand detail on the bar's (opposite) surface — tokens/hues.css */
  --sig-2-line:       var(--sig-2-line-inverse);
  /* Status text (a red "Sign out" in a drawer's footer actions, a notice
     line) — the page's values are tuned for the page surface, not the bar. */
  --negative-text:    color-mix(in oklab, var(--negative) 55%, var(--text-on-inverse));
  --positive-text:    color-mix(in oklab, var(--positive) 55%, var(--text-on-inverse));
  --notice-text:      color-mix(in oklab, var(--notice) 55%, var(--text-on-inverse));
  --info-text:        color-mix(in oklab, var(--info) 55%, var(--text-on-inverse));
}
/* Normal-surface header. `theme` sets data-appearance (use the page's
   surfaces instead of the inverse bar). "light"/"dark" also set data-theme to
   pin the scheme (a dark header on a light app); "inherit" sets no data-theme,
   so the header follows the page's theme — including data-theme="system". */
.prism-appheader[data-appearance] { background: var(--surface-card); color: var(--text-primary); border-bottom: 1px solid var(--border-default); }
.prism-appheader[data-appearance] .prism-appheader-nav :is(a, button) { color: var(--text-secondary); }
.prism-appheader[data-appearance] .prism-appheader-nav :is(a, button):hover { background: var(--fill-subtle); color: var(--text-primary); }
.prism-appheader[data-appearance] .prism-appheader-nav :is(a, button)[aria-current="page"] { color: var(--text-primary); }
.prism-appheader[data-appearance] .prism-appheader-menu:hover,
.prism-appheader[data-appearance] .prism-appheader-action:hover { background: var(--fill-subtle); }
.prism-appheader[data-appearance] .prism-appheader-action[aria-pressed="true"] { background: var(--fill-muted); }
.prism-appheader[data-appearance] .prism-appheader-menu:focus-visible,
.prism-appheader[data-appearance] .prism-appheader-nav :is(a, button):focus-visible,
.prism-appheader[data-appearance] .prism-appheader-action:focus-visible { outline-color: var(--focus-ring); }
.prism-appheader[data-appearance] .prism-appheader-action .prism-appheader-dot { box-shadow: 0 0 0 2px var(--surface-card); }
.prism-appheader a { color: inherit; text-decoration: none; }

/* hamburger / menu toggle — only shows when a side nav exists */
.prism-appheader-menu {
  display: inline-flex; align-items: center; justify-content: center;
  width: var(--topbar-height); flex: none;
  background: transparent; border: 0; color: inherit; cursor: pointer;
  transition: background-color var(--duration-fast) var(--ease-standard);
}
.prism-appheader-menu:hover { background: color-mix(in oklab, var(--text-on-inverse) 10%, transparent); }
.prism-appheader-menu:focus-visible { outline: 2px solid var(--text-on-inverse); outline-offset: -2px; }
.prism-appheader-menu > svg { width: var(--icon-md); height: var(--icon-md); }

/* brand lockup */
.prism-appheader-brand {
  display: inline-flex; align-items: center; gap: var(--space-2);
  /* Shrinks before the actions do: a long school name truncates instead of
     pushing the actions off a phone screen. */
  padding-inline: var(--space-4); flex: 0 1 auto; min-inline-size: 0; overflow: hidden;
  font-family: var(--font-display); font-weight: 700; font-size: var(--text-base);
  letter-spacing: -0.01em;
}
.prism-appheader-brand .accent { font-weight: 400; opacity: 0.8; }
/* Sized by HEIGHT with inline-size:auto, so a square logomark AND a wide
   wordmark both fit. Override --brand-mark-height when re-skinning. */
.prism-appheader-brand img, .prism-appheader-brand svg { block-size: var(--brand-mark-height, 22px); inline-size: auto; width: auto; flex: none; }
.prism-appheader-brand > :not(img, svg) { min-inline-size: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* inline primary nav */
/* Nav lives inside a flexible wrap alongside the "More" overflow menu; it clips
   rather than overlapping the actions, and JS moves non-fitting links into More. */
.prism-appheader-navwrap { display: flex; align-items: stretch; flex: 1 1 auto; min-inline-size: 0; margin-inline-start: var(--space-2); position: relative; }
.prism-appheader-nav { display: flex; align-items: stretch; min-inline-size: 0; overflow: hidden; }
.prism-appheader-more { position: relative; flex: none; display: flex; align-items: stretch; }
.prism-appheader-morebtn {
  display: inline-flex; align-items: center; gap: 4px; padding-inline: var(--space-4);
  font-size: var(--text-sm); font-weight: var(--weight-medium); white-space: nowrap;
  border: 0; background: transparent; cursor: pointer; color: color-mix(in oklch, var(--text-on-inverse) 74%, transparent);
}
.prism-appheader-morebtn > svg { width: var(--icon-sm); height: var(--icon-sm); transition: transform var(--duration-fast) var(--ease-standard); }
.prism-appheader-morebtn[aria-expanded="true"] > svg { transform: rotate(180deg); }
.prism-appheader-morebtn:hover { background: color-mix(in oklab, var(--text-on-inverse) 10%, transparent); color: var(--text-on-inverse); }
.prism-appheader-morebtn:focus-visible { outline: 2px solid var(--text-on-inverse); outline-offset: -2px; }
.prism-appheader[data-appearance] .prism-appheader-morebtn { color: var(--text-secondary); }
.prism-appheader[data-appearance] .prism-appheader-morebtn:hover { background: var(--fill-subtle); color: var(--text-primary); }
.prism-appheader[data-appearance] .prism-appheader-morebtn:focus-visible { outline-color: var(--focus-ring); }
.prism-appheader-moremenu { position: absolute; inset-block-start: 100%; inset-inline-end: 0; min-inline-size: 180px; z-index: var(--z-dropdown); margin-block-start: 4px; }
/* Hidden mirror: all links, for stable width measurement (matches nav-link box) */
.prism-appheader-measure { position: absolute; inset-block-start: 0; inset-inline-start: 0; visibility: hidden; pointer-events: none; display: flex; white-space: nowrap; }
.prism-appheader-measure > span { display: inline-flex; align-items: center; padding-inline: var(--space-4); font-size: var(--text-sm); font-weight: var(--weight-medium); white-space: nowrap; }
.prism-appheader-nav :is(a, button) {
  display: inline-flex; align-items: center; padding-inline: var(--space-4);
  border: 0; background: transparent; cursor: pointer; font-family: inherit; text-decoration: none;
  font-size: var(--text-sm); font-weight: var(--weight-medium);
  color: color-mix(in oklch, var(--text-on-inverse) 74%, transparent); position: relative; white-space: nowrap;
  transition: background-color var(--duration-fast) var(--ease-standard), color var(--duration-fast) var(--ease-standard);
}
.prism-appheader-nav :is(a, button):hover { background: color-mix(in oklab, var(--text-on-inverse) 10%, transparent); color: var(--text-on-inverse); }
.prism-appheader-nav :is(a, button):focus-visible { outline: 2px solid var(--text-on-inverse); outline-offset: -2px; }
.prism-appheader-nav :is(a, button)[aria-current="page"] { color: var(--text-on-inverse); }
.prism-appheader-nav :is(a, button)[aria-current="page"]::after {
  /* the school's second colour when it sets --sig-2, else the accent */
  content: ""; position: absolute; inset-inline: 0; bottom: 0; height: 3px; background: var(--sig-2-line, var(--accent));
}

/* actions cluster (pushed to the end) */
.prism-appheader-actions { display: flex; align-items: stretch; margin-inline-start: auto; flex: none; }
.prism-appheader-action {
  display: inline-flex; align-items: center; justify-content: center;
  width: var(--topbar-height); flex: none;
  background: transparent; border: 0; color: inherit; cursor: pointer; position: relative;
  transition: background-color var(--duration-fast) var(--ease-standard);
}
.prism-appheader-action:hover { background: color-mix(in oklab, var(--text-on-inverse) 10%, transparent); }
.prism-appheader-action[aria-pressed="true"] { background: color-mix(in oklab, var(--text-on-inverse) 14%, transparent); }
.prism-appheader-action:focus-visible { outline: 2px solid var(--text-on-inverse); outline-offset: -2px; }
.prism-appheader-action > svg { width: var(--icon-md); height: var(--icon-md); }
.prism-appheader-action .prism-appheader-dot {
  position: absolute; top: 14px; inset-inline-end: 16px; width: 8px; height: 8px;
  border-radius: 50%; background: var(--negative); box-shadow: 0 0 0 2px var(--surface-inverse);
}
.prism-appheader-action[data-variant="profile"] { width: auto; padding-inline: var(--space-3); gap: var(--space-2); }

/* centered slot for custom action nodes (avatar, menus) so they don't stretch */
.prism-appheader-slot { display: inline-flex; align-items: center; padding-inline: var(--space-3); flex: none; }

/* ---------- Side nav (drawer) — opens from the inline-end, by the menu button ---------- */
.prism-sidenav {
  /* fixed (not absolute): a modal overlay anchored to the viewport, so it stays
     put on scroll and doesn't depend on the header being its containing block —
     robust whether or not the consumer keeps the header sticky. */
  position: fixed; inset-block-start: var(--topbar-height); inset-inline-end: 0; inset-inline-start: auto;
  inline-size: var(--sidebar-width); block-size: calc(100vh - var(--topbar-height));
  /* matches the header bar: inverse by default, resolved surfaces under an explicit theme */
  background: var(--surface-inverse); color: var(--text-on-inverse); border-inline-start: 1px solid var(--border-inverse);
  padding: var(--space-3); display: flex; flex-direction: column; gap: var(--space-0-5);
  transform: translateX(100%); transition: transform var(--duration-normal) var(--ease-emphasized);
  z-index: var(--z-overlay); overflow-y: auto; overflow-x: hidden;
}
[dir="rtl"] .prism-sidenav { transform: translateX(-100%); }
.prism-sidenav[data-open="true"] { transform: translateX(0); box-shadow: var(--shadow-lg); }
/* Custom drawer content (a passed-in Sidebar etc.) owns its own layout — drop
   the built-in list padding/gap so it fills the off-canvas shell edge-to-edge. */
.prism-sidenav[data-custom="true"] { padding: 0; gap: 0; }
/* explicit light/dark header → drawer follows the resolved surface (inherits data-theme) */
.prism-appheader[data-appearance] .prism-sidenav { background: var(--surface-card); color: var(--text-primary); border-inline-start-color: var(--border-default); }
.prism-sidenav-item {
  display: flex; align-items: center; gap: var(--space-3); inline-size: 100%; text-decoration: none;
  height: var(--size-touch); padding-inline: var(--space-3); border: 0; background: transparent;
  border-radius: var(--radius-control); cursor: pointer; text-align: start;
  font-family: var(--body-font); font-size: var(--text-base); font-weight: var(--weight-medium);
  color: color-mix(in oklab, var(--text-on-inverse) 82%, transparent); transition: var(--transition-colors);
}
.prism-sidenav-item:hover { background: color-mix(in oklab, var(--text-on-inverse) 10%, transparent); color: var(--text-on-inverse); }
.prism-sidenav-item:focus-visible { outline: var(--focus-ring-width) solid var(--text-on-inverse); outline-offset: -2px; }
.prism-sidenav-item[aria-current="page"] { background: color-mix(in oklab, var(--text-on-inverse) 14%, transparent); color: var(--text-on-inverse); font-weight: var(--weight-semibold); }
/* explicit-theme drawer items use surface-relative tokens */
.prism-appheader[data-appearance] .prism-sidenav-item { color: var(--text-secondary); }
.prism-appheader[data-appearance] .prism-sidenav-item:hover { background: var(--fill-subtle); color: var(--text-primary); }
.prism-appheader[data-appearance] .prism-sidenav-item:focus-visible { outline-color: var(--focus-ring); }
.prism-appheader[data-appearance] .prism-sidenav-item[aria-current="page"] { background: var(--accent-subtle); color: var(--accent-text); }
.prism-sidenav-item > svg { width: var(--icon-md); height: var(--icon-md); flex: none; }
/* drawer groups (drawerGroups / sideNavExtra / the collapsed nav) */
.prism-appheader-drawergroup { display: flex; flex-direction: column; gap: var(--space-0-5); }
.prism-appheader-drawergroup + .prism-appheader-drawergroup { margin-block-start: var(--space-3); padding-block-start: var(--space-3); border-block-start: 1px solid var(--border-subtle); }
.prism-appheader-drawerlabel { padding: var(--space-1) var(--space-3); font-size: var(--text-xs); font-weight: var(--weight-semibold); color: var(--text-tertiary); }
.prism-sidenav-scrim {
  /* starts below the header, like the drawer, so the header's Close (x) button
     isn't covered by its own scrim */
  position: fixed; inset: 0; inset-block-start: var(--topbar-height); background: var(--surface-scrim); z-index: var(--z-overlay);
  animation: prism-fade var(--duration-fast) var(--ease-standard);
}

/* ---------- Responsive: collapse inline nav under the breakpoint ---------- */
.prism-appheader[data-collapsed="true"] .prism-appheader-nav { display: none; }
/* on phones the drawer fills the screen regardless of the rail width */
@media (max-width: 639.98px) {
  .prism-sidenav { inline-size: 100%; }
}

/* ---------------- Print ----------------
   App chrome isn't part of the document: the bar and its drawer are hidden
   on paper. */
@media print {
  .prism-appheader, .prism-sidenav, .prism-sidenav-scrim { display: none !important; }
}

/* ===== components/layout/layout.css ===== */
/* ============================================================
   Prism · Layout shell patterns
   PageHero · SideNav · AppFooter
   Built from role tokens so they scale across density + tiers
   and mirror under dir="rtl".
   ============================================================ */

/* ---------------- PageHero ---------------- */
.prism-page-hero {
  position: relative;
  display: flex;
  gap: var(--gap-section);
  align-items: center;
  padding: var(--pad-card);
  border-radius: var(--radius-surface);
  background: var(--surface-card);
  border: var(--border-width) solid var(--border-subtle);
  box-shadow: var(--shadow-sm), var(--bevel-soft);
  overflow: hidden;
  isolation: isolate;
}
.prism-page-hero[data-tone="primary"] { background: var(--section-primary); border-color: transparent; color: var(--section-primary-on); }
.prism-page-hero[data-tone="secondary"] { background: var(--section-secondary); border-color: var(--section-secondary-border); }
.prism-page-hero[data-tone="tertiary"] { background: var(--section-tertiary); border-color: var(--section-tertiary-border); }
.prism-page-hero[data-tone="accent"] { background: var(--accent); border-color: transparent; color: var(--accent-on); }
.prism-page-hero[data-tone="primary"] :where(.prism-hero-title, .prism-hero-eyebrow),
.prism-page-hero[data-tone="accent"] :where(.prism-hero-title, .prism-hero-eyebrow) { color: inherit; }
.prism-page-hero[data-align="center"] { flex-direction: column; text-align: center; }
.prism-page-hero[data-align="center"] .prism-hero-actions { justify-content: center; }

.prism-hero-body { flex: 1 1 auto; min-inline-size: 0; display: flex; flex-direction: column; gap: var(--gap-stack); }
.prism-hero-eyebrow {
  font-family: var(--font-display); font-size: var(--fs-caption); font-weight: var(--weight-semibold);
  text-transform: uppercase; letter-spacing: var(--tracking-caps); color: var(--text-tertiary);
  display: inline-flex; align-items: center; gap: var(--gap-inline); margin: 0;
}
.prism-page-hero[data-tone="primary"] .prism-hero-eyebrow,
.prism-page-hero[data-tone="accent"] .prism-hero-eyebrow { color: inherit; opacity: 0.85; }
.prism-hero-title {
  font-family: var(--heading-font); font-size: var(--fs-display); font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-tighter); line-height: var(--leading-tight); margin: 0;
  color: var(--text-primary); text-wrap: balance;
}
/* lede: assert calm sentence typography so it can't inherit the display
   tracking/weight of a heading ancestor (which crushed the words together). */
.prism-hero-desc { font-size: var(--fs-lead); color: var(--text-secondary); margin: 0; max-inline-size: 60ch; letter-spacing: normal; font-weight: var(--weight-regular); }
.prism-page-hero[data-tone="primary"] .prism-hero-desc,
.prism-page-hero[data-tone="accent"] .prism-hero-desc { color: inherit; opacity: 0.9; }
.prism-hero-actions { display: flex; flex-wrap: wrap; gap: var(--gap-inline); margin-block-start: var(--space-2); }
.prism-hero-media { flex: 0 1 42%; align-self: stretch; display: flex; align-items: center; justify-content: center; min-inline-size: 0; }
.prism-hero-media > * { max-inline-size: 100%; border-radius: var(--radius-card); }
.prism-page-hero[data-align="center"] .prism-hero-media { flex-basis: auto; inline-size: 100%; }
/* title sizes (the card defaults to --fs-display) */
.prism-hero-title[data-size="hero"] { font-size: var(--fs-hero); line-height: var(--leading-none); }
.prism-hero-title[data-size="showcase"] {
  font-size: var(--fs-showcase); line-height: var(--lh-showcase); letter-spacing: var(--tracking-showcase);
}
/* decoration: behind the content (the hero isolates its stacking context) */
.prism-hero-decoration { position: absolute; inset: 0; z-index: -1; overflow: hidden; pointer-events: none; }
.prism-hero-decoration > :where(img, svg, video, canvas) { inline-size: 100%; block-size: 100%; object-fit: cover; display: block; }

/* variant="band": an edge-to-edge marketing band. No card chrome; the
   content is held to --hero-max in the middle by the inline padding, so the
   band's background and decoration still reach both edges. */
.prism-page-hero[data-variant="band"] {
  --hero-max: var(--container-xl);
  border: 0; border-radius: 0; box-shadow: none;
  padding-block: clamp(var(--space-12), 9vw, var(--space-32));
  padding-inline: max(var(--layout-gutter), (100% - var(--hero-max)) / 2);
}
/* untinted, the band is the page itself: the decoration or page shows through */
.prism-page-hero[data-variant="band"]:not([data-tone]) { background: transparent; }
.prism-page-hero[data-variant="band"] .prism-hero-desc { font-size: var(--fs-lead); max-inline-size: 52ch; }
.prism-page-hero[data-variant="band"] .prism-hero-actions { margin-block-start: var(--space-4); }
.prism-page-hero[data-variant="band"][data-align="center"] { align-items: center; }
.prism-page-hero[data-variant="band"][data-align="center"] .prism-hero-desc { margin-inline: auto; }
@media (max-width: 1023.98px) {
  .prism-page-hero { flex-direction: column; align-items: stretch; }
  .prism-hero-media { order: -1; }
}

/* ---------------- SideNav (persistent rail) ---------------- */
.prism-sidenav-shell {
  display: flex; flex-direction: column;
  inline-size: var(--sidebar-width); flex: none;
  block-size: 100%;
  background: var(--surface-card);
  border-inline-end: var(--border-width) solid var(--border-default);
  padding: var(--pad-card);
  gap: var(--gap-section);
  transition: inline-size var(--duration-normal) var(--ease-standard);
}
.prism-sidenav-shell[data-collapsed="true"] { inline-size: calc(var(--control-xl) + var(--space-4)); }
.prism-sidenav-brand { display: flex; align-items: center; gap: var(--gap-inline); padding: var(--space-2); color: var(--accent); min-block-size: var(--control-md); }
.prism-sidenav-brand-word { font-family: var(--font-display); font-weight: var(--weight-bold); font-size: var(--fs-h4); letter-spacing: -0.01em; color: var(--text-primary); white-space: nowrap; overflow: hidden; }
.prism-sidenav-shell[data-collapsed="true"] .prism-sidenav-brand-word { display: none; }

.prism-sidenav-groups { display: flex; flex-direction: column; gap: var(--space-5); overflow-y: auto; overflow-x: hidden; flex: 1; }
.prism-sidenav-group { display: flex; flex-direction: column; gap: var(--space-0-5); }
.prism-sidenav-grouplabel {
  font-size: var(--text-xs); font-weight: var(--weight-semibold); color: var(--text-tertiary);
  padding: var(--space-2) var(--space-3) var(--space-1);
}
.prism-sidenav-shell[data-collapsed="true"] .prism-sidenav-grouplabel { display: none; }
.prism-sidenav-link {
  display: flex; align-items: center; gap: var(--space-3);
  inline-size: 100%; border: 0; background: transparent; cursor: pointer;
  padding: 0 var(--space-3); min-block-size: var(--size-touch); block-size: var(--size-touch);
  border-radius: var(--radius-control); text-align: start;
  font-family: var(--font-body); font-size: var(--fs-small); font-weight: var(--weight-medium);
  color: var(--text-secondary); transition: var(--transition-colors); text-decoration: none;
}
.prism-sidenav-link > svg { inline-size: var(--icon-md); block-size: var(--icon-md); flex: none; }
.prism-sidenav-link-label { flex: 1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.prism-sidenav-shell[data-collapsed="true"] .prism-sidenav-link-label { display: none; }
.prism-sidenav-shell[data-collapsed="true"] .prism-sidenav-link { justify-content: center; padding: 0; }
.prism-sidenav-link:hover { background: var(--fill-subtle); color: var(--text-primary); }
.prism-sidenav-link:focus-visible { outline: var(--focus-ring-width) solid var(--focus-ring); outline-offset: -2px; }
.prism-sidenav-link[aria-current="page"] { background: var(--accent-subtle); color: var(--accent-text); font-weight: var(--weight-semibold); }
.prism-sidenav-badge {
  flex: none; font-family: var(--font-body); font-weight: var(--weight-semibold); font-size: var(--text-xs); line-height: 1;
  background: var(--accent); color: var(--accent-on); min-inline-size: 20px; block-size: 20px; padding: 0 var(--space-1-5);
  display: inline-flex; align-items: center; justify-content: center; border-radius: var(--radius-pill);
}
.prism-sidenav-shell[data-collapsed="true"] .prism-sidenav-badge { display: none; }
.prism-sidenav-foot { margin-block-start: auto; position: relative; }

/* Section variant — a section nav inside the content area, not the app rail:
   no full height, surface or edge rule; the parent decides the width. */
.prism-sidenav-shell[data-variant="section"] { block-size: auto; inline-size: 100%; background: none; border-inline-end: 0; padding: 0; gap: var(--gap-stack); }

/* Collapse below a size tier (collapseBelow): the list hides behind a
   disclosure button that shows the current item. */
.prism-sidenav-disclosure {
  display: none; align-items: center; gap: var(--space-3);
  inline-size: 100%; min-block-size: var(--size-touch); padding: 0 var(--space-3);
  border: var(--border-width) solid var(--border-default); border-radius: var(--radius-control);
  background: var(--surface-card); color: var(--text-primary); cursor: pointer; text-align: start;
  font-family: var(--font-body); font-size: var(--fs-small); font-weight: var(--weight-semibold);
}
.prism-sidenav-disclosure > svg { inline-size: var(--icon-md); block-size: var(--icon-md); flex: none; }
.prism-sidenav-disclosure > svg:last-child { margin-inline-start: auto; transition: transform var(--duration-fast) var(--ease-standard); }
.prism-sidenav-shell[data-open="true"] .prism-sidenav-disclosure > svg:last-child { transform: rotate(180deg); }
.prism-sidenav-disclosure:focus-visible { outline: var(--focus-ring-width) solid var(--focus-ring); outline-offset: 2px; }
@media (max-width: 1023.98px) {
  .prism-sidenav-shell[data-collapse-below="desktop"] { inline-size: 100%; block-size: auto; border-inline-end: 0; }
  .prism-sidenav-shell[data-collapse-below="desktop"] .prism-sidenav-disclosure { display: flex; }
  .prism-sidenav-shell[data-collapse-below="desktop"]:not([data-open="true"]) .prism-sidenav-groups { display: none; }
  .prism-sidenav-shell[data-collapse-below="desktop"] .prism-sidenav-collapse { display: none; }
}
@media (max-width: 639.98px) {
  .prism-sidenav-shell[data-collapse-below="tablet"] { inline-size: 100%; block-size: auto; border-inline-end: 0; }
  .prism-sidenav-shell[data-collapse-below="tablet"] .prism-sidenav-disclosure { display: flex; }
  .prism-sidenav-shell[data-collapse-below="tablet"]:not([data-open="true"]) .prism-sidenav-groups { display: none; }
  .prism-sidenav-shell[data-collapse-below="tablet"] .prism-sidenav-collapse { display: none; }
}
.prism-sidenav-user { display: flex; align-items: center; gap: var(--space-3); padding: var(--space-2); border-radius: var(--radius-control); }
.prism-sidenav-user-meta { min-inline-size: 0; }
.prism-sidenav-shell[data-collapsed="true"] .prism-sidenav-user-meta { display: none; }
.prism-sidenav-user-name { font-size: var(--fs-small); font-weight: var(--weight-semibold); color: var(--text-primary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.prism-sidenav-user-sub { font-size: var(--text-xs); color: var(--text-tertiary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.prism-sidenav-collapse {
  position: absolute; top: 50%; inset-inline-end: calc(-1 * var(--pad-card));
  transform: translate(50%, -50%);
  display: inline-flex; align-items: center; justify-content: center;
  inline-size: var(--control-md); block-size: var(--control-md); flex: none;
  border: var(--border-width) solid var(--border-default); background: var(--surface-card);
  color: var(--text-secondary); cursor: pointer; border-radius: var(--radius-pill); box-shadow: var(--shadow-sm);
  transition: background var(--duration-fast) var(--ease-standard), color var(--duration-fast) var(--ease-standard);
}
[dir="rtl"] .prism-sidenav-collapse { transform: translate(-50%, -50%); }
.prism-sidenav-collapse:hover { background: var(--fill-subtle); color: var(--text-primary); }
.prism-sidenav-collapse:focus-visible { outline: var(--focus-ring-width) solid var(--focus-ring); outline-offset: 2px; }
.prism-sidenav-collapse > svg { inline-size: var(--icon-md); block-size: var(--icon-md); transition: transform var(--duration-normal) var(--ease-standard); }
.prism-sidenav-shell[data-collapsed="true"] .prism-sidenav-collapse > svg { transform: rotate(180deg); }
[dir="rtl"] .prism-sidenav-collapse > svg { transform: rotate(180deg); }
[dir="rtl"] .prism-sidenav-shell[data-collapsed="true"] .prism-sidenav-collapse > svg { transform: rotate(0deg); }

/* ---------------- Sidebar (rich, header/scroll/footer regions) ---------------- */
.prism-sidebar {
  display: flex; flex-direction: column;
  inline-size: var(--sidebar-width); flex: none;
  block-size: 100%; max-block-size: 100vh;
  background: var(--surface-card);
  border-inline-end: var(--border-width) solid var(--border-default);
  color: var(--text-primary);
  overflow: hidden;
}
.prism-sidebar[data-side="right"] { border-inline-end: 0; border-inline-start: var(--border-width) solid var(--border-default); }
.prism-sidebar[data-collapsed="true"] { inline-size: calc(var(--control-xl) + var(--space-4)); }
/* HEADER — always visible (no scroll) */
.prism-sidebar-header { flex: none; padding: var(--space-5) var(--space-4) var(--space-4); }
.prism-sidebar-hero { display: flex; flex-direction: column; gap: var(--space-3); }
.prism-sidebar-hero-row { display: flex; align-items: center; gap: var(--space-3); min-inline-size: 0; }
.prism-sidebar-title { font-family: var(--font-display); font-weight: var(--weight-bold); font-size: var(--fs-h3); letter-spacing: -0.01em; margin: 0; overflow-wrap: anywhere; }
.prism-sidebar-meta { display: flex; flex-direction: column; gap: var(--space-0-5); min-inline-size: 0; }
.prism-sidebar-meta-primary { font-family: var(--label-font); font-weight: var(--weight-semibold); font-size: var(--fs-small); color: var(--text-primary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.prism-sidebar-meta-secondary { font-size: var(--text-xs); color: var(--text-tertiary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.prism-sidebar-header-extra { margin-block-start: var(--space-4); }
/* hue: the hero header takes the hue's tint (data-hue on the aside also
   re-points the current link, focus ring and accents) */
.prism-sidebar[data-hue] .prism-sidebar-header { background: var(--hue-surface); border-block-end: var(--border-width) solid var(--hue-border); }
.prism-sidebar[data-hue] .prism-sidebar-meta-secondary { color: var(--text-secondary); }
/* MIDDLE — internal scroll */
.prism-sidebar-body { flex: 1 1 auto; min-block-size: 0; overflow-y: auto; overflow-x: hidden; padding: var(--space-2) var(--space-3); display: flex; flex-direction: column; gap: var(--space-1); }
.prism-sidebar-section + .prism-sidebar-section { margin-block-start: var(--space-2); padding-block-start: var(--space-2); border-block-start: var(--border-width) solid var(--border-subtle); }
.prism-sidebar-section-label { font-size: var(--fs-caption); font-weight: var(--weight-semibold); color: var(--text-tertiary); padding: var(--space-2) var(--space-2) var(--space-1); }
/* section content: a control (theme switcher…) under the section's links */
.prism-sidebar-section-content { padding: var(--space-1) var(--space-2) var(--space-2); min-inline-size: 0; }
.prism-sidebar-link {
  display: flex; align-items: center; gap: var(--space-3);
  inline-size: 100%; border: 0; background: transparent; cursor: pointer;
  padding: 0 var(--space-3); min-block-size: var(--control-md);
  position: relative;
  border-radius: var(--radius-control);
  font-family: var(--body-font); font-size: var(--fs-small); font-weight: var(--weight-medium);
  color: var(--text-secondary); text-align: start; text-decoration: none;
  transition: var(--transition-colors);
}
.prism-sidebar-link > svg { inline-size: var(--icon-md); block-size: var(--icon-md); flex: none; }
.prism-sidebar-link-label { flex: 1; min-inline-size: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.prism-sidebar-link:hover { background: var(--fill-subtle); color: var(--text-primary); }
.prism-sidebar-link:focus-visible { outline: var(--focus-ring-width) solid var(--focus-ring); outline-offset: -2px; }
.prism-sidebar-link[aria-current="page"] { background: var(--accent-subtle); color: var(--accent-text); font-weight: var(--weight-semibold); }
/* With a secondary brand colour (--sig-2), the current item also gets a
   marker bar on its inline-start edge. Without one the bar is transparent. */
.prism-sidebar-link[aria-current="page"]::before {
  content: ""; position: absolute; inset-inline-start: 0; inset-block: var(--space-1-5);
  inline-size: 3px; border-radius: var(--radius-pill); background: var(--sig-2-line, transparent);
}
.prism-sidebar-link[aria-current="page"] .prism-sidebar-badge { background: var(--accent); color: var(--accent-on); }
.prism-sidebar-badge { flex: none; font-family: var(--label-font); font-weight: var(--weight-semibold); font-size: var(--fs-caption); line-height: 1; background: var(--fill-muted); color: var(--text-primary); min-inline-size: 20px; block-size: 20px; padding: 0 var(--space-1-5); display: inline-flex; align-items: center; justify-content: center; border-radius: var(--radius-pill); }
.prism-sidebar-disc-icon { flex: none; color: var(--text-tertiary); transition: transform var(--duration-fast) var(--ease-standard); }
.prism-sidebar-disc-icon > svg { inline-size: var(--icon-sm); block-size: var(--icon-sm); display: block; }
.prism-sidebar-link[aria-expanded="true"] .prism-sidebar-disc-icon { transform: rotate(90deg); }
[dir="rtl"] .prism-sidebar-link[aria-expanded="true"] .prism-sidebar-disc-icon { transform: rotate(-90deg); }
.prism-sidebar-children { display: flex; flex-direction: column; gap: 1px; margin: var(--space-0-5) 0 var(--space-0-5) 0; padding-inline-start: calc(var(--icon-md) + var(--space-3)); }
.prism-sidebar[data-collapsed="true"] .prism-sidebar-children { display: none; }
.prism-sidebar-child {
  display: flex; align-items: center; gap: var(--space-2);
  inline-size: 100%; border: 0; background: transparent; cursor: pointer;
  padding: 0 var(--space-3); min-block-size: var(--control-sm);
  border-radius: var(--radius-control);
  font-family: var(--body-font); font-size: var(--fs-small); color: var(--text-secondary);
  text-align: start; text-decoration: none; position: relative;
  transition: var(--transition-colors);
}
.prism-sidebar-child:hover { background: var(--fill-subtle); color: var(--text-primary); }
.prism-sidebar-child:focus-visible { outline: var(--focus-ring-width) solid var(--focus-ring); outline-offset: -2px; }
.prism-sidebar-child[aria-current="page"] { color: var(--accent-text); font-weight: var(--weight-semibold); }
/* collapsed: hide labels/badges/section labels, center icons */
.prism-sidebar[data-collapsed="true"] .prism-sidebar-link-label,
.prism-sidebar[data-collapsed="true"] .prism-sidebar-badge,
.prism-sidebar[data-collapsed="true"] .prism-sidebar-disc-icon,
.prism-sidebar[data-collapsed="true"] .prism-sidebar-section-label,
.prism-sidebar[data-collapsed="true"] .prism-sidebar-section-content,
.prism-sidebar[data-collapsed="true"] .prism-sidebar-meta,
.prism-sidebar[data-collapsed="true"] .prism-sidebar-user-meta,
.prism-sidebar[data-collapsed="true"] .prism-sidebar-user-caret,
.prism-sidebar[data-collapsed="true"] .prism-sidebar-title { display: none; }
.prism-sidebar[data-collapsed="true"] .prism-sidebar-link,
.prism-sidebar[data-collapsed="true"] .prism-sidebar-user { justify-content: center; padding-inline: 0; }
.prism-sidebar[data-collapsed="true"] .prism-sidebar-hero-row { justify-content: center; }
/* FOOTER — always visible (no scroll) */
/* COLLAPSE — `collapsible` adds this toggle under the nav. The chevron points
   at the edge the sidebar folds toward, and flips once it's a rail. */
.prism-sidebar-collapse-row { flex: none; display: flex; justify-content: flex-end; padding: var(--space-1) var(--space-3); }
.prism-sidebar[data-collapsed="true"] .prism-sidebar-collapse-row { justify-content: center; }
.prism-sidebar-collapse {
  display: inline-flex; align-items: center; justify-content: center;
  inline-size: var(--control-sm); block-size: var(--control-sm);
  border: var(--border-width) solid var(--border-default); border-radius: var(--radius-control);
  background: var(--surface-card); color: var(--text-secondary); cursor: pointer;
  transition: var(--transition-colors);
}
.prism-sidebar-collapse > svg { inline-size: var(--icon-sm); block-size: var(--icon-sm); transition: transform var(--duration-fast) var(--ease-standard); }
.prism-sidebar-collapse:hover { background: var(--fill-subtle); color: var(--text-primary); }
.prism-sidebar-collapse:focus-visible { outline: var(--focus-ring-width) solid var(--focus-ring); outline-offset: 2px; }
.prism-sidebar[data-collapsed="true"] .prism-sidebar-collapse > svg,
.prism-sidebar[data-side="right"]:not([data-collapsed="true"]) .prism-sidebar-collapse > svg { transform: rotate(180deg); }
[dir="rtl"] .prism-sidebar:not([data-side="right"]):not([data-collapsed="true"]) .prism-sidebar-collapse > svg { transform: rotate(180deg); }
[dir="rtl"] .prism-sidebar[data-collapsed="true"]:not([data-side="right"]) .prism-sidebar-collapse > svg { transform: none; }

/* collapseBelow — fold to the icon rail under a size tier, in CSS alone (no
   flash on load). Labels are visually hidden, not removed, so every link
   keeps its accessible name; the toggle hides because the rail is forced. */
@media (max-width: 1023.98px) {
  .prism-sidebar[data-collapse-below="desktop"] { inline-size: calc(var(--control-xl) + var(--space-4)); }
  .prism-sidebar[data-collapse-below="desktop"] :is(.prism-sidebar-badge, .prism-sidebar-disc-icon, .prism-sidebar-section-label, .prism-sidebar-meta,
    .prism-sidebar-user-caret, .prism-sidebar-title, .prism-sidebar-meta-secondary, .prism-sidebar-header-extra,
    .prism-sidebar-children, .prism-sidebar-collapse-row, .prism-sidebar-section-content) { display: none; }
  .prism-sidebar[data-collapse-below="desktop"] :is(.prism-sidebar-link-label, .prism-sidebar-user-meta) {
    position: absolute; inline-size: 1px; block-size: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap;
  }
  .prism-sidebar[data-collapse-below="desktop"] :is(.prism-sidebar-link, .prism-sidebar-user) { justify-content: center; padding-inline: 0; }
  .prism-sidebar[data-collapse-below="desktop"] .prism-sidebar-hero-row { justify-content: center; }
  .prism-sidebar[data-collapse-below="desktop"] .prism-sidebar-actions[data-layout="row"] { flex-direction: column; }
  .prism-sidebar[data-collapse-below="desktop"] .prism-sidebar-actions[data-layout="row"] .prism-sidebar-action { flex: none; inline-size: 100%; }
}
@media (max-width: 639.98px) {
  .prism-sidebar[data-collapse-below="tablet"] { inline-size: calc(var(--control-xl) + var(--space-4)); }
  .prism-sidebar[data-collapse-below="tablet"] :is(.prism-sidebar-badge, .prism-sidebar-disc-icon, .prism-sidebar-section-label, .prism-sidebar-meta,
    .prism-sidebar-user-caret, .prism-sidebar-title, .prism-sidebar-meta-secondary, .prism-sidebar-header-extra,
    .prism-sidebar-children, .prism-sidebar-collapse-row, .prism-sidebar-section-content) { display: none; }
  .prism-sidebar[data-collapse-below="tablet"] :is(.prism-sidebar-link-label, .prism-sidebar-user-meta) {
    position: absolute; inline-size: 1px; block-size: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap;
  }
  .prism-sidebar[data-collapse-below="tablet"] :is(.prism-sidebar-link, .prism-sidebar-user) { justify-content: center; padding-inline: 0; }
  .prism-sidebar[data-collapse-below="tablet"] .prism-sidebar-hero-row { justify-content: center; }
  .prism-sidebar[data-collapse-below="tablet"] .prism-sidebar-actions[data-layout="row"] { flex-direction: column; }
  .prism-sidebar[data-collapse-below="tablet"] .prism-sidebar-actions[data-layout="row"] .prism-sidebar-action { flex: none; inline-size: 100%; }
}

.prism-sidebar-footer { flex: none; padding: var(--space-3); border-block-start: var(--border-width) solid var(--border-subtle); position: relative; }
/* footerActions — direct actions pinned in the fixed footer (Settings, Sign
   out…). They reuse the nav-link look; "row" puts them side by side. In the
   icon rail (collapsed or collapseBelow) they stack, icon-only. */
.prism-sidebar-actions { display: flex; flex-direction: column; gap: var(--space-0-5); }
.prism-sidebar-actions + .prism-sidebar-user { margin-block-start: var(--space-2); }
/* row: a compact bar — icon over a small label, equal widths, one line — so
   three or four actions fit side by side in the sidebar's width. */
.prism-sidebar-actions[data-layout="row"] { flex-direction: row; flex-wrap: nowrap; }
.prism-sidebar-actions[data-layout="row"] .prism-sidebar-action {
  flex: 1 1 0; inline-size: auto; min-inline-size: 0;
  flex-direction: column; justify-content: center; gap: var(--space-0-5);
  padding: var(--space-1-5) var(--space-1); font-size: var(--fs-caption);
}
.prism-sidebar-actions[data-layout="row"] .prism-sidebar-action .prism-sidebar-link-label { flex: none; max-inline-size: 100%; text-align: center; }
.prism-sidebar-action[data-tone="negative"] { color: var(--negative-text); }
.prism-sidebar-action[data-tone="negative"]:hover { background: var(--negative-subtle); color: var(--negative-text); }
.prism-sidebar[data-collapsed="true"] .prism-sidebar-actions[data-layout="row"] { flex-direction: column; }
.prism-sidebar[data-collapsed="true"] .prism-sidebar-actions[data-layout="row"] .prism-sidebar-action { flex: none; inline-size: 100%; }
.prism-sidebar-user {
  display: flex; align-items: center; gap: var(--space-3);
  inline-size: 100%; border: 0; background: transparent; cursor: pointer;
  padding: var(--space-2); border-radius: var(--radius-control);
  text-align: start; transition: var(--transition-colors);
}
.prism-sidebar-user:hover { background: var(--fill-subtle); }
.prism-sidebar-user:focus-visible { outline: var(--focus-ring-width) solid var(--focus-ring); outline-offset: -2px; }
.prism-sidebar-user-meta { flex: 1; min-inline-size: 0; display: flex; flex-direction: column; } /* name over role, not run together */
.prism-sidebar-user-name { font-family: var(--label-font); font-weight: var(--weight-semibold); font-size: var(--fs-small); color: var(--text-primary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.prism-sidebar-user-sub { font-size: var(--text-xs); color: var(--text-tertiary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.prism-sidebar-user-caret { flex: none; color: var(--text-tertiary); }
.prism-sidebar-user-caret > svg { inline-size: var(--icon-sm); block-size: var(--icon-sm); }
.prism-sidebar-usermenu {
  position: absolute; inset-block-end: calc(100% - var(--space-1)); inset-inline: var(--space-3);
  background: var(--surface-overlay); border: var(--border-width) solid var(--border-default);
  border-radius: var(--radius-card); box-shadow: var(--shadow-lg); padding: var(--space-1);
  z-index: var(--z-dropdown); animation: prism-pop var(--duration-fast) var(--ease-standard);
}
.prism-sidebar-usermenu-item {
  display: flex; align-items: center; gap: var(--space-3);
  inline-size: 100%; border: 0; background: transparent; cursor: pointer;
  padding: var(--space-2) var(--space-3); min-block-size: var(--control-md);
  border-radius: var(--radius-control);
  font-family: var(--body-font); font-size: var(--fs-small); color: var(--text-primary);
  text-align: start; transition: var(--transition-colors);
}
.prism-sidebar-usermenu-item > svg { inline-size: var(--icon-sm); block-size: var(--icon-sm); flex: none; color: var(--text-secondary); }
.prism-sidebar-usermenu-item:hover { background: var(--fill-subtle); }
.prism-sidebar-usermenu-item:focus-visible { outline: var(--focus-ring-width) solid var(--focus-ring); outline-offset: -2px; }
.prism-sidebar-usermenu-item[data-tone="negative"] { color: var(--negative-text); }
.prism-sidebar-usermenu-item[data-tone="negative"] > svg { color: var(--negative-text); }
.prism-sidebar-usermenu-sep { block-size: 1px; background: var(--border-subtle); margin: var(--space-1) 0; }

/* ---------------- AppFooter ---------------- */
.prism-footer {
  background: var(--surface-card);
  border-block-start: var(--border-width) solid var(--border-default);
  padding: var(--gap-section) var(--layout-gutter);
  color: var(--text-secondary);
}
.prism-footer[data-tone="inverse"] { background: var(--surface-inverse); color: var(--text-on-inverse); border-block-start: 0; }
.prism-footer-inner { max-inline-size: var(--container-xl); margin-inline: auto; display: flex; flex-direction: column; gap: var(--gap-section); }
.prism-footer-top { display: flex; flex-wrap: wrap; gap: var(--gap-section); justify-content: space-between; }
.prism-footer-brandcol { flex: 1 1 240px; max-inline-size: 360px; display: flex; flex-direction: column; gap: var(--gap-stack); }
.prism-footer-brand { display: flex; align-items: center; gap: var(--gap-inline); color: var(--accent); }
.prism-footer[data-tone="inverse"] .prism-footer-brand { color: inherit; }
/* The brand row is accent-coloured (it tints a logomark); the wordmark text is
   set apart so it reads as body text. AppFooter's `wordmark` prop renders it. */
.prism-footer-brand-word { font-family: var(--font-display); font-weight: var(--weight-bold); font-size: var(--fs-h4); color: var(--text-primary); }
.prism-footer[data-tone="inverse"] .prism-footer-brand-word { color: inherit; }
.prism-footer-tagline { font-size: var(--fs-small); color: var(--text-tertiary); margin: 0; max-inline-size: 40ch; }
.prism-footer[data-tone="inverse"] .prism-footer-tagline { color: inherit; opacity: 0.7; }
.prism-footer-social { display: flex; gap: var(--gap-inline); margin-block-start: var(--space-1); }
.prism-footer-social a {
  display: inline-flex; align-items: center; justify-content: center;
  inline-size: var(--control-md); block-size: var(--control-md); border-radius: var(--radius-control);
  color: var(--text-secondary); transition: var(--transition-colors);
}
.prism-footer-social a:hover { background: var(--fill-subtle); color: var(--text-primary); }
/* inverse footer: icons take the footer's ink (the page's --text-secondary is dark on dark) */
.prism-footer[data-tone="inverse"] .prism-footer-social a { color: inherit; opacity: 0.8; }
.prism-footer[data-tone="inverse"] .prism-footer-social a:hover { opacity: 1; background: color-mix(in oklab, var(--text-on-inverse) 10%, transparent); }
.prism-footer-social a:focus-visible { outline: var(--focus-ring-width) solid var(--focus-ring); outline-offset: 2px; }
.prism-footer-social svg { inline-size: var(--icon-md); block-size: var(--icon-md); }

.prism-footer-cols { display: flex; flex-wrap: wrap; gap: var(--gap-section); }
.prism-footer-col { display: flex; flex-direction: column; gap: var(--gap-stack); min-inline-size: 120px; }
.prism-footer-col-title { font-family: var(--label-font); font-size: var(--fs-small); font-weight: var(--weight-semibold); color: var(--text-primary); margin: 0; }
.prism-footer[data-tone="inverse"] .prism-footer-col-title { color: inherit; }
.prism-footer-col a { font-size: var(--fs-small); color: var(--text-secondary); text-decoration: none; }
.prism-footer-col a:hover { color: var(--text-link); text-decoration: underline; text-underline-offset: 0.15em; }
.prism-footer[data-tone="inverse"] .prism-footer-col a { color: inherit; opacity: 0.8; }
.prism-footer[data-tone="inverse"] .prism-footer-col a:hover { opacity: 1; }
.prism-footer-bottom {
  display: flex; flex-wrap: wrap; gap: var(--gap-stack) var(--gap-section); align-items: center; justify-content: space-between;
  padding-block-start: var(--gap-stack); border-block-start: var(--border-width) solid var(--border-subtle);
  font-size: var(--text-xs); color: var(--text-tertiary);
}
.prism-footer[data-tone="inverse"] .prism-footer-bottom { border-block-start-color: var(--border-inverse); color: inherit; opacity: 0.75; }
.prism-footer-legal { display: flex; flex-wrap: wrap; gap: var(--gap-inline) var(--space-5); align-items: center; }
.prism-footer-legal a { color: inherit; text-decoration: none; }
.prism-footer-legal a:hover { text-decoration: underline; text-underline-offset: 0.15em; }

/* Independent (ungrouped) primary links — horizontal, wraps */
.prism-footer-links { display: flex; flex-wrap: wrap; gap: var(--gap-stack) var(--gap-section); align-items: center; }
.prism-footer-links a { font-size: var(--fs-small); font-weight: var(--weight-medium); color: var(--text-secondary); text-decoration: none; }
.prism-footer-links a:hover { color: var(--text-link); text-decoration: underline; text-underline-offset: 0.15em; }
.prism-footer[data-tone="inverse"] .prism-footer-links a { color: inherit; opacity: 0.85; }
.prism-footer[data-tone="inverse"] .prism-footer-links a:hover { opacity: 1; }

/* Small viewports: stack regions, left-align, full-width link groups */
@media (max-width: 639.98px) {
  .prism-footer-top { flex-direction: column; gap: var(--gap-section); }
  /* In the stacked column, flex-basis is a HEIGHT: 240px left a blank band
     under a short brand. Size the brand column to its content instead. */
  .prism-footer-brandcol { max-inline-size: none; flex: 0 0 auto; }
  .prism-footer-cols { gap: var(--gap-section) var(--space-10); }
  .prism-footer-col { flex: 1 1 40%; min-inline-size: 100px; }
  .prism-footer-bottom { flex-direction: column; align-items: flex-start; gap: var(--gap-stack); }
}

/* ============================================================
   MediaHero — full-bleed hero with image/video background.
   Variants: bare (text on media) · box (translucent/solid panel) ·
   cards (bottom-aligned nav cards) · carousel (animated slides).
   Content sits on light text over a dark scrim for legibility,
   independent of theme.
   ============================================================ */
.prism-mhero {
  position: relative; isolation: isolate; overflow: hidden;
  border-radius: var(--radius-surface);
  display: flex; flex-direction: column;
  padding: var(--space-10) var(--space-12);
  color: oklch(1 0 0);
}
.prism-mhero[data-size="sm"] { min-block-size: 340px; }
.prism-mhero[data-size="md"] { min-block-size: 480px; }
.prism-mhero[data-size="lg"] { min-block-size: 620px; }
.prism-mhero[data-size="full"] { min-block-size: 100svh; border-radius: 0; }
/* vertical placement of content */
.prism-mhero[data-align="center"] { justify-content: center; }
.prism-mhero[data-align="end"] { justify-content: flex-end; }

.prism-mhero-layer { position: absolute; inset: 0; z-index: -2; }
.prism-mhero-media { position: absolute; inset: 0; inline-size: 100%; block-size: 100%; object-fit: cover; }
/* crossfade stack for carousel */
.prism-mhero-slidebg { position: absolute; inset: 0; opacity: 0; transition: opacity var(--duration-slow, 600ms) var(--ease-standard); }
.prism-mhero-slidebg[data-active="true"] { opacity: 1; }
.prism-mhero-scrim {
  position: absolute; inset: 0; z-index: -1;
  background:
    linear-gradient(to top, oklch(0 0 0 / 0.72) 0%, oklch(0 0 0 / 0.30) 42%, oklch(0 0 0 / 0.12) 100%),
    linear-gradient(to right, oklch(0 0 0 / 0.45), oklch(0 0 0 / 0) 70%);
}
.prism-mhero[data-align="center"] .prism-mhero-scrim {
  background: radial-gradient(120% 120% at 50% 50%, oklch(0 0 0 / 0.20), oklch(0 0 0 / 0.62));
}
.prism-mhero[data-scrim="soft"] .prism-mhero-scrim { opacity: 0.6; }
.prism-mhero[data-scrim="strong"] .prism-mhero-scrim { opacity: 1; background:
    linear-gradient(to top, oklch(0 0 0 / 0.85) 0%, oklch(0 0 0 / 0.5) 50%, oklch(0 0 0 / 0.3) 100%); }

.prism-mhero-inner { position: relative; inline-size: 100%; max-inline-size: var(--container-xl); margin-inline: auto; display: flex; flex-direction: column; }
.prism-mhero[data-align="center"] .prism-mhero-content { text-align: center; align-items: center; margin-inline: auto; }
.prism-mhero-content { display: flex; flex-direction: column; gap: var(--gap-stack); align-items: flex-start; max-inline-size: 60ch; }

.prism-mhero-eyebrow { font-family: var(--font-display); font-size: var(--fs-small); font-weight: var(--weight-semibold); text-transform: uppercase; letter-spacing: var(--tracking-caps); opacity: 0.92; margin: 0; }
.prism-mhero-title { font-family: var(--font-display); font-weight: var(--weight-bold); font-size: var(--fs-display); line-height: var(--leading-tight); letter-spacing: -0.02em; margin: 0; color: inherit; text-wrap: balance; }
.prism-mhero-text { font-size: var(--fs-lead); line-height: var(--leading-normal); opacity: 0.92; margin: 0; max-inline-size: 56ch; letter-spacing: normal; font-weight: var(--weight-regular); }
.prism-mhero-actions { display: flex; flex-wrap: wrap; gap: var(--gap-inline); margin-block-start: var(--space-2); }

/* box variant — content sits in a translucent/solid panel */
.prism-mhero-box {
  align-self: flex-start;
  max-inline-size: min(560px, 100%);
  padding: var(--pad-card);
  border-radius: var(--radius-card);
  background: oklch(0 0 0 / 0.42);
  backdrop-filter: blur(12px) saturate(1.1);
  -webkit-backdrop-filter: blur(12px) saturate(1.1);
  border: var(--border-width) solid oklch(1 0 0 / 0.16);
  box-shadow: var(--shadow-lg);
}
.prism-mhero[data-align="center"] .prism-mhero-box { align-self: center; }
.prism-mhero-box[data-box="solid"] { background: var(--surface-card); color: var(--text-primary); backdrop-filter: none; -webkit-backdrop-filter: none; border-color: var(--border-default); }
.prism-mhero-box[data-box="solid"] .prism-mhero-title { color: var(--text-primary); }
.prism-mhero-box[data-box="light"] { background: oklch(1 0 0 / 0.9); color: var(--text-primary); border-color: oklch(1 0 0 / 0.6); }
.prism-mhero-box[data-box="light"] .prism-mhero-title { color: var(--text-primary); }

/* bottom nav cards */
.prism-mhero-cards { position: relative; display: grid; grid-template-columns: repeat(var(--hero-card-cols, 4), 1fr); gap: var(--space-4); margin-block-start: var(--gap-section); }
.prism-mhero-navcard {
  display: flex; flex-direction: column; gap: var(--space-1-5); text-align: start;
  padding: var(--pad-card); border-radius: var(--radius-card);
  background: oklch(0 0 0 / 0.38); backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
  border: var(--border-width) solid oklch(1 0 0 / 0.16); color: inherit; cursor: pointer;
  transition: var(--transition-transform), background-color var(--duration-fast) var(--ease-standard), border-color var(--duration-fast) var(--ease-standard);
}
.prism-mhero-navcard:hover { background: oklch(0 0 0 / 0.55); border-color: oklch(1 0 0 / 0.3); transform: translateY(-2px); }
.prism-mhero-navcard:focus-visible { outline: var(--focus-ring-width) solid oklch(1 0 0); outline-offset: 2px; }
.prism-mhero-navcard-ic { inline-size: var(--icon-xl); block-size: var(--icon-xl); margin-block-end: var(--space-0-5); opacity: 0.95; }
.prism-mhero-navcard-ic svg { inline-size: 100%; block-size: 100%; }
.prism-mhero-navcard-title { font-family: var(--font-display); font-weight: var(--weight-semibold); font-size: var(--fs-h4); }
.prism-mhero-navcard-text { font-size: var(--fs-small); opacity: 0.85; }

/* carousel: entrance animation for active slide content + dots */
@media (prefers-reduced-motion: no-preference) {
  .prism-mhero-anim { animation: prism-mhero-in var(--duration-slow, 600ms) var(--ease-emphasized) both; }
}
@keyframes prism-mhero-in { from { opacity: 0; transform: translateY(16px); } to { opacity: 1; transform: none; } }
.prism-mhero-dots { position: absolute; inset-block-end: var(--space-5); inset-inline: 0; display: flex; gap: var(--space-2); justify-content: center; z-index: 2; }
.prism-mhero[data-align="end"] .prism-mhero-dots { inset-block-end: var(--space-3); }
.prism-mhero-dot { inline-size: 28px; block-size: 4px; border-radius: var(--radius-pill); border: 0; padding: 0; background: oklch(1 0 0 / 0.4); cursor: pointer; transition: background-color var(--duration-fast) var(--ease-standard); }
.prism-mhero-dot[aria-current="true"] { background: oklch(1 0 0); }
.prism-mhero-dot:focus-visible { outline: 2px solid oklch(1 0 0); outline-offset: 3px; }
.prism-mhero-arrow {
  position: absolute; inset-block-start: 50%; transform: translateY(-50%); z-index: 2;
  inline-size: var(--control-lg); block-size: var(--control-lg); border-radius: var(--radius-pill);
  display: inline-flex; align-items: center; justify-content: center;
  background: oklch(0 0 0 / 0.4); border: var(--border-width) solid oklch(1 0 0 / 0.2); color: oklch(1 0 0); cursor: pointer;
}
.prism-mhero-arrow:hover { background: oklch(0 0 0 / 0.62); }
.prism-mhero-arrow:focus-visible { outline: 2px solid oklch(1 0 0); outline-offset: 2px; }
.prism-mhero-arrow[data-dir="prev"] { inset-inline-start: var(--space-4); }
.prism-mhero-arrow[data-dir="next"] { inset-inline-end: var(--space-4); }
.prism-mhero-arrow svg { inline-size: var(--icon-md); block-size: var(--icon-md); }
[dir="rtl"] .prism-mhero-arrow svg { transform: scaleX(-1); }

@media (max-width: 1023.98px) {
  .prism-mhero { padding: var(--space-8) var(--space-5); }
  .prism-mhero-cards { grid-template-columns: 1fr 1fr; }
  .prism-mhero-arrow { display: none; }
}
@media (max-width: 639.98px) {
  .prism-mhero-cards { grid-template-columns: 1fr; }
}

/* ---------------- List + ListRow (tappable rows) ----------------
   One real control per row (<li><button> or <a>), at least --control-xl
   (56px) tall: a phone-first touch target. Rows are divided by a hairline. */
.prism-list { margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; }
.prism-list-item { margin: 0; padding: 0; }
.prism-list-item + .prism-list-item { border-block-start: var(--border-width) solid var(--border-subtle); }
.prism-listrow {
  display: flex; align-items: center; gap: var(--space-3);
  inline-size: 100%; min-block-size: var(--control-xl);
  padding: var(--space-2) var(--space-3);
  border: 0; border-radius: var(--radius-control); background: transparent;
  font: inherit; color: var(--text-primary); text-align: start; text-decoration: none;
  cursor: pointer; -webkit-tap-highlight-color: transparent;
  transition: var(--transition-colors);
}
.prism-listrow:hover { background: var(--fill-subtle); }
.prism-listrow:active { background: var(--fill-subtle-hover); }
.prism-listrow:focus-visible { outline: var(--focus-ring-width) solid var(--focus-ring); outline-offset: -2px; }
.prism-listrow[data-disabled="true"] { cursor: not-allowed; opacity: 0.45; background: transparent; }
/* Read-only row: full contrast, no press feedback. */
.prism-listrow[data-static="true"] { cursor: auto; }
.prism-listrow[data-static="true"]:hover, .prism-listrow[data-static="true"]:active { background: transparent; }
.prism-listrow-leading, .prism-listrow-trailing { flex: none; display: inline-flex; align-items: center; gap: var(--space-2); }
.prism-listrow-leading > svg { inline-size: var(--icon-md); block-size: var(--icon-md); color: var(--text-secondary); }
.prism-listrow-text { flex: 1 1 auto; min-inline-size: 0; display: flex; flex-direction: column; gap: var(--space-0-5); }
.prism-listrow-label { font-size: var(--fs-body); font-weight: var(--weight-medium); overflow-wrap: anywhere; }
.prism-listrow-desc { font-size: var(--fs-small); color: var(--text-secondary); overflow-wrap: anywhere; }
.prism-listrow-chevron { flex: none; display: inline-flex; color: var(--text-tertiary); }
.prism-listrow-chevron > svg { inline-size: var(--icon-sm); block-size: var(--icon-sm); }
[dir="rtl"] .prism-listrow-chevron > svg { transform: scaleX(-1); }

/* ---------------- Print ----------------
   Navigation and the site footer are screen chrome: hidden on paper. A page
   hero keeps its copy but drops its card look and media. */
@media print {
  .prism-sidebar, .prism-sidenav-shell, .prism-footer { display: none !important; }
}

/* ===== components/cards/cards.css ===== */
/* ============================================================
   Prism · Card variants
   EditorialCard · MetricCard · HeroCard · TileCard · ProgressCard
   All build on the base .prism-card surface (border + bevel +
   shadow). Scoped pc-* classes; consume role tokens so they
   respond to density, size tier, theme and brand.
   ============================================================ */

/* shared bits */
.pc-thumb { background: var(--fill-subtle); color: var(--text-tertiary); display: grid; place-items: center; overflow: hidden; }
.pc-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.pc-thumb svg { width: 28px; height: 28px; }
.pc-eyebrow { font-family: var(--font-display); font-size: var(--fs-caption); font-weight: var(--weight-semibold); text-transform: uppercase; letter-spacing: var(--tracking-caps); color: var(--text-tertiary); margin: 0; }
.pc-actions { display: flex; align-items: center; gap: var(--gap-inline); flex-wrap: wrap; }
.pc-actions.end { justify-content: flex-end; }

/* ---------------- EditorialCard ---------------- */
.pc-editorial { display: flex; flex-direction: column; overflow: hidden; }
.pc-editorial[data-layout="row"] { flex-direction: row; }
.pc-editorial .pc-thumb { aspect-ratio: 16 / 9; }
.pc-editorial[data-layout="row"] .pc-thumb { aspect-ratio: auto; width: 38%; flex: none; }
.pc-editorial .pc-ed-body { display: flex; flex-direction: column; gap: var(--space-1); padding: var(--pad-card); flex: 1; }
.pc-editorial .pc-ed-body > .pc-eyebrow { margin-bottom: var(--space-0-5); }
.pc-editorial .pc-ed-body > p { margin-top: var(--space-1); }
.pc-editorial .pc-ed-meta { display: flex; align-items: center; gap: var(--space-2); font-size: var(--text-xs); color: var(--text-tertiary); }
.pc-editorial .pc-ed-meta .dot { width: 3px; height: 3px; border-radius: 50%; background: var(--text-tertiary); }
.pc-editorial h3 { font-family: var(--font-display); font-size: var(--fs-h4); font-weight: 600; line-height: var(--leading-snug); margin: 0; letter-spacing: -0.01em; }
.pc-editorial p { font-size: var(--text-sm); color: var(--text-secondary); line-height: var(--leading-normal); margin: 0; }
.pc-editorial .pc-actions { margin-top: auto; padding-top: var(--space-3); }

/* ---------------- MetricCard ---------------- */
.pc-metric { display: flex; flex-direction: column; gap: var(--space-3); padding: var(--pad-card); height: 100%; box-sizing: border-box; }
.pc-metric .pc-metric-mid { flex: 1; display: flex; align-items: center; min-height: 56px; }
.pc-metric .pc-metric-mid > * { width: 100%; }
.pc-metric .pc-actions { margin-top: 0; }
/* The eyebrow and the delta pill (or icon) share the first row; the figure
   takes the full width below them, so a long amount isn't squeezed beside
   the pill. Without an eyebrow the figure sits beside the pill. */
.pc-metric .pc-metric-top { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: start; gap: var(--space-1-5) var(--space-3); }
.pc-metric .pc-metric-top > :is(.pc-delta, .pc-icon) { grid-column: 2; grid-row: 1; }
.pc-metric .pc-metric-top:has(.pc-eyebrow) .pc-metric-figure { grid-column: 1 / -1; grid-row: 2; }
/* min-width 0 lets the heading column shrink, so a long eyebrow wraps (even
   a single long word) instead of overflowing the card on a phone. */
.pc-metric .pc-metric-head { display: contents; }
.pc-metric .pc-eyebrow { overflow-wrap: break-word; }
/* The figure never paints outside the card. The card is a size container and
   MetricCard sets --pc-metric-chars: a long figure shrinks to fill the card (0.55em a character: the display face with a wide
   ₹, plus slack), clamped to --text-base … --text-4xl; past that it wraps after a leading
   currency symbol (MetricCard puts a <wbr> there), then anywhere. The unit
   wraps under the figure rather than overflowing. */
.pc-metric { container-type: inline-size; }
.pc-metric .pc-metric-figure { display: flex; flex-wrap: wrap; align-items: baseline; column-gap: 6px; min-inline-size: 0; }
.pc-metric .pc-metric-val { font-family: var(--font-display); font-size: clamp(var(--text-base), calc(100cqi / (var(--pc-metric-chars, 1) * 0.55)), var(--text-4xl)); font-weight: 700; letter-spacing: -0.02em; line-height: 1.05; min-inline-size: 0; max-inline-size: 100%; overflow-wrap: anywhere; }
.pc-cur { white-space: nowrap; }
.pc-metric .pc-metric-unit { font-size: var(--text-lg); color: var(--text-tertiary); font-weight: 500; }
.pc-metric .pc-delta { display: inline-flex; align-items: center; gap: var(--space-0-5); font-size: var(--text-xs); font-weight: var(--weight-semibold); padding: var(--space-0-5) var(--space-2); border-radius: var(--radius-pill); }
.pc-metric .pc-delta svg { width: 13px; height: 13px; }
.pc-metric .pc-delta[data-dir="up"] { background: var(--positive-subtle); color: var(--positive-text); }
.pc-metric .pc-delta[data-dir="down"] { background: var(--negative-subtle); color: var(--negative-text); }
.pc-metric .pc-delta[data-dir="flat"] { background: var(--fill-subtle); color: var(--text-secondary); }
.pc-metric .pc-spark { width: 100%; height: 64px; display: block; }
.pc-metric .pc-icon { width: 40px; height: 40px; border-radius: var(--radius-card); background: var(--accent-subtle); color: var(--accent-text); display: grid; place-items: center; flex: none; }
.pc-metric .pc-icon svg { width: 20px; height: 20px; }

/* ---------------- HeroCard (section navigation) ---------------- */
.pc-hero { position: relative; overflow: hidden; min-height: 220px; display: flex; flex-direction: column; justify-content: flex-end; color: oklch(1 0 0); border: 0; }
.pc-hero .pc-hero-bg { position: absolute; inset: 0; background-size: cover; background-position: center; }
.pc-hero .pc-hero-bg::after { content: ""; position: absolute; inset: 0; background: linear-gradient(to top, oklch(0.18 0.02 264 / 0.92), oklch(0.18 0.02 264 / 0.45) 55%, oklch(0.18 0.02 264 / 0.2)); }
.pc-hero[data-tint="brand"] .pc-hero-bg::after { background: linear-gradient(to top, oklch(0.30 0.22 264 / 0.94), oklch(0.30 0.22 264 / 0.55) 55%, oklch(0.30 0.22 264 / 0.25)); }
.pc-hero .pc-hero-content { position: relative; padding: var(--pad-card); display: flex; flex-direction: column; gap: var(--space-1); }
.pc-hero .pc-hero-num { margin-bottom: var(--space-1); }
.pc-hero p { margin-top: var(--space-1); }
.pc-hero .pc-hero-num { font-family: var(--font-mono); font-size: var(--text-sm); font-weight: 600; opacity: 0.85; letter-spacing: 0.04em; }
.pc-hero h3 { font-family: var(--font-display); font-size: var(--fs-h2); font-weight: 700; letter-spacing: -0.02em; line-height: 1.1; margin: 0; color: inherit; }
.pc-hero p { font-size: var(--text-sm); opacity: 0.9; line-height: var(--leading-normal); margin: 0; max-width: 42ch; }
.pc-hero .pc-hero-lead { display: inline-flex; align-items: center; gap: var(--space-1-5); font-family: var(--font-display); font-weight: 600; font-size: var(--text-sm); margin-top: var(--space-2); }
.pc-hero .pc-hero-lead svg { width: 16px; height: 16px; }
.pc-hero[data-interactive="true"] { cursor: pointer; transition: transform var(--duration-fast) var(--ease-standard), box-shadow var(--duration-fast) var(--ease-standard); }
.pc-hero[data-interactive="true"]:hover { transform: translateY(-2px); box-shadow: var(--shadow-lg); }
.pc-hero[data-interactive="true"]:hover .pc-hero-lead svg { transform: translateX(2px); transition: transform var(--duration-fast) var(--ease-standard); }
.pc-hero:focus-visible { outline: var(--focus-ring-width) solid var(--focus-ring); outline-offset: var(--focus-ring-offset-width); }

/* ---------------- TileCard (IRE / 10-foot navigation) ---------------- */
.pc-tile { display: flex; flex-direction: column; gap: var(--space-4); padding: var(--pad-card); text-align: start; width: 100%; height: 100%; box-sizing: border-box; }
.pc-tile .pc-tile-ic { width: 64px; height: 64px; border-radius: var(--radius-card); background: var(--accent-subtle); color: var(--accent-text); display: grid; place-items: center; flex: none; transition: var(--transition-colors); }
.pc-tile .pc-tile-ic svg { width: 32px; height: 32px; }
/* the title is a real heading; with href/onPress its text is the CardAction,
   whose hit area covers the tile (core.css draws the focus ring on the tile) */
.pc-tile :is(.pc-tile-title, h3) { font-family: var(--font-display); font-size: var(--fs-h3); font-weight: 600; margin: 0; letter-spacing: -0.01em; overflow-wrap: break-word; }
.pc-tile p { font-size: var(--fs-small); color: var(--text-secondary); margin: var(--space-1) 0 0; line-height: var(--leading-normal); }
.pc-tile .pc-tile-text { flex: 1; min-inline-size: 0; }
.pc-tile[data-interactive="true"]:not(:has([data-disabled="true"])):hover .pc-tile-ic { background: var(--accent); color: var(--accent-on); background-image: var(--sheen); box-shadow: var(--bevel); }
/* size: xs for dense settings grids, sm for dashboard grids, lg for 10-foot
   screens (md is the default above) */
.pc-tile[data-size="sm"] { gap: var(--space-3); }
.pc-tile[data-size="sm"] .pc-tile-ic { width: 44px; height: 44px; }
.pc-tile[data-size="sm"] .pc-tile-ic svg { width: 22px; height: 22px; }
.pc-tile[data-size="sm"] :is(.pc-tile-title, h3) { font-size: var(--fs-h5); }
/* xs: a row — small icon beside a body-size title, for dense settings grids */
.pc-tile[data-size="xs"] { flex-direction: row; align-items: flex-start; gap: var(--space-3); padding: var(--space-3) var(--space-4); }
.pc-tile[data-size="xs"] .pc-tile-ic { width: 32px; height: 32px; border-radius: var(--radius-control); }
.pc-tile[data-size="xs"] .pc-tile-ic svg { width: 18px; height: 18px; }
.pc-tile[data-size="xs"] :is(.pc-tile-title, h3) { font-family: var(--label-font); font-size: var(--text-base); letter-spacing: 0; line-height: var(--leading-snug); }
.pc-tile[data-size="xs"] p { font-size: var(--text-xs); margin-block-start: 2px; }
.pc-tile[data-size="lg"] .pc-tile-ic { width: 80px; height: 80px; }
.pc-tile[data-size="lg"] .pc-tile-ic svg { width: 40px; height: 40px; }
.pc-tile[data-size="lg"] :is(.pc-tile-title, h3) { font-size: var(--fs-h2); }

/* ---------------- ProgressCard ---------------- */
.pc-progress { display: flex; flex-direction: column; gap: var(--space-3); padding: var(--pad-card); height: 100%; box-sizing: border-box; }
.pc-progress .pc-prog-head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--space-3); }
.pc-progress h3 { font-family: var(--font-display); font-size: var(--fs-h4); font-weight: 600; margin: 0; letter-spacing: -0.01em; }
.pc-progress .pc-prog-sub { font-size: var(--text-sm); color: var(--text-secondary); margin: var(--space-0-5) 0 0; }
.pc-progress .pc-prog-pct { font-family: var(--font-display); font-size: var(--text-2xl); font-weight: 700; letter-spacing: -0.01em; }
.pc-progress .pc-actions { margin-top: auto; padding-top: var(--space-1); }

/* ---------------- StatCard (compare related metrics) ---------------- */
.pc-stat { display: flex; flex-direction: column; gap: var(--space-4); padding: var(--pad-card); height: 100%; box-sizing: border-box; }
.pc-stat .pc-stat-head { display: flex; align-items: center; gap: var(--space-2); }
.pc-stat h3 { font-family: var(--font-display); font-size: var(--fs-h4); font-weight: 600; margin: 0; letter-spacing: -0.01em; }
/* Every stat gets a column; they wrap onto more rows when the card is narrow.
   Each item draws its divider in the gap before it, and the grid clips the
   divider of whichever item starts a row, so dividers only sit between stats. */
/* Figures never paint outside the card. StatCard sets --pc-stat-max (the
   longest plain-text figure, in characters): every column is at least wide
   enough for it at --text-base, so long amounts get wide columns or a row
   each. Each item is a size container and --pc-stat-chars sizes its figure to
   fill it (0.66em a character: the widest face plus slack), clamped to --text-base …
   --text-2xl. Past that a figure wraps after a leading currency symbol
   (StatCard puts a <wbr> there), then anywhere. */
.pc-stat .pc-stat-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, max(4.5rem, calc(var(--pc-stat-max, 0) * 0.66 * var(--text-base)))), 1fr)); align-items: start; gap: var(--space-4) var(--space-6); overflow-x: clip; }
.pc-stat .pc-stat-item { position: relative; min-inline-size: 0; overflow-wrap: anywhere; container-type: inline-size; }
.pc-stat .pc-stat-item::before { content: ""; position: absolute; inset-block: 0; inset-inline-start: calc(var(--space-6) / -2); inline-size: 1px; background: var(--border-default); }
.pc-stat .pc-stat-item .l { font-size: var(--fs-caption); color: var(--text-secondary); margin: 0 0 var(--space-1); }
.pc-stat .pc-stat-item .v { font-family: var(--figure-font, var(--font-display)); font-size: clamp(var(--text-base), calc(100cqi / (var(--pc-stat-chars, 1) * 0.66)), var(--text-2xl)); max-inline-size: 100%; font-weight: 700; letter-spacing: -0.01em; }
.pc-stat[data-value-font="display"] .pc-stat-item .v { font-family: var(--font-display); }
.pc-stat[data-value-font="mono"] .pc-stat-item .v { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
.pc-stat[data-value-font="body"] .pc-stat-item .v { font-family: var(--font-body); }
.pc-stat .pc-stat-item .d { font-size: var(--text-xs); font-weight: var(--weight-semibold); margin-top: var(--space-0-5); }
.pc-stat .pc-stat-item .d[data-dir="up"] { color: var(--positive-text); }
.pc-stat .pc-stat-item .d[data-dir="down"] { color: var(--negative-text); }
/* Per-stat tone: the value takes the intent colour AND an edge bar beside it,
   so the state isn't carried by colour alone. */
.pc-stat .pc-stat-item[data-tone] .v { display: inline-flex; align-items: center; gap: var(--space-2); }
.pc-stat .pc-stat-item[data-tone] .v::before { content: ""; inline-size: 4px; align-self: stretch; border-radius: var(--radius-pill); background: currentColor; }
.pc-stat .pc-stat-fig { min-inline-size: 0; }
.pc-stat .pc-stat-item[data-tone="negative"] .v { color: var(--negative-text); }
.pc-stat .pc-stat-item[data-tone="notice"] .v { color: var(--notice-text); }
.pc-stat .pc-stat-item[data-tone="positive"] .v { color: var(--positive-text); }

/* ---------------- ProfileCard ---------------- */
.pc-profile { display: flex; flex-direction: column; align-items: center; text-align: center; gap: var(--space-2); padding: var(--pad-card); height: 100%; box-sizing: border-box; justify-content: center; }
.pc-profile[data-layout="row"] { flex-direction: row; align-items: center; text-align: start; }
.pc-profile h3 { font-family: var(--font-display); font-size: var(--fs-h4); font-weight: 600; margin: 0; letter-spacing: -0.01em; }
.pc-profile .pc-profile-role { font-size: var(--text-sm); color: var(--text-secondary); margin: 0; }
.pc-profile .pc-profile-body { display: flex; flex-direction: column; gap: var(--space-0-5); flex: 1; }
.pc-profile .pc-profile-meta { font-size: var(--text-xs); color: var(--text-tertiary); margin: var(--space-1) 0 0; display: flex; gap: var(--space-2); align-items: center; flex-wrap: wrap; }
.pc-profile[data-layout="stack"] .pc-profile-meta { justify-content: center; }
.pc-profile .pc-actions { margin-top: var(--space-2); }
.pc-profile[data-layout="stack"] .pc-actions { justify-content: center; }

/* ---------------- PlanCard (pricing) ---------------- */
.pc-plan { display: flex; flex-direction: column; gap: var(--space-4); padding: var(--pad-card); position: relative; height: 100%; box-sizing: border-box; }
.pc-plan[data-featured="true"] { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent), var(--shadow-md); }
.pc-plan .pc-plan-flag { position: absolute; inset-block-start: -1px; inset-inline-end: var(--space-4); transform: translateY(-50%); background: var(--accent); color: var(--accent-on); background-image: var(--sheen); box-shadow: var(--bevel); font-family: var(--label-font); font-weight: var(--weight-semibold); font-size: var(--text-xs); padding: var(--space-1) var(--space-2); border-radius: var(--radius-pill); }
.pc-plan .pc-plan-name { font-family: var(--font-display); font-size: var(--fs-h4); font-weight: 600; margin: 0; }
.pc-plan .pc-plan-price { display: flex; align-items: baseline; gap: var(--space-1); }
.pc-plan .pc-plan-price .amt { font-family: var(--font-display); font-size: var(--text-4xl); font-weight: 700; letter-spacing: -0.02em; }
.pc-plan .pc-plan-price .per { font-size: var(--text-sm); color: var(--text-tertiary); }
.pc-plan .pc-plan-desc { font-size: var(--text-sm); color: var(--text-secondary); margin: 0; line-height: var(--leading-normal); }
.pc-plan .pc-plan-features { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--space-3); }
.pc-plan .pc-plan-features li { display: flex; align-items: flex-start; gap: var(--space-2); font-size: var(--text-sm); color: var(--text-primary); }
.pc-plan .pc-plan-features svg { width: 16px; height: 16px; flex: none; color: var(--positive-text); margin-top: var(--space-0-5); }
.pc-plan .pc-plan-cta { margin-top: auto; padding-top: var(--space-2); }

/* ---------------- MediaCard (now playing) ---------------- */
.pc-media { display: flex; gap: var(--space-4); padding: var(--pad-card); align-items: center; }
.pc-media .pc-media-art { width: 76px; height: 76px; border-radius: var(--radius-card); background: var(--accent-subtle); color: var(--accent-text); display: grid; place-items: center; flex: none; overflow: hidden; box-shadow: var(--bevel-soft); }
.pc-media .pc-media-art img { width: 100%; height: 100%; object-fit: cover; }
.pc-media .pc-media-art svg { width: 30px; height: 30px; }
.pc-media .pc-media-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: var(--space-1); }
.pc-media .pc-media-eyebrow { font-family: var(--font-display); font-size: var(--fs-caption); font-weight: var(--weight-semibold); text-transform: uppercase; letter-spacing: var(--tracking-caps); color: var(--text-tertiary); margin: 0; }
.pc-media .pc-media-title { font-family: var(--font-display); font-size: var(--fs-h4); font-weight: 600; margin: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pc-media .pc-media-sub { font-size: var(--text-sm); color: var(--text-secondary); margin: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pc-media .pc-media-scrub { height: 4px; border-radius: var(--radius-pill); background: var(--fill-muted); overflow: hidden; margin-top: var(--space-1-5); }
.pc-media .pc-media-scrub > div { height: 100%; background: var(--accent); border-radius: inherit; }
.pc-media .pc-media-controls { display: flex; align-items: center; gap: var(--space-1); margin-top: var(--space-1-5); }
.pc-media .pc-media-time { font-family: var(--font-mono); font-size: var(--text-xs); color: var(--text-tertiary); }

/* ===== components/datetime/datetime.css ===== */
/* ============================================================
   Prism · Date & time component styles
   Calendar · DatePicker · DateRangePicker · TimePicker
   ============================================================ */

/* ---------------- Field trigger (shared) ---------------- */
.prism-datefield { position: relative; }
.prism-datefield-trigger { position: relative; display: flex; align-items: center; }
.prism-datefield-trigger .prism-input { padding-inline-start: var(--space-10); cursor: pointer; text-align: start; }
.prism-datefield-icon { position: absolute; inset-inline-start: var(--space-3); color: var(--text-tertiary); display: inline-flex; pointer-events: none; }
.prism-datefield-icon > svg { width: var(--icon-md); height: var(--icon-md); }
/* isClearable: × at the trailing edge, with room kept for it */
.prism-datefield-trigger[data-clearable="true"] .prism-input { padding-inline-end: var(--space-10); }
.prism-datefield-clear {
  position: absolute; inset-inline-end: var(--space-2);
  display: inline-flex; align-items: center; justify-content: center;
  inline-size: var(--control-sm); block-size: var(--control-sm); padding: 0;
  border: 0; border-radius: var(--radius-control); background: transparent;
  color: var(--text-secondary); cursor: pointer; transition: var(--transition-colors);
}
.prism-datefield-clear:hover { background: var(--fill-subtle); color: var(--text-primary); }
.prism-datefield-clear:focus-visible { outline: var(--focus-ring-width) solid var(--focus-ring); outline-offset: 1px; }
.prism-datefield-clear > svg { width: var(--icon-sm); height: var(--icon-sm); }
/* Opened as popover="manual" in the top layer and placed by script against the
   viewport (fixed), so a Dialog body or card overflow never clips it. The
   inset/margin/padding/colour lines undo the browser's [popover] defaults. */
.prism-datefield-pop {
  position: fixed; inset: auto; top: 0; left: 0; margin: 0; padding: 0;
  max-inline-size: calc(100vw - 2 * var(--space-2)); overflow: auto; box-sizing: border-box;
  color: var(--text-primary);
  background: var(--surface-overlay);
  border: var(--border-width) solid var(--border-default);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-lg), var(--bevel-soft);
  z-index: var(--z-dropdown);
  animation: prism-pop var(--duration-fast) var(--ease-standard);
}

/* ---------------- Calendar ---------------- */
/* flex row of month panels: one 16.5rem panel by default, N side-by-side when
   `months` > 1 (multi-month range picking). fit-content so the popover hugs it. */
.prism-calendar { display: flex; gap: var(--space-4); padding: var(--space-3); inline-size: fit-content; max-inline-size: 100%; }
.prism-cal-month { inline-size: 16.5rem; flex: none; }
.prism-cal-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: var(--space-2); gap: var(--space-2); }
/* keeps the month title centred on middle panels, which have no nav button */
.prism-cal-navspacer { inline-size: var(--control-sm); block-size: var(--control-sm); flex: none; }
.prism-cal-title { font-family: var(--font-display); font-weight: var(--weight-semibold); font-size: var(--fs-small); color: var(--text-primary); }
.prism-cal-nav { display: flex; gap: var(--space-0-5); }
/* showMonthYearPicker: month + year selects in place of the title */
.prism-cal-jump { display: inline-flex; gap: var(--space-1); min-inline-size: 0; }
.prism-cal-select {
  margin: 0; font: inherit; font-size: var(--fs-small); font-weight: var(--weight-semibold); color: var(--text-primary);
  block-size: var(--control-sm); padding-inline: var(--space-2); min-inline-size: 0;
  background: var(--surface-card); border: var(--border-width) solid var(--border-default); border-radius: var(--radius-control);
  cursor: pointer;
}
.prism-cal-select:hover { border-color: var(--border-strong); }
.prism-cal-select:focus-visible { outline: var(--focus-ring-width) solid var(--focus-ring); outline-offset: 1px; }
.prism-cal-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: var(--space-0-5); }
.prism-cal-wd { display: flex; align-items: center; justify-content: center; height: 28px; font-size: var(--text-xs); color: var(--text-tertiary); font-weight: var(--weight-semibold); }
.prism-cal-day {
  height: 34px; border: 0; background: transparent; border-radius: var(--radius-control);
  font: inherit; font-size: var(--fs-small); color: var(--text-primary); cursor: pointer;
  display: flex; align-items: center; justify-content: center; position: relative;
  transition: var(--transition-colors);
}
.prism-cal-day:hover:not(:disabled) { background: var(--fill-subtle); }
.prism-cal-day:focus-visible { outline: var(--focus-ring-width) solid var(--focus-ring); outline-offset: -2px; }
.prism-cal-day[data-outside="true"] { color: var(--text-disabled); }
.prism-cal-day[data-today="true"] { box-shadow: inset 0 0 0 var(--border-width-strong) var(--accent-border); font-weight: var(--weight-semibold); }
.prism-cal-day:disabled { opacity: 0.4; cursor: not-allowed; }
.prism-cal-day[data-in-range="true"] { background: var(--accent-subtle); border-radius: 0; }
.prism-cal-day[data-range-start="true"] { border-start-start-radius: var(--radius-control); border-end-start-radius: var(--radius-control); }
.prism-cal-day[data-range-end="true"] { border-start-end-radius: var(--radius-control); border-end-end-radius: var(--radius-control); }
.prism-cal-day[data-selected="true"] { background: var(--accent); background-image: var(--sheen); color: var(--accent-on); box-shadow: var(--bevel); }

/* ---------------- TimePicker list ---------------- */
.prism-timelist { max-height: 14rem; overflow-y: auto; padding: var(--space-1); min-width: 9rem; }
.prism-timeopt {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-2);
  width: 100%; border: 0; background: transparent; cursor: pointer; text-align: start;
  padding: var(--space-2) var(--space-3); border-radius: var(--radius-control);
  font: inherit; font-size: var(--fs-small); color: var(--text-primary);
}
.prism-timeopt:hover, .prism-timeopt[data-focused="true"] { background: var(--fill-subtle); }
.prism-timeopt[aria-selected="true"] { color: var(--accent-text); font-weight: var(--weight-semibold); }
.prism-timeopt-check { color: var(--accent-text); display: inline-flex; }
.prism-timeopt-check > svg { width: 15px; height: 15px; }

/* ============================================================
   TimeDial · drum time picker (12/24h, AM/PM, full-width Save)
   ============================================================ */
.prism-timedial {
  position: relative; overflow: hidden; box-sizing: border-box;
  inline-size: 100%; max-inline-size: 32rem;
  background: var(--surface-card);
  border: var(--border-width) solid var(--border-default);
  border-radius: var(--radius-surface);
  color: var(--text-primary);
}
/* three columns, vertically centred: [format] [drum] [meridiem] */
.prism-timedial-body {
  display: grid; grid-template-columns: auto 1fr auto; align-items: center;
  gap: var(--space-4); padding: var(--space-5) var(--pad-card);
  min-block-size: 13rem; /* TimeDial and DateDial reserve equal height */
}
.prism-timedial-modes, .prism-timedial-meridiem { display: flex; flex-direction: column; gap: var(--space-2); align-self: center; }
.prism-timedial-modes { align-items: flex-start; }
.prism-timedial-meridiem { align-items: flex-end; }
.prism-timedial-meridiem[data-hidden="true"] { visibility: hidden; }
/* the format + meridiem selectors are proportionately large, centred beside the drum */
.prism-timedial-toggle {
  border: 0; background: transparent; cursor: pointer; padding: 4px 0; line-height: 1.1;
  font-family: var(--label-font); font-size: var(--fs-h5); font-weight: var(--weight-semibold);
  color: var(--text-tertiary); border-block-start: 2px solid transparent;
}
.prism-timedial-toggle[aria-pressed="true"] { color: var(--accent-text); border-block-start-color: var(--accent); }
.prism-timedial-toggle:focus-visible { outline: var(--focus-ring-width) solid var(--focus-ring); outline-offset: 2px; }
.prism-timedial-toggle[disabled] { opacity: 0.35; cursor: default; }

.prism-timedial-main { display: flex; flex-direction: column; align-items: center; gap: var(--space-2); min-inline-size: 0; }
.prism-timedial-title { font-family: var(--font-mono); font-size: var(--fs-caption); text-transform: uppercase; letter-spacing: var(--tracking-caps); color: var(--text-tertiary); }
.prism-timedial-wheels { display: flex; align-items: center; justify-content: center; gap: var(--space-3); }
.prism-timedial-colon { font-family: var(--font-display); font-size: var(--text-4xl); font-weight: var(--weight-bold); color: var(--text-secondary); }
.prism-timedial-wheel { display: flex; flex-direction: column; align-items: center; gap: 2px; min-inline-size: 3.2ch; user-select: none; touch-action: none; cursor: grab; }
.prism-timedial-wheel:active { cursor: grabbing; }
.prism-timedial-wheel:focus-visible { outline: var(--focus-ring-width) solid var(--focus-ring); outline-offset: 4px; border-radius: var(--radius-card); }
.prism-timedial-cell { border: 0; background: transparent; cursor: pointer; font-family: var(--font-display); line-height: 1; text-align: center; padding: 0; color: inherit; }
.prism-timedial-cell[data-pos="prev"], .prism-timedial-cell[data-pos="next"] { font-size: var(--text-xl); font-weight: var(--weight-medium); color: var(--text-tertiary); opacity: 0.5; }
.prism-timedial-cell[data-pos="cur"] {
  font-size: var(--text-6xl); font-weight: var(--weight-bold); color: var(--text-primary); letter-spacing: -0.02em;
  cursor: text;
  /* a faint underline signals the value is editable; it brightens on hover/focus */
  text-decoration: underline dotted color-mix(in oklch, var(--text-tertiary) 55%, transparent);
  text-decoration-thickness: 2px; text-underline-offset: 8px;
  transition: text-decoration-color var(--duration-fast) var(--ease-standard);
}
.prism-timedial-cell[data-pos="cur"]:hover, .prism-timedial-cell[data-pos="cur"]:focus-visible { text-decoration-color: var(--accent); }
/* click-to-type editing of the selected value */
.prism-timedial-input {
  inline-size: 2.6ch; text-align: center; border: 0; background: transparent; padding: 0; outline: 0;
  font-family: var(--font-display); font-size: var(--text-6xl); font-weight: var(--weight-bold);
  color: var(--accent-text); letter-spacing: -0.02em; border-block-end: 2px solid var(--accent);
  caret-color: var(--accent); text-align: center;
}
.prism-timedial-input::placeholder { color: var(--text-tertiary); opacity: 0.55; }
/* the dial has no outer padding, so its Save bar sits flush */
.prism-timedial .prism-actionbar { --actionbar-inset: 0; margin-block-start: 0; }
/* Industry: the selected readout reads as a lit instrument value */
[data-theme="industry"] .prism-timedial-cell[data-pos="cur"] { text-shadow: var(--led-text-glow); }

/* ---- DateDial — date sibling of TimeDial (reuses the drum classes) ---- */
.prism-datedial .prism-timedial-body { grid-template-columns: 1fr; }
.prism-datedial .prism-timedial-wheels { gap: var(--space-5); align-items: flex-start; }
.prism-datedial-col { display: flex; flex-direction: column; align-items: center; gap: var(--space-1); }
.prism-datedial-lab { font-family: var(--font-mono); font-size: var(--fs-caption); text-transform: uppercase; letter-spacing: var(--tracking-caps); color: var(--text-tertiary); }
.prism-datedial .prism-timedial-wheel { min-inline-size: 4ch; }
.prism-datedial .prism-timedial-input { inline-size: 4.5ch; }

/* ===== components/typography/typography.css ===== */
/* ============================================================
   Prism · Typography
   ------------------------------------------------------------
   Ready-made type-role classes (the React <Heading>/<Text>/<Eyebrow>/
   <Blockquote>/<Pullquote>/<Prose> components render these), plus a
   comprehensive .prism-prose longform treatment for CMS / markdown.

   Every size points at a responsive --fs-* role (tokens/scales.css), so
   type reflows across mobile → tablet → desktop → cinema and respects
   density. Colors/space/weights are all tokens — no raw values.
   ============================================================ */

/* ---------------- Headings (display family) ---------------- */
/* PageHero's root also carries .prism-hero (kept for existing selectors);
   its layout is keyed to .prism-page-hero, and the type role skips it so
   the section and everything in it keep their own type. */
.prism-showcase,
.prism-hero:not(.prism-page-hero),
.prism-display,
.prism-h1, .prism-h2, .prism-h3, .prism-h4, .prism-h5, .prism-h6 {
  font-family: var(--font-display);
  color: var(--text-primary);
  margin: 0;
  text-wrap: balance;
}
/* marketing heroes only — tight leading for two or three huge lines */
.prism-showcase {
  font-size: var(--fs-showcase);
  line-height: var(--lh-showcase);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-showcase);
}
.prism-hero:not(.prism-page-hero) {
  font-size: var(--fs-hero);
  line-height: var(--leading-none);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-tighter);
}
.prism-display {
  font-size: var(--fs-display);
  line-height: var(--leading-tight);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-tighter);
}
.prism-h1 {
  font-size: var(--fs-h1);
  line-height: var(--leading-tight);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-tight);
}
.prism-h2 {
  font-size: var(--fs-h2);
  line-height: var(--leading-snug);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-tight);
}
.prism-h3 {
  font-size: var(--fs-h3);
  line-height: var(--leading-snug);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-tight);
}
.prism-h4 {
  font-size: var(--fs-h4);
  line-height: var(--leading-snug);
  font-weight: var(--weight-semibold);
}
.prism-h5 {
  font-size: var(--fs-h5);
  line-height: var(--leading-normal);
  font-weight: var(--weight-semibold);
}
.prism-h6 {
  font-size: var(--fs-h6);
  line-height: var(--leading-normal);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-wide);
}

/* ---------------- Eyebrow / overline ---------------- */
.prism-eyebrow {
  font-family: var(--font-body);
  font-size: var(--fs-caption);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--text-tertiary);
  margin: 0;
}

/* ---------------- Body & inline (body family) ---------------- */
.prism-lead,
.prism-body-lg, .prism-body, .prism-body-sm,
.prism-small, .prism-caption {
  font-family: var(--font-body);
  margin: 0;
}
.prism-lead {
  font-size: var(--fs-lead);
  line-height: var(--leading-snug);
  color: var(--text-secondary);
  text-wrap: pretty;
}
.prism-body-lg { font-size: var(--fs-body-lg); line-height: var(--leading-relaxed); color: var(--text-primary); text-wrap: pretty; }
.prism-body    { font-size: var(--fs-body);    line-height: var(--leading-normal);  color: var(--text-primary); text-wrap: pretty; }
.prism-body-sm { font-size: var(--fs-body-sm); line-height: var(--leading-normal);  color: var(--text-secondary); text-wrap: pretty; }
.prism-small   { font-size: var(--fs-small);   line-height: var(--leading-normal);  color: var(--text-secondary); }
.prism-caption { font-size: var(--fs-caption); line-height: var(--leading-normal);  color: var(--text-tertiary); }

/* Tone modifiers (compose with any body/heading role) */
.prism-t-secondary { color: var(--text-secondary); }
.prism-t-tertiary  { color: var(--text-tertiary); }
.prism-t-accent    { color: var(--accent-text); }
.prism-t-positive  { color: var(--positive-text); }
.prism-t-notice    { color: var(--notice-text); }  /* amber: awaiting, ongoing, near expiry */
.prism-t-negative  { color: var(--negative-text); }
.prism-t-info      { color: var(--info-text); }
/* Text with a leading icon (Text `icon`): the icon sits in a box one line tall,
   so it centres on the FIRST line even when the text wraps, and it takes the
   text's colour (so a tone colours both). */
.prism-t-withicon { display: flex; align-items: flex-start; gap: var(--gap-inline); }
span.prism-t-withicon { display: inline-flex; }
.prism-t-icon { flex: none; display: inline-flex; align-items: center; block-size: calc(1em * var(--leading-normal)); block-size: 1lh; }
.prism-t-icon > svg { inline-size: 1.1em; block-size: 1.1em; }
.prism-t-withicon > .prism-t-body { min-inline-size: 0; }
/* mono: admission / reference numbers — monospace face, tabular figures */
.prism-t-mono { font-family: var(--font-mono); font-variant-numeric: tabular-nums slashed-zero; letter-spacing: 0; }

/* Constrain any text block to a readable measure */
.prism-measure { max-inline-size: var(--measure); }

/* ---------------- Blockquote ---------------- */
.prism-blockquote {
  margin: 0;
  padding-inline-start: var(--space-5);
  border-inline-start: var(--border-width-strong) solid var(--accent-border);
  color: var(--text-secondary);
}
.prism-blockquote > p {
  font-size: var(--fs-body-lg);
  line-height: var(--leading-relaxed);
  font-style: italic;
  margin: 0;
  text-wrap: pretty;
}
.prism-blockquote cite,
.prism-blockquote footer {
  display: block;
  margin-top: var(--space-3);
  font-size: var(--fs-small);
  font-style: normal;
  color: var(--text-tertiary);
}
.prism-blockquote cite::before,
.prism-blockquote footer::before { content: "— "; }
/* sm — a short quoted note in a card or list row: body size, tighter rule */
.prism-blockquote[data-size="sm"] { padding-inline-start: var(--space-3); border-inline-start-width: var(--border-width); }
.prism-blockquote[data-size="sm"] > p { font-size: var(--fs-body); line-height: var(--leading-normal); }
.prism-blockquote[data-size="sm"] cite,
.prism-blockquote[data-size="sm"] footer { margin-top: var(--space-1); font-size: var(--fs-caption); }

/* ---------------- Pull quote ---------------- */
.prism-pullquote {
  margin: 0;
  position: relative;
  padding-block: var(--space-4);
}
.prism-pullquote > p {
  font-family: var(--font-display);
  font-size: var(--fs-h2);
  line-height: var(--leading-snug);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-tight);
  color: var(--text-primary);
  margin: 0;
  text-wrap: balance;
}
.prism-pullquote[data-accent="true"] > p { color: var(--accent-text); }
.prism-pullquote > footer {
  margin-top: var(--space-4);
  font-family: var(--font-body);
  font-size: var(--fs-small);
  font-weight: var(--weight-semibold);
  color: var(--text-tertiary);
}
.prism-pullquote > footer span { display: block; font-weight: var(--weight-regular); }

/* ============================================================
   Longform / prose  (.prism-prose)
   Apply to a container of CMS- or markdown-generated HTML. Sets a
   readable measure and consistent vertical rhythm; styles every
   common element with tokens.
   ============================================================ */
.prism-prose {
  font-family: var(--font-body);
  font-size: var(--fs-body);
  line-height: var(--leading-relaxed);
  color: var(--text-primary);
  max-inline-size: var(--measure);
}
.prism-prose > :first-child { margin-block-start: 0; }
.prism-prose > :last-child  { margin-block-end: 0; }

.prism-prose p { margin-block: var(--space-4); text-wrap: pretty; }

.prism-prose h2 {
  font-family: var(--font-display); font-weight: var(--weight-bold);
  font-size: var(--fs-h2); line-height: var(--leading-snug);
  letter-spacing: var(--tracking-tight);
  margin-block: var(--space-10) var(--space-3);
  text-wrap: balance;
}
.prism-prose h3 {
  font-family: var(--font-display); font-weight: var(--weight-semibold);
  font-size: var(--fs-h3); line-height: var(--leading-snug);
  margin-block: var(--space-8) var(--space-2); text-wrap: balance;
}
.prism-prose h4 {
  font-family: var(--font-display); font-weight: var(--weight-semibold);
  font-size: var(--fs-h4); line-height: var(--leading-snug);
  margin-block: var(--space-6) var(--space-2);
}
.prism-prose h2 + *, .prism-prose h3 + *, .prism-prose h4 + * { margin-block-start: 0; }

.prism-prose ul, .prism-prose ol { margin-block: var(--space-4); padding-inline-start: var(--space-6); }
.prism-prose li { margin-block: var(--space-2); }
.prism-prose li::marker { color: var(--text-tertiary); }
.prism-prose ul ul, .prism-prose ol ol, .prism-prose ul ol, .prism-prose ol ul { margin-block: var(--space-2); }

.prism-prose a {
  color: var(--text-link);
  text-decoration: underline;
  text-decoration-color: var(--accent-border);
  text-underline-offset: 2px;
}
.prism-prose a:hover { color: var(--text-link-hover); text-decoration-color: currentColor; }

.prism-prose strong { font-weight: var(--weight-bold); color: var(--text-primary); }
.prism-prose em { font-style: italic; }
.prism-prose small { font-size: var(--fs-small); color: var(--text-secondary); }

.prism-prose code {
  font-family: var(--font-mono);
  font-size: 0.9em;
  background: var(--fill-subtle);
  border: var(--border-width) solid var(--border-subtle);
  border-radius: var(--radius-xs);
  padding: 0.1em 0.35em;
}
.prism-prose pre {
  font-family: var(--font-mono);
  font-size: var(--fs-small);
  line-height: var(--leading-normal);
  background: var(--surface-sunken);
  border: var(--border-width) solid var(--border-subtle);
  border-radius: var(--radius-md);
  padding: var(--space-4);
  overflow-x: auto;
  margin-block: var(--space-5);
}
.prism-prose pre code { background: none; border: 0; padding: 0; font-size: inherit; }

.prism-prose blockquote {
  margin-block: var(--space-5); margin-inline: 0;
  padding-inline-start: var(--space-5);
  border-inline-start: var(--border-width-strong) solid var(--accent-border);
  color: var(--text-secondary); font-style: italic;
}

.prism-prose hr { border: 0; border-top: var(--border-width) solid var(--border-default); margin-block: var(--space-10); }

.prism-prose img, .prism-prose video {
  max-inline-size: 100%; height: auto; border-radius: var(--radius-md); margin-block: var(--space-5);
}
.prism-prose figure { margin: var(--space-6) 0; }
.prism-prose figcaption { font-size: var(--fs-caption); color: var(--text-tertiary); margin-top: var(--space-2); text-align: center; }

.prism-prose table { width: 100%; border-collapse: collapse; margin-block: var(--space-5); font-size: var(--fs-small); }
.prism-prose th, .prism-prose td { text-align: start; padding: var(--space-2) var(--space-3); border-bottom: var(--border-width) solid var(--border-subtle); }
.prism-prose th { font-weight: var(--weight-semibold); color: var(--text-secondary); }

/* ===== components/states/states.css ===== */
/* ============================================================
   Prism · Status states
   EmptyState — first-run · no-results · error · offline · success
   ============================================================ */

.prism-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: var(--space-4);
  padding: var(--space-8) var(--space-5);
  color: var(--text-primary);
}

/* media — tinted disc holding the icon (or a custom illustration) */
.prism-empty-media {
  flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  width: 72px; height: 72px; border-radius: var(--radius-pill);
  background: var(--fill-muted); color: var(--text-tertiary);
}
.prism-empty-media > svg { width: 34px; height: 34px; }
.prism-empty-media img,
.prism-empty-media picture { width: 100%; height: 100%; object-fit: contain; border-radius: inherit; }
/* when a full illustration is supplied, drop the disc chrome */
.prism-empty[data-illustration="true"] .prism-empty-media {
  width: auto; height: auto; background: transparent; border-radius: 0;
}

.prism-empty-copy { display: flex; flex-direction: column; gap: var(--space-2); max-inline-size: 44ch; }
.prism-empty-title {
  font-family: var(--font-display); font-weight: var(--weight-semibold);
  font-size: var(--fs-h5); line-height: var(--leading-tight); color: var(--text-primary);
  margin: 0;
}
.prism-empty-text { font-size: var(--fs-body-sm); color: var(--text-secondary); line-height: var(--leading-normal); text-wrap: pretty; margin: 0; }
.prism-empty-actions { display: flex; flex-wrap: wrap; gap: var(--space-3); justify-content: center; margin-block-start: var(--space-1); }
.prism-empty-aux { font-size: var(--text-xs); color: var(--text-tertiary); }
.prism-empty-aux a { color: var(--text-link); }

/* ---- tone per variant (only the media disc carries the hue) ---- */
.prism-empty[data-variant="no-results"] .prism-empty-media { background: var(--accent-subtle); color: var(--accent-text); }
.prism-empty[data-variant="error"]      .prism-empty-media { background: var(--negative-subtle); color: var(--negative-text); }
.prism-empty[data-variant="offline"]    .prism-empty-media { background: var(--notice-subtle); color: var(--notice-text); }
.prism-empty[data-variant="success"]    .prism-empty-media { background: var(--positive-subtle); color: var(--positive-text); }

/* ---- sizes ---- */
/* page — full-viewport / large region */
.prism-empty[data-size="page"] { padding: var(--space-10) var(--space-5); gap: var(--space-5); }
.prism-empty[data-size="page"] .prism-empty-media { width: 88px; height: 88px; }
.prism-empty[data-size="page"] .prism-empty-media > svg { width: 42px; height: 42px; }
.prism-empty[data-size="page"] .prism-empty-title { font-size: var(--fs-h3); }
.prism-empty[data-size="page"] .prism-empty-text { font-size: var(--fs-body); }

/* section — inside a card / panel (the default) */
.prism-empty[data-size="section"] { padding: var(--space-8) var(--space-6); }

/* inline — tight, horizontal; for a table region or small panel */
.prism-empty[data-size="inline"] {
  flex-direction: row; text-align: start; align-items: center;
  gap: var(--space-4); padding: var(--space-5);
}
.prism-empty[data-size="inline"] .prism-empty-media { width: 44px; height: 44px; }
.prism-empty[data-size="inline"] .prism-empty-media > svg { width: 22px; height: 22px; }
.prism-empty[data-size="inline"] .prism-empty-copy { align-items: flex-start; }
.prism-empty[data-size="inline"] .prism-empty-title { font-size: var(--fs-body); }
.prism-empty[data-size="inline"] .prism-empty-text { font-size: var(--fs-body-sm); }
.prism-empty[data-size="inline"] .prism-empty-actions { justify-content: flex-start; margin-block-start: 0; }
.prism-empty[data-size="inline"] .prism-empty-main { display: flex; flex-direction: column; gap: var(--space-3); }

/* a bordered well wrapper for empty regions that need a container */
.prism-empty-well {
  border: var(--border-width) dashed var(--border-default);
  border-radius: var(--radius-card);
  background: var(--surface-sunken, var(--surface-card));
}


/* Permission is a boundary, not a failure: neutral disc, never the error tint. */
.prism-empty[data-variant="permission"] .prism-empty-media { color: var(--text-secondary); background: var(--fill-subtle); }
/* Printed verbatim and selectable — it is the first thing support asks for. */
.prism-empty-ref { margin: var(--space-2) 0 0; display: inline-flex; align-items: center; gap: var(--space-2); font-size: var(--text-xs); color: var(--text-tertiary); }
.prism-empty-ref > code { font-family: var(--font-mono); color: var(--text-secondary); background: var(--fill-subtle); border-radius: var(--radius-xs); padding: var(--space-0-5) var(--space-1-5); user-select: all; }

/* ---------------- SpotIllustration ----------------
   Line art that takes the container's hue: the disc and the accent line
   follow --accent-subtle / --accent, so data-hue or data-signature on any
   ancestor recolours it. The object line stays neutral. */
.prism-spot { display: block; inline-size: 128px; block-size: auto; aspect-ratio: 4 / 3; flex: none; overflow: visible; }
.prism-spot[data-size="sm"] { inline-size: 96px; }
.prism-spot[data-size="lg"] { inline-size: 176px; }
.prism-spot .prism-spot-bg { fill: var(--accent-subtle); stroke: none; }
.prism-spot .prism-spot-ink { stroke: var(--text-secondary); }
.prism-spot .prism-spot-hue { stroke: var(--accent); }
/* inside EmptyState: the drawing replaces the disc at its own size */
.prism-empty-media > .prism-spot { inline-size: 128px; block-size: auto; }
.prism-empty-media > .prism-spot[data-size="sm"] { inline-size: 96px; }
.prism-empty-media > .prism-spot[data-size="lg"] { inline-size: 176px; }
/* A SpotIllustration inside EmptyState takes the variant's tone, the way the
   icon disc does — a success state reads green, not like every other state. */
.prism-empty[data-variant="success"] .prism-spot    { --accent: var(--positive); --accent-subtle: var(--positive-subtle); }
.prism-empty[data-variant="error"] .prism-spot      { --accent: var(--negative); --accent-subtle: var(--negative-subtle); }
.prism-empty[data-variant="offline"] .prism-spot    { --accent: var(--notice); --accent-subtle: var(--notice-subtle); }
.prism-empty[data-variant="permission"] .prism-spot { --accent: var(--text-secondary); --accent-subtle: var(--fill-subtle); }
/* inline: the 44px icon disc would squeeze a drawing to a smudge — give the
   illustration its own box with a readable minimum, and drop it on a phone
   where the row has no room for it */
.prism-empty[data-size="inline"][data-illustration="true"] .prism-empty-media { width: auto; height: auto; }
/* An illustration replaces the disc entirely: no tinted box behind it (the
   variant tint above would otherwise paint the whole drawing's rectangle),
   and the icon-glyph sizes (> svg: 22/34/42px) must not squash the drawing. */
.prism-empty[data-illustration="true"][data-variant] .prism-empty-media { background: transparent; }
.prism-empty[data-size] .prism-empty-media > svg.prism-spot { width: 128px; height: auto; }
.prism-empty[data-size] .prism-empty-media > svg.prism-spot[data-size="sm"] { width: 96px; }
.prism-empty[data-size] .prism-empty-media > svg.prism-spot[data-size="lg"] { width: 176px; }
.prism-empty[data-size="inline"] .prism-empty-media > svg.prism-spot { width: 88px; min-inline-size: 80px; flex: none; }
@media (max-width: 639.98px) { .prism-empty[data-size="inline"][data-illustration="true"] .prism-empty-media { display: none; } }

/* ===== components/charts/charts.css ===== */
/* ============================================================
   Prism · Charts (SVG primitives)
   Sparkline · LineChart · BarChart · DonutChart · Gauge · Legend
   ============================================================ */

.prism-chart { width: 100%; color: var(--text-secondary); }
.prism-chart svg { display: block; width: 100%; height: auto; overflow: visible; }
.prism-chart-svg text { font-family: var(--font-mono); fill: var(--text-tertiary); font-size: var(--fs-caption); }
.prism-chart-axis-title { fill: var(--text-secondary); font-family: var(--label-font); font-size: var(--fs-caption); font-weight: var(--weight-semibold); }
.prism-chart-grid { stroke: var(--border-subtle); stroke-width: 1; }
.prism-chart-axis { stroke: var(--border-default); stroke-width: 1; }
.prism-chart-zero { stroke: var(--border-strong); stroke-width: 1; }

/* legend */
.prism-legend { display: flex; flex-wrap: wrap; gap: var(--space-2) var(--space-4); margin-block-start: var(--space-3); }
.prism-legend[data-align="center"] { justify-content: center; }
.prism-legend-item { display: inline-flex; align-items: center; gap: var(--space-1-5); font-size: var(--text-xs); color: var(--text-secondary); }
.prism-legend-swatch { width: 11px; height: 11px; border-radius: var(--radius-xs); flex: none; }
.prism-legend-swatch[data-shape="line"] { height: 3px; border-radius: var(--radius-pill); width: 14px; }
.prism-legend-swatch[data-shape="dot"] { border-radius: var(--radius-pill); }

/* sparkline (axis-less inline trend) */
.prism-spark { display: block; width: 100%; height: auto; overflow: visible; }

/* donut center label */
.prism-donut-wrap { position: relative; display: inline-grid; place-items: center; }
.prism-donut-center { position: absolute; inset: 0; display: grid; place-content: center; text-align: center; gap: 1px; }
.prism-donut-value { font-family: var(--font-display); font-weight: var(--weight-bold); font-size: var(--text-base); line-height: 1; color: var(--text-primary); }
.prism-donut-label { font-size: var(--text-xs); color: var(--text-tertiary); }

/* gauge */
.prism-gauge { display: inline-grid; place-items: center; position: relative; }
.prism-gauge-readout { position: absolute; inset-block-end: 4%; text-align: center; display: grid; gap: 0; }
.prism-gauge-value { font-family: var(--font-display); font-weight: var(--weight-bold); font-size: var(--text-xl); line-height: 1; color: var(--text-primary); }
.prism-gauge-value .u { font-size: 0.5em; font-weight: var(--weight-semibold); color: var(--text-tertiary); margin-inline-start: var(--space-0-5); }
.prism-gauge-label { font-size: var(--text-xs); color: var(--text-tertiary); }

/* tooltip-ish value bubble on bars/points (static, no JS hover required) */
.prism-chart-value { fill: var(--text-secondary); font-family: var(--font-mono); font-size: var(--fs-caption); }

/* screen-reader data-table fallback for every chart. The class sits on a
   <div> AROUND the <table>, never on the table itself: a table ignores
   width: 1px and lays out at its content size, and clip / contain don't
   remove that from the page's scrollable overflow — a 40-row BarChart's
   table widened a 390px page to 529px. A 1px overflow:hidden box does. */
.prism-chart-sr {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ============================================================
   WaterfallChart
   ============================================================ */
.prism-wf-connector { stroke: var(--border-strong); stroke-width: 1; stroke-dasharray: 3 3; }
.prism-wf-value { font-family: var(--font-mono); font-size: var(--fs-caption); fill: var(--text-secondary); }

/* ============================================================
   FunnelChart — length-proportional rows, not a trapezoid
   ============================================================ */
/* ONE grid owns all three columns, so every row, the drop-off annotations
   and any future footer align by construction — no measured widths. */
.prism-funnel { display: grid; grid-template-columns: 132px 1fr auto; column-gap: var(--space-3); row-gap: var(--space-2); align-items: center; }
/* Resilience: a row wrapper (older builds, or a caller grouping rows) would
   otherwise be placed as a SINGLE grid item and shear every row sideways.
   display:contents dissolves it into the parent grid. */
.prism-funnel-row, .prism-bullet-row { display: contents; }
.prism-funnel-label { font-size: var(--text-xs); color: var(--text-secondary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.prism-funnel-track { display: block; border-radius: var(--radius-xs); background: var(--series-track); overflow: hidden; }
.prism-funnel-fill { display: block; block-size: 100%; border-radius: var(--radius-xs); }
.prism-funnel-value { display: inline-flex; align-items: baseline; gap: var(--space-2); font-family: var(--font-mono); font-size: var(--text-xs); font-variant-numeric: tabular-nums; color: var(--text-primary); white-space: nowrap; }
.prism-funnel-rate { color: var(--text-tertiary); font-weight: var(--weight-regular); font-size: var(--text-xs); }
/* sits in the track column, between the two bars it describes */
/* spans to the last column so the row is FULL — otherwise auto-placement
   puts the next stage's label in column 3 and every row shears sideways. */
.prism-funnel-drop {
  grid-column: 2 / -1; display: inline-flex; align-items: center; gap: var(--space-1);
  font-family: var(--font-mono); font-size: var(--fs-caption); color: var(--text-tertiary);
}
.prism-funnel-drop > svg { width: 11px; height: 11px; color: var(--negative); }

/* ============================================================
   BulletChart — bands · measure · target tick
   ============================================================ */
.prism-bullet { display: grid; grid-template-columns: 132px 1fr auto; column-gap: var(--space-3); row-gap: var(--space-2); align-items: center; }
.prism-bullet-label { font-size: var(--text-xs); color: var(--text-secondary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.prism-bullet-track { position: relative; display: block; border-radius: var(--radius-xs); background: var(--series-track); overflow: hidden; }
/* bands stack from the start edge, each drawn over the last — later stops are wider */
.prism-bullet-band { position: absolute; inset-block: 0; inset-inline-start: 0; display: block; background: var(--surface-stripe, var(--fill-subtle)); }
.prism-bullet-band[data-step="0"] { background: color-mix(in oklch, var(--text-tertiary) 22%, transparent); z-index: 2; }
.prism-bullet-band[data-step="1"] { background: color-mix(in oklch, var(--text-tertiary) 13%, transparent); z-index: 1; }
.prism-bullet-band[data-step="2"] { background: color-mix(in oklch, var(--text-tertiary) 7%, transparent); }
.prism-bullet-measure {
  position: absolute; inset-block: 5px; inset-inline-start: 0; z-index: 3;
  display: block; border-radius: 1px; background: var(--text-secondary);
}
.prism-bullet-measure[data-hit="true"] { background: var(--positive); }
.prism-bullet-target { position: absolute; inset-block: 1px; z-index: 4; inline-size: 2px; margin-inline-start: -1px; background: var(--text-primary); }
.prism-bullet-value { display: inline-flex; align-items: baseline; gap: var(--space-2); font-family: var(--font-mono); font-size: var(--text-xs); font-variant-numeric: tabular-nums; color: var(--text-primary); white-space: nowrap; min-inline-size: 84px; justify-content: flex-end; }
.prism-bullet-vs { font-size: var(--text-xs); font-weight: var(--weight-regular); color: var(--text-tertiary); }
.prism-bullet-vs[data-hit="true"] { color: var(--positive); }
/* same track column as the bars, so ticks land under them at any width */
.prism-bullet-axis { grid-column: 2; display: flex; justify-content: space-between; font-family: var(--font-mono); font-size: var(--fs-caption); color: var(--text-tertiary); white-space: nowrap; }

/* ============================================================
   ComboChart
   ============================================================ */
.prism-combo-y2 { fill: var(--text-tertiary); }
.prism-combo-axis-label { font-family: var(--font-mono); font-size: var(--fs-caption); fill: var(--text-tertiary); }
.prism-legend-axis { font-style: normal; font-family: var(--font-mono); font-size: var(--fs-caption); color: var(--text-tertiary); }
.prism-legend-swatch[data-shape="line"] { block-size: 3px; border-radius: 2px; align-self: center; }

/* ============================================================
   HeatmapGrid · CalendarHeatmap · CohortGrid
   Five discrete buckets, and "no data" is hatched — never the
   lowest bucket, because missing and zero are different facts.
   ============================================================ */
.prism-heatmap { display: grid; grid-template-columns: max-content repeat(var(--hm-cols), minmax(0, 1fr)); gap: var(--space-0-5); align-items: stretch; }
.prism-hm-corner { display: block; }
.prism-hm-xlabel { font-family: var(--font-mono); font-size: var(--fs-caption); color: var(--text-tertiary); text-align: center; padding-block-end: var(--space-1); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.prism-hm-ylabel { font-size: var(--text-xs); color: var(--text-secondary); padding-inline-end: var(--space-3); align-self: center; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-inline-size: 132px; }
.prism-hm-cell { display: flex; align-items: center; justify-content: center; block-size: var(--hm-cell-h, 34px); border-radius: var(--radius-xs); background: var(--series-track); }
.prism-hm-cell > b { font-family: var(--font-mono); font-size: var(--fs-caption); font-weight: var(--weight-regular); color: var(--text-primary); font-variant-numeric: tabular-nums; }
.prism-hm-cell > b[data-dark="true"] { color: var(--surface-page); }
/* no data — hatched, so it can never be mistaken for the lowest bucket */
.prism-hm-cell[data-empty="true"], .prism-calheat-cell[data-empty="true"], .prism-co-cell[data-future="true"] {
  background: repeating-linear-gradient(135deg, transparent 0 3px, color-mix(in oklch, var(--text-tertiary) 22%, transparent) 3px 4px);
}
.prism-hm-legend { display: flex; align-items: center; gap: var(--space-0-5); margin-block-start: var(--space-3); font-family: var(--font-mono); font-size: var(--fs-caption); color: var(--text-tertiary); }
.prism-hm-legend-swatch { inline-size: 18px; block-size: 10px; border-radius: 1px; }
.prism-hm-legend > span:first-child { margin-inline-end: var(--space-2); }
.prism-hm-legend > span:last-child { margin-inline-start: var(--space-2); }

/* CalendarHeatmap
   Rows are real flex rows (role="row"), so the grid keeps its semantics.
   The calendar is max-content wide inside its own scroll box: a short range
   has no scrollbar, a long one scrolls there (never the page). Month labels
   are positioned over their week and may run past it; the trailing padding
   leaves room for the last one, so a one-week range never clips "Oct". */
.prism-calheat {
  --cal-gap: var(--space-0-5); --cal-surface: var(--surface-card);
  position: relative; min-inline-size: 0; max-inline-size: 100%;
}
/* steps: zero, then four mixes from the surface toward --accent-text — the
   accent tuned to read on the card in every theme (the --accent FILL is
   deepened for white ink, so on a dark card it would top out under 3:1).
   data-hue re-points it to the hue's text colour. The zero step and the
   base cell are a whisper of ink on the surface, so they follow the theme
   (--series-track is light-only). Diverging keeps --chart-div-1…5. */
.prism-calheat { --cal-ink: var(--accent-text); --cal-zero: color-mix(in oklab, var(--text-primary) 9%, var(--cal-surface)); }
.prism-calheat [data-step="0"] { background: var(--cal-zero); }
.prism-calheat [data-step="1"] { background: color-mix(in oklab, var(--cal-ink) 24%, var(--cal-surface)); }
.prism-calheat [data-step="2"] { background: color-mix(in oklab, var(--cal-ink) 48%, var(--cal-surface)); }
.prism-calheat [data-step="3"] { background: color-mix(in oklab, var(--cal-ink) 74%, var(--cal-surface)); }
.prism-calheat [data-step="4"] { background: var(--cal-ink); }
.prism-calheat[data-scale="diverging"] [data-step="1"] { background: var(--chart-div-1); }
.prism-calheat[data-scale="diverging"] [data-step="2"] { background: var(--chart-div-2); }
.prism-calheat[data-scale="diverging"] [data-step="3"] { background: var(--chart-div-3); }
.prism-calheat[data-scale="diverging"] [data-step="4"] { background: var(--chart-div-4); }
.prism-calheat[data-scale="diverging"] [data-step="5"] { background: var(--chart-div-5); }

/* weekday labels sit in their own column beside the scroll box, so they stay
   in view while a long range scrolls (the grid rows hold only days) */
.prism-calheat-frame { display: flex; align-items: flex-start; min-inline-size: 0; max-inline-size: 100%; }
.prism-calheat-dows { flex: none; display: flex; flex-direction: column; gap: var(--cal-gap); padding-block: var(--space-1); padding-inline-end: var(--space-2); font-family: var(--font-mono); font-size: var(--fs-caption); color: var(--text-tertiary); }
.prism-calheat-dows-gap { block-size: 1.5em; }
.prism-calheat-dow { block-size: var(--cal-size); line-height: var(--cal-size); white-space: nowrap; }
.prism-calheat-scroll { flex: 1 1 auto; min-inline-size: 0; overflow-x: auto; overflow-y: hidden; padding-block: var(--space-1); scrollbar-width: thin; }
.prism-calheat-body { inline-size: max-content; padding-inline: var(--space-1) 2.75em; }
.prism-calheat-months { position: relative; block-size: 1.5em; font-family: var(--font-mono); font-size: var(--fs-caption); color: var(--text-tertiary); }
.prism-calheat-month { position: absolute; inset-block-start: 0; inset-inline-start: calc(var(--col) * (var(--cal-size) + var(--cal-gap))); inline-size: max-content; white-space: nowrap; line-height: 1.5; }
.prism-calheat-grid { display: flex; flex-direction: column; gap: var(--cal-gap); }
.prism-calheat-row { display: flex; align-items: center; gap: var(--cal-gap); }
.prism-calheat-cell { scroll-margin: 6px; flex: none; display: block; inline-size: var(--cal-size); block-size: var(--cal-size); border-radius: 2px; background: var(--cal-zero, var(--series-track)); }
.prism-calheat-cell[data-out="true"] { background: transparent; }
/* after today: drawn empty, an outline only */
.prism-calheat-cell[data-future="true"] { background: transparent; box-shadow: inset 0 0 0 1px var(--border-subtle); }
.prism-calheat-cell[role="gridcell"]:hover { box-shadow: inset 0 0 0 1px var(--text-secondary); }
.prism-calheat-cell[role="gridcell"]:focus-visible { outline: var(--focus-ring-width) solid var(--focus-ring); outline-offset: 1px; }
.prism-calheat-cell[data-selectable="true"] { cursor: pointer; }
.prism-calheat-cell[data-today="true"] { box-shadow: inset 0 0 0 1px var(--text-primary); }
/* selected: a ring in ink, so it isn't carried by colour alone */
.prism-calheat-cell[data-selected="true"] { outline: 2px solid var(--text-primary); outline-offset: 1px; }

.prism-calheat-legend { display: flex; flex-wrap: wrap; align-items: center; gap: var(--cal-gap); margin-block-start: var(--space-2); padding-inline-start: var(--space-1); font-family: var(--font-mono); font-size: var(--fs-caption); color: var(--text-tertiary); }
.prism-calheat-legend > span:not(.prism-calheat-cell) { margin-inline: var(--space-1); }
.prism-calheat-legend > span:first-child { margin-inline-start: 0; }
.prism-calheat-key { flex: none; }
.prism-calheat-key-gap { margin-inline-start: var(--space-3); }

/* tooltip: inside the chart box, clamped by the component, never wider */
.prism-calheat-tip {
  position: absolute; z-index: 2; pointer-events: none; max-inline-size: min(22rem, 100%);
  padding: var(--space-1) var(--space-2); border-radius: var(--radius-sm);
  background: var(--surface-inverse); color: var(--text-on-inverse);
  font-family: var(--body-font); font-size: var(--text-xs); line-height: 1.35; box-shadow: var(--shadow-md);
}

/* CohortGrid */
.prism-cohort { display: grid; grid-template-columns: max-content max-content repeat(var(--co-cols), minmax(0, 1fr)); gap: var(--space-0-5); }
.prism-co-corner { font-family: var(--font-mono); font-size: var(--fs-caption); color: var(--text-tertiary); align-self: end; padding-block-end: var(--space-1); }
.prism-co-size-head { text-align: end; padding-inline: var(--space-3) var(--space-3); }
.prism-co-head { font-family: var(--font-mono); font-size: var(--fs-caption); color: var(--text-tertiary); text-align: center; padding-block-end: var(--space-1); }
.prism-co-label { font-size: var(--text-xs); color: var(--text-secondary); align-self: center; white-space: nowrap; padding-inline-end: var(--space-2); }
.prism-co-size { font-family: var(--font-mono); font-size: var(--fs-caption); color: var(--text-tertiary); align-self: center; text-align: end; padding-inline-end: var(--space-3); font-variant-numeric: tabular-nums; }
.prism-co-cell { display: flex; align-items: center; justify-content: center; block-size: var(--co-cell-h, 32px); border-radius: var(--radius-xs); background: var(--series-track); }
.prism-co-cell > b { font-family: var(--font-mono); font-size: var(--fs-caption); font-weight: var(--weight-regular); color: var(--text-primary); font-variant-numeric: tabular-nums; }
.prism-co-cell > b[data-dark="true"] { color: var(--surface-page); }
.prism-co-avg { background: transparent; border-block-start: var(--border-width) solid var(--border-strong); border-radius: 0; }
.prism-co-avg > b { color: var(--text-secondary); }
.prism-co-avg-label { color: var(--text-tertiary); font-family: var(--font-mono); font-size: var(--fs-caption); padding-block-start: var(--space-2); }

/* ============================================================
   Treemap — squarified; labels carry the precision area can't
   ============================================================ */
.prism-treemap { position: relative; }
.prism-tm-tile { position: absolute; display: flex; flex-direction: column; justify-content: flex-end; gap: 1px; padding: var(--space-2) var(--space-3); border-radius: var(--radius-xs); overflow: hidden; }
.prism-tm-label { font-size: var(--text-xs); font-weight: var(--weight-semibold); color: var(--surface-page); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.prism-tm-value { font-family: var(--font-mono); font-size: var(--fs-caption); color: color-mix(in oklch, var(--surface-page) 82%, transparent); white-space: nowrap; }
.prism-tm-value > i { font-style: normal; opacity: .72; }
/* the two lightest rungs need dark text */
.prism-tm-tile[style*="--series-1"] .prism-tm-label, .prism-tm-tile[style*="--series-2"] .prism-tm-label { color: oklch(0.2 0.02 250); }
.prism-tm-tile[style*="--series-1"] .prism-tm-value, .prism-tm-tile[style*="--series-2"] .prism-tm-value { color: oklch(0.2 0.02 250 / 0.75); }

/* ============================================================
   ScatterPlot
   ============================================================ */
.prism-sc-divider { stroke: var(--border-strong); stroke-width: 1; stroke-dasharray: 4 3; }
.prism-sc-quad { font-family: var(--font-mono); font-size: var(--fs-caption); fill: var(--text-tertiary); }
.prism-sc-dot { fill-opacity: .82; stroke: var(--surface-card); stroke-width: 1.5; }
.prism-sc-point-label { font-size: var(--fs-caption); fill: var(--text-primary); }
.prism-sc-axis-label { font-family: var(--font-mono); font-size: var(--fs-caption); fill: var(--text-tertiary); }

/* ---------- Material contract ----------
   These rules name material tokens the Industry theme redefines, so the
   component materialises under data-theme="industry" with NO entry in
   components/themes/industry.css. Every token has a base no-op in
   tokens/elevation.css, so all of this is inert in the base themes.
   See docs/INDUSTRY_THEME.md §9 route (a). */

/* A track is a slot milled into the panel; the mark travels inside it. Cells in
   a heatmap, calendar or cohort grid stay FLAT on purpose — hundreds of bevelled
   cells is noise, and the grid container is what should read as recessed. */
.prism-funnel-track, .prism-bullet-track { box-shadow: var(--well); }

/* ===== components/dashboard/dashboard.css ===== */
/* ============================================================
   Prism · Dashboard shell
   ------------------------------------------------------------
   A 12-column widget grid that reflows on CONTAINER width, so a
   dashboard inside a split pane or drawer collapses correctly.
   Widget states are per widget, never per page.
   ============================================================ */

/* The WRAPPER is the query container. A container query cannot restyle the
   element that DECLARES container-type — put it on the grid itself and every
   column-count rule below silently becomes a no-op. */
.prism-dash { container-type: inline-size; }
.prism-dash-grid { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); gap: var(--space-5); align-items: start; }
.prism-dash-grid[data-dense] { gap: var(--space-3); }
.prism-dash-grid > [style*="--widget-rows"] { grid-row: span var(--widget-rows, 1); }
.prism-kpi-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: var(--space-4); }
/* fit="content": tiles start at their content's width, grow to fill the line
   and wrap onto more lines. (Values aren't lined up across tiles here — a
   content-width tile's label doesn't wrap, so there's nothing to align.) */
.prism-kpi-row[data-fit="content"] { display: flex; flex-wrap: wrap; }
.prism-kpi-row[data-fit="content"] > * { flex: 1 1 auto; max-inline-size: 100%; }

/* Width is a SEMANTIC size, and each breakpoint maps it to columns itself.
   A raw column count cannot survive a change of denominator: 4-of-12 is a
   third, but the same 4 against 6 columns is two thirds — so a numeric span
   silently doubles a widget's share at the mid breakpoint and two "thirds"
   stop fitting on one row. Named sizes never drift that way. */
.prism-dash-grid > [data-size] { grid-column: span 12; }
.prism-dash-grid > [data-size="two-thirds"] { grid-column: span 8; }
.prism-dash-grid > [data-size="half"] { grid-column: span 6; }
.prism-dash-grid > [data-size="third"] { grid-column: span 4; }
.prism-dash-grid > [data-size="quarter"] { grid-column: span 3; }
/* Escape hatch for a genuine one-off; prefer a named size. */
.prism-dash-grid > [style*="--widget-span"] { grid-column: span min(var(--widget-span, 12), 12); }

/* Coarsen to halves rather than shrinking: thirds and quarters pair up two per
   row, two-thirds goes full. Nothing is left with an empty gutter beside it. */
@container (max-width: 880px) {
  .prism-dash-grid > [data-size="two-thirds"] { grid-column: span 12; }
  .prism-dash-grid > [data-size="third"],
  .prism-dash-grid > [data-size="quarter"] { grid-column: span 6; }
  .prism-dash-grid > [style*="--widget-span"] { grid-column: span min(var(--widget-span, 12), 12); }
}
@container (max-width: 520px) {
  .prism-dash-grid > [data-size],
  .prism-dash-grid > [style*="--widget-span"] { grid-column: 1 / -1; }
  .prism-kpi-row { grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); }
}

/* The comparison toggle is a real Checkbox, so it only needs its own gap. */
.prism-timerange-compare { font-size: var(--text-xs); color: var(--text-secondary); gap: var(--space-2); align-items: center; }

/* ---------------- WidgetFrame ---------------- */
.prism-widget { display: flex; flex-direction: column; min-inline-size: 0; background: var(--surface-card); border: var(--border-width) solid var(--border-subtle); border-radius: var(--radius-card); padding: var(--space-5); gap: var(--space-4); }
.prism-widget-head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--space-4); }
.prism-widget-titles { display: flex; flex-direction: column; gap: var(--space-0-5); min-inline-size: 0; }
.prism-widget-title { margin: 0; font-size: var(--text-sm); font-weight: var(--weight-semibold); color: var(--text-primary); }
.prism-widget-sub { margin: 0; font-size: var(--text-xs); color: var(--text-tertiary); }
.prism-widget-actions { display: flex; align-items: center; gap: var(--space-2); flex: none; }
.prism-widget-body { min-inline-size: 0; }
.prism-widget-foot { margin: 0; font-size: var(--text-xs); color: var(--text-tertiary); }

/* State surfaces — the widget degrades, the page does not */
.prism-widget-state { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: var(--space-3); padding: var(--space-8) var(--space-4); text-align: center; }
.prism-widget-state > p { margin: 0; font-size: var(--text-xs); color: var(--text-secondary); max-inline-size: 34ch; }
.prism-widget-state-icon { display: inline-flex; color: var(--text-tertiary); }
.prism-widget-state-icon > svg { width: 26px; height: 26px; }
.prism-widget-state-icon[data-intent="danger"] { color: var(--negative-text); }

/* Skeletons are shaped like the content they replace, so nothing jumps. */
.prism-widget-skeleton { display: block; --sk: color-mix(in oklch, var(--text-tertiary) 13%, transparent); animation: prism-widget-pulse 1.6s ease-in-out infinite; }
.prism-widget-skeleton[data-shape="chart"] { block-size: 180px; background: linear-gradient(to top, var(--sk) 0 34%, transparent 34%) 4% 100% / 9% 42% no-repeat, linear-gradient(to top, var(--sk) 0 62%, transparent 62%) 18% 100% / 9% 70% no-repeat, linear-gradient(to top, var(--sk) 0 48%, transparent 48%) 32% 100% / 9% 55% no-repeat, linear-gradient(to top, var(--sk) 0 78%, transparent 78%) 46% 100% / 9% 86% no-repeat, linear-gradient(to top, var(--sk) 0 56%, transparent 56%) 60% 100% / 9% 64% no-repeat, linear-gradient(to top, var(--sk) 0 88%, transparent 88%) 74% 100% / 9% 96% no-repeat, linear-gradient(to top, var(--sk) 0 70%, transparent 70%) 88% 100% / 9% 78% no-repeat; }
.prism-widget-skeleton[data-shape="table"] { block-size: 168px; background-image: repeating-linear-gradient(to bottom, var(--sk) 0 12px, transparent 12px 34px); }
.prism-widget-skeleton[data-shape="kpi"] { block-size: 62px; background: linear-gradient(var(--sk) 0 0) 0 0 / 42% 12px no-repeat, linear-gradient(var(--sk) 0 0) 0 22px / 68% 26px no-repeat; }
.prism-widget-skeleton[data-shape="text"] { block-size: 76px; background: linear-gradient(var(--sk) 0 0) 0 0 / 100% 10px no-repeat, linear-gradient(var(--sk) 0 0) 0 22px / 96% 10px no-repeat, linear-gradient(var(--sk) 0 0) 0 44px / 88% 10px no-repeat, linear-gradient(var(--sk) 0 0) 0 66px / 54% 10px no-repeat; }
@keyframes prism-widget-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.52; } }
@media (prefers-reduced-motion: reduce) { .prism-widget-skeleton { animation: none; } }

/* ---------------- KpiTile ---------------- */
.prism-kpi { display: flex; flex-direction: column; gap: var(--space-1); min-inline-size: 0; background: var(--surface-card); border: var(--border-width) solid var(--border-subtle); border-radius: var(--radius-card); padding: var(--space-4) var(--space-5); }
/* Labels wrap rather than truncate ("Follow-ups due today" in a row of five). */
.prism-kpi-label { font-size: var(--text-xs); color: var(--text-tertiary); min-inline-size: 0; overflow-wrap: break-word; }
.prism-kpi-body { display: flex; flex-direction: column; gap: var(--space-1); min-inline-size: 0; }
/* In a KpiRow of tiles, values line up even when one label wraps: each tile
   spans two rows of the row's grid (label, body) and shares them via subgrid,
   so every label row is as tall as the tallest label on that line. */
.prism-kpi-row:not([data-fit="content"]):not(:has(> :not(.prism-kpi))) > .prism-kpi:has(> .prism-kpi-body) {
  display: grid; grid-row: span 2; grid-template-rows: subgrid; row-gap: var(--space-1); align-content: start;
}
/* Figures use the body face unless a theme sets --figure-font (a school whose
   --font-display is a serif can set --figure-font: var(--font-display) once),
   or a tile picks one with valueFont. */
.prism-kpi-value { font-family: var(--figure-font, var(--body-font)); font-size: var(--text-2xl); font-weight: var(--weight-semibold); color: var(--text-primary); letter-spacing: -0.01em; font-variant-numeric: tabular-nums; line-height: 1.15; }
/* The figure never paints outside its tile. The tile is a size container and
   KpiTile sets --kpi-chars (the figure's length); the figure takes the size
   at which that many characters fill the tile — 0.66em each: the widest face
   (mono, ~0.62em with the wide ₹) plus slack — clamped to --text-base …
   --text-2xl, so a short figure keeps the full size and only a long one
   shrinks. A figure that isn't plain text sizes as a 16-character one.
   Past --text-base it wraps: after a leading currency symbol or a
   digit-group comma (KpiTile puts <wbr>s there), then anywhere.
   A fit="content" tile sizes to its content, so it can't be a size container;
   it keeps the full size (its content width already fits the figure). */
.prism-kpi { container-type: inline-size; }
.prism-kpi-value {
  font-size: clamp(var(--text-base), calc(100cqi / (var(--kpi-chars, 16) * 0.66)), var(--text-2xl));
  min-inline-size: 0; max-inline-size: 100%; overflow-wrap: anywhere;
}
.prism-kpi-row[data-fit="content"] > .prism-kpi { container-type: normal; }
.prism-kpi-row[data-fit="content"] > .prism-kpi .prism-kpi-value { font-size: var(--text-2xl); }
.prism-kpi-cur { white-space: nowrap; }
.prism-kpi[data-value-font="display"] .prism-kpi-value { font-family: var(--font-display); }
.prism-kpi[data-value-font="mono"] .prism-kpi-value { font-family: var(--font-mono); }
.prism-kpi[data-value-font="body"] .prism-kpi-value { font-family: var(--font-body); }
.prism-kpi-unit { font-style: normal; font-size: var(--text-base); font-weight: var(--weight-regular); color: var(--text-secondary); margin-inline-start: var(--space-0-5); }
/* The arrow states the fact (which way), the colour states the judgement (good or not). */
.prism-kpi-delta { display: inline-flex; align-items: center; gap: var(--space-0-5); font-size: var(--text-xs); font-variant-numeric: tabular-nums; color: var(--text-secondary); }
.prism-kpi-delta > svg { width: 13px; height: 13px; flex: none; }
.prism-kpi-delta[data-good="true"] { color: var(--positive-text); }
.prism-kpi-delta[data-good="false"] { color: var(--negative-text); }
.prism-kpi-comparison { font-style: normal; color: var(--text-tertiary); margin-inline-start: var(--space-2); }
.prism-kpi-spark { margin-block-start: var(--space-2); }
.prism-kpi-target { font-size: var(--text-xs); color: var(--text-tertiary); }
.prism-kpi-head { display: flex; align-items: flex-start; gap: var(--space-1-5); min-inline-size: 0; }
.prism-kpi-head > .prism-kpi-label { flex: 1 1 auto; }
.prism-kpi-icon { flex: none; display: inline-flex; color: var(--text-tertiary); }
.prism-kpi-icon > svg { inline-size: var(--icon-sm); block-size: var(--icon-sm); }
/* tone: an attention edge plus a glyph by the label (never colour alone) */
.prism-kpi[data-tone] { border-inline-start: 3px solid var(--kpi-tone); }
.prism-kpi[data-tone="negative"] { --kpi-tone: var(--negative); --kpi-tone-text: var(--negative-text); }
.prism-kpi[data-tone="notice"]   { --kpi-tone: var(--notice);   --kpi-tone-text: var(--notice-text); }
.prism-kpi[data-tone="positive"] { --kpi-tone: var(--positive); --kpi-tone-text: var(--positive-text); }
.prism-kpi-toneglyph { flex: none; inline-size: var(--icon-sm); block-size: var(--icon-sm); color: var(--kpi-tone-text); margin-inline-start: auto; }
/* href: the whole tile is a link to its list */
a.prism-kpi { color: inherit; text-decoration: none; cursor: pointer; transition: var(--transition-colors), box-shadow var(--duration-fast) var(--ease-standard); }
a.prism-kpi:hover { border-color: var(--border-default); box-shadow: var(--shadow-md); }
a.prism-kpi:focus-visible { outline: var(--focus-ring-width) solid var(--focus-ring); outline-offset: 2px; }

/* ---------------- TimeRangeControl ---------------- */
.prism-timerange { display: flex; align-items: center; flex-wrap: wrap; gap: var(--space-3) var(--space-4); }
/* The resolved dates are not optional decoration — they are what makes a
   screenshot of this dashboard reproducible weeks later. */
.prism-timerange-resolved { font-family: var(--font-mono); font-size: var(--text-xs); color: var(--text-tertiary); font-variant-numeric: tabular-nums; }

/* ---------- Material contract ----------
   These rules name material tokens the Industry theme redefines, so the
   component materialises under data-theme="industry" with NO entry in
   components/themes/industry.css. Every token has a base no-op in
   tokens/elevation.css, so all of this is inert in the base themes.
   See docs/INDUSTRY_THEME.md §9 route (a). */

.prism-widget {
  background-image: var(--grain), var(--skeuo-card);
  background-size: var(--grain-size), auto;
  background-blend-mode: overlay, normal;
  box-shadow: var(--bevel), var(--shadow-contact);
}
/* Nested inside a widget, so the softer swing — depth attenuates with nesting. */
.prism-kpi {
  background-image: var(--grain), var(--skeuo-raised-soft);
  background-size: var(--grain-size), auto;
  background-blend-mode: overlay, normal;
  box-shadow: var(--bevel-soft);
}

/* ===== components/controls/controls.css ===== */
/* ============================================================
   Prism · Control affordances
   Dial · Keypad · OTPInput · FaderBank · RangeSlider
   ------------------------------------------------------------
   Base (theme-neutral) styling. The Industry theme adds its
   machined material over the top in themes/industry.css.
   ============================================================ */

/* ---------------- Dial ---------------- */
.prism-dial { display: inline-flex; flex-direction: column; align-items: center; gap: var(--space-3); }
.prism-dial-label { font-size: var(--text-xs); color: var(--text-tertiary); text-align: center; }
.prism-dial-stage { position: relative; display: grid; place-items: center; }
/* Explicitly centred rather than relying on inset + viewBox scaling, so the
   arc stays concentric with the knob at any size. */
.prism-dial-arc { position: absolute; inset-block-start: 50%; inset-inline-start: 50%; transform: translate(-50%, -50%); inline-size: 100%; block-size: 100%; overflow: visible; pointer-events: none; }
.prism-dial-arc-track { fill: none; stroke: var(--fill-subtle); stroke-width: 6; stroke-linecap: round; }
.prism-dial-arc-fill { fill: none; stroke: var(--accent); stroke-width: 6; stroke-linecap: round; }
.prism-dial-knob {
  position: relative; inline-size: calc(100% - 28px); block-size: calc(100% - 28px);
  border-radius: 50%; display: grid; place-items: center;
  background: var(--surface-raised); border: var(--border-width) solid var(--border-default);
  box-shadow: var(--shadow-sm); cursor: grab; touch-action: none; user-select: none;
}
.prism-dial-knob:active { cursor: grabbing; }
.prism-dial-knob:focus-visible { outline: var(--focus-ring-width) solid var(--focus-ring); outline-offset: 3px; }
.prism-dial[data-disabled] .prism-dial-knob { cursor: not-allowed; opacity: 0.5; }
/* The arc must dim too: an accent-bright arc around a greyed knob reads as
   interactive and contradicts the disabled state. */
.prism-dial[data-disabled] .prism-dial-arc-fill { stroke: var(--text-tertiary); opacity: 0.45; }
.prism-dial[data-disabled] .prism-dial-arc-track { opacity: 0.5; }
/* The pointer is a spoke from centre to rim, so its angle is unambiguous. It
   is an indicator, so it takes --led: the accent in base themes, an emissive
   notch under Industry. */
/* transform-origin must be the KNOB CENTRE, or the notch swings on a small
   circle offset from the ring and never lines up with the arc's end. It is
   expressed as a percentage of the notch's own height, so: with the notch top
   at 7% and its height 11% of the knob, the centre is (50 - 7) / 11 = 391%. */
.prism-dial-pointer {
  position: absolute; inset-block-start: 7%; inset-inline-start: 50%; margin-inline-start: -1.var(--space-1);
  inline-size: 3px; block-size: 11%; border-radius: 2px;
  background: var(--led); box-shadow: var(--led-glow);
  transform-origin: 50% 391%;
}
/* A knob is a raised ring around a RECESSED face. Without the inset centre the
   numeral floats on the crown and the whole control reads as a printed circle
   rather than a part — this is the single detail that makes it a knob. */
.prism-dial-face {
  inline-size: 71%; block-size: 71%; border-radius: 50%;
  display: grid; place-items: center; text-align: center;
  background-image: var(--skeuo-well-grad); box-shadow: var(--well);
}
.prism-dial-readout { font-family: var(--font-mono); font-size: var(--text-lg); font-weight: var(--weight-semibold); color: var(--text-primary); font-variant-numeric: tabular-nums; line-height: 1; }
.prism-dial-unit { font-style: normal; font-size: 0.6em; color: var(--text-tertiary); margin-inline-start: var(--space-0-5); }

/* ---------------- Keypad ---------------- */
.prism-keypad { display: grid; grid-template-columns: repeat(3, minmax(56px, 1fr)); gap: var(--space-2); }
.prism-keypad-key {
  display: inline-flex; align-items: center; justify-content: center;
  font-family: var(--font-mono); font-size: var(--text-2xl); font-weight: var(--weight-semibold);
  color: var(--text-primary); background: var(--surface-raised);
  border: var(--border-width) solid var(--border-default); border-radius: var(--radius-control);
  cursor: pointer; user-select: none; -webkit-tap-highlight-color: transparent;
  transition: var(--transition-colors);
}
.prism-keypad-key[data-variant="quiet"] { background: transparent; border-color: transparent; color: var(--text-secondary); }
.prism-keypad-key > svg { width: 26px; height: 26px; }
.prism-keypad-key:hover:not(:disabled) { background: var(--fill-subtle); }
/* The press state is the ONLY confirmation a digit registered — there is no
   haptic fallback here, so it is a hard treatment, not a hover-ish tint. */
.prism-keypad-key:active:not(:disabled) { background: var(--fill-muted); transform: translateY(1px); }
.prism-keypad-key:focus-visible { outline: var(--focus-ring-width) solid var(--focus-ring); outline-offset: 2px; }
.prism-keypad-key:disabled { opacity: 0.4; cursor: not-allowed; }
.prism-keypad-blank { display: block; }
.prism-keypad-submit {
  grid-column: 1 / -1; min-block-size: var(--control-height);
  font-family: var(--label-font); font-size: var(--text-sm); font-weight: var(--weight-semibold);
  color: var(--accent-on); background: var(--accent); background-image: var(--sheen);
  border: var(--border-width) solid var(--accent); border-radius: var(--radius-control);
  cursor: pointer; box-shadow: var(--bevel); transition: var(--transition-colors);
}
.prism-keypad-submit:hover:not(:disabled) { background-color: var(--accent-hover); }
.prism-keypad-submit:focus-visible { outline: var(--focus-ring-width) solid var(--focus-ring); outline-offset: 2px; }
.prism-keypad-submit:disabled { opacity: 0.45; cursor: not-allowed; }

/* ---------------- OTPInput ---------------- */
.prism-otp { display: flex; gap: var(--space-2); }
.prism-otp-box {
  inline-size: 48px; block-size: 58px; padding: 0; text-align: center;
  font-family: var(--font-mono); font-size: var(--text-2xl); font-weight: var(--weight-semibold);
  color: var(--text-primary); background: var(--surface-sunken);
  border: var(--border-width) solid var(--border-strong); border-radius: var(--radius-control);
  transition: box-shadow var(--duration-fast) var(--ease-standard), border-color var(--duration-fast) var(--ease-standard), color var(--duration-fast) var(--ease-standard);
}
.prism-otp-box:hover:not(:disabled) { border-color: var(--accent); }
.prism-otp-box:focus { outline: var(--focus-ring-width) solid var(--focus-ring); outline-offset: -1px; border-color: var(--accent); }
.prism-otp-box:disabled { opacity: 0.5; cursor: not-allowed; }
.prism-otp[data-invalid] .prism-otp-box { border-color: var(--negative); }

/* ---------------- FaderBank ---------------- */
.prism-faders { display: flex; align-items: flex-end; gap: var(--space-4); }
.prism-fader { display: flex; flex-direction: column; align-items: center; gap: var(--space-2); }
.prism-fader-readout { font-family: var(--font-mono); font-size: var(--text-xs); color: var(--text-secondary); font-variant-numeric: tabular-nums; }
.prism-fader-slot {
  position: relative; inline-size: 34px; block-size: var(--fader-h, 180px);
  display: grid; place-items: center; touch-action: none;
}
.prism-fader-track { position: absolute; inset-block: 0; inline-size: 6px; border-radius: var(--radius-xs); background: var(--series-track); }
/* Optional snap detents (present only when `snap` is set): engraved cross-marks
   the cap clicks to. Passed ones light up. */
.prism-fader-tick {
  position: absolute; inset-inline: 50%; inline-size: 12px; block-size: 2px;
  transform: translate(-50%, 50%); border-radius: var(--radius-pill);
  background: var(--border-strong); pointer-events: none;
}
.prism-fader-tick[data-on="true"] { background: var(--accent); }
/* Fill grows UP from the bottom, so a bank of faders reads as a silhouette. */
.prism-fader-fill { position: absolute; inset-block-end: 0; inline-size: 6px; border-radius: var(--radius-xs); background: var(--accent); }
.prism-fader-cap {
  position: absolute; inline-size: 30px; block-size: 20px; border-radius: var(--radius-xs);
  background: var(--surface-raised); border: var(--border-width) solid var(--border-default);
  box-shadow: var(--shadow-sm); cursor: grab;
}
.prism-fader-cap::after { content: ""; position: absolute; inset-block-start: 50%; inset-inline: 6px; block-size: 1px; background: var(--border-strong); }
.prism-fader-slot:focus-visible { outline: var(--focus-ring-width) solid var(--focus-ring); outline-offset: 2px; border-radius: var(--radius-control); }
.prism-fader-label { font-size: var(--text-xs); color: var(--text-tertiary); max-inline-size: 56px; text-align: center; }
.prism-fader[data-disabled] { opacity: 0.5; }
.prism-fader[data-disabled] .prism-fader-cap { cursor: not-allowed; }

/* ---------------- RangeSlider (two thumbs) ---------------- */
.prism-range { display: flex; flex-direction: column; gap: var(--space-3); }
.prism-range-head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-4); }
.prism-range-label { font-size: var(--text-xs); color: var(--text-tertiary); }
.prism-range-value { font-family: var(--font-mono); font-size: var(--text-xs); color: var(--text-primary); font-variant-numeric: tabular-nums; }
.prism-range-stage { position: relative; block-size: 24px; display: grid; align-items: center; touch-action: none; }
.prism-range-track { position: absolute; inset-inline: 0; block-size: 6px; border-radius: var(--radius-xs); background: var(--fill-subtle); }
.prism-range-fill { position: absolute; block-size: 6px; border-radius: var(--radius-xs); background: var(--accent); }
.prism-range-thumb {
  position: absolute; inline-size: 20px; block-size: 20px; border-radius: 50%;
  background: var(--surface-card); border: 2px solid var(--accent);
  box-shadow: var(--shadow-sm); cursor: grab; margin-inline-start: -10px;
}
.prism-range-thumb:active { cursor: grabbing; }
.prism-range-thumb:focus-visible { outline: var(--focus-ring-width) solid var(--focus-ring); outline-offset: 2px; }
.prism-range[data-disabled] { opacity: 0.5; }
.prism-range[data-disabled] .prism-range-thumb { cursor: not-allowed; }


/* ---------------- CommandPalette ---------------- */
.prism-cmd-scrim { position: fixed; inset: 0; z-index: 900; display: grid; justify-items: center; align-content: start; padding-block-start: 12vh; background: var(--surface-scrim); backdrop-filter: blur(2px); }
.prism-cmd { inline-size: min(640px, calc(100vw - 32px)); display: flex; flex-direction: column; background: var(--surface-overlay); border: var(--border-width) solid var(--border-default); border-radius: var(--radius-card); box-shadow: var(--shadow-xl); overflow: hidden; }
.prism-cmd-field { display: flex; align-items: center; gap: var(--space-3); padding: var(--space-4) var(--space-5); border-block-end: var(--border-width) solid var(--border-subtle); }
.prism-cmd-icon { display: inline-flex; color: var(--text-tertiary); flex: none; }
.prism-cmd-icon > svg { width: 18px; height: 18px; }
.prism-cmd-input { flex: 1; min-inline-size: 0; border: 0; background: transparent; color: var(--text-primary); font-family: var(--body-font); font-size: var(--text-base); outline: none; }
.prism-cmd-input::placeholder { color: var(--text-tertiary); }
.prism-cmd-list { max-block-size: min(52vh, 420px); overflow-y: auto; padding: var(--space-2); }
.prism-cmd-empty { margin: 0; padding: var(--space-8) var(--space-4); text-align: center; font-size: var(--text-sm); color: var(--text-tertiary); }
.prism-cmd-group + .prism-cmd-group { margin-block-start: var(--space-2); }
/* Every row's group is stated, because a palette mixes verbs with nouns. */
.prism-cmd-grouplabel { margin: 0; padding: var(--space-2) var(--space-3); font-family: var(--font-mono); font-size: var(--fs-caption); color: var(--text-tertiary); }
.prism-cmd-item { display: flex; align-items: center; gap: var(--space-3); padding: var(--space-3); border-radius: var(--radius-control); cursor: pointer; }
.prism-cmd-item[data-selected] { background: var(--fill-subtle); }
.prism-cmd-item-icon { display: inline-flex; color: var(--text-secondary); flex: none; }
.prism-cmd-item-icon > svg { width: 16px; height: 16px; }
.prism-cmd-item-label { flex: 1; min-inline-size: 0; font-size: var(--text-sm); color: var(--text-primary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.prism-cmd-item-detail { font-size: var(--text-xs); color: var(--text-tertiary); flex: none; }
.prism-cmd-item-kbd { font-family: var(--font-mono); font-size: var(--fs-caption); color: var(--text-tertiary); border: var(--border-width) solid var(--border-subtle); border-radius: var(--radius-xs); padding: var(--space-0-5) var(--space-1); flex: none; }
.prism-cmd-footer { padding: var(--space-3) var(--space-5); border-block-start: var(--border-width) solid var(--border-subtle); font-size: var(--text-xs); color: var(--text-tertiary); }

/* ---------------- AlertTicker ---------------- */
/* Standing conditions, not transient events: no auto-dismiss, always a count. */
.prism-ticker { display: flex; align-items: center; flex-wrap: wrap; gap: var(--space-2) var(--space-3); padding: var(--space-3) var(--space-4); border: var(--border-width) solid var(--border-default); border-radius: var(--radius-control); background: var(--surface-card); }
.prism-ticker-dot { flex: none; inline-size: 8px; block-size: 8px; border-radius: 50%; background: var(--notice); }
.prism-ticker[data-intent="negative"] { border-color: var(--negative-border); background: var(--negative-subtle); }
.prism-ticker[data-intent="negative"] .prism-ticker-dot { background: var(--negative); }
.prism-ticker[data-intent="positive"] { border-color: var(--positive-border); background: var(--positive-subtle); }
.prism-ticker[data-intent="positive"] .prism-ticker-dot { background: var(--positive); }
.prism-ticker[data-intent="info"] { border-color: var(--info-border); background: var(--info-subtle); }
.prism-ticker[data-intent="info"] .prism-ticker-dot { background: var(--info); }
.prism-ticker-body { flex: 1 1 26ch; min-inline-size: 26ch; display: flex; align-items: baseline; flex-wrap: wrap; gap: var(--space-0-5) var(--space-3); background: none; border: 0; padding: 0; text-align: start; font: inherit; color: inherit; cursor: pointer; }
.prism-ticker-body:disabled { cursor: default; }
.prism-ticker-body:focus-visible { outline: var(--focus-ring-width) solid var(--focus-ring); outline-offset: 2px; border-radius: var(--radius-xs); }
.prism-ticker-time { font-family: var(--font-mono); font-size: var(--text-xs); color: var(--text-tertiary); flex: none; }
/* The label keeps a readable minimum and the DETAIL yields first — otherwise
   the nav and acknowledge keys crush the alert text to three characters, which
   is the one thing on the banner that has to be readable. */
.prism-ticker-label { flex: 1 1 auto; min-inline-size: 0; font-size: var(--text-sm); font-weight: var(--weight-medium); color: var(--text-primary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.prism-ticker-detail { flex: 0 1 auto; min-inline-size: 0; font-size: var(--text-xs); color: var(--text-secondary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.prism-ticker-nav { display: flex; align-items: center; gap: var(--space-0-5); flex: none; }
.prism-ticker-step { display: inline-flex; align-items: center; justify-content: center; inline-size: 24px; block-size: 24px; border: 0; background: transparent; color: var(--text-secondary); border-radius: var(--radius-xs); cursor: pointer; }
.prism-ticker-step > svg { width: 15px; height: 15px; }
.prism-ticker-step:hover { background: var(--fill-subtle); color: var(--text-primary); }
.prism-ticker-step:focus-visible { outline: var(--focus-ring-width) solid var(--focus-ring); outline-offset: 1px; }
/* The count says how much is wrong, not just what — never hidden. */
.prism-ticker-count { font-family: var(--font-mono); font-size: var(--text-xs); color: var(--text-tertiary); font-variant-numeric: tabular-nums; min-inline-size: 30px; text-align: center; }
.prism-ticker-ack { flex: none; font-family: var(--label-font); font-size: var(--text-xs); font-weight: var(--weight-semibold); color: var(--text-primary); background: transparent; border: var(--border-width) solid var(--border-strong); border-radius: var(--radius-control); padding: var(--space-1) var(--space-3); cursor: pointer; }
.prism-ticker-ack:hover { background: var(--fill-subtle); }
.prism-ticker-ack:focus-visible { outline: var(--focus-ring-width) solid var(--focus-ring); outline-offset: 2px; }

/* ---------------- Skeleton ---------------- */
.prism-skeleton-stack { display: flex; flex-direction: column; gap: var(--space-2); }
.prism-skeleton { display: block; background: color-mix(in oklch, var(--text-tertiary) 13%, transparent); border-radius: var(--radius-xs); animation: prism-skeleton-pulse 1.6s ease-in-out infinite; }
.prism-skeleton[data-shape="line"] { block-size: 11px; }
.prism-skeleton[data-shape="block"] { block-size: 120px; border-radius: var(--radius-sm); }
.prism-skeleton[data-shape="circle"] { inline-size: 40px; block-size: 40px; border-radius: 50%; }
.prism-skeleton[data-shape="table"] { block-size: 168px; border-radius: var(--radius-sm); background: repeating-linear-gradient(to bottom, color-mix(in oklch, var(--text-tertiary) 13%, transparent) 0 12px, transparent 12px 34px); }
.prism-skeleton[data-shape="chart"] { block-size: 150px; background: none; }
.prism-skeleton[data-shape="chart"] { --sk: color-mix(in oklch, var(--text-tertiary) 13%, transparent); background: linear-gradient(to top, var(--sk) 0 34%, transparent 34%) 4% 100% / 9% 42% no-repeat, linear-gradient(to top, var(--sk) 0 62%, transparent 62%) 18% 100% / 9% 70% no-repeat, linear-gradient(to top, var(--sk) 0 48%, transparent 48%) 32% 100% / 9% 55% no-repeat, linear-gradient(to top, var(--sk) 0 78%, transparent 78%) 46% 100% / 9% 86% no-repeat, linear-gradient(to top, var(--sk) 0 56%, transparent 56%) 60% 100% / 9% 64% no-repeat, linear-gradient(to top, var(--sk) 0 88%, transparent 88%) 74% 100% / 9% 96% no-repeat, linear-gradient(to top, var(--sk) 0 70%, transparent 70%) 88% 100% / 9% 78% no-repeat; }
@keyframes prism-skeleton-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.52; } }
@media (prefers-reduced-motion: reduce) { .prism-skeleton { animation: none; } }

/* ---------------- Carousel ---------------- */
.prism-carousel { display: flex; flex-direction: column; gap: var(--space-3); min-inline-size: 0; }
.prism-carousel-head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-4); }
.prism-carousel-label { margin: 0; font-family: var(--heading-font); font-size: var(--text-sm); font-weight: var(--weight-semibold); color: var(--text-primary); }
.prism-carousel-nav { display: flex; align-items: center; gap: var(--space-2); margin-inline-start: auto; }
.prism-carousel-step { display: inline-flex; align-items: center; justify-content: center; inline-size: 30px; block-size: 30px; border: var(--border-width) solid var(--border-default); border-radius: var(--radius-control); background: var(--surface-card); color: var(--text-secondary); cursor: pointer; transition: var(--transition-colors); }
.prism-carousel-step > svg { width: 16px; height: 16px; }
.prism-carousel-step:hover:not(:disabled) { background: var(--fill-subtle); color: var(--text-primary); }
.prism-carousel-step:focus-visible { outline: var(--focus-ring-width) solid var(--focus-ring); outline-offset: 2px; }
/* Disabled at the ends is the point: a looping row can never answer
   "have I seen everything?". */
.prism-carousel-step:disabled { opacity: 0.35; cursor: not-allowed; }
.prism-carousel-scroll { display: flex; gap: var(--space-4); overflow-x: auto; overflow-y: hidden; scroll-snap-type: x mandatory; scrollbar-width: none; padding-block-end: var(--space-0-5); }
.prism-carousel-scroll::-webkit-scrollbar { display: none; }
.prism-carousel-scroll:focus-visible { outline: var(--focus-ring-width) solid var(--focus-ring); outline-offset: 3px; border-radius: var(--radius-sm); }
.prism-carousel-scroll > * { flex: none; scroll-snap-align: start; }
.prism-carousel-scroll[data-snap="center"] > * { scroll-snap-align: center; }
/* Peek is what actually tells people the row scrolls — far more reliable
   than an arrow they may never look at. */
.prism-carousel-scroll[data-peek] { padding-inline-end: 12%; }

/* ---------- Material contract ----------
   These rules name material tokens the Industry theme redefines, so the
   component materialises under data-theme="industry" with NO entry in
   components/themes/industry.css. Every token has a base no-op in
   tokens/elevation.css, so all of this is inert in the base themes.
   See docs/INDUSTRY_THEME.md §9 route (a). */

/* A knob is THE machined object — it gets the full treatment, and a real drop
   shadow rather than a contact shadow: it stands proud of the panel. */
.prism-dial-knob {
  background-image: var(--grain), var(--skeuo-raised);
  background-size: var(--grain-size), auto;
  background-blend-mode: overlay, normal;
  box-shadow: var(--bevel), var(--shadow-md);
}

/* Keypad and step keys travel when pressed: the material changes, not the shade. */
.prism-keypad-key, .prism-keypad-submit, .prism-ticker-step, .prism-ticker-ack, .prism-carousel-step {
  background-image: var(--grain), var(--skeuo-raised);
  background-size: var(--grain-size), auto;
  background-blend-mode: overlay, normal;
  box-shadow: var(--bevel), var(--shadow-contact);
}
.prism-keypad-key:active:not(:disabled),
.prism-keypad-submit:active:not(:disabled),
.prism-ticker-step:active:not(:disabled),
.prism-ticker-ack:active:not(:disabled),
.prism-carousel-step:active:not(:disabled) {
  background-image: none;
  box-shadow: var(--press);
  transform: translateY(0.5px);
}

/* Recessed: anything a value travels inside, or a character is typed into.
   A code cell gets the DEEP well — at 48×58 the standard one is a hairline. */
.prism-otp-box { background-image: var(--skeuo-well-grad); box-shadow: var(--well-deep); }
.prism-fader-track, .prism-range-track { background-image: var(--skeuo-well-grad); box-shadow: var(--well); }
/* A focused cell is a lit well, not a recoloured one: the recess stays, the
   rim picks up the indicator colour, and the glow spills out of the hole. */
.prism-otp-box:focus, .prism-otp-box:focus-visible {
  border-color: color-mix(in oklch, var(--led) 52%, transparent);
  box-shadow: var(--well-deep), var(--led-glow-soft);
}
/* A typed character is lit — that is the feedback the cell exists to give. */
.prism-otp-box[data-filled="true"] { color: var(--accent-text); text-shadow: var(--led-text-glow); }

/* Fader cap and range thumbs are knobs that ride in the well. */
.prism-fader-cap, .prism-range-thumb {
  background-image: var(--grain), var(--skeuo-raised);
  background-size: var(--grain-size), auto;
  background-blend-mode: overlay, normal;
  box-shadow: var(--bevel), var(--shadow-contact);
}

/* ---------- Value ramp ----------
   A filled track brightens with its value. The ramp is sized to the WHOLE
   track and then clipped by the fill, so brightness encodes the value's
   POSITION ON THE SCALE — a low value shows only the ramp's moderate dark end.
   Restretching the gradient inside the fill instead would make every value
   equally bright at both ends, and the ramp would say nothing.

   Components pass --span (the fill's length as a percentage of the track) and,
   for a two-ended fill, --lo (where the fill starts). A range fill is then a
   WINDOW onto the same global ramp, which is why it works here too: it shows
   where in the scale the interval sits, not how wide it is. */
.prism-fader-fill, .prism-range-fill { box-shadow: var(--bevel-soft); }
.prism-range-fill, .prism-fader-fill { overflow: hidden; }
.prism-range-fill::before {
  content: ""; position: absolute; inset-block: 0;
  inset-inline-start: calc(-100% * var(--lo, 0) / var(--span, 100));
  inline-size: calc(100% * 100 / var(--span, 100));
  background-image: var(--value-ramp);
}
.prism-fader-fill { --ramp-angle: 0deg; /* @kind other */ }
.prism-fader-fill::before {
  content: ""; position: absolute; inset-inline: 0; inset-block-end: 0;
  block-size: calc(100% * 100 / var(--span, 100));
  background-image: var(--value-ramp);
}
/* The RTL flip lives once, at document scope, in tokens/elevation.css. */

/* The palette is frosted glass over the live screen. */
.prism-cmd {
  background-image: var(--grain);
  background-size: var(--grain-size);
  background-blend-mode: overlay;
  box-shadow: var(--bevel-soft), var(--shadow-xl);
}
.prism-cmd-item[aria-selected="true"] { box-shadow: var(--edge-light), var(--led-glow-soft); }

/* An alert ticker is a full-bleed instrument bar. */
.prism-ticker {
  background-image: var(--grain), var(--skeuo-raised);
  background-size: var(--grain-size), auto;
  background-blend-mode: overlay, normal;
  box-shadow: var(--edge-light);
}


/* ============================================================
   MOTION · the control family moves like parts
   ------------------------------------------------------------
   Settle-on-click/key for the range thumbs and fader caps (see forms.css for
   the rule); the dial index turns with a short mechanical lag while dragged
   and settles over the full duration on a key; a key press travels; a typed
   code glyph lands with a small pop. All gated on reduced motion.
   ============================================================ */
@media (prefers-reduced-motion: no-preference) {
  .prism-range[data-settling="true"] .prism-range-thumb { transition: inset-inline-start var(--duration-settle) var(--ease-settle), box-shadow var(--duration-fast) var(--ease-standard); }
  .prism-range[data-settling="true"] .prism-range-fill  { transition: inset-inline-start var(--duration-settle) var(--ease-settle), inline-size var(--duration-settle) var(--ease-settle); }
  .prism-fader[data-settling="true"] .prism-fader-cap   { transition: inset-block-end var(--duration-settle) var(--ease-settle), box-shadow var(--duration-fast) var(--ease-standard); }
  .prism-fader[data-settling="true"] .prism-fader-fill  { transition: block-size var(--duration-settle) var(--ease-settle); }
  .prism-dial-pointer { transition: transform 90ms var(--ease-out); }
  .prism-dial[data-settling="true"] .prism-dial-pointer { transition: transform var(--duration-settle) var(--ease-settle); }
  .prism-dial-arc-fill { transition: d 90ms var(--ease-out); }
  .prism-dial[data-settling="true"] .prism-dial-arc-fill { transition: d var(--duration-settle) var(--ease-settle); }
  .prism-keypad-key { transition: transform var(--duration-instant) var(--ease-standard), background-color var(--duration-fast) var(--ease-standard), box-shadow var(--duration-fast) var(--ease-standard); }
  .prism-otp-box[data-filled="true"] { animation: prism-glyph-land 160ms var(--ease-out); }
  @keyframes prism-glyph-land { from { transform: scale(1.06); } }
}

/* ===== components/business/business.css ===== */
/* ============================================================
   Prism · Business app shells
   KanbanBoard · RecordShell · LineItemEditor · ResourceTimeline · ImportMapper
   ============================================================ */

/* ---------------- KanbanBoard ---------------- */
.prism-kanban { display: flex; gap: var(--space-4); overflow-x: auto; align-items: flex-start; padding-block-end: var(--space-2); }
.prism-kanban-col { flex: 0 0 292px; display: flex; flex-direction: column; gap: var(--space-2); background: var(--surface-sunken); border: var(--border-width) solid var(--border-subtle); border-radius: var(--radius-card); padding: var(--space-3); }
.prism-kanban-col[data-over] { border-color: var(--accent); background: var(--accent-subtle); }
.prism-kanban-head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); }
.prism-kanban-title { font-family: var(--label-font); font-size: var(--text-sm); font-weight: var(--weight-semibold); color: var(--text-primary); }
.prism-kanban-count { font-family: var(--font-mono); font-size: var(--text-xs); color: var(--text-tertiary); font-variant-numeric: tabular-nums; }
.prism-kanban-count > i { font-style: normal; }
/* Over the WIP limit must read as WRONG, not as a quiet badge — the whole
   reason to lay work out in columns is to see where too much is in flight. */
.prism-kanban-head[data-state="over"] .prism-kanban-title,
.prism-kanban-head[data-state="over"] .prism-kanban-count { color: var(--negative-text); }
.prism-kanban-head[data-state="at"] .prism-kanban-count { color: var(--notice-text); }
.prism-kanban-total { margin: 0; font-family: var(--font-mono); font-size: var(--text-xs); color: var(--text-secondary); font-variant-numeric: tabular-nums; }
.prism-kanban-warn { margin: 0; padding: var(--space-2) var(--space-3); font-size: var(--text-xs); line-height: 1.45; color: var(--negative-text); background: var(--negative-subtle); border: var(--border-width) solid var(--negative-border); border-radius: var(--radius-sm); text-wrap: pretty; }
.prism-kanban-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--space-2); min-block-size: 40px; }
.prism-kanban-empty { padding: var(--space-5) 0; text-align: center; font-size: var(--text-xs); color: var(--text-tertiary); }
.prism-kanban-card { display: flex; flex-direction: column; gap: var(--space-2); padding: var(--space-3); background: var(--surface-card); border: var(--border-width) solid var(--border-subtle); border-radius: var(--radius-sm); box-shadow: var(--shadow-xs); cursor: grab; }
.prism-kanban-card[data-dragging] { opacity: 0.4; }
.prism-kanban-card-top { display: flex; align-items: flex-start; gap: var(--space-2); }
.prism-kanban-card-title { flex: 1; min-inline-size: 0; text-align: start; background: none; border: 0; padding: 0; font-family: var(--body-font); font-size: var(--text-sm); font-weight: var(--weight-medium); color: var(--text-primary); cursor: pointer; }
.prism-kanban-card-title:hover { color: var(--accent); }
.prism-kanban-card-title:focus-visible { outline: var(--focus-ring-width) solid var(--focus-ring); outline-offset: 2px; border-radius: var(--radius-xs); }
.prism-kanban-card-detail { margin: 0; font-size: var(--text-xs); color: var(--text-tertiary); }
.prism-kanban-card-foot { display: flex; align-items: center; gap: var(--space-3); flex-wrap: wrap; }
.prism-kanban-card-value { font-family: var(--font-mono); font-size: var(--text-xs); font-weight: var(--weight-semibold); color: var(--text-primary); font-variant-numeric: tabular-nums; }
.prism-kanban-card-owner { font-size: var(--text-xs); color: var(--text-secondary); }
/* Age is the signal a board exists to surface — a stale card must look stale. */
.prism-kanban-card-age { margin-inline-start: auto; font-family: var(--font-mono); font-size: var(--text-xs); color: var(--text-tertiary); }
.prism-kanban-card-age[data-stale] { color: var(--negative-text); font-weight: var(--weight-semibold); }
.prism-kanban-menuwrap { position: relative; flex: none; }
.prism-kanban-menubtn { display: inline-flex; align-items: center; justify-content: center; inline-size: 22px; block-size: 22px; border: 0; background: transparent; color: var(--text-tertiary); border-radius: var(--radius-xs); cursor: pointer; }
.prism-kanban-menubtn > svg { width: 15px; height: 15px; }
.prism-kanban-menubtn:hover { background: var(--fill-subtle); color: var(--text-primary); }
.prism-kanban-menubtn:focus-visible { outline: var(--focus-ring-width) solid var(--focus-ring); outline-offset: 1px; }
/* The move menu is the keyboard and touch path — never decoration. */
.prism-kanban-menu { position: absolute; inset-inline-end: 0; inset-block-start: calc(100% + 4px); z-index: 5; min-inline-size: 172px; padding: var(--space-2); background: var(--surface-overlay); border: var(--border-width) solid var(--border-default); border-radius: var(--radius-sm); box-shadow: var(--shadow-lg); }
.prism-kanban-menulabel { margin: 0 0 var(--space-1); padding-inline: var(--space-2); font-family: var(--font-mono); font-size: var(--fs-caption); color: var(--text-tertiary); }
.prism-kanban-menuitem { display: block; inline-size: 100%; text-align: start; padding: var(--space-2); border: 0; background: none; font-family: var(--body-font); font-size: var(--text-sm); color: var(--text-primary); border-radius: var(--radius-xs); cursor: pointer; }
.prism-kanban-menuitem:hover { background: var(--fill-subtle); }
.prism-kanban-menuitem:focus-visible { outline: var(--focus-ring-width) solid var(--focus-ring); outline-offset: -1px; }

/* ---------------- RecordShell ---------------- */
.prism-record { display: flex; flex-direction: column; min-inline-size: 0; }
/* The identity block never scrolls away: on a long record, "which record am I
   in?" and "what state is it in?" recur constantly. */
.prism-record-head { position: sticky; inset-block-start: 0; z-index: 4; display: grid; grid-template-columns: 1fr auto; gap: var(--space-3) var(--space-5); padding: var(--space-5) var(--space-6) 0; background: var(--surface-page); border-block-end: var(--border-width) solid var(--border-subtle); }
.prism-record-ident { min-inline-size: 0; }
.prism-record-eyebrow { margin: 0 0 var(--space-1); font-family: var(--font-mono); font-size: var(--fs-caption); letter-spacing: var(--tracking-caps); text-transform: uppercase; color: var(--text-tertiary); }
.prism-record-titlerow { display: flex; align-items: center; gap: var(--space-3); flex-wrap: wrap; }
.prism-record-title { margin: 0; font-family: var(--heading-font); font-size: var(--text-2xl); font-weight: var(--weight-semibold); letter-spacing: var(--heading-tracking, -0.02em); color: var(--text-primary); }
.prism-record-subtitle { margin: var(--space-1) 0 0; font-size: var(--text-sm); color: var(--text-secondary); }
.prism-record-actions { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; justify-content: flex-end; }
.prism-record-tabs { grid-column: 1 / -1; display: flex; gap: var(--space-1); overflow-x: auto; scrollbar-width: none; }
.prism-record-tabs::-webkit-scrollbar { display: none; }
.prism-record-tab { display: inline-flex; align-items: center; gap: var(--space-2); padding: var(--space-3) var(--space-3); border: 0; background: none; font-family: var(--label-font); font-size: var(--text-sm); font-weight: var(--weight-medium); color: var(--text-secondary); cursor: pointer; white-space: nowrap; border-block-end: 2px solid transparent; margin-block-end: -1px; }
.prism-record-tab:hover { color: var(--text-primary); }
.prism-record-tab[data-selected] { color: var(--accent); border-block-end-color: var(--accent); }
.prism-record-tab:focus-visible { outline: var(--focus-ring-width) solid var(--focus-ring); outline-offset: -2px; border-radius: var(--radius-xs); }
/* A count on the tab tells you whether the tab is worth opening. */
.prism-record-tabcount { font-family: var(--font-mono); font-size: var(--fs-caption); color: var(--text-tertiary); background: var(--fill-subtle); border-radius: var(--radius-pill); padding: 1px var(--space-1-5); }
.prism-record-tab[data-selected] .prism-record-tabcount { color: var(--accent); background: var(--accent-subtle); }
.prism-record-body { display: grid; grid-template-columns: minmax(0, 1fr) 296px; gap: var(--space-6); padding: var(--space-6); align-items: start; }
.prism-record-main { min-inline-size: 0; display: flex; flex-direction: column; gap: var(--space-5); }
/* Carries role="tabpanel" without generating a box, so <main> keeps its
   landmark and the column's gap still applies to the real content. */
.prism-record-panel { display: contents; }
/* Facts, never editable work. */
.prism-record-aside { display: flex; flex-direction: column; gap: var(--space-4); min-inline-size: 0; }
.prism-record-facts { background: var(--surface-card); border: var(--border-width) solid var(--border-subtle); border-radius: var(--radius-card); padding: var(--space-4) var(--space-5); }
.prism-record-factstitle { margin: 0 0 var(--space-3); font-family: var(--label-font); font-size: var(--fs-caption); font-weight: var(--weight-semibold); color: var(--text-tertiary); }
/* A real <dl>, so each label stays bound to its value for assistive tech. */
.prism-record-factslist { margin: 0; display: flex; flex-direction: column; gap: var(--space-3); }
.prism-record-fact { display: grid; grid-template-columns: 1fr auto; gap: var(--space-3); align-items: baseline; }
.prism-record-fact > dt { margin: 0; font-size: var(--text-xs); color: var(--text-tertiary); }
.prism-record-fact > dd { margin: 0; font-size: var(--text-sm); color: var(--text-primary); text-align: end; }
@media (max-width: 1023.98px) {
  .prism-record-body { grid-template-columns: minmax(0, 1fr); }
}

/* ---------------- LineItemEditor ---------------- */
.prism-lineitems { display: flex; flex-direction: column; gap: var(--space-3); min-inline-size: 0; }
/* The table keeps legible column widths and scrolls inside a narrow column,
   rather than collapsing its numeric inputs to nothing. */
.prism-lineitems-scroll { overflow-x: auto; margin-inline: calc(var(--space-2) * -1); padding-inline: var(--space-2); }
.prism-lineitems-table { inline-size: 100%; min-inline-size: 780px; border-collapse: collapse; table-layout: fixed; }
/* Fixed widths so the money columns never fight the description for space.
   These sum to 574px, which is why the table minimum is 780 — the remainder is
   the description, and it needs ~200px to be usable. */
.prism-lineitems-table thead th:nth-child(2) { inline-size: 78px; }
.prism-lineitems-table thead th:nth-child(3) { inline-size: 116px; }
.prism-lineitems-table thead th:nth-child(4) { inline-size: 84px; }
.prism-lineitems-table thead th:nth-child(5) { inline-size: 136px; }
.prism-lineitems-table thead th:nth-child(6) { inline-size: 116px; }
.prism-lineitems-table thead th:nth-child(7) { inline-size: 44px; }
.prism-lineitems-table th, .prism-lineitems-table td { padding: var(--space-2) var(--space-2); vertical-align: top; text-align: start; }
.prism-lineitems-table thead th { font-family: var(--label-font); font-size: var(--text-xs); font-weight: var(--weight-semibold); color: var(--text-tertiary); border-block-end: var(--border-width) solid var(--border-default); padding-block-end: var(--space-2); }
.prism-lineitems-table tbody tr { border-block-end: var(--border-width) solid var(--border-subtle); }
.prism-lineitems-desc { inline-size: auto; }
/* Numbers align right with tabular figures so digits stack — that is what
   makes a column of money scannable. */
.prism-lineitems-num { text-align: end; font-variant-numeric: tabular-nums; }
.prism-lineitems-num .prism-input { text-align: end; font-family: var(--font-mono); inline-size: 100%; padding-inline: var(--space-2); }
.prism-lineitems-select { inline-size: 100%; text-align: start; }
.prism-lineitems-amount { font-family: var(--font-mono); font-weight: var(--weight-semibold); color: var(--text-primary); white-space: nowrap; padding-block-start: calc(var(--space-2) + var(--space-2)); }
.prism-lineitems-text { font-size: var(--text-sm); color: var(--text-primary); }
.prism-lineitems-detail { display: block; margin-block-start: var(--space-0-5); font-size: var(--text-xs); color: var(--text-tertiary); }
.prism-lineitems-none { text-align: center; padding: var(--space-6); font-size: var(--text-sm); color: var(--text-tertiary); }
.prism-lineitems-remove { display: inline-flex; align-items: center; justify-content: center; inline-size: 30px; block-size: 30px; margin-block-start: var(--space-1); border: 0; background: transparent; color: var(--text-tertiary); border-radius: var(--radius-xs); cursor: pointer; }
.prism-lineitems-remove > svg { width: 16px; height: 16px; }
.prism-lineitems-remove:hover { background: var(--negative-subtle); color: var(--negative-text); }
.prism-lineitems-remove:focus-visible { outline: var(--focus-ring-width) solid var(--focus-ring); outline-offset: 1px; }
.prism-lineitems-add { align-self: flex-start; padding: var(--space-2) var(--space-3); font-family: var(--label-font); font-size: var(--text-sm); font-weight: var(--weight-medium); color: var(--accent); background: none; border: var(--border-width) dashed var(--border-strong); border-radius: var(--radius-control); cursor: pointer; }
.prism-lineitems-add:hover { background: var(--accent-subtle); border-color: var(--accent); }
.prism-lineitems-add:focus-visible { outline: var(--focus-ring-width) solid var(--focus-ring); outline-offset: 2px; }
.prism-lineitems-foot { display: flex; gap: var(--space-6); justify-content: space-between; align-items: flex-start; flex-wrap: wrap; padding-block-start: var(--space-3); }
.prism-lineitems-note { margin: 0; flex: 1 1 24ch; font-size: var(--text-xs); color: var(--text-tertiary); line-height: 1.55; text-wrap: pretty; }
.prism-lineitems-totals { margin: 0; margin-inline-start: auto; min-inline-size: 268px; display: flex; flex-direction: column; gap: var(--space-2); }
.prism-lineitems-totals > div { display: grid; grid-template-columns: 1fr auto; gap: var(--space-4); align-items: baseline; }
.prism-lineitems-totals dt { margin: 0; font-size: var(--text-sm); color: var(--text-secondary); }
.prism-lineitems-totals dd { margin: 0; font-family: var(--font-mono); font-size: var(--text-sm); color: var(--text-primary); font-variant-numeric: tabular-nums; }
.prism-lineitems-grand { padding-block-start: var(--space-2); border-block-start: var(--border-width) solid var(--border-default); }
.prism-lineitems-grand dt { font-family: var(--label-font); font-size: var(--text-base); font-weight: var(--weight-semibold); color: var(--text-primary); }
.prism-lineitems-grand dd { font-size: var(--text-lg); font-weight: var(--weight-semibold); }
.prism-lineitems-sr { position: absolute; inline-size: 1px; block-size: 1px; padding: 0; margin: -1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0; }

/* ---------------- ResourceTimeline ---------------- */
.prism-restime { display: flex; flex-direction: column; min-inline-size: 0; overflow-x: auto; }
.prism-restime-head { display: grid; grid-template-columns: var(--rt-label) minmax(0, 1fr); border-block-end: var(--border-width) solid var(--border-default); }
.prism-restime-corner { border-inline-end: var(--border-width) solid var(--border-subtle); }
.prism-restime-axis { position: relative; block-size: 28px; }
.prism-restime-tick { position: absolute; inset-block-end: 5px; transform: translateX(-50%); font-family: var(--font-mono); font-size: var(--fs-caption); color: var(--text-tertiary); white-space: nowrap; }
.prism-restime-rows { display: flex; flex-direction: column; }
.prism-restime-row { display: grid; grid-template-columns: var(--rt-label) minmax(0, 1fr); align-items: center; border-block-end: var(--border-width) solid var(--border-subtle); }
.prism-restime-label { display: flex; flex-direction: column; gap: 1px; padding-inline: var(--space-3) var(--space-3); border-inline-end: var(--border-width) solid var(--border-subtle); min-inline-size: 0; }
.prism-restime-name { font-size: var(--text-sm); font-weight: var(--weight-medium); color: var(--text-primary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.prism-restime-sub { font-size: var(--text-xs); color: var(--text-tertiary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* A row with a double-booking is flagged at row level too, so it is findable
   without scanning the whole width. */
.prism-restime-row[data-conflict] .prism-restime-label { box-shadow: inset 3px 0 0 var(--negative); }
.prism-restime-lane { position: relative; block-size: 100%; }
.prism-restime-grid { position: absolute; inset-block: 0; inline-size: 1px; background: var(--border-subtle); }
.prism-restime-now { position: absolute; inset-block: 0; inline-size: 2px; background: var(--accent); opacity: 0.8; z-index: 1; }
.prism-restime-bar { position: absolute; inset-block: 7px; display: flex; align-items: center; padding-inline: var(--space-2); border: var(--border-width) solid transparent; border-radius: var(--radius-xs); background: var(--accent); color: var(--accent-on); font-family: var(--body-font); font-size: var(--text-xs); cursor: pointer; overflow: hidden; }
/* A fill and its ink are ONE PAIR. The default bar takes --accent/--accent-on
   because that pair is declared in every theme; it must never take a --chart-*
   or --series-* token, which are data-mark colours with no ink partner — under
   Industry those are remapped to the light end of a luminance ladder and white
   label text collapses to ~1.2:1. Each intent below names its own pair. */
.prism-restime-bar[data-intent="notice"] { background: var(--notice); color: var(--notice-on, var(--surface-inverse)); }
.prism-restime-bar[data-intent="positive"] { background: var(--positive); color: var(--positive-on); }
.prism-restime-bar[data-intent="negative"] { background: var(--negative); color: var(--negative-on); }
.prism-restime-bar[data-intent="quiet"] { background: var(--fill-muted); color: var(--text-primary); }
/* An overlap is a conflict and must be visible — hatching plus a hard border,
   because two bars stacked on each other hide the very thing you need to see. */
.prism-restime-bar[data-conflict] { border-color: var(--negative); background-image: repeating-linear-gradient(135deg, oklch(0 0 0 / 0.14) 0 5px, transparent 5px 12px); z-index: 2; }
.prism-restime-bar[data-conflict] > * { text-shadow: 0 1px 2px oklch(0 0 0 / 0.35); }
.prism-restime-bar:focus-visible { outline: var(--focus-ring-width) solid var(--focus-ring); outline-offset: 1px; }
.prism-restime-barlabel { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.prism-restime-sr { position: absolute; inline-size: 1px; block-size: 1px; padding: 0; margin: -1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0; }

/* ---------------- ImportMapper ---------------- */
.prism-mapper { display: flex; flex-direction: column; gap: var(--space-4); min-inline-size: 0; }
.prism-mapper-head { display: flex; gap: var(--space-5); justify-content: space-between; align-items: flex-start; flex-wrap: wrap; padding: var(--space-4) var(--space-5); background: var(--surface-card); border: var(--border-width) solid var(--border-subtle); border-radius: var(--radius-card); }
.prism-mapper-file { margin: 0; font-family: var(--font-mono); font-size: var(--text-sm); color: var(--text-primary); }
.prism-mapper-rows { margin: var(--space-0-5) 0 0; font-size: var(--text-xs); color: var(--text-tertiary); }
/* Answered from the FIELD side: which of MY required fields is unfilled? */
.prism-mapper-required { min-inline-size: 220px; }
.prism-mapper-reqhead { margin: 0 0 var(--space-2); font-size: var(--text-xs); font-weight: var(--weight-semibold); color: var(--negative-text); }
.prism-mapper-required[data-complete] .prism-mapper-reqhead { color: var(--positive-text); }
.prism-mapper-reqlist { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: var(--space-2); }
.prism-mapper-reqlist > li { font-family: var(--font-mono); font-size: var(--fs-caption); padding: var(--space-0-5) var(--space-2); border-radius: var(--radius-pill); color: var(--text-tertiary); background: var(--fill-subtle); border: var(--border-width) solid var(--border-subtle); }
.prism-mapper-reqlist > li[data-done] { color: var(--positive-text); background: var(--positive-subtle); border-color: var(--positive-border); }
.prism-mapper-table { inline-size: 100%; border-collapse: collapse; }
.prism-mapper-table th, .prism-mapper-table td { padding: var(--space-3); text-align: start; vertical-align: top; }
.prism-mapper-table thead th { font-family: var(--label-font); font-size: var(--text-xs); font-weight: var(--weight-semibold); color: var(--text-tertiary); border-block-end: var(--border-width) solid var(--border-default); }
.prism-mapper-table tbody tr { border-block-end: var(--border-width) solid var(--border-subtle); }
/* A skipped column stays visibly marked — a silently ignored column is how
   half a spreadsheet goes missing. */
.prism-mapper-table tbody tr[data-skipped] { background: var(--surface-stripe); }
.prism-mapper-table tbody tr[data-skipped] .prism-mapper-colname { color: var(--text-tertiary); }
.prism-mapper-col { min-inline-size: 148px; }
.prism-mapper-colname { display: block; font-size: var(--text-sm); font-weight: var(--weight-medium); color: var(--text-primary); }
.prism-mapper-type { display: inline-block; margin-block-start: var(--space-0-5); font-family: var(--font-mono); font-size: var(--fs-caption); text-transform: uppercase; letter-spacing: var(--tracking-caps); color: var(--text-tertiary); }
/* Real values from the file are what turn a guess into a decision. */
.prism-mapper-samples { display: flex; flex-wrap: wrap; gap: var(--space-2); align-items: center; }
.prism-mapper-sample { font-family: var(--font-mono); font-size: var(--text-xs); color: var(--text-secondary); background: var(--fill-subtle); border-radius: var(--radius-xs); padding: var(--space-0-5) var(--space-1-5); max-inline-size: 22ch; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.prism-mapper-blanks { font-size: var(--fs-caption); font-family: var(--font-mono); color: var(--notice-text); }
.prism-mapper-select { max-inline-size: 260px; }
.prism-mapper-mismatch { display: flex; align-items: center; gap: var(--space-1); margin: var(--space-2) 0 0; font-size: var(--text-xs); color: var(--notice-text); }
.prism-mapper-mismatch > svg { width: 14px; height: 14px; flex: none; }

/* ---------- Material contract ----------
   These rules name material tokens the Industry theme redefines, so the
   component materialises under data-theme="industry" with NO entry in
   components/themes/industry.css. Every token has a base no-op in
   tokens/elevation.css, so all of this is inert in the base themes.
   See docs/INDUSTRY_THEME.md §9 route (a). */

/* Raised: the things you read off. */
.prism-kanban-card {
  background-image: var(--grain), var(--skeuo-card);
  background-size: var(--grain-size), auto;
  background-blend-mode: overlay, normal;
  box-shadow: var(--bevel), var(--shadow-contact);
}
.prism-record-facts {
  background-image: var(--grain), var(--skeuo-card);
  background-size: var(--grain-size), auto;
  background-blend-mode: overlay, normal;
  box-shadow: var(--bevel), var(--shadow-contact);
}
.prism-mapper-head, .prism-mapper-sample {
  background-image: var(--grain), var(--skeuo-card);
  background-size: var(--grain-size), auto;
  background-blend-mode: overlay, normal;
  box-shadow: var(--bevel), var(--shadow-contact);
}

/* A sticky identity bar is a full-bleed panel: catch light, no bottom shade. */
.prism-record-head {
  background-image: var(--grain), var(--skeuo-raised);
  background-size: var(--grain-size), auto;
  background-blend-mode: overlay, normal;
  box-shadow: var(--edge-light);
}

/* Recessed: containers that hold other things. A kanban column is a slot. */
.prism-kanban-col, .prism-mapper-reqlist {
  background-image: var(--skeuo-well-grad);
  box-shadow: var(--well);
}

/* Keys. */
.prism-kanban-menubtn {
  background-image: var(--grain), var(--skeuo-raised-soft);
  background-size: var(--grain-size), auto;
  background-blend-mode: overlay, normal;
  box-shadow: var(--bevel-soft);
}
.prism-kanban-menubtn:active:not(:disabled) { background-image: none; box-shadow: var(--press); }
.prism-lineitems-add, .prism-lineitems-remove {
  background-image: var(--grain), var(--skeuo-raised-soft);
  background-size: var(--grain-size), auto;
  background-blend-mode: overlay, normal;
  box-shadow: var(--bevel-soft);
}
.prism-lineitems-add, .prism-lineitems-remove:active:not(:disabled) { background-image: none; box-shadow: var(--press); }

/* Small pills take the catch light only — too small to carry a bevel. */
.prism-record-tabcount { background-image: var(--sheen); box-shadow: var(--bevel-soft); }

/* A floating menu is frosted glass over the live screen, not an opaque card. */
.prism-kanban-menu {
  background-image: var(--grain);
  background-size: var(--grain-size);
  background-blend-mode: overlay;
  box-shadow: var(--bevel-soft), var(--shadow-lg);
}

/* A schedule bar is a lit solid — deliberately NOT gel. Gel marks say "this is
   a measurement"; a booking is an object you drag, and a timeline shows dozens
   at once, which is exactly where gloss turns to plastic. */
.prism-restime-bar { background-image: var(--sheen); box-shadow: var(--bevel-soft); }

/* ===== components/lockups/lockups.css ===== */
/* ============================================================
   Prism · Lockups — compositional headers
   PageHeader (app page top) · SectionHeader (in-page divider)
   Heroes (PageHero / MediaHero) live in layout/.
   ============================================================ */

/* ---------------- PageHeader ---------------- */
.prism-pageheader { display: flex; flex-direction: column; gap: var(--space-4);
  /* As a grid/flex item its minimum width would be its longest word, widening
     the column (and the page) on a phone; let it shrink so the title wraps. */
  min-inline-size: 0; }
.prism-pageheader-top {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: var(--space-5); flex-wrap: wrap;
}
/* The title block takes the room and shrinks; actions stay beside it at the
   top until the title would get narrower than ~20rem, then wrap below. A long
   subtitle no longer pushes the actions down. */
.prism-pageheader-main { display: flex; align-items: flex-start; gap: var(--space-4); min-width: 0; flex: 1 1 20rem; }
.prism-pageheader-lead { flex: none; display: inline-flex; }
.prism-pageheader-lead > svg { width: 28px; height: 28px; color: var(--accent-text); }
.prism-pageheader-titles { display: flex; flex-direction: column; gap: var(--space-2); min-width: 0; }
.prism-pageheader-titlerow { display: flex; align-items: center; gap: var(--space-3); flex-wrap: wrap; }
.prism-pageheader-eyebrow {
  font-family: var(--label-font); font-weight: var(--weight-semibold);
  font-size: var(--fs-caption); letter-spacing: var(--tracking-caps); text-transform: uppercase;
  /* the school's second colour (--sig-2) when set; a hue still wins */
  color: var(--sig-2-text, var(--text-tertiary)); margin-block-end: calc(-1 * var(--space-1));
  overflow-wrap: break-word;
}
/* min-width: 0 + break-word: a long word (a school or ward name) wraps at a
   phone's width instead of pushing the header off-screen. */
.prism-pageheader-title {
  margin: 0; font-family: var(--font-display); font-weight: var(--weight-semibold);
  font-size: var(--fs-h2); line-height: var(--leading-tight); color: var(--text-primary);
  letter-spacing: -0.01em; text-wrap: balance;
  min-width: 0; max-inline-size: 100%; overflow-wrap: break-word;
}
.prism-pageheader-subtitle { margin: 0; font-size: var(--fs-body); color: var(--text-secondary); text-wrap: pretty; max-inline-size: 70ch; overflow-wrap: break-word; }
/* a subtitle given as nodes is a <div>: space its paragraphs, not its edges */
.prism-pageheader-subtitle > :where(p, ul, ol) { margin: 0; }
.prism-pageheader-subtitle > * + * { margin-block-start: var(--space-2); }
/* size="lg": long-form pages — the title stays above the Prose h2s below it */
.prism-pageheader[data-size="lg"] .prism-pageheader-title { font-size: var(--fs-h1); font-weight: var(--weight-bold); letter-spacing: var(--tracking-tight); }
.prism-pageheader[data-size="lg"] .prism-pageheader-subtitle { font-size: var(--fs-lead); }
/* hue: the eyebrow and lead icon take the hue; band adds a bar across the top */
.prism-pageheader[data-hue] .prism-pageheader-eyebrow { color: var(--hue-text); }
.prism-pageheader[data-band="true"] { border-block-start: 4px solid var(--hue, var(--accent)); padding-block-start: var(--space-4); }
.prism-pageheader-meta { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2) var(--space-4); font-size: var(--fs-body-sm); color: var(--text-tertiary); }
.prism-pageheader-meta-item { display: inline-flex; align-items: center; gap: var(--space-1-5); }
.prism-pageheader-meta-item > svg { width: var(--icon-sm); height: var(--icon-sm); }
/* May shrink below its one-line width, so the buttons wrap on a phone
   instead of scrolling the page sideways. */
.prism-pageheader-actions { display: flex; align-items: center; gap: var(--space-3); flex: 0 1 auto; min-width: 0; max-inline-size: 100%; flex-wrap: wrap; }
.prism-pageheader-tabs { border-top: var(--border-width) solid var(--border-subtle); padding-block-start: var(--space-2); }
.prism-pageheader[data-bleed="true"] { padding-block-end: var(--space-4); border-bottom: var(--border-width) solid var(--border-default); }

/* ---------------- SectionHeader ---------------- */
.prism-sectionheader {
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: var(--space-4); flex-wrap: wrap;
 min-inline-size: 0; }
.prism-sectionheader-titles { display: flex; flex-direction: column; gap: var(--space-0-5); min-width: 0; }
.prism-sectionheader-eyebrow {
  font-family: var(--label-font); font-weight: var(--weight-semibold);
  font-size: var(--fs-caption); letter-spacing: var(--tracking-caps); text-transform: uppercase;
  color: var(--text-tertiary);
}
.prism-sectionheader-title {
  margin: 0; font-family: var(--font-display); font-weight: var(--weight-semibold);
  font-size: var(--fs-h4); line-height: var(--leading-tight); color: var(--text-primary);
}
.prism-sectionheader-desc { margin: 0; font-size: var(--fs-body-sm); color: var(--text-secondary); text-wrap: pretty; max-inline-size: 64ch; }
/* May shrink and wrap, so a row of actions never pushes the page sideways. */
.prism-sectionheader-actions { display: flex; align-items: center; gap: var(--space-2); flex: 0 1 auto; flex-wrap: wrap; min-width: 0; max-inline-size: 100%; }
.prism-sectionheader[data-size="lg"] .prism-sectionheader-title { font-size: var(--fs-h3); }
.prism-sectionheader[data-size="sm"] .prism-sectionheader-title { font-size: var(--fs-h5); }
/* xs: a label-style heading for a section inside a card or form */
.prism-sectionheader[data-size="xs"] { align-items: center; gap: var(--space-2) var(--space-3); }
.prism-sectionheader[data-size="xs"] .prism-sectionheader-title {
  font-family: var(--label-font); font-size: var(--fs-caption); font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-caps); text-transform: uppercase; line-height: var(--leading-snug);
  color: var(--text-secondary);
}
.prism-sectionheader[data-size="xs"] .prism-sectionheader-desc { font-size: var(--fs-caption); }
.prism-sectionheader[data-rule="true"] { border-bottom: var(--border-width) solid var(--border-default); padding-block-end: var(--space-3); }

/* ===== components/permissions/permissions.css ===== */
/* ============================================================
   Prism · Permission & role states
   RestrictedState · LockedOverlay · ReadOnlyBanner · RoleBadge
   ============================================================ */

/* RestrictedState reuses the .prism-empty layout; these tune the media tone */
.prism-empty[data-variant="locked"]   .prism-empty-media { background: var(--intent-premium-subtle); color: var(--intent-premium-text); }
.prism-empty[data-variant="no-access"] .prism-empty-media { background: var(--fill-muted); color: var(--text-secondary); }
.prism-empty[data-variant="read-only"] .prism-empty-media { background: var(--info-subtle); color: var(--info-text); }
/* an illustration (illustration prop) takes the variant's tone */
.prism-empty[data-variant="no-access"] .prism-spot { --accent: var(--text-secondary); --accent-subtle: var(--fill-subtle); }
.prism-empty[data-variant="locked"] .prism-spot    { --accent: var(--intent-premium-text); --accent-subtle: var(--intent-premium-subtle); }
.prism-empty[data-variant="read-only"] .prism-spot { --accent: var(--info-text); --accent-subtle: var(--info-subtle); }

/* ---------------- LockedOverlay ---------------- */
.prism-lockoverlay { position: relative; display: grid; border-radius: var(--radius-card); overflow: hidden; isolation: isolate; }
.prism-lockoverlay-content { grid-area: 1 / 1; filter: blur(3px) saturate(0.7); opacity: 0.55; pointer-events: none; user-select: none; }
.prism-lockoverlay-veil {
  grid-area: 1 / 1; z-index: 1;
  display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center;
  gap: var(--space-3); padding: var(--space-8) var(--space-6);
  background: color-mix(in oklch, var(--surface-card) 62%, transparent);
  backdrop-filter: blur(1px);
}
.prism-lockoverlay-badge {
  display: inline-flex; align-items: center; justify-content: center;
  width: 52px; height: 52px; border-radius: var(--radius-pill);
  background: var(--intent-premium-subtle); color: var(--intent-premium-text);
  border: var(--border-width) solid var(--intent-premium-border);
}
.prism-lockoverlay-badge > svg { width: 26px; height: 26px; }
.prism-lockoverlay-title { font-family: var(--font-display); font-weight: var(--weight-semibold); font-size: var(--fs-h5); color: var(--text-primary); margin: 0; }
.prism-lockoverlay-text { font-size: var(--fs-body-sm); color: var(--text-secondary); margin: 0; max-inline-size: 38ch; text-wrap: pretty; }
.prism-lockoverlay-actions { display: flex; gap: var(--space-2); flex-wrap: wrap; justify-content: center; margin-block-start: var(--space-1); }

/* ---------------- ReadOnlyBanner ---------------- */
.prism-readonly {
  display: flex; align-items: center; gap: var(--space-3);
  padding: var(--space-3) var(--space-4); border-radius: var(--radius-md);
  background: var(--info-subtle); border: var(--border-width) solid var(--info-border);
  border-inline-start: 3px solid var(--info);
  font-size: var(--fs-body-sm); color: var(--text-primary);
}
.prism-readonly-icon { flex: none; color: var(--info-text); display: inline-flex; }
.prism-readonly-icon > svg { width: var(--icon-md); height: var(--icon-md); }
.prism-readonly-body { flex: 1 1 auto; min-width: 0; }
.prism-readonly-title { font-weight: var(--weight-semibold); }
.prism-readonly-text { color: var(--text-secondary); }
.prism-readonly-actions { flex: none; display: flex; gap: var(--space-2); }

/* ---------------- RoleBadge ---------------- */
.prism-rolebadge {
  display: inline-flex; align-items: center; gap: var(--space-1);
  height: 22px; padding: 0 var(--space-2); border-radius: var(--radius-pill);
  font-family: var(--label-font); font-size: var(--text-xs); font-weight: var(--weight-semibold);
  background: var(--fill-subtle); color: var(--text-secondary); border: var(--border-width) solid var(--border-default);
  white-space: nowrap;
}
.prism-rolebadge > svg { width: 13px; height: 13px; }
.prism-rolebadge[data-role="owner"]  { background: var(--intent-premium-subtle); color: var(--intent-premium-text); border-color: var(--intent-premium-border); }
.prism-rolebadge[data-role="admin"]  { background: var(--accent-subtle); color: var(--accent-text); border-color: var(--accent-border); }
.prism-rolebadge[data-role="editor"] { background: var(--positive-subtle); color: var(--positive-text); border-color: var(--positive-border); }
.prism-rolebadge[data-role="viewer"] { background: var(--fill-subtle); color: var(--text-secondary); }

/* ===== components/privacy/privacy.css ===== */
/* ============================================================
   Prism · Privacy & compliance
   MaskedField · SensitivityTag · ConsentBanner · AuditLogEntry · SessionTimeoutDialog
   ============================================================ */

/* ---------------- MaskedField ---------------- */
.prism-masked { display: flex; flex-direction: column; gap: var(--space-1); min-inline-size: 0; }
.prism-masked-label { font-size: var(--fs-caption); color: var(--text-secondary); font-family: var(--label-font); }
.prism-masked-row {
  display: inline-flex; align-items: center; gap: var(--space-2);
  padding: var(--space-3) var(--space-3) var(--space-3) var(--space-4);
  background: var(--surface-sunken); border: var(--border-width) solid var(--border-default);
  border-radius: var(--radius-md); min-inline-size: 0;
}
.prism-masked-value {
  font-family: var(--font-mono); font-size: var(--fs-body-sm); letter-spacing: .06em;
  color: var(--text-primary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; flex: 1 1 auto;
}
.prism-masked[data-revealed="true"] .prism-masked-value { letter-spacing: normal; }
.prism-masked-actions { display: inline-flex; gap: var(--space-0-5); flex: none; }
.prism-masked-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 28px; height: 28px; border-radius: var(--radius-sm);
  border: 0; background: transparent; color: var(--text-secondary); cursor: pointer;
}
.prism-masked-btn:hover { background: var(--fill-subtle); color: var(--text-primary); }
.prism-masked-btn:focus-visible { outline: var(--focus-ring-width) solid var(--focus-ring); outline-offset: 1px; }
.prism-masked-btn[aria-pressed="true"] { color: var(--accent-text); }
.prism-masked-btn > svg { width: 16px; height: 16px; }

/* ---------------- SensitivityTag ---------------- */
.prism-senstag {
  display: inline-flex; align-items: center; gap: var(--space-1);
  height: 22px; padding: 0 var(--space-2); border-radius: var(--radius-pill);
  font-family: var(--label-font); font-size: var(--text-xs); font-weight: var(--weight-semibold);
  background: var(--fill-subtle); color: var(--text-secondary); border: var(--border-width) solid var(--border-default);
  white-space: nowrap; letter-spacing: .02em;
}
.prism-senstag > svg { width: 13px; height: 13px; }
.prism-senstag[data-level="pii"]          { background: var(--info-subtle); color: var(--info-text); border-color: var(--info-border); }
.prism-senstag[data-level="phi"]          { background: var(--positive-subtle); color: var(--positive-text); border-color: var(--positive-border); }
.prism-senstag[data-level="financial"]    { background: var(--intent-premium-subtle); color: var(--intent-premium-text); border-color: var(--intent-premium-border); }
.prism-senstag[data-level="confidential"] { background: var(--notice-subtle); color: var(--notice-text); border-color: var(--notice-border); }
.prism-senstag[data-level="restricted"]   { background: var(--negative-subtle); color: var(--negative-text); border-color: var(--negative-border); }

/* ---------------- ConsentBanner ---------------- */
.prism-consent {
  display: flex; align-items: flex-start; gap: var(--space-4);
  padding: var(--space-4) var(--space-5);
  background: var(--surface-card); border: var(--border-width) solid var(--border-default);
  border-radius: var(--radius-card); box-shadow: var(--shadow-md);
}
.prism-consent[data-position="fixed"] {
  position: fixed; inset-block-end: var(--space-4); inset-inline: var(--space-4);
  z-index: var(--z-overlay, 60); max-inline-size: 760px; margin-inline: auto;
}
.prism-consent-icon {
  flex: none; display: inline-flex; align-items: center; justify-content: center;
  width: 40px; height: 40px; border-radius: var(--radius-pill);
  background: var(--accent-subtle); color: var(--accent-text);
}
.prism-consent-icon > svg { width: 22px; height: 22px; }
.prism-consent-body { flex: 1 1 auto; min-inline-size: 0; }
.prism-consent-title { font-family: var(--font-display); font-weight: var(--weight-semibold); font-size: var(--fs-h5); color: var(--text-primary); margin: 0 0 var(--space-0-5); }
.prism-consent-text { font-size: var(--fs-body-sm); color: var(--text-secondary); margin: 0; max-inline-size: 64ch; text-wrap: pretty; line-height: 1.5; }
.prism-consent-text a { color: var(--accent-text); }
.prism-consent-actions { flex: none; display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; align-self: center; }
.prism-consent-btn {
  height: 36px; padding: 0 var(--space-4); border-radius: var(--radius-control);
  font-family: var(--label-font); font-size: var(--fs-body-sm); font-weight: var(--weight-semibold);
  cursor: pointer; border: var(--border-width) solid transparent; white-space: nowrap;
}
.prism-consent-btn:focus-visible { outline: var(--focus-ring-width) solid var(--focus-ring); outline-offset: 2px; }
.prism-consent-btn.is-accent  { background: var(--accent); color: var(--accent-on, #fff); }
.prism-consent-btn.is-accent:hover { background: var(--accent-hover, var(--accent)); }
.prism-consent-btn.is-neutral { background: var(--fill-subtle); color: var(--text-primary); border-color: var(--border-default); }
.prism-consent-btn.is-neutral:hover { background: var(--fill-muted); }
.prism-consent-btn.is-quiet   { background: transparent; color: var(--text-secondary); }
.prism-consent-btn.is-quiet:hover { background: var(--fill-subtle); color: var(--text-primary); }
@media (max-width: 1023.98px) {
  .prism-consent { flex-direction: column; }
  .prism-consent-actions { width: 100%; }
  .prism-consent-btn { flex: 1 1 auto; }
}

/* ---------------- AuditLogEntry ---------------- */
.prism-auditlog {
  list-style: none; margin: 0; padding: 0;
  /* Entries respond to the LIST's width, not the viewport: in a sidebar the
     time column would otherwise squeeze the body to a word per line. */
  container: prism-auditlog / inline-size;
}
.prism-audit-entry {
  display: grid; grid-template-columns: 28px 1fr auto; gap: var(--space-3);
  padding-block: var(--space-3); position: relative;
}
.prism-audit-rail { position: relative; display: flex; justify-content: center; }
.prism-audit-rail::before {
  content: ""; position: absolute; inset-block: -12px; inset-block-start: 28px;
  inline-size: 2px; background: var(--border-subtle);
}
.prism-audit-entry:last-child .prism-audit-rail::before { display: none; }
.prism-audit-marker {
  position: relative; z-index: 1; flex: none;
  width: 28px; height: 28px; border-radius: var(--radius-pill);
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--fill-subtle); color: var(--text-secondary);
  border: var(--border-width) solid var(--border-default);
}
.prism-audit-marker > svg { width: 15px; height: 15px; }
.prism-audit-entry[data-tone="create"] .prism-audit-marker { background: var(--positive-subtle); color: var(--positive-text); border-color: var(--positive-border); }
.prism-audit-entry[data-tone="edit"]   .prism-audit-marker { background: var(--accent-subtle); color: var(--accent-text); border-color: var(--accent-border); }
.prism-audit-entry[data-tone="delete"] .prism-audit-marker { background: var(--negative-subtle); color: var(--negative-text); border-color: var(--negative-border); }
.prism-audit-entry[data-tone="view"]   .prism-audit-marker { background: var(--info-subtle); color: var(--info-text); border-color: var(--info-border); }
.prism-audit-entry[data-tone="access"] .prism-audit-marker { background: var(--intent-premium-subtle); color: var(--intent-premium-text); border-color: var(--intent-premium-border); }
.prism-audit-entry[data-tone="alert"]  .prism-audit-marker { background: var(--notice-subtle); color: var(--notice-text); border-color: var(--notice-border); }
.prism-audit-body { min-inline-size: 0; overflow-wrap: anywhere; } /* long IDs / emails wrap instead of overflowing */
.prism-audit-line { margin: 0; font-size: var(--fs-body-sm); color: var(--text-secondary); line-height: 1.45; }
.prism-audit-actor { color: var(--text-primary); font-weight: var(--weight-semibold); }
.prism-audit-target { color: var(--text-primary); font-weight: var(--weight-medium); }
.prism-audit-detail { margin: var(--space-0-5) 0 0; font-size: var(--fs-body-sm); color: var(--text-secondary); overflow-wrap: anywhere; }
.prism-audit-meta { margin: var(--space-0-5) 0 0; font-family: var(--font-mono); font-size: var(--text-xs); color: var(--text-tertiary); }
.prism-audit-time { font-family: var(--font-mono); font-size: var(--text-xs); color: var(--text-tertiary); white-space: nowrap; padding-block-start: var(--space-1-5); }
/* Narrow list (a sidebar, a drawer): the time moves above the body and the
   body gets the full width; the marker rail spans both rows. */
@container prism-auditlog (max-width: 360px) {
  .prism-audit-entry { grid-template-columns: 28px 1fr; grid-template-rows: auto 1fr; row-gap: var(--space-0-5); }
  .prism-audit-rail { grid-column: 1; grid-row: 1 / span 2; }
  .prism-audit-time { grid-column: 2; grid-row: 1; padding-block-start: var(--space-1); white-space: normal; }
  .prism-audit-body { grid-column: 2; grid-row: 2; }
}

/* ---------------- SessionTimeoutDialog ---------------- */
.prism-session-scrim {
  position: fixed; inset: 0; z-index: var(--z-modal, 80);
  display: grid; place-items: center; padding: var(--space-5);
  background: var(--surface-scrim, oklch(0 0 0 / 0.45));
}
.prism-session {
  inline-size: min(420px, 100%); text-align: center;
  background: var(--surface-card); border: var(--border-width) solid var(--border-default);
  border-radius: var(--radius-lg); box-shadow: var(--shadow-xl);
  padding: var(--space-6) var(--space-6) var(--space-5);
}
.prism-session-ring {
  width: 96px; height: 96px; border-radius: 50%; margin: 0 auto var(--space-4);
  display: grid; place-items: center;
}
.prism-session-ring-in {
  width: 76px; height: 76px; border-radius: 50%; background: var(--surface-card);
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: var(--space-0-5);
  color: var(--text-secondary); box-shadow: var(--well, inset 0 0 0 1px var(--border-subtle));
}
.prism-session-ring-in > svg { width: 20px; height: 20px; }
.prism-session-count { font-family: var(--font-mono); font-size: var(--text-lg); font-weight: var(--weight-semibold); color: var(--text-primary); }
.prism-session[data-danger="true"] .prism-session-count { color: var(--negative-text); }
.prism-session-title { font-family: var(--font-display); font-weight: var(--weight-semibold); font-size: var(--fs-h4); color: var(--text-primary); margin: 0 0 var(--space-1-5); }
.prism-session-text { font-size: var(--fs-body-sm); color: var(--text-secondary); margin: 0 auto var(--space-5); max-inline-size: 40ch; text-wrap: pretty; line-height: 1.5; }
.prism-session-actions { display: flex; gap: var(--space-2); justify-content: center; flex-wrap: wrap; }
.prism-session-btn {
  height: 40px; padding: 0 var(--space-5); border-radius: var(--radius-control);
  font-family: var(--label-font); font-size: var(--fs-body-sm); font-weight: var(--weight-semibold);
  cursor: pointer; border: var(--border-width) solid transparent;
}
.prism-session-btn:focus-visible { outline: var(--focus-ring-width) solid var(--focus-ring); outline-offset: 2px; }
.prism-session-btn.is-accent  { background: var(--accent); color: var(--accent-on, #fff); }
.prism-session-btn.is-accent:hover { background: var(--accent-hover, var(--accent)); }
.prism-session-btn.is-neutral { background: var(--fill-subtle); color: var(--text-primary); border-color: var(--border-default); }
.prism-session-btn.is-neutral:hover { background: var(--fill-muted); }

/* ===== components/workflow/workflow.css ===== */
/* ============================================================
   Prism · Workflow patterns
   StatusPipeline · ActivityTimeline (rail) · ReviewActionBar
   ============================================================ */

/* ---------------- StatusPipeline ---------------- */
.prism-pipeline {
  list-style: none; margin: 0; padding: 0;
  display: flex; align-items: flex-start;
}
.prism-pipeline-step {
  position: relative; flex: 1 1 0; min-inline-size: 0;
  display: flex; flex-direction: column; align-items: center; gap: var(--space-2);
  text-align: center;
}
/* connector line between nodes */
.prism-pipeline-step::before {
  content: ""; position: absolute; block-size: 2px; inset-block-start: 15px;
  inset-inline-start: calc(-50% + 16px); inline-size: calc(100% - 32px);
  background: var(--border-strong);
}
.prism-pipeline-step:first-child::before { content: none; }
.prism-pipeline-node {
  position: relative; z-index: 1;
  inline-size: 32px; block-size: 32px; border-radius: 50%;
  display: grid; place-items: center; flex: none;
  background: var(--surface-card);
  border: 2px solid var(--border-strong); color: var(--text-tertiary);
  font-family: var(--font-display); font-weight: var(--weight-semibold); font-size: var(--fs-caption);
}
.prism-pipeline-node > svg { inline-size: 16px; block-size: 16px; }
.prism-pipeline-text { display: flex; flex-direction: column; gap: 1px; min-inline-size: 0; max-inline-size: 100%; }
.prism-pipeline-label { font-size: var(--fs-body-sm); font-weight: var(--weight-medium); color: var(--text-secondary); line-height: 1.25; }
.prism-pipeline-sub { font-size: var(--text-xs); color: var(--text-tertiary); line-height: 1.3; }

/* states */
.prism-pipeline-step[data-status="done"] .prism-pipeline-node {
  background: var(--accent); border-color: var(--accent); color: var(--accent-on);
}
.prism-pipeline-step[data-status="done"]::before { background: var(--accent); }
.prism-pipeline-step[data-status="done"] .prism-pipeline-label { color: var(--text-primary); }

.prism-pipeline-step[data-status="current"] .prism-pipeline-node {
  background: var(--accent-subtle); border-color: var(--accent); color: var(--accent-text);
  box-shadow: 0 0 0 4px var(--accent-subtle);
}
.prism-pipeline-step[data-status="current"] .prism-pipeline-label { color: var(--text-primary); font-weight: var(--weight-semibold); }

.prism-pipeline-step[data-status="rejected"] .prism-pipeline-node {
  background: var(--negative); border-color: var(--negative); color: var(--negative-on);
}
.prism-pipeline-step[data-status="rejected"] .prism-pipeline-label { color: var(--negative-text); font-weight: var(--weight-semibold); }
/* dim nodes after a rejection / that are upcoming */
.prism-pipeline-step[data-status="upcoming"] .prism-pipeline-label,
.prism-pipeline-step[data-status="upcoming"] .prism-pipeline-sub { opacity: .85; }

/* compact size */
.prism-pipeline[data-size="sm"] .prism-pipeline-node { inline-size: 26px; block-size: 26px; font-size: var(--fs-caption); }
.prism-pipeline[data-size="sm"] .prism-pipeline-node > svg { inline-size: 13px; block-size: 13px; }
.prism-pipeline[data-size="sm"] .prism-pipeline-step::before { inset-block-start: 12px; }

/* vertical orientation — for detail sidebars */
.prism-pipeline[data-orientation="vertical"] { flex-direction: column; align-items: stretch; }
.prism-pipeline[data-orientation="vertical"] .prism-pipeline-step {
  flex-direction: row; align-items: flex-start; text-align: start;
  gap: var(--space-3); padding-block-end: var(--space-4);
}
.prism-pipeline[data-orientation="vertical"] .prism-pipeline-step::before {
  inline-size: 2px; block-size: 100%;
  inset-block-start: 32px; inset-inline-start: 15px; inset-inline-end: auto;
}
.prism-pipeline[data-orientation="vertical"] .prism-pipeline-step:last-child { padding-block-end: 0; }
.prism-pipeline[data-orientation="vertical"] .prism-pipeline-text { padding-block-start: var(--space-1); }

/* ---------------- ActivityTimeline ---------------- */
/* the .prism-auditlog rail is styled in privacy.css; these add grouping */
.prism-timeline-groups { display: flex; flex-direction: column; gap: var(--space-5); }
.prism-timeline-group { display: flex; flex-direction: column; gap: var(--space-2); }
.prism-timeline-grouplabel {
  margin: 0 0 var(--space-1); font-family: var(--label-font);
  font-size: var(--fs-caption); font-weight: var(--weight-semibold);
  color: var(--text-tertiary);
}

/* ---------------- ReviewActionBar ---------------- */
.prism-reviewbar {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-4);
  padding: var(--space-3) var(--space-5);
  background: var(--surface-card);
  border: var(--border-width) solid var(--border-subtle);
  border-radius: var(--radius-card);
  flex-wrap: wrap;
}
.prism-reviewbar[data-sticky="true"] {
  position: sticky; inset-block-end: var(--space-4); z-index: 5;
  box-shadow: var(--shadow-md);
}
.prism-reviewbar-info { display: flex; flex-direction: column; gap: var(--space-0-5); min-inline-size: 0; }
.prism-reviewbar-summary { font-size: var(--fs-body); font-weight: var(--weight-medium); color: var(--text-primary); }
.prism-reviewbar-meta { font-size: var(--text-sm); color: var(--text-secondary); }
.prism-reviewbar-actions { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; }
.prism-reviewbar-reject.prism-btn { color: var(--negative-text); }
.prism-reviewbar-reject.prism-btn:hover { background: var(--negative-subtle); }


/* ---------------- ApprovalChain ---------------- */
/* Shows PEOPLE and their decisions — StatusPipeline shows a record's lifecycle.
   Different questions: "who is holding this up?" vs "where is this?". */
.prism-approvals { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; }
.prism-approvals-step { display: grid; grid-template-columns: 22px minmax(0, 1fr); gap: var(--space-3); }
.prism-approvals-rail { position: relative; display: flex; flex-direction: column; align-items: center; }
.prism-approvals-node { flex: none; inline-size: 11px; block-size: 11px; margin-block-start: var(--space-1); border-radius: 50%; background: var(--surface-card); border: 2px solid var(--border-strong); }
.prism-approvals-line { flex: 1; inline-size: 2px; background: var(--border-subtle); margin-block: var(--space-0-5); }
.prism-approvals-step[data-status="approved"] .prism-approvals-node { background: var(--positive); border-color: var(--positive); }
.prism-approvals-step[data-status="approved"] .prism-approvals-line { background: var(--positive); opacity: 0.4; }
.prism-approvals-step[data-status="current"] .prism-approvals-node { background: var(--accent); border-color: var(--accent); box-shadow: 0 0 0 4px var(--accent-subtle); }
.prism-approvals-step[data-status="rejected"] .prism-approvals-node { background: var(--negative); border-color: var(--negative); }
/* Blocked, never "upcoming": a rejection means these will not be asked for, and
   showing them as pending makes people wait for an approval that never comes. */
.prism-approvals-step[data-status="blocked"] .prism-approvals-node { background: transparent; border-color: var(--border-subtle); border-style: dashed; }
.prism-approvals-body { padding-block: 0 var(--space-5); min-inline-size: 0; }
.prism-approvals-step:last-child .prism-approvals-body { padding-block-end: 0; }
.prism-approvals-stephead { display: flex; align-items: baseline; gap: var(--space-3); flex-wrap: wrap; }
.prism-approvals-steplabel { font-family: var(--label-font); font-size: var(--text-sm); font-weight: var(--weight-semibold); color: var(--text-primary); }
.prism-approvals-step[data-status="blocked"] .prism-approvals-steplabel { color: var(--text-tertiary); }
/* The parallel RULE is printed where the reader can check it — "any 2 of 3" and
   "all 3 in order" are completely different governance. */
.prism-approvals-rule { font-family: var(--font-mono); font-size: var(--fs-caption); color: var(--text-tertiary); background: var(--fill-subtle); border-radius: var(--radius-pill); padding: var(--space-0-5) var(--space-2); }
/* The wait is the only actionable number here. */
.prism-approvals-waiting { font-family: var(--font-mono); font-size: var(--text-xs); color: var(--notice-text); }
.prism-approvals-waiting[data-breach] { color: var(--negative-text); font-weight: var(--weight-semibold); }
.prism-approvals-blocked { font-family: var(--font-mono); font-size: var(--fs-caption); color: var(--text-tertiary); }
.prism-approvals-people { display: flex; flex-direction: column; gap: var(--space-2); margin-block-start: var(--space-2); }
/* A parallel group is drawn AS A GROUP — braced and inset — not as a sequence. */
.prism-approvals-people[data-parallel] { gap: var(--space-2); padding-inline-start: var(--space-3); border-inline-start: 2px solid var(--border-default); }
.prism-approvals-person { display: grid; grid-template-columns: 18px minmax(0, 1fr) auto; gap: var(--space-2) var(--space-3); align-items: baseline; }
.prism-approvals-mark { display: inline-flex; align-items: center; justify-content: center; color: var(--text-tertiary); }
.prism-approvals-mark > svg { width: 13px; height: 13px; }
.prism-approvals-person[data-status="approved"] .prism-approvals-mark { color: var(--positive-text); }
.prism-approvals-person[data-status="rejected"] .prism-approvals-mark { color: var(--negative-text); }
.prism-approvals-person[data-status="current"] .prism-approvals-mark { color: var(--notice-text); }
.prism-approvals-who { display: flex; align-items: baseline; gap: var(--space-2); flex-wrap: wrap; min-inline-size: 0; }
.prism-approvals-name { font-size: var(--text-sm); color: var(--text-primary); }
.prism-approvals-person[data-status="blocked"] .prism-approvals-name,
.prism-approvals-person[data-status="upcoming"] .prism-approvals-name { color: var(--text-secondary); }
.prism-approvals-role { font-size: var(--text-xs); color: var(--text-tertiary); }
/* A delegation is a materially different fact and audits turn on it. */
.prism-approvals-delegate { font-size: var(--text-xs); font-style: italic; color: var(--notice-text); }
.prism-approvals-at { font-family: var(--font-mono); font-size: var(--text-xs); color: var(--text-tertiary); white-space: nowrap; }
/* Visible reasoning is the control that stops rubber-stamping — never hidden. */
.prism-approvals-comment { grid-column: 2 / -1; margin: var(--space-0-5) 0 0; padding: var(--space-2) var(--space-3); font-size: var(--text-xs); line-height: 1.5; color: var(--text-secondary); background: var(--fill-subtle); border-radius: var(--radius-sm); text-wrap: pretty; }
.prism-approvals[data-size="sm"] .prism-approvals-body { padding-block-end: var(--space-4); }
.prism-approvals[data-size="sm"] .prism-approvals-steplabel { font-size: var(--text-xs); }

/* ===== components/tv/tv.css ===== */
/* ============================================================
   Prism TV kit — the 10-foot tier
   All sizes in cqw (1% of the 16:9 stage width) so a scene scales
   to any screen. Keyed off --tv-* tokens (see tokens/scales.css).
   Class prefix: prism-tv-*  ·  focusables carry [data-tv-focus]
   ============================================================ */

.prism-tv-scene {
  --tv-foc: var(--tv-focus-color, oklch(1 0 0 / 0.95));
  --tv-glass: oklch(1 0 0 / 0.1);
  --tv-glass-strong: oklch(1 0 0 / 0.14);
  --tv-glass-border: oklch(1 0 0 / 0.18);
  container-type: size; position: relative; width: 100%; aspect-ratio: 16 / 9; overflow: hidden;
  font-family: var(--font-body); color: oklch(1 0 0); background: oklch(0.09 0.012 270);
  isolation: isolate; outline: none;
}
.prism-tv-scene * { box-sizing: border-box; }

/* crossfading cinematic backdrop (two stacked layers) */
.prism-tv-bg { position: absolute; inset: -4cqw; z-index: 0; background-size: cover; background-position: center;
  filter: blur(2.2cqw) saturate(1.25) brightness(0.5); opacity: 0; transform: scale(1.06);
  transition: opacity 0.7s var(--ease-standard); }
.prism-tv-bg.is-on { opacity: 1; }
.prism-tv-scrim { position: absolute; inset: 0; z-index: 1; pointer-events: none; background:
    radial-gradient(120% 80% at 80% -10%, oklch(0.6 0.16 300 / 0.22), transparent 55%),
    linear-gradient(180deg, oklch(0.05 0.01 270 / 0.55) 0%, transparent 22%, transparent 52%, oklch(0.05 0.01 270 / 0.85) 100%),
    linear-gradient(90deg, oklch(0.05 0.01 270 / 0.78) 0%, oklch(0.05 0.01 270 / 0.25) 42%, transparent 70%); }

.prism-tv-inner { position: relative; z-index: 2; height: 100%; overflow: hidden;
  padding: var(--tv-safe-top, 3.5%) 0 0; display: flex; flex-direction: column; gap: 2cqw; }
.prism-tv-port { position: relative; flex: 1 1 auto; min-height: 0; overflow: hidden; }
.prism-tv-scrollbody { display: flex; flex-direction: column; gap: 2cqw;
  transition: transform 0.5s var(--ease-emphasized); will-change: transform; }

/* safe-area inset helper for direct children of the scene */
.prism-tv-safe { padding-inline: var(--tv-safe-x, 5.5%); }

/* ---------- top bar / menu ---------- */
.prism-tv-topbar { display: flex; align-items: center; gap: 2cqw; flex: none; padding-inline: var(--tv-safe-x, 5.5%); }
.prism-tv-brand { display: inline-flex; align-items: center; gap: 0.9cqw; font-family: var(--font-display);
  font-weight: 800; font-size: 1.8cqw; letter-spacing: -0.02em; }
.prism-tv-brand .mark { width: 1.6cqw; height: 1.6cqw; border-radius: 0.45cqw;
  background: conic-gradient(from 210deg, oklch(0.7 0.2 30), oklch(0.6 0.25 300), oklch(0.65 0.2 230), oklch(0.7 0.2 30));
  box-shadow: 0 0 1.6cqw oklch(0.6 0.25 300 / 0.6); }
.prism-tv-tabs { display: flex; align-items: center; gap: 0.4cqw; padding: 0.5cqw; border-radius: var(--radius-pill);
  background: var(--tv-glass); backdrop-filter: blur(2cqw) saturate(1.6); -webkit-backdrop-filter: blur(2cqw) saturate(1.6);
  border: 1px solid var(--tv-glass-border); box-shadow: inset 0 1px 0 oklch(1 0 0 / 0.18), 0 1cqw 2cqw oklch(0 0 0 / 0.25); }
.prism-tv-tab { appearance: none; border: 0; background: transparent; color: oklch(1 0 0 / 0.78); cursor: pointer;
  font-family: var(--font-display); font-weight: 600; font-size: 1.4cqw; padding: 0.7cqw 1.6cqw; border-radius: var(--radius-pill);
  white-space: nowrap; transition: color var(--duration-fast) var(--ease-standard), background var(--duration-fast) var(--ease-standard); }
.prism-tv-tab[aria-current="true"] { background: oklch(1 0 0 / 0.92); color: oklch(0.2 0.03 280); box-shadow: 0 0.5cqw 1.4cqw oklch(0 0 0 / 0.3); }
.prism-tv-topbar-end { margin-inline-start: auto; display: flex; align-items: center; gap: 1.6cqw; color: oklch(1 0 0 / 0.85); }
.prism-tv-clock { font-family: var(--font-display); font-weight: 700; font-size: 1.7cqw; text-align: end; }
.prism-tv-clock small { display: block; font-weight: 500; font-size: 0.95cqw; opacity: 0.7; margin-top: -0.2cqw; }
.prism-tv-avatar { width: 3.6cqw; height: 3.6cqw; border-radius: var(--radius-pill); display: grid; place-items: center;
  font-family: var(--font-display); font-weight: 800; font-size: 1.5cqw;
  background: linear-gradient(140deg, oklch(0.62 0.2 30), oklch(0.5 0.24 320)); color: oklch(1 0 0); box-shadow: 0 0.6cqw 1.6cqw oklch(0 0 0 / 0.4); }

/* ---------- focus signature (shared) ---------- */
.prism-tv-foc { position: relative; cursor: pointer; outline: none;
  transition: transform var(--duration-normal) var(--ease-emphasized), box-shadow var(--duration-normal) var(--ease-standard); }
.prism-tv-foc::after { content: ""; position: absolute; inset: 0; border-radius: inherit; pointer-events: none; opacity: 0;
  box-shadow: 0 0 0 var(--tv-focus-ring, 3px) var(--tv-foc), 0 0 0 calc(var(--tv-focus-ring, 3px) + 2px) oklch(0 0 0 / 0.35), var(--tv-focus-shadow, 0 2cqw 5cqw oklch(0 0 0 / 0.5));
  background: linear-gradient(150deg, oklch(1 0 0 / 0.26) 0%, transparent 32%);
  transition: opacity var(--duration-normal) var(--ease-standard); }
.prism-tv-foc.is-tv-focused { z-index: 5; }
.prism-tv-foc.is-tv-focused::after { opacity: 1; }
.prism-tv-foc.is-tv-pressed { transform: scale(0.96) !important; }

/* ---------- buttons ---------- */
.prism-tv-btn { display: inline-flex; align-items: center; justify-content: center; gap: 0.8cqw; height: var(--tv-btn-h, 4.6cqw);
  padding: 0 2.8cqw; border: 0; border-radius: var(--radius-pill); font-family: var(--font-display); font-weight: 700; font-size: 1.6cqw;
  color: oklch(1 0 0); background: var(--tv-glass-strong); backdrop-filter: blur(2cqw) saturate(1.6); -webkit-backdrop-filter: blur(2cqw) saturate(1.6);
  border: 1px solid oklch(1 0 0 / 0.2); box-shadow: inset 0 1px 0 oklch(1 0 0 / 0.18); }
.prism-tv-btn svg { width: 1.9cqw; height: 1.9cqw; }
.prism-tv-btn.is-round { width: var(--tv-btn-h, 4.6cqw); padding: 0; }
.prism-tv-btn[data-variant="primary"] { background: oklch(1 0 0); color: oklch(0.18 0.03 280); border-color: transparent; box-shadow: 0 0.8cqw 2cqw oklch(0 0 0 / 0.35); }
.prism-tv-btn[data-variant="accent"] { background: linear-gradient(135deg, oklch(0.66 0.2 28), oklch(0.56 0.22 350)); color: oklch(1 0 0); border-color: transparent; }
.prism-tv-btn.prism-tv-foc.is-tv-focused { transform: scale(1.06); }

/* ---------- hero ---------- */
.prism-tv-hero { min-height: 30cqw; flex: none; display: flex; flex-direction: column; justify-content: flex-end; gap: 1.1cqw;
  max-width: 58%; padding: 0 0 1cqw var(--tv-safe-x, 5.5%); }
.prism-tv-kicker { display: inline-flex; align-items: center; gap: 0.7cqw; font-family: var(--font-display); font-size: 1.1cqw;
  font-weight: 700; text-transform: uppercase; letter-spacing: 0.16em; color: oklch(1 0 0 / 0.92); }
.prism-tv-kicker .pip { width: 0.8cqw; height: 0.8cqw; border-radius: 50%; background: oklch(0.7 0.2 30); box-shadow: 0 0 1.4cqw oklch(0.7 0.2 30); }
.prism-tv-hero-title { font-family: var(--font-display); font-size: 5.4cqw; font-weight: 800; letter-spacing: -0.035em; line-height: 0.95;
  margin: 0; text-shadow: 0 0.3cqw 2.4cqw oklch(0 0 0 / 0.5); }
.prism-tv-hero-meta { display: flex; align-items: center; gap: 1.1cqw; font-size: 1.4cqw; color: oklch(1 0 0 / 0.88); font-weight: 500; }
.prism-tv-hero-meta .tag { border: 1px solid oklch(1 0 0 / 0.45); border-radius: 0.5cqw; padding: 0.05cqw 0.7cqw; font-size: 1.05cqw; font-weight: 700; }
.prism-tv-hero-meta .star { color: oklch(0.85 0.16 90); }
.prism-tv-synopsis { font-size: 1.4cqw; line-height: 1.45; color: oklch(1 0 0 / 0.82); max-width: 88%; margin: 0.2cqw 0 0; }
.prism-tv-actions { display: flex; gap: 1.2cqw; margin-top: 1.2cqw; }

/* ---------- rails + cards ---------- */
.prism-tv-rails { display: flex; flex-direction: column; gap: 1.8cqw; padding-bottom: 4cqw; }
.prism-tv-rail { overflow: visible; }
.prism-tv-rail-head { display: flex; align-items: baseline; gap: 1.2cqw; padding-inline: var(--tv-safe-x, 5.5%); margin-bottom: 1.1cqw; }
.prism-tv-rail-title { font-family: var(--font-display); font-size: 1.9cqw; font-weight: 700; margin: 0; letter-spacing: -0.01em; }
.prism-tv-rail-more { font-size: 1.2cqw; color: oklch(1 0 0 / 0.5); font-weight: 600; }
.prism-tv-track { display: flex; gap: 1.4cqw; padding-inline: var(--tv-safe-x, 5.5%);
  transition: transform 0.5s var(--ease-emphasized); will-change: transform; }

.prism-tv-card { flex: none; border: 0; padding: 0; background: transparent; text-align: start; color: inherit; display: flex; flex-direction: column; gap: 0.9cqw; }
.prism-tv-card-art { position: relative; border-radius: 1.4cqw; overflow: hidden; background-size: cover; background-position: center; box-shadow: 0 1cqw 2.6cqw oklch(0 0 0 / 0.4); }
.prism-tv-card[data-shape="wide"] .prism-tv-card-art { width: 24cqw; aspect-ratio: 16 / 9; }
.prism-tv-card[data-shape="poster"] .prism-tv-card-art { width: 15cqw; aspect-ratio: 2 / 3; }
.prism-tv-card[data-shape="square"] .prism-tv-card-art { width: 16cqw; aspect-ratio: 1 / 1; }
.prism-tv-card-art::before { content: ""; position: absolute; inset: 0; background: linear-gradient(to top, oklch(0.06 0.02 270 / 0.7), transparent 50%); }
.prism-tv-badge { position: absolute; inset-block-start: 1cqw; inset-inline-end: 1cqw; font-family: var(--font-display); font-weight: 700; font-size: 0.95cqw;
  padding: 0.2cqw 0.7cqw; border-radius: 0.5cqw; background: oklch(0.06 0.02 270 / 0.6); backdrop-filter: blur(1cqw); border: 1px solid oklch(1 0 0 / 0.2); }
.prism-tv-card-ovl { position: absolute; inset-inline: 1.1cqw; inset-block-end: 1.1cqw; display: flex; align-items: center; gap: 0.8cqw; }
.prism-tv-card-ovl svg { width: 2.2cqw; height: 2.2cqw; filter: drop-shadow(0 1px 4px oklch(0 0 0 / 0.6)); }
.prism-tv-prog { position: absolute; inset-inline: 1.1cqw; inset-block-end: 1.1cqw; height: 0.5cqw; border-radius: var(--radius-pill); background: oklch(1 0 0 / 0.3); overflow: hidden; }
.prism-tv-prog > div { height: 100%; background: oklch(0.7 0.2 30); border-radius: inherit; }
.prism-tv-card-cap { padding-inline: 0.2cqw; }
.prism-tv-card-name { font-family: var(--font-display); font-weight: 600; font-size: 1.35cqw; line-height: 1.15; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; display: block; }
.prism-tv-card-sub { font-size: 1.05cqw; color: oklch(1 0 0 / 0.62); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; display: block; margin-top: 0.1cqw; }
.prism-tv-card[data-shape="poster"] .prism-tv-card-cap { opacity: 0; transition: opacity var(--duration-normal) var(--ease-standard); }
.prism-tv-card[data-shape="poster"].is-tv-focused .prism-tv-card-cap,
.prism-tv-card[data-shape="poster"] .prism-tv-card-art.is-tv-focused ~ .prism-tv-card-cap { opacity: 1; }

/* ---------- remote help / hint ---------- */
.prism-tv-hint { position: absolute; z-index: 6; inset-block-end: 2cqw; inset-inline-end: 2.4cqw; display: flex; align-items: center; gap: 0.8cqw;
  font-size: 1.05cqw; font-weight: 600; color: oklch(1 0 0 / 0.7); padding: 0.6cqw 1.2cqw; border-radius: var(--radius-pill);
  background: oklch(1 0 0 / 0.07); backdrop-filter: blur(2cqw); border: 1px solid oklch(1 0 0 / 0.12); }
.prism-tv-hint kbd { font-family: var(--font-display); font-weight: 700; background: oklch(1 0 0 / 0.14); border-radius: 0.4cqw; padding: 0.05cqw 0.5cqw; }
.prism-tv-helpcard { display: grid; grid-template-columns: auto 1fr; gap: 1cqw 1.6cqw; align-items: center;
  padding: 2.4cqw; border-radius: 2cqw; background: oklch(0.1 0.02 270 / 0.7); backdrop-filter: blur(3cqw); border: 1px solid var(--tv-glass-border); font-size: 1.4cqw; }
.prism-tv-helpcard kbd { font-family: var(--font-display); font-weight: 700; font-size: 1.4cqw; min-width: 3cqw; text-align: center;
  padding: 0.5cqw 0.9cqw; border-radius: 0.7cqw; background: oklch(1 0 0 / 0.14); border: 1px solid oklch(1 0 0 / 0.2); }

/* ---------- overlay / modal ---------- */
.prism-tv-overlay { position: absolute; inset: 0; z-index: 30; display: grid; place-items: center;
  background: oklch(0.04 0.01 270 / 0.72); backdrop-filter: blur(1.4cqw); }
.prism-tv-modal { width: 52cqw; max-width: 80%; padding: 3.4cqw; border-radius: 2.4cqw;
  background: oklch(0.13 0.018 270 / 0.92); border: 1px solid var(--tv-glass-border); box-shadow: 0 4cqw 10cqw oklch(0 0 0 / 0.6);
  display: flex; flex-direction: column; gap: 1.6cqw; }
.prism-tv-modal h2 { font-family: var(--font-display); font-size: 3cqw; font-weight: 800; letter-spacing: -0.02em; margin: 0; }
.prism-tv-modal p { font-size: 1.5cqw; line-height: 1.5; color: oklch(1 0 0 / 0.82); margin: 0; }
.prism-tv-modal-actions { display: flex; gap: 1.2cqw; margin-top: 1cqw; }

/* ---------- toast ---------- */
.prism-tv-toasts { position: absolute; z-index: 40; inset-block-start: var(--tv-safe-y, 6.5%); inset-inline-end: var(--tv-safe-x, 5.5%);
  display: flex; flex-direction: column; gap: 1cqw; align-items: flex-end; pointer-events: none; }
.prism-tv-toast { display: flex; align-items: center; gap: 1.1cqw; padding: 1.2cqw 1.8cqw; border-radius: 1.4cqw; font-size: 1.4cqw; font-weight: 600;
  color: oklch(1 0 0); background: oklch(0.14 0.02 270 / 0.88); backdrop-filter: blur(2cqw); border: 1px solid var(--tv-glass-border); box-shadow: 0 1.4cqw 3cqw oklch(0 0 0 / 0.45);
  animation: prism-tv-toast-in 0.4s var(--ease-emphasized) both; }
.prism-tv-toast svg { width: 2cqw; height: 2cqw; }
.prism-tv-toast[data-tone="success"] svg { color: oklch(0.78 0.16 155); }
.prism-tv-toast[data-tone="danger"] svg { color: oklch(0.7 0.2 25); }
@keyframes prism-tv-toast-in { from { opacity: 0; transform: translateX(2cqw); } }

/* ---------- media transport controls ---------- */
.prism-tv-controls { position: relative; display: flex; flex-direction: column; gap: 1.4cqw; padding: 2.4cqw var(--tv-safe-x, 5.5%);
  background: linear-gradient(0deg, oklch(0.04 0.01 270 / 0.92), transparent); }
.prism-tv-controls-meta { display: flex; align-items: baseline; gap: 1.2cqw; }
.prism-tv-controls-title { font-family: var(--font-display); font-size: 2.6cqw; font-weight: 800; margin: 0; letter-spacing: -0.02em; }
.prism-tv-controls-sub { font-size: 1.3cqw; color: oklch(1 0 0 / 0.7); }
.prism-tv-scrub { display: flex; align-items: center; gap: 1.4cqw; font-variant-numeric: tabular-nums; font-size: 1.2cqw; color: oklch(1 0 0 / 0.8); }
.prism-tv-scrub-track { position: relative; flex: 1; height: 0.7cqw; border-radius: var(--radius-pill); background: oklch(1 0 0 / 0.22); overflow: hidden; }
.prism-tv-scrub-fill { position: absolute; inset-block: 0; inset-inline-start: 0; background: oklch(0.78 0.16 25); border-radius: inherit; }
.prism-tv-scrub-buf { position: absolute; inset-block: 0; inset-inline-start: 0; background: oklch(1 0 0 / 0.25); }
.prism-tv-transport { display: flex; align-items: center; justify-content: center; gap: 1.6cqw; }

/* ---------- QR handoff ---------- */
.prism-tv-qr { display: flex; align-items: center; gap: 2.6cqw; padding: 2.8cqw; border-radius: 2cqw;
  background: oklch(0.12 0.018 270 / 0.85); border: 1px solid var(--tv-glass-border); backdrop-filter: blur(2cqw); }
.prism-tv-qr-code { width: 16cqw; height: 16cqw; border-radius: 1.2cqw; background: oklch(1 0 0); padding: 1cqw; flex: none; display: grid; place-items: center; }
.prism-tv-qr-code img, .prism-tv-qr-code svg, .prism-tv-qr-code canvas { width: 100%; height: 100%; }
.prism-tv-qr-body h3 { font-family: var(--font-display); font-size: 2.4cqw; font-weight: 800; margin: 0 0 0.6cqw; }
.prism-tv-qr-body p { font-size: 1.4cqw; line-height: 1.5; color: oklch(1 0 0 / 0.78); margin: 0; max-width: 34cqw; }

/* ---------- language selector ---------- */
.prism-tv-langs { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1.2cqw; }
.prism-tv-lang { display: flex; align-items: center; gap: 1.2cqw; padding: 1.4cqw 1.8cqw; border: 1px solid var(--tv-glass-border); border-radius: 1.4cqw;
  background: var(--tv-glass); color: oklch(1 0 0); text-align: start; }
.prism-tv-lang .flag { font-size: 2.4cqw; line-height: 1; }
.prism-tv-lang .endonym { font-family: var(--font-display); font-weight: 700; font-size: 1.6cqw; }
.prism-tv-lang .english { font-size: 1.1cqw; color: oklch(1 0 0 / 0.6); }
.prism-tv-lang.prism-tv-foc.is-tv-focused { transform: scale(1.04); }

/* ---------- idle / screensaver ---------- */
.prism-tv-idle { position: absolute; inset: 0; z-index: 50; display: flex; flex-direction: column; justify-content: flex-end;
  padding: var(--tv-safe-y, 6.5%) var(--tv-safe-x, 5.5%); background-size: cover; background-position: center;
  background-color: oklch(0.09 0.02 265 / 0.84); backdrop-filter: blur(24px); -webkit-backdrop-filter: blur(24px);
  opacity: 0; pointer-events: none; transition: opacity 1s var(--ease-standard); }
.prism-tv-scene.tv-idle .prism-tv-idle { opacity: 1; pointer-events: auto; }
/* full-screen ambient scrim: legible over art AND over the base colour if art fails to load */
.prism-tv-idle::after { content: ""; position: absolute; inset: 0; pointer-events: none;
  background:
    radial-gradient(120% 75% at 50% 8%, oklch(0.22 0.05 265 / 0.55), transparent 62%),
    linear-gradient(0deg, oklch(0.04 0.015 270 / 0.94) 0%, oklch(0.04 0.015 270 / 0.34) 52%, oklch(0.05 0.02 270 / 0.55) 100%); }
.prism-tv-idle-clock { position: relative; z-index: 1; font-family: var(--font-display); font-weight: 800; font-size: 9cqw; line-height: 1; letter-spacing: -0.03em; text-shadow: 0 0.4cqw 3cqw oklch(0 0 0 / 0.6); }
.prism-tv-idle-meta { position: relative; z-index: 1; font-size: 1.8cqw; color: oklch(1 0 0 / 0.85); margin-top: 0.6cqw; }
.prism-tv-idle-hint { position: relative; z-index: 1; font-size: 1.3cqw; color: oklch(1 0 0 / 0.6); margin-top: 1.6cqw; }

/* ---------- emergency / alert ---------- */
.prism-tv-emergency { position: absolute; inset: 0; z-index: 60; display: flex; flex-direction: column; justify-content: center; gap: 2cqw;
  padding: var(--tv-safe-y, 6.5%) 12cqw; color: oklch(1 0 0);
  background: linear-gradient(135deg, oklch(0.45 0.2 28), oklch(0.32 0.16 18)); }
.prism-tv-emergency .badge { display: inline-flex; align-items: center; gap: 0.9cqw; align-self: flex-start; font-family: var(--font-display); font-weight: 800;
  text-transform: uppercase; letter-spacing: 0.12em; font-size: 1.3cqw; padding: 0.7cqw 1.4cqw; border-radius: var(--radius-pill); background: oklch(1 0 0 / 0.16); border: 1px solid oklch(1 0 0 / 0.4); }
.prism-tv-emergency .badge svg { width: 1.8cqw; height: 1.8cqw; }
.prism-tv-emergency h1 { font-family: var(--font-display); font-size: 5.6cqw; font-weight: 800; line-height: 0.98; letter-spacing: -0.03em; margin: 0; }
.prism-tv-emergency p { font-size: 2cqw; line-height: 1.45; max-width: 60cqw; margin: 0; color: oklch(1 0 0 / 0.92); }
.prism-tv-emergency .instructions { display: flex; gap: 2.4cqw; margin-top: 1cqw; font-size: 1.5cqw; }

@media (prefers-reduced-motion: reduce) {
  .prism-tv-foc, .prism-tv-btn, .prism-tv-track, .prism-tv-bg, .prism-tv-scrollbody, .prism-tv-idle { transition: none !important; }
  .prism-tv-foc.is-tv-focused, .prism-tv-btn.is-tv-focused, .prism-tv-lang.is-tv-focused { transform: none !important; }
  .prism-tv-toast { animation: none !important; }
}

/* ===== components/industry/industry-charts.css ===== */
/* ============================================================
   Prism · Industry chart family (extruded)
   RingChart · DialGauge · TrendChart · ColumnChart · RankBars · SignalWave
   ------------------------------------------------------------
   Charts are the ONE place the Industry theme is allowed to be
   glossy. A data mark is a machined, lit solid: a bright top
   face, a swept face, a dark side wall and a soft cast shadow.
   Everything else in the theme stays matte, so gloss reads as
   "this object is data" rather than as decoration.

   Each mark reads a local --c (its series colour) and spells the
   faces out in its own rule. That repetition is deliberate: a
   custom property containing var(--c) resolves --c on the element
   where the PROPERTY is declared, not where it is used — so
   piping the recipe through --extrude-sweep would silently paint
   every mark in --accent. The --extrude-* tokens document the
   recipe and serve authors who set --c on the same element; the
   marks below inline it so per-series colour actually lands.
   Outside the Industry theme --c falls back to --accent and the
   marks still render, just monochrome.
   ============================================================ */

.prism-xchart { inline-size: 100%; color: var(--text-secondary); font-family: var(--body-font); }
.prism-xchart-head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-4); margin-block-end: var(--space-4); }
.prism-xchart-title { font-family: var(--label-font); font-size: var(--fs-small); font-weight: var(--weight-semibold); color: var(--text-secondary); margin: 0; }
.prism-xchart-value { font-family: var(--font-mono); font-size: var(--text-lg); color: var(--text-primary); }
.prism-xchart-sr { position: absolute; inline-size: 1px; block-size: 1px; padding: 0; margin: -1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0; }

/* ---------------- RingChart · extruded allocation ring ---------------- */
.prism-ring { position: relative; display: inline-grid; place-items: center; flex: none; }
.prism-ring-layer {
  position: absolute; inset: 0; border-radius: 50%;
  mask: radial-gradient(farthest-side, transparent calc(100% - var(--rt)), #000 calc(100% - var(--rt)));
  -webkit-mask: radial-gradient(farthest-side, transparent calc(100% - var(--rt)), #000 calc(100% - var(--rt)));
}
/* the wall is the gel's own shadow, not a moulded side face: offset,
   darkened and blurred so the mark looks like it is sitting IN light */
.prism-ring-wall { transform: translateY(var(--extrude-depth, 5px)); filter: blur(1.5px) saturate(0.7); opacity: 0.85; }
.prism-ring-face { filter: drop-shadow(0 0 10px oklch(0.10 0.01 250 / 0.45)); }
/* broad catch light across the whole ring */
.prism-ring-spec { background: linear-gradient(155deg, oklch(1 0 0 / 0.16) 0%, oklch(1 0 0 / 0.03) 32%, transparent 54%); mix-blend-mode: screen; }
/* the gel tell: a bright hairline running the INNER edge of the ring */
.prism-ring-gloss {
  position: absolute;
  inset: calc(var(--rt) - 4px);
  border-radius: 50%;
  box-shadow: 0 0 0 1.5px oklch(1 0 0 / 0.30), 0 0 7px oklch(1 0 0 / 0.14);
  pointer-events: none;
}
/* and a soft outer bloom so the ring spills light onto the surface */
.prism-ring-bloom {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  mask: radial-gradient(farthest-side, transparent calc(100% - var(--rt)), #000 calc(100% - var(--rt)));
  -webkit-mask: radial-gradient(farthest-side, transparent calc(100% - var(--rt)), #000 calc(100% - var(--rt)));
  filter: blur(9px) saturate(1.25);
  opacity: 0.55;
  pointer-events: none;
}
/* Centre content is bounded to the ring's inner circle (100% − two ring
   widths) and padded, so a long value never touches the inner edge of the band. */
.prism-ring-center {
  position: relative; z-index: 1; box-sizing: border-box;
  inline-size: calc(100% - 2 * var(--rt)); block-size: calc(100% - 2 * var(--rt));
  padding: var(--space-3);
  display: grid; place-content: center; text-align: center; gap: var(--space-0-5);
  overflow: hidden;
  container-type: inline-size;
}
/* The value scales to the ring it sits in: cqi is the centre's own width, so a
   200px ring with a 30px band gives ~21px type, and a long value shrinks rather
   than touching the band. The centre is a size container for this reason. */
.prism-ring-value { font-family: var(--heading-font); font-weight: var(--weight-bold); font-size: min(var(--fs-h3), 18cqi); letter-spacing: var(--heading-tracking, -0.02em); line-height: 1; color: var(--text-primary); white-space: nowrap; }
.prism-ring-label { font-family: var(--font-mono); font-size: var(--fs-caption); text-transform: uppercase; letter-spacing: var(--tracking-caps); color: var(--text-tertiary); }

/* ---------------- DialGauge · extruded 270° gauge ---------------- */
.prism-dialgauge { position: relative; display: inline-grid; place-items: center; flex: none; }
.prism-dialgauge-ticks {
  position: absolute; inset: -9px; border-radius: 50%;
  background: repeating-conic-gradient(from 222deg, var(--lineart-stroke-quiet, oklch(0.8 0 0 / 0.3)) 0deg 0.5deg, transparent 0.5deg 9deg);
  mask: radial-gradient(farthest-side, transparent calc(100% - 5px), #000 calc(100% - 5px));
  -webkit-mask: radial-gradient(farthest-side, transparent calc(100% - 5px), #000 calc(100% - 5px));
}
.prism-dialgauge-readout { position: relative; text-align: center; z-index: 1; display: grid; gap: var(--space-0-5); }
.prism-dialgauge-value { font-family: var(--font-mono); font-weight: var(--weight-semibold); font-size: var(--text-4xl); line-height: 1; letter-spacing: -0.02em; color: var(--text-primary); }
.prism-dialgauge-value .u { font-size: 0.44em; color: var(--text-tertiary); margin-inline-start: var(--space-0-5); }
.prism-dialgauge-label { font-family: var(--font-mono); font-size: var(--fs-caption); text-transform: uppercase; letter-spacing: var(--tracking-caps); color: var(--text-tertiary); }

/* ---------------- TrendChart · lit line & area ---------------- */
.prism-trend svg { display: block; inline-size: 100%; block-size: auto; overflow: visible; }
.prism-trend-grid { stroke: var(--border-subtle); stroke-width: 1; }
.prism-trend-axis { stroke: var(--border-default); stroke-width: 1; }
.prism-trend-line { fill: none; stroke-width: 3.25; stroke-linecap: round; stroke-linejoin: round; }
.prism-trend-tick { font-family: var(--font-mono); font-size: var(--fs-caption); fill: var(--text-tertiary); }
.prism-trend[data-variant="spark"] .prism-trend-line { stroke-width: 2; }

/* ---------------- ColumnChart · extruded columns ---------------- */
.prism-columns { display: flex; align-items: flex-end; gap: var(--space-2); block-size: var(--col-h, 150px); }
.prism-columns-col { flex: 1; block-size: 100%; display: flex; flex-direction: column; justify-content: flex-end; align-items: center; gap: var(--space-2); min-inline-size: 0; }
.prism-columns-slot { flex: 1 1 auto; inline-size: 100%; min-block-size: 0; display: flex; align-items: flex-end; }
/* Frosted gel rod: a luminous translucent body, a soft frosted lid at the top
   and a diffuse glow — lit from within, not a glossy plastic face. */
.prism-columns-bar {
  position: relative;
  inline-size: 100%;
  border-radius: var(--radius-md) var(--radius-md) var(--radius-xs) var(--radius-xs);
  background-image: linear-gradient(180deg,
    color-mix(in oklch, var(--c, var(--accent)) 46%, white) 0%,
    color-mix(in oklch, var(--c, var(--accent)) 88%, white) 15%,
    var(--c, var(--accent)) 50%,
    color-mix(in oklch, var(--c, var(--accent)) 64%, black) 100%);
  box-shadow:
    inset 0 1px 0 oklch(1 0 0 / 0.5),
    inset 0 0 14px color-mix(in oklch, var(--c, var(--accent)) 38%, transparent),
    0 0 22px color-mix(in oklch, var(--c, var(--accent)) 26%, transparent);
  transition: block-size var(--duration-slow) var(--ease-standard);
}
/* frosted top lid — a soft bright cap that fades down, not a hard streak */
.prism-columns-bar::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background-image: linear-gradient(180deg, oklch(1 0 0 / 0.32) 0%, oklch(1 0 0 / 0.06) 18%, transparent 44%);
  pointer-events: none;
}
.prism-columns-bar[data-muted="true"] {
  background-image: linear-gradient(180deg, oklch(0.315 0.006 250) 0%, oklch(0.238 0.005 250) 52%, oklch(0.183 0.004 250) 100%);
  box-shadow: inset 0 1.5px 0 oklch(1 0 0 / 0.15), inset 1.5px 0 0 oklch(1 0 0 / 0.07), inset -1.5px 0 0 oklch(0 0 0 / 0.45);
}
.prism-columns-bar[data-muted="true"]::after { opacity: 0.4; }
.prism-columns-lab { font-family: var(--font-mono); font-size: var(--fs-caption); color: var(--text-tertiary); white-space: nowrap; }
.prism-columns-val { font-family: var(--font-mono); font-size: var(--fs-caption); color: var(--text-secondary); }

/* ---------------- RankBars · horizontal ranking ---------------- */
.prism-rank { display: flex; flex-direction: column; gap: var(--space-3); }
.prism-rank-row { display: grid; grid-template-columns: minmax(0, 8.5rem) 1fr auto; align-items: center; gap: var(--space-3); }
.prism-rank-lab { font-size: var(--fs-small); color: var(--text-secondary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.prism-rank-track { position: relative; block-size: 16px; border-radius: 4px; background-color: var(--series-track, var(--fill-muted)); box-shadow: var(--well); overflow: hidden; }
.prism-rank-fill {
  position: relative;
  block-size: 100%;
  border-radius: var(--radius-xs);
  background-image: linear-gradient(90deg, color-mix(in oklch, var(--c, var(--accent)) 70%, black) 0%, var(--c, var(--accent)) 55%, color-mix(in oklch, var(--c, var(--accent)) 46%, white) 100%);
  box-shadow: inset 0 1.5px 0 color-mix(in oklch, var(--c, var(--accent)) 34%, white), inset 1.5px 0 0 color-mix(in oklch, var(--c, var(--accent)) 58%, white), inset -1.5px 0 0 color-mix(in oklch, var(--c, var(--accent)) 60%, black), 0 0 14px color-mix(in oklch, var(--c, var(--accent)) 42%, transparent), 0 0 40px color-mix(in oklch, var(--c, var(--accent)) 18%, transparent);
  transition: inline-size var(--duration-slow) var(--ease-standard);
}
.prism-rank-fill::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background-image: linear-gradient(178deg, oklch(1 0 0 / 0.30) 0%, oklch(1 0 0 / 0.04) 34%, transparent 60%);
  pointer-events: none;
}
.prism-rank-val { font-family: var(--font-mono); font-size: var(--text-xs); color: var(--text-primary); min-inline-size: 4ch; text-align: end; }

/* ---------------- SignalWave · live signal ---------------- */
.prism-wave { display: flex; align-items: flex-end; gap: var(--space-0-5); block-size: var(--wave-h, 72px); }
.prism-wave-bar {
  flex: 1; min-inline-size: 2px; border-radius: 2px;
  background-image: linear-gradient(0deg, color-mix(in oklch, var(--led) 52%, black) 0%, var(--led) 58%, color-mix(in oklch, var(--led) 62%, white) 100%);
  background-size: 100% var(--wave-h, 72px);
  background-position: bottom;
  background-repeat: no-repeat;
  box-shadow: inset 0 1.5px 0 oklch(1 0 0 / 0.30), 0 0 8px color-mix(in oklch, var(--led) 26%, transparent);
  transition: block-size 90ms linear;
}
.prism-wave[data-peak="true"] .prism-wave-bar { box-shadow: inset 0 1px 0 oklch(1 0 0 / 0.22), 0 0 8px color-mix(in oklch, var(--led) 30%, transparent); }

@media (prefers-reduced-motion: reduce) {
  .prism-columns-bar, .prism-rank-fill, .prism-wave-bar { transition: none; }
}

/* ===== components/industry/industry-controls.css ===== */
/* ============================================================
   Prism · Industry controls
   RulerPicker
   ------------------------------------------------------------
   Controls that belong to the instrument rather than to a form:
   a value you set by feel, against a scale you can read.
   ============================================================ */

.prism-ruler { display: flex; flex-direction: column; gap: var(--space-3); }

/* ---------- heading with an inline mode select ---------- */
.prism-ruler-head {
  display: flex; align-items: center; justify-content: center; gap: var(--space-2);
  font-family: var(--heading-font);
  font-size: var(--fs-h4);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--heading-tracking, -0.02em);
  text-align: center;
}
.prism-ruler-label { color: var(--text-tertiary); }
.prism-ruler-select { position: relative; display: inline-flex; align-items: center; gap: var(--space-2); color: var(--text-primary); }
.prism-ruler-select select {
  appearance: none; -webkit-appearance: none;
  background: transparent; border: 0; border-radius: var(--radius-xs, 3px);
  color: inherit; font: inherit; letter-spacing: inherit;
  padding: 0 var(--space-0-5); cursor: pointer;
}
.prism-ruler-select select:focus-visible { outline: var(--focus-ring-width, 2px) solid var(--focus-ring); outline-offset: 3px; }
.prism-ruler-select select option { background: var(--surface-overlay); color: var(--text-primary); }
.prism-ruler-select svg { color: var(--text-tertiary); flex: none; }

/* ---------- stage: the flag is pinned, the scale travels ---------- */
.prism-ruler-stage { position: relative; --ruler-flag-clearance: 62px; padding-block-start: var(--ruler-flag-clearance); } /* clearance = flag block + pointer; geometry, not rhythm */

.prism-ruler-flag {
  position: absolute; inset-block-start: 0; inset-inline-start: 50%;
  transform: translateX(-50%);
  display: flex; flex-direction: column; align-items: center;
  z-index: 2; pointer-events: none;
}
.prism-ruler-flag-pill {
  display: inline-flex; align-items: center;
  min-block-size: 40px; padding: 0 var(--space-4);
  border-radius: var(--radius-control);
  background: var(--led);
  color: oklch(0.16 0.02 250);
  font-family: var(--font-mono);
  font-weight: var(--weight-bold);
  font-size: var(--text-xl);
  letter-spacing: -0.01em;
  white-space: nowrap;
  box-shadow: inset 0 1.5px 0 oklch(1 0 0 / 0.34), var(--led-glow);
}
.prism-ruler-flag-stem {
  inline-size: 2px; block-size: 46px;
  background: var(--led);
  box-shadow: var(--led-glow-soft);
}

/* ---------- the scale ---------- */
.prism-ruler-scroll {
  overflow-x: auto; overflow-y: hidden;
  scrollbar-width: none;
  padding-inline: 50%;
  cursor: grab;
  touch-action: pan-y;
  overscroll-behavior-x: contain;
}
.prism-ruler-scroll::-webkit-scrollbar { display: none; }
.prism-ruler-scroll[data-drag="true"] { cursor: grabbing; }
.prism-ruler-scroll:focus-visible { outline: var(--focus-ring-width, 2px) solid var(--focus-ring); outline-offset: 2px; border-radius: var(--radius-control); }

.prism-ruler-track {
  position: relative;
  block-size: 68px;
  /* major ticks first so they paint over the minor run */
  background-image:
    repeating-linear-gradient(90deg, var(--lineart-stroke) 0 1.5px, transparent 1.5px calc(var(--tick-gap) * var(--major))),
    repeating-linear-gradient(90deg, var(--lineart-stroke-quiet) 0 1px, transparent 1px var(--tick-gap));
  background-size: 100% 30px, 100% 18px;
  background-position: left bottom, left bottom;
  background-repeat: repeat-x, repeat-x;
}
.prism-ruler-major {
  position: absolute; inset-block-start: 4px;
  transform: translateX(-50%);
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  color: var(--text-tertiary);
  white-space: nowrap;
  pointer-events: none;
}

/* ===== components/theming/theming.css ===== */
/* ============================================================
   Prism · ThemeBuilder — in-app brand-theme editor.
   A controls panel + a live preview built from real Prism
   components (recoloured by tokens set inline on .prism-tb-stage)
   + a theme.css / tokens.json export. All token-driven.
   ============================================================ */
.prism-themebuilder {
  display: grid;
  grid-template-columns: minmax(280px, 360px) 1fr;
  gap: var(--space-5);
  align-items: start;
  font-family: var(--body-font);
  color: var(--text-primary);
}
@media (max-width: 1023.98px) { .prism-themebuilder { grid-template-columns: 1fr; } }

/* ---- controls ---- */
.prism-tb-controls {
  display: flex; flex-direction: column; gap: var(--space-3);
  padding: var(--space-4);
  background: var(--surface-card); color: var(--text-primary);
  border: var(--border-width) solid var(--border-subtle);
  border-radius: var(--radius-card); box-shadow: var(--shadow-sm);
}
.prism-tb-sec-title {
  font-family: var(--font-mono); font-size: var(--text-xs); font-weight: var(--weight-semibold);
  color: var(--text-tertiary);
  margin-block-start: var(--space-2); padding-block-start: var(--space-3);
  border-block-start: var(--border-width) solid var(--border-subtle);
}
.prism-tb-sec-title:first-child { margin-block-start: 0; padding-block-start: 0; border-block-start: 0; }
.prism-tb-sub { font-size: var(--text-xs); font-weight: var(--weight-semibold); color: var(--text-tertiary); }

.prism-tb-color { display: flex; flex-direction: column; gap: var(--space-1); }
.prism-tb-colorline { display: flex; align-items: center; gap: var(--space-2); }
.prism-tb-swatch-sm { inline-size: 24px; block-size: 24px; flex: none; border-radius: var(--radius-sm); border: var(--border-width) solid var(--border-default); }
.prism-tb-cname { flex: 1; font-size: var(--text-sm); font-weight: var(--weight-medium); }
.prism-tb-badge { font-family: var(--font-mono); font-size: var(--fs-caption); font-weight: var(--weight-bold); padding: 2px var(--space-1-5); border-radius: var(--radius-sm); flex: none; }
.prism-tb-badge-ok { background: var(--positive-subtle); color: var(--positive-text); }
.prism-tb-badge-warn { background: var(--notice-subtle); color: var(--notice-text); }
.prism-tb-badge-bad { background: var(--negative-subtle); color: var(--negative-text); }
.prism-tb-hex { inline-size: 28px; block-size: 28px; padding: 0; border: var(--border-width) solid var(--border-default); border-radius: var(--radius-sm); background: none; cursor: pointer; flex: none; }
.prism-tb-hextx { inline-size: 76px; flex: none; font-family: var(--font-mono); font-size: var(--text-xs); padding: var(--space-1) var(--space-2); border: var(--border-width) solid var(--border-default); border-radius: var(--radius-sm); background: var(--surface-page); color: var(--text-primary); }

.prism-tb-field { display: flex; flex-direction: column; gap: var(--space-0-5); }
.prism-tb-field-row { display: flex; justify-content: space-between; align-items: baseline; font-size: var(--text-sm); font-weight: var(--weight-medium); color: var(--text-secondary); }
.prism-tb-num { font-family: var(--font-mono); font-size: var(--text-xs); color: var(--text-primary); font-variant-numeric: tabular-nums; }
.prism-tb-range { inline-size: 100%; accent-color: var(--accent); cursor: pointer; }
.prism-tb-range:focus-visible { outline: var(--focus-ring-width) solid var(--focus-ring); outline-offset: 3px; border-radius: var(--radius-sm); }

.prism-tb-fld { display: flex; flex-direction: column; gap: var(--space-1); }
.prism-tb-flabel { font-size: var(--text-sm); font-weight: var(--weight-medium); color: var(--text-secondary); text-transform: capitalize; }
.prism-tb-fld input[type="text"] { inline-size: 100%; padding: var(--space-2) var(--space-3); border: var(--border-width) solid var(--border-default); border-radius: var(--radius-control); background: var(--surface-page); color: var(--text-primary); font-family: var(--font-mono); font-size: var(--text-sm); }

.prism-tb-seg { display: inline-flex; flex-wrap: wrap; border: var(--border-width) solid var(--border-default); border-radius: var(--radius-control); overflow: hidden; background: var(--surface-page); }
.prism-tb-seg button {
  appearance: none; border: 0; background: transparent; color: var(--text-secondary);
  font-family: var(--font-mono); font-size: var(--text-xs); font-weight: var(--weight-semibold);
  padding: var(--space-1) var(--space-3); cursor: pointer; border-inline-start: var(--border-width) solid var(--border-subtle);
}
.prism-tb-seg button:first-child { border-inline-start: 0; }
.prism-tb-seg button[aria-pressed="true"] { background: var(--accent); color: var(--accent-on); }

/* ---- preview ---- */
.prism-tb-preview {
  display: flex; flex-direction: column; gap: var(--space-3);
  padding: var(--space-4);
  background: var(--surface-card); color: var(--text-primary);
  border: var(--border-width) solid var(--border-subtle);
  border-radius: var(--radius-card); box-shadow: var(--shadow-sm);
}
.prism-tb-preview-head { display: flex; align-items: center; justify-content: space-between; }
.prism-tb-preview-title { font-size: var(--fs-caption); color: var(--text-tertiary); font-weight: var(--weight-semibold); }
.prism-tb-themetoggle {
  font-family: var(--font-mono); font-size: var(--text-xs); font-weight: var(--weight-semibold);
  padding: var(--space-1) var(--space-3); border-radius: var(--radius-pill);
  background: var(--fill-subtle); color: var(--text-secondary);
  border: var(--border-width) solid var(--border-subtle); cursor: pointer;
}
.prism-tb-themetoggle:hover { color: var(--text-primary); }
.prism-tb-themetoggle:focus-visible { outline: var(--focus-ring-width) solid var(--focus-ring); outline-offset: 2px; }
/* the stage carries the live brand tokens; real Prism components inside inherit them */
.prism-tb-stage {
  display: flex; flex-direction: column; gap: var(--space-4);
  padding: var(--space-4);
  background: var(--surface-card); color: var(--text-primary);
  border: var(--border-width) solid var(--border-default);
  border-radius: var(--radius-card);
}
.prism-tb-swatches { display: flex; gap: var(--space-0-5); }
.prism-tb-chip { flex: 1 1 0; block-size: 24px; border-radius: var(--radius-sm); }
.prism-tb-chip:first-child { border-start-start-radius: var(--radius-control); border-end-start-radius: var(--radius-control); }
.prism-tb-chip:last-child { border-start-end-radius: var(--radius-control); border-end-end-radius: var(--radius-control); }
.prism-tb-demo { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3); }
.prism-tb-link { color: var(--text-link); font-weight: var(--weight-medium); text-decoration: underline; text-underline-offset: 2px; cursor: pointer; }

/* ---- export ---- */
.prism-tb-export { grid-column: 1 / -1; display: flex; flex-direction: column; gap: var(--space-2); }
.prism-tb-export-head { display: flex; align-items: center; gap: var(--space-3); flex-wrap: wrap; }
.prism-tb-export-title { font-size: var(--text-sm); font-weight: var(--weight-semibold); color: var(--text-primary); margin-inline-end: auto; }
.prism-tb-code {
  margin: 0; padding: var(--space-4); overflow: auto; max-block-size: 340px;
  background: var(--surface-sunken); color: var(--text-primary);
  border: var(--border-width) solid var(--border-subtle); border-radius: var(--radius-card);
  font-family: var(--font-mono); font-size: var(--text-xs); line-height: 1.6;
}

/* ===== components/themes/industry.css ===== */
/* ============================================================
   Prism · INSTRUMENT structural layer — shared by INDUSTRY + LABORATORY
   ------------------------------------------------------------
   Every rule here is keyed to :is([data-theme="industry"],
   [data-theme="laboratory"]) and reads the recipes in the shared
   instrument block of tokens/theme-industry.css, which in turn read each
   face's tactile kit (--t-*). Switching data-theme re-skins identical
   markup with no gaps; components/themes/laboratory.css holds only the
   few rules that are structurally different on the light face.

   The brief (docs/MATERIAL_SPEC.md): real surfaces under one soft light;
   depth spent on what a hand touches; emission as a filament; travel
   shown by motion. Four material tiers:

     T1 BODY     cards, toolbars, panels, tables — quiet: a hairline seam,
                 a soft top light, one ambient shadow. Bodies are the
                 ground the keys stand on.
     T2 KEY      buttons, keypad keys, steppers, caps, thumbs, the knob —
                 matte face, soft edge light, a two-step side wall, contact
                 occlusion, a soft cast; pressing travels the key 1.5px and
                 collapses the wall.
     WELL        anything a value travels in or a glyph is typed into —
                 inner occlusion with a lit lower lip; deeper for slots.
     LED         a domed core, a 1px collar, a 4–6px soft edge. Tabs and
                 nav carry a filament bar. Nothing blooms.

   Imported last so it layers over the component defaults.
   ============================================================ */

/* ---------- Canvas · flat bench ---------- */
:is([data-theme="industry"], [data-theme="laboratory"]) { background-image: none; }

/* ---------- T1 · bodies ---------- */
:is([data-theme="industry"], [data-theme="laboratory"]) :is(
  .prism-card, .prism-toolbar, .prism-listbox, .prism-empty-well,
  .prism-sidenav, .prism-sidenav-shell, .prism-sidebar, .prism-page-hero, .prism-grain,
  .prism-datagrid, .prism-accordion, .prism-consent, .prism-reviewbar, .prism-readonly,
  .prism-widget, .prism-kpi, .prism-appheader
) {
  background-color: var(--surface-card);
  background-image: var(--t-body-face);
  border: 0;
  box-shadow: var(--t-body-shadow);
}
/* Card states the body rule above would erase (it zeroes the border and owns
   the shadow): the tone edge, the selected ring, and the reduced-motion
   "just arrived" ring. */
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-card[data-tone] { border-inline-start: 4px solid var(--card-tone); }
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-card[data-hue]:not(.pc-tile) { border-block-start: 4px solid var(--hue); }
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-kpi[data-tone] { border-inline-start: 3px solid var(--kpi-tone); }
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-card[data-selected="true"] { box-shadow: 0 0 0 2px var(--accent), var(--t-body-shadow); }
/* an inset card is a recess in its parent body, not another raised body */
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-card[data-variant="inset"] {
  background-color: var(--t-well-fill); background-image: var(--t-well-face-soft); box-shadow: var(--t-well-soft);
}
@media (prefers-reduced-motion: reduce) {
  :is([data-theme="industry"], [data-theme="laboratory"]) .prism-card[data-highlighted="true"] { box-shadow: 0 0 0 2px var(--accent-border), var(--t-body-shadow); }
}
/* Alerts keep the tone tint their own sheet sets; they are flat plates. */
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-alert {
  background-image: none;
  box-shadow: 0 0 0 1px var(--t-seam), 0 1px 2px -1px var(--t-ao);
}
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-accordion-trigger { background-image: none; box-shadow: none; }

/* The default header, its drawer, and the inverse-tone footer are built on
   the inverse token pair. Industry sets that pair LIGHT (for light callouts
   and tooltips), so those dark bars turned into light bars with hardcoded
   white ink. Re-pin the pair for JUST these three components. */
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-appheader,
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-sidenav,
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-footer[data-tone="inverse"] {
  --surface-inverse: var(--surface-raised);
  --text-on-inverse: var(--text-primary);
  --border-inverse: var(--border-strong);
}

/* ---------- T2 · keys ---------- */
:is([data-theme="industry"], [data-theme="laboratory"]) :is(
  .prism-btn:not([data-variant="quiet"], [data-variant="prompt"]), .prism-icon-btn:not([data-variant="quiet"], [data-variant="negative-quiet"]), .prism-fab,
  .prism-consent-btn, .prism-session-btn, .prism-num-step,
  .prism-keypad-key, .prism-keypad-submit, .prism-ticker-step, .prism-ticker-ack, .prism-carousel-step
) {
  background-color: var(--t-key);
  background-image: var(--t-key-face);
  border: 0;
  box-shadow: var(--t-key-shadow);
  font-weight: 500;
}
/* Filled keys keep their colour; the face light and the wall follow it.
   The local --t-fill is what the shadows below read. */
:is([data-theme="industry"], [data-theme="laboratory"]) :is(
  .prism-btn[data-variant="accent"], .prism-fab, .prism-icon-btn[data-variant="accent"], .prism-keypad-submit,
  .prism-consent-btn.is-accent, .prism-session-btn.is-accent
) { --t-fill: var(--accent); color: var(--accent-on); }
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-btn[data-variant="positive"] { --t-fill: var(--positive); }
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-btn[data-variant="notice"]   { --t-fill: var(--notice); }
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-btn[data-variant="negative"] { --t-fill: var(--negative); }
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-icon-btn[data-variant="negative"] { --t-fill: var(--negative); color: var(--negative-on); }
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-icon-btn[data-variant="negative-quiet"] { color: var(--negative-text); }
:is([data-theme="industry"], [data-theme="laboratory"]) :is(
  .prism-btn[data-variant="accent"], .prism-fab, .prism-icon-btn[data-variant="accent"], .prism-keypad-submit,
  .prism-consent-btn.is-accent, .prism-session-btn.is-accent,
  .prism-btn[data-variant="positive"], .prism-btn[data-variant="notice"], .prism-btn[data-variant="negative"],
  .prism-icon-btn[data-variant="negative"]
) {
  background-color: var(--t-fill);
  /* a LINEAR top light, so a full-width key never shows a band */
  background-image: linear-gradient(180deg, oklch(1 0 0 / 0.16), oklch(1 0 0 / 0.04) 45%, transparent 60%, oklch(0 0 0 / 0.08));
  box-shadow: inset 0 1.5px 1.5px oklch(1 0 0 / 0.32), inset 0 -1.5px 2px oklch(0 0 0 / 0.14),
    0 1px 0 color-mix(in oklch, var(--t-fill) 78%, black), 0 2px 0 color-mix(in oklch, var(--t-fill) 62%, black),
    0 3px 2px -1px var(--t-ao), 0 10px 18px -10px color-mix(in oklch, var(--t-fill) 45%, transparent);
}
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-btn[data-variant="outline"] {
  background-color: transparent; background-image: none; box-shadow: none;
  border: var(--border-width) solid var(--border-strong); color: var(--text-primary);
}
/* a prompt opener is a field, not a key: a shallow pressing, sentence-case */
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-btn[data-variant="prompt"] {
  background-color: var(--t-well-fill); background-image: var(--t-well-face-soft);
  border: 0; box-shadow: var(--t-well-soft); font-weight: var(--weight-regular);
  text-transform: none; letter-spacing: normal;
}
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-btn[data-variant="negative-outline"] {
  background-color: transparent; background-image: none; box-shadow: none;
  border: var(--border-width) solid var(--negative-border); color: var(--negative-text);
}
/* hover: the key catches a little more light. press: it travels. */
:is([data-theme="industry"], [data-theme="laboratory"]) :is(
  .prism-btn:not([data-variant="quiet"], [data-variant="outline"], [data-variant="negative-outline"], [data-variant="prompt"]), .prism-icon-btn:not([data-variant="quiet"], [data-variant="negative-quiet"]),
  .prism-fab, .prism-keypad-key, .prism-keypad-submit, .prism-num-step
):hover:not([disabled]):not(:disabled) { filter: brightness(var(--t-hover)); }
:is([data-theme="industry"], [data-theme="laboratory"]) :is(
  .prism-btn:not([data-variant="quiet"], [data-variant="outline"], [data-variant="negative-outline"], [data-variant="prompt"]), .prism-icon-btn:not([data-variant="quiet"], [data-variant="negative-quiet"]),
  .prism-fab, .prism-keypad-key, .prism-keypad-submit, .prism-num-step,
  .prism-consent-btn, .prism-session-btn, .prism-ticker-step, .prism-ticker-ack, .prism-carousel-step
):active:not([disabled]):not(:disabled) {
  transform: translateY(1.5px);
  filter: brightness(0.97);
  box-shadow: var(--t-key-shadow-down);
}
/* the keypad sits in a recessed tray, like a calculator face */
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-keypad {
  padding: 10px; border-radius: var(--radius-card);
  background-color: var(--t-well-fill); background-image: var(--t-well-face);
  box-shadow: var(--t-well);
}

/* ---------- WELLS · fields, tracks, code cells ---------- */
:is([data-theme="industry"], [data-theme="laboratory"]) :is(
  .prism-segmented, .prism-switch-track, .prism-checkbox-box, .prism-radio-dot, .prism-well,
  .prism-slider-track, .prism-progress-track, .prism-meter-track, .prism-fader-track, .prism-range-track,
  .prism-bullet-track, .prism-funnel-track, .prism-rank-track, .prism-step-marker, .prism-pipeline-node
) {
  background-color: var(--t-well-fill); background-image: var(--t-well-face);
  border: 0; box-shadow: var(--t-well);
}
/* a text field is a shallow pressing, not a slot */
:is([data-theme="industry"], [data-theme="laboratory"]) :is(
  .prism-input, .prism-combobox-multi, .prism-dropzone, .prism-masked-row, .prism-dg-input
) {
  background-color: var(--t-well-fill); background-image: var(--t-well-face-soft);
  border: 0; box-shadow: var(--t-well-soft);
}
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-input:is(:focus, :focus-visible) { box-shadow: var(--t-well-soft), var(--t-ring); }
/* code cells are display windows: deeper, and the typed glyph is the feedback */
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-otp-box {
  background-color: var(--t-well-fill); background-image: var(--t-well-face);
  border: 0; box-shadow: var(--t-well-deep); font-weight: 500; color: var(--text-primary);
}
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-otp-box:is(:focus, :focus-visible) { outline: 0; box-shadow: var(--t-well-deep), var(--t-ring); }
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-otp-box[data-filled="true"] { color: var(--text-primary); text-shadow: none; }
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-otp[data-invalid] .prism-otp-box { box-shadow: var(--t-well-deep), 0 0 0 1px var(--negative); }
/* slots the caps ride in are a touch deeper */
:is([data-theme="industry"], [data-theme="laboratory"]) :is(.prism-fader-track, .prism-slider-track, .prism-range-track) { box-shadow: var(--t-well-deep); }
/* fills are matte solids with a soft inner top light */
:is([data-theme="industry"], [data-theme="laboratory"]) :is(.prism-slider-fill, .prism-progress-fill, .prism-meter-fill, .prism-fader-fill, .prism-range-fill) {
  background-image: none; background-color: var(--accent);
  box-shadow: inset 0 1px 0 oklch(1 0 0 / 0.30), inset 0 -1px 0 oklch(0 0 0 / 0.12);
}
:is([data-theme="industry"], [data-theme="laboratory"]) :is(.prism-slider-fill, .prism-range-fill)::before { background-image: none; }
[dir="rtl"] :is([data-theme="industry"], [data-theme="laboratory"]) :is(.prism-slider-fill, .prism-progress-fill) { background-position: right center; }

/* ---------- small keys · caps, thumbs, the switch knob ----------
   Every thumb wears an accent collar and every cap an accent index, so the
   live control is findable at a glance. */
:is([data-theme="industry"], [data-theme="laboratory"]) :is(.prism-fader-cap, .prism-range-thumb, .prism-slider-thumb, .prism-switch-thumb) {
  background-color: var(--t-key); background-image: var(--t-key-face);
  border: 0; box-shadow: var(--t-key-shadow-sm);
}
:is([data-theme="industry"], [data-theme="laboratory"]) :is(.prism-slider-thumb, .prism-range-thumb) {
  width: 22px; height: 22px;
  box-shadow: inset 0 0 0 2.5px var(--accent), var(--t-key-shadow-sm);
}
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-slider-thumb:hover,
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-slider-track:active .prism-slider-thumb { border-color: transparent; }
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-slider-thumb:active {
  box-shadow: inset 0 0 0 2.5px var(--accent), var(--t-edge), 0 0.5px 0 var(--t-wall), 0 1px 1px -0.5px var(--t-ao), 0 0 0 4px color-mix(in oklch, var(--accent) 16%, transparent);
}
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-fader-cap { inline-size: 32px; block-size: 22px; border-radius: 6px; }
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-fader-cap::after { background: var(--accent); opacity: 1; block-size: 2px; border-radius: 1px; }
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-fader[data-disabled] .prism-fader-cap::after { background: var(--text-tertiary); opacity: .5; }
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-slider-value { color: var(--text-primary); }
:is([data-theme="industry"], [data-theme="laboratory"]) :is(.prism-slider-tick, .prism-fader-tick)[data-on="true"] { background: var(--accent); box-shadow: none; }

/* switch: the track is a lit channel when on, the thumb a small key */
:is([data-theme="industry"], [data-theme="laboratory"]) :is(.prism-switch[data-checked="true"], .prism-switch:where(:has(> input:checked))) .prism-switch-track {
  background-color: var(--accent); background-image: linear-gradient(180deg, oklch(0 0 0 / 0.14), transparent 50%);
  box-shadow: inset 0 2px 3px oklch(0 0 0 / 0.20), 0 1px 0 var(--t-hi-soft), 0 0 0 1px color-mix(in oklch, var(--accent) 18%, transparent);
}
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-switch-thumb { background-color: oklch(0.985 0.002 95); color: var(--text-tertiary); }

/* segmented: the selected segment is a key seated in the well, with a
   filament and accent ink so the selection is findable */
:is([data-theme="industry"], [data-theme="laboratory"]) :is(.prism-segmented-btn[data-selected="true"], .prism-segmented-btn[aria-pressed="true"]) {
  position: relative; color: var(--accent-text);
  background-color: var(--t-key); background-image: var(--t-key-face);
  box-shadow: var(--t-key-shadow-sm);
}
:is([data-theme="industry"], [data-theme="laboratory"]) :is(.prism-segmented-btn[data-selected="true"], .prism-segmented-btn[aria-pressed="true"])::after {
  content: ""; position: absolute; inset-inline: 26%; inset-block-start: 2px; block-size: 2px; border-radius: 2px;
  background: var(--accent); box-shadow: 0 0 4px color-mix(in oklch, var(--accent) 50%, transparent);
}

/* selectedVariant="accent": the seated key is lit — an accent fill (a shade
   deeper, so white ink still clears 4.5:1 under the highlight), a soft top
   highlight like a checked checkbox, and an on-ink filament */
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-segmented[data-selected-variant="accent"] .prism-segmented-btn[aria-pressed="true"] {
  color: var(--accent-on); background-color: color-mix(in oklab, var(--accent) 86%, black);
  background-image: radial-gradient(130% 100% at 50% -10%, oklch(1 0 0 / 0.16), transparent 62%);
}
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-segmented[data-selected-variant="accent"] .prism-segmented-btn[aria-pressed="true"]::after {
  background: var(--accent-on); box-shadow: none; opacity: 0.7;
}

/* checkbox / radio: a small well that becomes a lit key */
:is([data-theme="industry"], [data-theme="laboratory"]) :is(:is(.prism-checkbox[data-checked="true"], .prism-checkbox:where(:has(> input:checked))), .prism-checkbox[data-indeterminate="true"]) .prism-checkbox-box,
:is([data-theme="industry"], [data-theme="laboratory"]) :is(.prism-radio[data-checked="true"], .prism-radio:where(:has(> input:checked))) .prism-radio-dot {
  background-color: var(--accent);
  background-image: radial-gradient(130% 100% at 50% -10%, oklch(1 0 0 / 0.30), transparent 62%);
  border-color: transparent;
  box-shadow: inset 0 1px 1px oklch(1 0 0 / 0.35), inset 0 -1px 1px oklch(0 0 0 / 0.16), 0 1px 0 color-mix(in oklch, var(--accent) 70%, black), 0 2px 3px -1px var(--t-ao);
}
:is([data-theme="industry"], [data-theme="laboratory"]) :is(.prism-checkbox[data-checked="true"], .prism-checkbox:where(:has(> input:checked))) .prism-checkbox-box > svg { filter: none; }
:is([data-theme="industry"], [data-theme="laboratory"]) :is(.prism-radio[data-checked="true"], .prism-radio:where(:has(> input:checked))) .prism-radio-dot::after { background: var(--accent-on); box-shadow: none; }

/* ---------- THE KNOB · the reference part ---------- */
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-dial-knob {
  background-color: var(--t-key);
  background-image: radial-gradient(120% 100% at 50% -6%, var(--t-hi-soft), transparent 60%), linear-gradient(180deg, transparent 50%, var(--t-lo));
  border: 0;
  box-shadow: inset 0 2px 2px var(--t-hi), inset 0 -2px 3px var(--t-lo),
    0 2px 0 var(--t-wall), 0 4px 0 var(--t-wall-2),
    0 6px 4px -2px var(--t-ao), 0 18px 28px -12px var(--t-cast);
}
/* knurled rim: a fine repeating shade around the outer band */
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-dial-knob::before {
  content: ""; position: absolute; inset: 0; border-radius: 50%; pointer-events: none;
  background: repeating-conic-gradient(from 0deg, var(--t-lo) 0deg 2.5deg, transparent 2.5deg 6deg);
  -webkit-mask: radial-gradient(farthest-side, transparent 80%, #000 82%, #000 96%, transparent 100%);
  mask: radial-gradient(farthest-side, transparent 80%, #000 82%, #000 96%, transparent 100%);
  opacity: .9;
}
/* recessed face: a shallow dish */
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-dial-face {
  background-color: var(--surface-card);
  background-image: radial-gradient(100% 100% at 50% 110%, var(--t-hi-soft), transparent 55%);
  box-shadow: inset 0 2px 3px var(--t-ao), inset 0 1px 0 var(--t-lo), inset 0 -1px 0 var(--t-hi-soft);
}
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-dial-pointer {
  background: var(--accent);
  box-shadow: 0 0 0 1px color-mix(in oklch, var(--accent) 18%, transparent), 0 0 4px color-mix(in oklch, var(--accent) 45%, transparent);
}
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-dial-arc-track { stroke: var(--t-well-fill); }
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-dial-arc-fill { filter: none; }
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-dial-readout { font-weight: 500; }

/* ---------- LEDs · dome + filament ---------- */
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-led {
  inline-size: 8px; block-size: 8px; border-radius: 50%; flex: none; display: inline-block; position: relative;
  background: var(--led); box-shadow: var(--led-glow);
}
:is([data-theme="industry"], [data-theme="laboratory"]) :is(.prism-badge-dot, .prism-ticker-dot, .prism-autosave-dot) { position: relative; }
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-badge-dot { background: var(--led); box-shadow: var(--led-glow); }
:is([data-theme="industry"], [data-theme="laboratory"]) :is(.prism-led, .prism-badge-dot)::before {
  content: ""; position: absolute; inset: 0; border-radius: inherit; pointer-events: none;
  background: radial-gradient(circle at 35% 28%, oklch(1 0 0 / 0.75), oklch(1 0 0 / 0) 42%);
}
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-led[data-tone="positive"] { background: var(--led-positive); box-shadow: inset 0 -1px 1px oklch(0 0 0 / 0.18), var(--led-glow-positive); }
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-led[data-tone="notice"]   { background: var(--led-notice);   box-shadow: inset 0 -1px 1px oklch(0 0 0 / 0.18), var(--led-glow-notice); }
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-led[data-tone="negative"] { background: var(--led-negative); box-shadow: inset 0 -1px 1px oklch(0 0 0 / 0.18), var(--led-glow-negative); }
:is([data-theme="industry"], [data-theme="laboratory"]) [data-tone="positive"] .prism-badge-dot { background: var(--led-positive); box-shadow: var(--led-glow-positive); }
:is([data-theme="industry"], [data-theme="laboratory"]) [data-tone="notice"] .prism-badge-dot   { background: var(--led-notice);   box-shadow: var(--led-glow-notice); }
:is([data-theme="industry"], [data-theme="laboratory"]) [data-tone="negative"] .prism-badge-dot { background: var(--led-negative); box-shadow: var(--led-glow-negative); }
/* print: LED glow (blurred shadows) rasterises to a hard square in PDFs —
   on paper the LED is a plain round dot */
@media print {
  :is([data-theme="industry"], [data-theme="laboratory"]) :is(.prism-led, .prism-badge-dot, .prism-ticker-dot, .prism-autosave-dot) { box-shadow: none !important; filter: none !important; }
  :is([data-theme="industry"], [data-theme="laboratory"]) :is(.prism-led, .prism-badge-dot)::before { display: none; }
}
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-led[data-state="off"] { background: var(--led-dim); box-shadow: inset 0 1px 1px var(--t-ao); }
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-led[data-state="off"]::before { opacity: .35; }
/* status dots that carry their own state colour take the matching edge */
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-ticker-dot { box-shadow: var(--led-glow-notice); }
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-ticker[data-intent="positive"] .prism-ticker-dot { box-shadow: var(--led-glow-positive); }
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-ticker[data-intent="negative"] .prism-ticker-dot { box-shadow: var(--led-glow-negative); }
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-ticker[data-intent="info"] .prism-ticker-dot     { box-shadow: var(--led-glow-soft); }
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-autosave-dot { box-shadow: var(--led-glow-soft); }
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-autosave[data-state="saved"] .prism-autosave-dot { box-shadow: var(--led-glow-positive); }
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-autosave[data-state="error"] .prism-autosave-dot { box-shadow: var(--led-glow-negative); }
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-autosave[data-state="saving"] .prism-autosave-dot,
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-autosave[data-state="unsaved"] .prism-autosave-dot { box-shadow: var(--led-glow-notice); }
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-appheader-action .prism-appheader-dot { box-shadow: 0 0 0 2px var(--surface-inverse), var(--led-glow-negative); }
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-appheader[data-appearance] .prism-appheader-action .prism-appheader-dot { box-shadow: 0 0 0 2px var(--surface-card), var(--led-glow-negative); }
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-navbtn-badge[data-dot="true"] { box-shadow: 0 0 0 2px var(--surface-card), var(--led-glow-negative); }
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-lit { color: var(--accent-text); text-shadow: none; }
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-led-bar { block-size: 2px; border-radius: 2px; background: var(--accent); box-shadow: 0 0 4px color-mix(in oklch, var(--accent) 45%, transparent); }

/* filament bars: selected tab, current nav item, selected record tab */
:is([data-theme="industry"], [data-theme="laboratory"]) :is(.prism-tab[aria-selected="true"], .prism-record-tab[aria-selected="true"]) { color: var(--text-primary); }
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-record-tab { position: relative; }
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-record-tab[aria-selected="true"]::after {
  content: ""; position: absolute; inset-inline: var(--space-3); inset-block-end: 0; block-size: 2px;
}
:is([data-theme="industry"], [data-theme="laboratory"]) :is(.prism-tab[aria-selected="true"], .prism-record-tab[aria-selected="true"])::after {
  background: var(--accent); box-shadow: 0 0 4px color-mix(in oklch, var(--accent) 45%, transparent);
}
:is([data-theme="industry"], [data-theme="laboratory"]) :is(.prism-sidenav-link, .prism-sidenav-item)[aria-current="page"] { position: relative; color: var(--text-primary); }
:is([data-theme="industry"], [data-theme="laboratory"]) :is(.prism-sidenav-link, .prism-sidenav-item)[aria-current="page"]::before {
  content: ""; position: absolute; inset-inline-start: 0; inset-block: 22%; inline-size: 2px; border-radius: 2px;
  background: var(--accent); box-shadow: 0 0 4px color-mix(in oklch, var(--accent) 45%, transparent);
}

/* ---------- pills · quiet, a whisper of edge ---------- */
:is([data-theme="industry"], [data-theme="laboratory"]) :is(
  .prism-badge, .prism-tag, .prism-avatar, .prism-sidenav-badge, .prism-senstag, .prism-rolebadge, .prism-dg-chip
) { background-image: none; box-shadow: inset 0 1px 0 var(--t-hi-soft), 0 0 0 1px var(--t-seam); border-color: transparent; }
/* the pill rule above owns the avatar's shadow; a status ring must survive it */
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-avatar[data-ring] {
  box-shadow: inset 0 1px 0 var(--t-hi-soft), 0 0 0 2px var(--avatar-ring-gap, var(--surface-card)), 0 0 0 4px var(--avatar-ring, var(--accent));
}

/* ---------- steppers and workflow nodes · recessed until reached, then a lit key ---------- */
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-step[data-state="current"] .prism-step-marker,
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-pipeline-step[data-status="current"] .prism-pipeline-node { box-shadow: var(--t-well), var(--t-ring); }
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-step[data-state="complete"] .prism-step-marker,
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-pipeline-step[data-status="done"] .prism-pipeline-node {
  background-color: var(--accent); color: var(--accent-on); border-color: transparent;
  background-image: radial-gradient(130% 100% at 50% -10%, oklch(1 0 0 / 0.30), transparent 62%);
  box-shadow: inset 0 1px 1px oklch(1 0 0 / 0.35), 0 1px 0 color-mix(in oklch, var(--accent) 70%, black), 0 2px 3px -1px var(--t-ao);
}
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-step[data-state="error"] .prism-step-marker { box-shadow: var(--t-well), 0 0 0 1px var(--negative), 0 0 0 4px color-mix(in oklch, var(--negative) 16%, transparent); }
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-pipeline-step[data-status="rejected"] .prism-pipeline-node { box-shadow: var(--t-well), 0 0 0 1px var(--negative), 0 0 0 4px color-mix(in oklch, var(--negative) 16%, transparent); }
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-step-line { background: var(--series-track); }
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-step-line[data-reached="true"] { background: var(--accent); box-shadow: none; }
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-approvals-step[data-status="approved"] .prism-approvals-node { box-shadow: var(--led-glow-positive); }
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-approvals-step[data-status="current"] .prism-approvals-node { box-shadow: var(--t-ring); }
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-approvals-step[data-status="rejected"] .prism-approvals-node { box-shadow: var(--led-glow-negative); }

/* ---------- glass overlays · blur stays, chrome goes ----------
   Elevation ladder: popover (menus) < transient (toast) < modal (dialog). */
:is([data-theme="industry"], [data-theme="laboratory"]) :is(.prism-modal-scrim, .prism-session-scrim, .prism-sidenav-scrim, .prism-cmd-scrim) {
  backdrop-filter: blur(var(--scrim-blur)) saturate(0.96);
  -webkit-backdrop-filter: blur(var(--scrim-blur)) saturate(0.96);
}
:is([data-theme="industry"], [data-theme="laboratory"]) :is(.prism-dialog, .prism-menu, .prism-toast, .prism-glass,
  .prism-session, .prism-dg-pop, .prism-dg-bulk, .prism-cmd, .prism-kanban-menu) {
  background-color: var(--surface-glass);
  background-image: none;
  backdrop-filter: blur(var(--glass-blur)) saturate(1.06);
  -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(1.06);
  border: 0;
  box-shadow: inset 0 1px 0 var(--t-hi-soft), 0 0 0 1px var(--t-seam), var(--shadow-md);
}
:is([data-theme="industry"], [data-theme="laboratory"]) :is(.prism-toast, .prism-glass) { box-shadow: inset 0 1px 0 var(--t-hi-soft), 0 0 0 1px var(--t-seam), var(--shadow-lg); }
:is([data-theme="industry"], [data-theme="laboratory"]) :is(.prism-dialog, .prism-session) { box-shadow: inset 0 1px 0 var(--t-hi-soft), 0 0 0 1px var(--t-seam), var(--shadow-xl); }

/* ---------- business & control layer · state through material ---------- */
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-kanban-col[data-over] { box-shadow: var(--t-well), var(--t-ring); border-color: transparent; }
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-kanban-head[data-state="over"] { border-color: var(--led-negative); }
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-kanban-warn { box-shadow: var(--t-well), 0 0 0 1px var(--negative); }
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-num-step { color: var(--text-secondary); }
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-num-step:hover:not(:disabled) { color: var(--text-primary); }
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-ruler-flag-pill {
  background: var(--accent); color: var(--accent-on);
  box-shadow: inset 0 1px 1px oklch(1 0 0 / 0.35), 0 1px 0 color-mix(in oklch, var(--accent) 70%, black), 0 2px 3px -1px var(--t-ao);
}
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-ruler-flag-stem { background: var(--accent); box-shadow: none; }
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-accent-fill {
  background-color: var(--accent); background-image: radial-gradient(130% 100% at 50% -10%, oklch(1 0 0 / 0.26), transparent 62%);
  box-shadow: inset 0 1.5px 1.5px oklch(1 0 0 / 0.35), 0 1px 0 color-mix(in oklch, var(--accent) 70%, black), 0 2px 3px -1px var(--t-ao);
}
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-bevel { box-shadow: var(--t-key-shadow); }

/* ---------- charts · matte solids with thickness ---------- */
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-columns-bar {
  background-color: var(--c, var(--accent));
  background-image: radial-gradient(120% 60% at 50% 0%, oklch(1 0 0 / 0.12), transparent 70%);
  border-radius: 6px 6px 3px 3px;
  box-shadow: inset 0 -3px 0 color-mix(in oklch, var(--c, var(--accent)) 74%, black), inset 0 1px 0 oklch(1 0 0 / 0.25), 0 2px 4px -1px var(--t-ao);
}
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-columns-bar::after { display: none; }
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-columns-bar[data-muted="true"] {
  background-image: none; background-color: var(--series-muted);
  box-shadow: inset 0 -3px 0 var(--series-muted-deep), inset 0 1px 0 var(--t-hi-soft), 0 2px 4px -1px var(--t-ao);
}
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-rank-fill {
  background-image: none; background-color: var(--c, var(--accent)); border-radius: 4px;
  box-shadow: inset 0 -2px 0 color-mix(in oklch, var(--c, var(--accent)) 74%, black), inset 0 1px 0 oklch(1 0 0 / 0.28);
}
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-rank-fill::after { display: none; }
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-rank-fill[data-muted="true"] { background-color: var(--series-muted); box-shadow: inset 0 -2px 0 var(--series-muted-deep); }
:is([data-theme="industry"], [data-theme="laboratory"]) :is(.prism-ring-spec, .prism-ring-gloss, .prism-ring-bloom) { display: none; }
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-ring-wall { transform: translateY(var(--extrude-depth)); filter: brightness(0.72) saturate(0.9); opacity: 1; }
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-ring-face { filter: drop-shadow(0 2px 3px var(--t-ao)); }
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-ring-value { font-weight: 600; letter-spacing: -0.03em; }
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-wave-bar {
  background-image: none; background-color: var(--accent);
  box-shadow: inset 0 1px 0 oklch(1 0 0 / 0.28), inset 0 -1px 0 oklch(0 0 0 / 0.14);
}
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-wave[data-peak="true"] .prism-wave-bar { box-shadow: inset 0 1px 0 oklch(1 0 0 / 0.28), 0 0 4px color-mix(in oklch, var(--accent) 40%, transparent); }
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-trend-line { stroke-width: 2.5; }
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-trend[data-variant="spark"] .prism-trend-line { stroke-width: 1.75; }
/* furniture recedes, data advances */
:is([data-theme="industry"], [data-theme="laboratory"]) :is(.prism-chart-grid, .prism-chart-axis) { stroke: var(--border-subtle); }
:is([data-theme="industry"], [data-theme="laboratory"]) :is(
  .prism-bullet-axis, .prism-combo-axis-label, .prism-legend-axis, .prism-co-avg-label, .prism-chart-axis-title
) { font-variant-numeric: tabular-nums; }

/* ---------- type · legends read the tokens; numerals are tabular ---------- */
:is([data-theme="industry"], [data-theme="laboratory"]) :is(
  .prism-btn, .prism-tab, .prism-segmented-btn, .prism-badge, .prism-hero-eyebrow, .prism-sidenav-grouplabel
) { text-transform: var(--legend-transform); letter-spacing: var(--legend-tracking); }
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-table th { letter-spacing: var(--legend-tracking); }
:is([data-theme="industry"], [data-theme="laboratory"]) :is(h1, h2, h3, h4, h5, h6,
  .prism-heading, .prism-hero-title, .prism-dialog-title, .prism-section-title, .prism-page-title, .prism-sidebar-title) {
  text-transform: var(--heading-transform); letter-spacing: var(--heading-tracking); font-weight: 600;
}
/* readouts carry the instrument feel through weight and tabular figures */
:is([data-theme="industry"], [data-theme="laboratory"]) :is(.prism-kpi-value, .prism-dialgauge-value, .prism-gauge-value) { font-weight: 500; letter-spacing: -0.035em; }
:is([data-theme="industry"], [data-theme="laboratory"]) :is(
  .prism-kpi-value, .prism-kpi-target, .prism-kpi-delta, .prism-kpi-comparison,
  .prism-delta, .prism-delta-val, .prism-delta-chg,
  .prism-chart-value, .prism-xchart-value, .prism-bullet-value, .prism-funnel-value,
  .prism-donut-value, .prism-ring-value, .prism-gauge-value, .prism-gauge-readout,
  .prism-dial-readout, .prism-dialgauge-value, .prism-dialgauge-readout,
  .prism-slider-value, .prism-range-value, .prism-fader-readout,
  .prism-dg-count, .prism-dg-bulk-count, .prism-dg-group-count,
  .prism-kanban-count, .prism-kanban-total, .prism-kanban-card-value,
  .prism-ticker-count, .prism-record-tabcount, .prism-multistep-stepcount,
  .prism-session-count, .prism-masked-value,
  .prism-lineitems-amount, .prism-lineitems-totals,
  .prism-tm-value, .prism-wf-value, .prism-timerange, .prism-timerange-compare
) { font-variant-numeric: tabular-nums slashed-zero; }

/* ---------- technical line art ---------- */
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-lineart { color: var(--lineart-stroke); display: block; }
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-lineart svg {
  display: block; inline-size: 100%; block-size: auto; fill: none; stroke: currentColor;
  stroke-width: var(--lineart-width); stroke-linecap: round; stroke-linejoin: round; vector-effect: non-scaling-stroke;
}
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-lineart[data-weight="hairline"] svg { stroke-width: var(--lineart-width-hairline); }
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-lineart[data-weight="lg"] svg { stroke-width: var(--lineart-width-lg); }
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-lineart[data-weight="bold"] svg { stroke-width: var(--lineart-width-bold); }
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-lineart [data-quiet] { stroke: var(--lineart-stroke-quiet); }
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-lineart [data-callout] { stroke: var(--lineart-callout); }
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-lineart [data-fill] { fill: var(--surface-sunken); stroke: none; }

/* ---------- instrument motion ----------
   Keys travel and settle; indicators fade rather than snap; spinners turn
   at a steady pace. All of it collapses under prefers-reduced-motion. */
:is([data-theme="industry"], [data-theme="laboratory"]) :is(.prism-spinner, .prism-btn-spinner) { animation-duration: var(--spin-duration); animation-timing-function: linear; }
:is([data-theme="industry"], [data-theme="laboratory"]) .prism-progress[data-indeterminate="true"] .prism-progress-fill { animation-duration: calc(var(--spin-duration) * 1.3); }
@media (prefers-reduced-motion: no-preference) {
  :is([data-theme="industry"], [data-theme="laboratory"]) :is(
    .prism-btn, .prism-icon-btn, .prism-fab, .prism-keypad-key, .prism-keypad-submit, .prism-num-step,
    .prism-fader-cap, .prism-range-thumb, .prism-slider-thumb, .prism-dial-knob, .prism-segmented-btn,
    .prism-switch-track, .prism-switch-thumb, .prism-tab, .prism-accordion-trigger, .prism-input,
    .prism-checkbox-box, .prism-radio-dot, .prism-sidenav-link, .prism-sidenav-item, .prism-tag, .prism-badge,
    .prism-card[data-interactive="true"]
  ) {
    transition: transform 90ms cubic-bezier(0.2, 0, 0, 1), box-shadow 120ms cubic-bezier(0.2, 0, 0, 1),
                filter 120ms ease, background-color 140ms ease, color 140ms ease, border-color 140ms ease;
  }
  :is([data-theme="industry"], [data-theme="laboratory"]) :is(.prism-led, .prism-badge-dot, .prism-statusdot-led) {
    transition: box-shadow var(--duration-normal) var(--ease-out), background-color var(--duration-normal) var(--ease-out);
  }
  /* settle-on-click: the theme's transition list above would otherwise outrank
     the base settle rules at equal specificity, so re-state them here */
  :is([data-theme="industry"], [data-theme="laboratory"]) .prism-slider[data-settling="true"] .prism-slider-thumb {
    transition: inset-inline-start var(--duration-settle) var(--ease-settle), box-shadow var(--duration-fast) var(--ease-standard), transform var(--duration-instant) var(--ease-standard);
  }
  :is([data-theme="industry"], [data-theme="laboratory"]) .prism-range[data-settling="true"] .prism-range-thumb {
    transition: inset-inline-start var(--duration-settle) var(--ease-settle), box-shadow var(--duration-fast) var(--ease-standard);
  }
  :is([data-theme="industry"], [data-theme="laboratory"]) .prism-fader[data-settling="true"] .prism-fader-cap {
    transition: inset-block-end var(--duration-settle) var(--ease-settle), box-shadow var(--duration-fast) var(--ease-standard);
  }
  /* a newly selected segment SEATS itself: it arrives from a hair above and its
     filament lights over the same beat */
  :is([data-theme="industry"], [data-theme="laboratory"]) :is(.prism-segmented-btn[data-selected="true"], .prism-segmented-btn[aria-pressed="true"]) {
    animation: prism-key-seat var(--duration-normal) var(--ease-settle);
  }
  :is([data-theme="industry"], [data-theme="laboratory"]) :is(.prism-segmented-btn[data-selected="true"], .prism-segmented-btn[aria-pressed="true"])::after,
  :is([data-theme="industry"], [data-theme="laboratory"]) :is(.prism-sidenav-link, .prism-sidenav-item)[aria-current="page"]::before {
    animation: prism-filament-in var(--duration-normal) var(--ease-out);
  }
  @keyframes prism-key-seat { from { transform: translateY(-1.5px); box-shadow: var(--t-edge), 0 2px 0 var(--t-wall), 0 3px 0 var(--t-wall-2), 0 5px 4px -1px var(--t-ao), 0 12px 20px -10px var(--t-cast); } }
  @keyframes prism-filament-in { from { opacity: 0; transform: scaleX(0.35); } }
}

/* ===== components/themes/laboratory.css ===== */
/* ============================================================
   Prism · LABORATORY theme — light-face DELTAS only
   ------------------------------------------------------------
   Laboratory shares the ENTIRE structural layer in
   components/themes/industry.css (every rule there is keyed to both
   faces and reads the recipes in the shared instrument block of
   tokens/theme-industry.css). tokens/theme-laboratory.css supplies the
   light face's values, so the same markup re-skins with no gaps.

   This file holds only what is structurally different on light:
     1. the modal / menu backdrop is a LIGHT frosted veil that leans on
        blur to separate the overlay from a bright page
     2. the switch thumb on the light face is the same white key; it
        needs no border because the track is a darker well around it
   Anything not here is inherited from the shared layer.
   ============================================================ */

/* 1 · a light veil, not a dark scrim */
[data-theme="laboratory"] :is(.prism-modal-scrim, .prism-sidenav-scrim, .prism-cmd-scrim, .prism-session-scrim) {
  backdrop-filter: blur(var(--scrim-blur)) saturate(1.05);
  -webkit-backdrop-filter: blur(var(--scrim-blur)) saturate(1.05);
}

/* 2 · the thumb rides in a darker well; no collar needed */
[data-theme="laboratory"] .prism-switch-thumb { border: 0; }

/* Prism component styles — GENERATED by build-registry.mjs. Do not edit by hand.
   Every component sheet plus the instrument-theme refinements, in cascade order.
   Import once, after prism-globals.css. */

/* Revision of this file — changes whenever any of it does, so `shadcn add --overwrite` always updates it. */
:root { --prism-components-css-rev: "7e7d8ed5f4c1"; }
