/* =========================================================
   APP SHELL + SECTIONS
   ========================================================= */

.app{
  display:grid;
  grid-template-columns:var(--sidebar-w) 1fr;
  min-height:100vh;
  background:var(--grad-fog), var(--obsidian-950);
}

/* ─────────── SIDEBAR ─────────── */
.sidebar{
  position:sticky;top:0;
  height:100vh;
  border-right:var(--bw-1) solid var(--obsidian-700);
  background:var(--surface-bar);
  backdrop-filter:blur(var(--blur-bar));
  padding:var(--s-6) var(--s-5);
  display:flex;flex-direction:column;gap:var(--s-8);
  overflow-y:auto;
  z-index:var(--z-sticky);
}
.brand{
  display:flex;align-items:center;gap:var(--s-3);
  padding-bottom:var(--s-6);
  border-bottom:var(--bw-1) solid var(--obsidian-800);
}
.brand-mark{
  width:36px;height:36px;border-radius:var(--r-md);
  background:var(--obsidian-850);
  display:grid;place-items:center;
  border:var(--bw-1) solid var(--obsidian-700);
  overflow:hidden;
}
.brand-mark img{width:26px;height:26px;object-fit:contain;filter:drop-shadow(0 0 8px color-mix(in srgb, var(--secondary-500) calc(var(--tint-edge-deep) * 100%), transparent))}
.brand-text{display:flex;flex-direction:column;line-height:1.1}
.brand-text .name{font-weight:700;font-size:var(--t-body);letter-spacing:var(--tr-snug)}
.brand-text .meta{font-family:var(--font-mono);font-size:var(--t-micro);color:var(--obsidian-300);letter-spacing:var(--tr-mono);text-transform:uppercase;margin-top:var(--s-0-5)}

.nav-group{display:flex;flex-direction:column;gap:var(--s-1);position:relative}
.nav-indicator{
  position:absolute;
  left:calc(-1 * var(--s-5));
  top:0;
  width:var(--bw-2);
  height:var(--s-4);
  background:var(--primary-500);
  border-radius:var(--r-xs);
  box-shadow:0 0 var(--s-3) var(--primary-500);
  transform:translateY(0);
  transition:transform var(--d-quick) var(--ease-standard), opacity var(--d-quick) var(--ease-standard);
  opacity:0;
  pointer-events:none;
  z-index:2;
}
.nav-group.has-active .nav-indicator{opacity:1}
@media (prefers-reduced-motion: reduce){
  .nav-indicator{transition:none}
}
.nav-label{
  font-family:var(--font-mono);
  font-size:var(--t-micro);
  letter-spacing:var(--tr-mono);
  text-transform:uppercase;
  color:var(--obsidian-300);
  padding:0 var(--s-3);
  margin-bottom:var(--s-2);
  display:flex;align-items:center;gap:var(--s-2);
}
.nav-label::before{content:"";width:4px;height:4px;background:var(--primary-500);border-radius:1px}
.nav-item{outline-offset:var(--s-0-5);
  display:flex;align-items:center;gap:var(--s-3);
  padding:var(--s-2) var(--s-3);
  border-radius:var(--r-md);
  font-size:var(--t-small);
  color:var(--obsidian-200);
  cursor:pointer;
  transition:all var(--d-quick) var(--ease-standard);
  position:relative;
  user-select:none;
}
.nav-item .num{
  font-family:var(--font-mono);
  font-size:var(--t-micro);
  color:var(--obsidian-300);
  letter-spacing:var(--tr-mono);
  min-width:calc(var(--s-4) + var(--s-0-5));
}
/* the sidebar wears the Bar material: a fill would read as a block over the blur, so the item never fills */
.nav-item:hover{color:var(--obsidian-050)}
.nav-item:active{color:var(--obsidian-300)}
.nav-item.active{
  background:linear-gradient(180deg, color-mix(in srgb, var(--primary-500) calc(var(--tint-fill) * 100%), transparent), color-mix(in srgb, var(--secondary-500) calc(var(--tint-faint) * 100%), transparent));
  color:var(--obsidian-100);
  border:var(--bw-1) solid color-mix(in srgb, var(--primary-500) calc(var(--tint-glow) * 100%), transparent);
  padding:var(--s-2) var(--s-3);
}
.nav-item.active .num{color:var(--primary-400)}
.nav-item.active::after{display:none}

.sidebar-footer{
  margin-top:auto;
  padding-top:var(--s-5);
  border-top:var(--bw-1) solid var(--obsidian-800);
  font-family:var(--font-mono);
  font-size:var(--t-micro);
  letter-spacing:var(--tr-mono);
  color:var(--obsidian-300);
  text-transform:uppercase;
  display:flex;flex-direction:column;gap:var(--s-1);
}
.sidebar-footer .status{display:flex;align-items:center;gap:var(--s-1)}
.sidebar-footer .status .dot{width:6px;height:6px;border-radius:50%;background:var(--success);box-shadow:0 0 8px var(--success)}

/* ─────────── MAIN ─────────── */
.main{min-width:0;display:flex;flex-direction:column;--page-gutter:var(--s-10);--topbar-h:calc(var(--s-12) + var(--bw-1) * 2)}
/* --page-gutter: the content's inline padding, which a floating control keeps from the top bar too (v5.3.0);
   --topbar-h: the bar's height, so a sticky control can sit that gutter below it. */
.topbar{
  position:sticky;top:0;z-index:var(--z-sticky);
  display:flex;align-items:center;justify-content:space-between;
  min-height:var(--topbar-h);box-sizing:border-box;
  padding:var(--s-4) var(--page-gutter);
  border-bottom:var(--bw-1) solid var(--obsidian-800);
  background:var(--surface-bar);
  backdrop-filter:blur(var(--blur-bar));
}
.breadcrumb{display:flex;align-items:center;gap:var(--s-2);font-family:var(--font-mono);font-size:var(--t-caption);letter-spacing:var(--tr-mono);text-transform:uppercase;color:var(--obsidian-300)}
.breadcrumb .sep{color:var(--obsidian-500)}
.breadcrumb .active{color:var(--obsidian-100)}
.breadcrumb a{color:inherit;text-decoration:none;border-radius:var(--r-sm);transition:color var(--d-quick) var(--ease-standard)}
.breadcrumb a:hover{color:var(--obsidian-100)}
.breadcrumb a:active{color:var(--obsidian-400)}
.breadcrumb a:focus-visible{outline:var(--focus-width) solid var(--obsidian-100);outline-offset:var(--s-0-5);box-shadow:var(--ring-halo)}
.topbar-actions{display:flex;align-items:center;gap:var(--s-3);font-family:var(--font-mono);font-size:var(--t-micro);letter-spacing:var(--tr-mono);text-transform:uppercase;color:var(--obsidian-300)}
.topbar-actions .kbd{font-family:var(--font-mono);font-size:var(--t-micro);padding:var(--s-0-5) var(--s-1);border:var(--bw-1) solid var(--obsidian-700);border-radius:var(--r-sm);color:var(--obsidian-300);background:var(--obsidian-850)}

.content{
  padding:var(--s-12) var(--page-gutter) var(--s-24);
  max-width:var(--content-max);
  width:100%;
  margin-inline:auto;
}

/* section visibility; the entrance (v5.2.0): three blocks rise in reading order,
   one --d-quick apart: the page header, the usage block, then the rest of the page together */
.section{display:none}
.section.active{display:block}
.section.active > *{animation:rise-in var(--d-slow) var(--ease-soft) both;animation-delay:calc(var(--d-quick) * 3)}
.section.active > .page-header{animation-delay:var(--d-quick)}
.section.active > .usage{animation-delay:calc(var(--d-quick) * 2)}
/* no usage block: the rest comes one step after the header */
.section.active > .page-header + :not(.usage),.section.active > .page-header + :not(.usage) ~ *{animation-delay:calc(var(--d-quick) * 2)}
@media (prefers-reduced-motion: reduce){
  .section.active > *{animation:none}
}
@keyframes rise-in{from{opacity:0;transform:translateY(32px)}} /* 32px = --s-8: a keyframe cannot read a var() */

/* ─────────── PAGE HEADERS ─────────── */
.page-header{margin-bottom:var(--s-16)}
.page-eyebrow{
  font-family:var(--font-mono);font-size:var(--t-caption);letter-spacing:var(--tr-mono);text-transform:uppercase;
  color:var(--primary-400);
  display:inline-flex;align-items:center;gap:var(--s-2);
  margin-bottom:var(--s-4);
}
.page-eyebrow::before{content:"";width:24px;height:1px;background:var(--primary-500)}
.page-title{
  font-size:var(--t-h1);
  line-height:var(--lh-tight);
  letter-spacing:var(--tr-tight);
  font-weight:700;
  margin:0 0 var(--s-5);
  max-width:14ch;
}
.page-title .accent{background:var(--grad-signal);-webkit-background-clip:text;background-clip:text;color:transparent}
.page-lede{
  font-size:var(--t-lead);
  line-height:var(--lh-loose);
  color:var(--obsidian-200);
  max-width:62ch;
  font-weight:400;
}
.page-meta{
  display:flex;flex-wrap:wrap;gap:var(--s-6);
  margin-top:var(--s-8);
  padding-top:var(--s-6);
  border-top:var(--bw-1) solid var(--obsidian-800);
}
.page-meta .mk{display:flex;flex-direction:column;gap:var(--s-0-5)}
.page-meta .mk .k{font-family:var(--font-mono);font-size:var(--t-micro);letter-spacing:var(--tr-mono);text-transform:uppercase;color:var(--obsidian-300)}
.page-meta .mk .v{font-size:var(--t-small);color:var(--obsidian-100);font-weight:500}

/* ─────────── SECTIONS INSIDE PAGES ─────────── */
.subsection{margin-bottom:var(--s-20)}
.subsection-head{
  display:flex;align-items:baseline;justify-content:space-between;
  margin-bottom:var(--s-8);
  padding-bottom:var(--s-4);
  border-bottom:var(--bw-1) solid var(--obsidian-800);
  gap:var(--s-6);
}
.subsection-title{
  font-size:var(--t-h4);
  font-weight:700;
  letter-spacing:var(--tr-snug);
  margin:0;
}
.subsection-num{
  font-family:var(--font-mono);
  font-size:var(--t-caption);
  letter-spacing:var(--tr-mono);
  color:var(--obsidian-300);
  text-transform:uppercase;
}
.page-rules{margin:0 0 var(--s-8);padding-left:var(--s-5);display:grid;gap:var(--s-3);font-size:var(--t-body);line-height:var(--lh-loose);color:var(--obsidian-200)}
.page-rules ul{margin:var(--s-2) 0 0;padding-left:var(--s-5);display:grid;gap:var(--s-2)}
.page-rules strong{font-weight:600;color:var(--obsidian-100)}
.page-rules code{font-size:var(--t-small);color:var(--obsidian-100)}
.page-rules-head{margin:var(--s-10) 0 var(--s-3);font-size:var(--t-h6);font-weight:700;letter-spacing:var(--tr-snug);color:var(--obsidian-100)}
.subsection-desc{
  font-size:var(--t-body);
  color:var(--obsidian-300);
  line-height:var(--lh-loose);
  max-width:72ch;
  margin-bottom:var(--s-8);
}

/* ─────────── GENERIC CARD ─────────── */
.card{
  background:var(--obsidian-800);
  color:var(--obsidian-100);
  border:var(--bw-1) solid var(--obsidian-700);
  border-radius:var(--r-lg);
  padding:var(--s-6);
  position:relative;
  transition:border-color var(--d-quick) var(--ease-standard), box-shadow var(--d-quick) var(--ease-standard);
}
.card:hover{border-color:var(--obsidian-600);box-shadow:var(--sh-2)}
.card-media{
  margin:var(--s-2) 0 var(--s-5);
  border-radius:var(--r-md);
  overflow:hidden;
}
.card-media > *{
  transition:transform var(--d-slow) var(--ease-decel);
  will-change:transform;
  margin:0 !important;
}
.card:hover .card-media > *,
.card:focus-within .card-media > *{
  transform:scale(1.05);
}
@media (prefers-reduced-motion: reduce){
  .card-media > *{transition:none}
  .card:hover .card-media > *,
  .card:focus-within .card-media > *{transform:none}
}
.card-meta{
  display:flex;align-items:center;justify-content:space-between;
  margin-bottom:var(--s-4);
  font-family:var(--font-mono);font-size:var(--t-micro);letter-spacing:var(--tr-mono);text-transform:uppercase;color:var(--obsidian-300);
}
.card-actions{
  display:flex;gap:var(--s-3);
  margin-top:var(--s-6);
}
/* Card · row (v5.0.0): one line of a list, the whole card is the link */
.card-row{
  display:grid;grid-template-columns:var(--s-16) minmax(0,1fr) auto;align-items:center;gap:var(--s-4);
  padding:var(--s-3);
  color:inherit;text-decoration:none;cursor:pointer;
}
.card-row:focus-visible{outline:var(--focus-width) solid var(--obsidian-100);outline-offset:var(--s-px);box-shadow:var(--ring-halo)}
.card-row .card-media{margin:0;width:var(--s-16);aspect-ratio:1}
.card-row .card-media > *{width:100%;height:100%;object-fit:cover}
.card-row .card-meta{margin:0 0 var(--s-1)}
.card-row h3{margin:0;font-size:var(--t-body);font-weight:600;letter-spacing:var(--tr-snug);line-height:var(--lh-snug)}
/* The strip (v5.3.0): the row card's left edge, --bw-2 in --card-strip, as Alert and Toast mark theirs. It is the
   declared exception to inline symmetry (§ Size). The hover keeps the strip: the card's border-color leaves this edge. */
.card-strip,.card.card-strip:hover{border-left:var(--bw-2) solid var(--card-strip)}
.card-row p{margin:var(--s-1) 0 0;font-size:var(--t-small);color:var(--obsidian-300);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
/* Card · feature (v5.0.0): the one highlighted item of a page, with its light */
.card-feature{
  display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:var(--s-10);
  padding:var(--s-8);
  background:var(--obsidian-900);border-color:var(--obsidian-800);border-radius:var(--r-xl);
  overflow:hidden;isolation:isolate;
}
.card-feature::before{
  content:"";position:absolute;z-index:-1;pointer-events:none;
  right:calc(-1 * var(--s-24));top:calc(-1 * var(--s-12));
  width:calc(var(--s-24) * 5);aspect-ratio:1;border-radius:50%;
  background:var(--primary-500);opacity:var(--tint-fill-deep);filter:blur(var(--blur-light));
}
.card-feature .card-media{margin:0}
.card-feature-side{display:flex;flex-direction:column;gap:var(--s-4)}
.card-feature-tags{display:flex;flex-wrap:wrap;gap:var(--s-2)}
.card-feature-body{display:flex;flex-direction:column;justify-content:space-between;gap:var(--s-6)}
.card-feature .card-meta{margin-bottom:var(--s-3)}
.card-feature h3{margin:0;font-size:var(--t-h4);font-weight:600;letter-spacing:var(--tr-tight);line-height:var(--lh-snug)}
.card-feature p{margin:0 0 var(--s-5);color:var(--obsidian-300);font-size:var(--t-body);line-height:var(--lh-loose)}
.card-feature-foot{display:flex;align-items:center;justify-content:space-between;gap:var(--s-4);flex-wrap:wrap}
.card-feature-time{font-family:var(--font-mono);font-size:var(--t-micro);letter-spacing:var(--tr-mono);text-transform:uppercase;color:var(--obsidian-300)}
.card-feature-tab{
  position:absolute;left:0;top:0;z-index:1;
  padding:var(--s-1) var(--s-4);border-radius:0 0 var(--r-xl) 0;
  background:var(--primary-500);color:var(--obsidian-050);box-shadow:var(--sh-glow);
  font-family:var(--font-mono);font-size:var(--t-micro);font-weight:700;letter-spacing:var(--tr-mono);text-transform:uppercase;
}
@media (max-width: 720px){
  .card-feature{grid-template-columns:1fr;gap:var(--s-5);padding:var(--s-5)}
  .card-feature-tab ~ .card-feature-side{margin-top:var(--s-4)}
}

/* grids */
.grid{display:grid;gap:var(--s-4)}
.grid-2{grid-template-columns:repeat(2,minmax(0,1fr))}
.grid-3{grid-template-columns:repeat(3,minmax(0,1fr))}
.grid-4{grid-template-columns:repeat(4,minmax(0,1fr))}
.grid-6{grid-template-columns:repeat(6,minmax(0,1fr))}
@media (max-width: 900px){.grid-3,.grid-4,.grid-6{grid-template-columns:repeat(2,minmax(0,1fr))}}

/* ─────────── § 3.36 SWATCH (v5.0.0) ───────────
   A token shown, not pressed: no hover, no focus. Colour forms are still; the motion tile moves because the motion is its value. The colour comes from --sw, set to var() of a token.
   Inline marker before a label, the gap is the container's; tile for one step of a palette.
   Always bordered with an inset 1px of --border-input, so the size stays and a dark colour reads on the page (WCAG 1.4.11). */
.swatch{display:inline-block;flex:none;width:var(--s-3);height:var(--s-3);border-radius:var(--r-xs);background:var(--sw, transparent);box-shadow:inset 0 0 0 var(--bw-1) var(--border-input);vertical-align:middle}
.swatch-tile{border:var(--bw-1) solid var(--obsidian-800);border-radius:var(--r-md);overflow:hidden;background:var(--obsidian-900)}
.swatch-tile-fill{height:var(--s-24);background:var(--sw, transparent);box-shadow:inset 0 calc(-1 * var(--bw-1)) 0 var(--border-input)}
.swatch-tile-meta{padding:var(--s-3) var(--s-4);display:flex;flex-direction:column;gap:var(--s-0-5)}
.swatch-tile-name{font-weight:600;font-size:var(--t-small);color:var(--obsidian-100)}
.swatch-tile-hex{font-family:var(--font-mono);font-size:var(--t-caption);color:var(--obsidian-200);letter-spacing:var(--tr-mono)}
.swatch-tile-role{font-family:var(--font-mono);font-size:var(--t-micro);letter-spacing:var(--tr-mono);text-transform:uppercase;color:var(--obsidian-300);margin-top:var(--s-0-5)}

/* Motion tile: one easing token at the duration it rides, on the standard easing graph (CSS Easing L1):
   time across, position up. The dot rides the curve; the ball on the rail at the right shares its height.
   --e and --d are var() of tokens, set on the tile. The move fills the first 40% of a cycle of 2.5 x --d, so the
   move lasts exactly --d and the rest holds the end. Three cycles and it rests on the end, under 5 s even on
   --d-slow (WCAG 2.2.2). The curve is set on each element: var() inside @keyframes is not read and falls back to ease. */
/* Radius tile: a neutral shape at the token's radius, 1:1. --sw-r is var() of a radius token, set on the tile. */
.swatch-tile-radius .swatch-tile-fill{display:flex;align-items:center;justify-content:center;background:var(--obsidian-950)}
.swatch-tile-shape{width:var(--s-24);height:calc(var(--s-24) * .6);border-radius:var(--sw-r, 0);background:var(--obsidian-800);box-shadow:inset 0 0 0 var(--bw-1) var(--obsidian-400)}
/* Icon tile: the album drawing 4x on its 16 grid, the 14 live area dashed (§ 3.1); 16 and 24 at 1:1 beside.
   The zoom is the same drawing in the same .icon, so the stroke is the real 1.5 grid units, scaled. */
.swatch-tile-icon .swatch-tile-fill{height:auto;display:flex;align-items:center;justify-content:center;gap:var(--s-5);padding:var(--s-5);background:var(--obsidian-950);color:var(--obsidian-100)}
.swatch-tile-zoom{position:relative;flex:none;width:var(--s-16);height:var(--s-16);background-image:linear-gradient(var(--obsidian-700) var(--bw-1),transparent var(--bw-1)),linear-gradient(90deg,var(--obsidian-700) var(--bw-1),transparent var(--bw-1));background-size:calc(100% / 16) calc(100% / 16);box-shadow:inset calc(-1 * var(--bw-1)) calc(-1 * var(--bw-1)) 0 var(--obsidian-700)}
.swatch-tile-zoom::after{content:"";position:absolute;inset:calc(100% / 16);border:var(--bw-1) dashed var(--obsidian-400);pointer-events:none}
.swatch-tile-zoom .swatch-tile-glyph{position:absolute;inset:0;width:100%;height:100%;color:var(--primary-300)}
.swatch-tile-sizes{display:flex;flex-direction:column;align-items:center;gap:var(--s-3)}
/* Shadow tile: a surface (--obsidian-850) on a section ground (--obsidian-900), where cards and popovers sit; --sw-sh is var() of a shadow or ring token. */
.swatch-tile-shadow .swatch-tile-fill{height:calc(var(--s-24) * 1.25);overflow:hidden;display:flex;align-items:center;justify-content:center;background:var(--obsidian-900)}
.swatch-tile-surface{width:var(--s-24);height:calc(var(--s-24) * .5);border-radius:var(--r-md);background:var(--obsidian-850);box-shadow:var(--sw-sh, none)}
/* Type tile: horizontal. The sample in its .ty-* class at full size on the page ground, cropped at the end of the
   line; a divider; then name, token, size / leading / tracking and role. Under --bp-md the specs drop below. */
.swatch-list{display:flex;flex-direction:column;gap:var(--s-3)}
.swatch-tile-type{display:flex}
.swatch-tile-type .swatch-tile-fill{flex:1;min-width:0;height:auto;max-height:calc(var(--s-24) * 1.25);display:flex;align-items:center;overflow:hidden;padding:var(--s-5) 0 var(--s-5) var(--s-5);background:var(--obsidian-950);box-shadow:none}
.swatch-type-sample{margin:0;white-space:nowrap;color:var(--obsidian-100)}
.swatch-tile-type .swatch-tile-meta{flex:none;width:calc(var(--s-24) * 2.25);justify-content:center;border-left:var(--bw-1) solid var(--border-input)}
@media (max-width: 720px){
  .swatch-tile-type{flex-direction:column}
  .swatch-tile-type .swatch-tile-meta{width:auto;border-left:0;border-top:var(--bw-1) solid var(--border-input)}
}
/* Space tile: horizontal, a row of the scale. A bar --sw-s long (var() of a spacing token), 1:1, on a 4px grid; a divider; name, token, px. */
.swatch-list-tight{gap:var(--s-2)}
.swatch-tile-space{display:flex}
.swatch-tile-space .swatch-tile-fill{flex:1;min-width:0;height:auto;display:flex;align-items:center;padding:var(--s-3) var(--s-5);overflow:hidden;box-shadow:none;background-color:var(--obsidian-950);background-image:linear-gradient(90deg,var(--obsidian-800) var(--bw-1),transparent var(--bw-1));background-size:var(--s-1) 100%;background-position:var(--s-5) 0}
.swatch-space-bar{display:block;flex:none;width:var(--sw-s, 0);min-width:var(--bw-1);height:var(--s-4);background:var(--primary-500)}
.swatch-tile-space .swatch-tile-meta{flex:none;width:calc(var(--s-24) * 2.25);flex-direction:row;align-items:baseline;gap:var(--s-4);border-left:var(--bw-1) solid var(--border-input)}
@media (max-width: 720px){
  .swatch-tile-space .swatch-tile-meta{width:auto;flex:none}
}
.swatch-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(190px,1fr));gap:var(--s-3)}
/* A row of examples that thins with its own width, never wraps: 4 tiles, 3 under 900px of row, 2 under 720, 1 under 480. */
.swatch-grid-4{display:flex;gap:var(--s-3);container-type:inline-size}
.swatch-grid-4 > .swatch-tile{flex:1 1 0;min-width:0}
@container (max-width: 900px){.swatch-grid-4 > .swatch-tile:nth-child(n+4){display:none}}
@container (max-width: 720px){.swatch-grid-4 > .swatch-tile:nth-child(n+3){display:none}}
@container (max-width: 480px){.swatch-grid-4 > .swatch-tile:nth-child(n+2){display:none}}
.swatch-tile-motion .swatch-tile-fill{height:auto;display:flex;justify-content:center;background:var(--obsidian-950);padding:var(--s-6) var(--s-5)}
.swatch-tile-plot{position:relative;flex:1 1 auto;max-width:calc(var(--s-24) * 2);aspect-ratio:1;margin:0 calc(var(--s-6) + var(--s-3)) 0 var(--s-2)}
.swatch-tile-plot svg{position:absolute;inset:0;width:100%;height:100%;overflow:visible}
.swatch-tile-axis{stroke:var(--obsidian-400);stroke-width:1;vector-effect:non-scaling-stroke}
.swatch-tile-guide{stroke:var(--obsidian-700);stroke-width:1;stroke-dasharray:2 3;vector-effect:non-scaling-stroke}
.swatch-tile-curve{fill:none;stroke:var(--primary-300);stroke-width:2;vector-effect:non-scaling-stroke}
.swatch-tile-tick{position:absolute;font-family:var(--font-mono);font-size:var(--t-micro);letter-spacing:var(--tr-mono);color:var(--obsidian-300);line-height:1}
.swatch-tile-tick-x{left:calc(-1 * var(--s-1));top:calc(-1 * var(--s-5))}
.swatch-tile-tick-1{left:calc(-1 * var(--s-3));top:calc(-1 * var(--s-1))}
.swatch-tile-tick-0{left:calc(-1 * var(--s-3));bottom:calc(-1 * var(--s-4))}
.swatch-tile-tick-d{right:var(--s-4);bottom:calc(-1 * var(--s-4))}
.swatch-tile-tick-t{right:0;bottom:calc(-1 * var(--s-4))}
.swatch-tile-time,.swatch-tile-pos{position:absolute;inset:0;pointer-events:none}
.swatch-tile-pos::after{content:"";position:absolute;left:0;bottom:0;width:var(--s-2);height:var(--s-2);margin:0 0 calc(var(--s-2) / -2) calc(var(--s-2) / -2);border-radius:var(--r-full);background:var(--primary-500)}
.swatch-tile-level{position:absolute;inset:0 calc(-1 * (var(--s-5) + var(--s-3))) 0 0;pointer-events:none}
.swatch-tile-level::after{content:"";position:absolute;left:0;right:0;bottom:0;border-top:var(--bw-1) dashed var(--obsidian-400)}
.swatch-tile-rail{position:absolute;top:calc(var(--s-3) / -2);bottom:calc(var(--s-3) / -2);right:calc(-1 * (var(--s-5) + var(--s-3)));width:var(--s-3);border-radius:var(--r-full);background:var(--obsidian-900)}
.swatch-tile-rise{position:absolute;top:calc(var(--s-3) / 2);bottom:calc(var(--s-3) / 2);left:0;right:0}
.swatch-tile-ball{position:absolute;left:0;bottom:0;width:var(--s-3);height:var(--s-3);margin-bottom:calc(var(--s-3) / -2);border-radius:var(--r-full);background:var(--primary-500)}
.swatch-tile-time,.swatch-tile-pos,.swatch-tile-level,.swatch-tile-rise{animation-duration:calc(var(--d, var(--d-base)) * 2.5);animation-iteration-count:3;animation-fill-mode:both}
.swatch-tile-time{animation-name:swatch-time;animation-timing-function:linear}
.swatch-tile-pos,.swatch-tile-level,.swatch-tile-rise{animation-name:swatch-rise;animation-timing-function:var(--e, var(--ease-standard))}
@keyframes swatch-time{0%{transform:none}40%,100%{transform:translateX(100%)}}
@keyframes swatch-rise{0%{transform:none}40%,100%{transform:translateY(-100%)}}
@media (prefers-reduced-motion: reduce){
  .swatch-tile-time,.swatch-tile-pos,.swatch-tile-level,.swatch-tile-rise{animation:none}
  .swatch-tile-time{transform:translateX(100%)}
  .swatch-tile-pos,.swatch-tile-level,.swatch-tile-rise{transform:translateY(-100%)}
}


.ty-display{font-size:var(--t-display);line-height:var(--lh-tight);letter-spacing:var(--tr-tight);font-weight:900}
.ty-h1{font-size:var(--t-h1);line-height:var(--lh-tight);letter-spacing:var(--tr-tight);font-weight:700}
.ty-h2{font-size:var(--t-h2);line-height:var(--lh-tight);letter-spacing:var(--tr-tight);font-weight:700}
.ty-h3{font-size:var(--t-h3);line-height:var(--lh-snug);letter-spacing:var(--tr-snug);font-weight:700}
.ty-h4{font-size:var(--t-h4);line-height:var(--lh-snug);letter-spacing:var(--tr-snug);font-weight:700}
.ty-h5{font-size:var(--t-h5);line-height:var(--lh-snug);letter-spacing:var(--tr-snug);font-weight:600}
.ty-h6{font-size:var(--t-h6);line-height:var(--lh-snug);font-weight:600}
.ty-lead{font-size:var(--t-lead);line-height:var(--lh-loose);font-weight:400;color:var(--obsidian-200)}
.ty-body{font-size:var(--t-body);line-height:var(--lh-loose);font-weight:400}
.ty-small{font-size:var(--t-small);line-height:var(--lh-normal);color:var(--obsidian-300)}
.ty-caption{font-size:var(--t-caption);line-height:var(--lh-normal);color:var(--obsidian-300)}
.ty-micro{font-size:var(--t-micro);line-height:var(--lh-normal);color:var(--obsidian-300)}
.ty-mono{font-family:var(--font-mono);font-size:var(--t-small);letter-spacing:var(--tr-mono);color:var(--obsidian-200);text-transform:uppercase}

/* ─────────── TOKEN TABLE ─────────── */
.table{
  width:100%;border-collapse:collapse;
  border:var(--bw-1) solid var(--obsidian-800);border-radius:var(--r-md);overflow:hidden;
  font-size:var(--t-small);
  color:var(--obsidian-100);
}
.table th,.table td{text-align:left;padding:var(--s-3) var(--s-4);border-bottom:var(--bw-1) solid var(--obsidian-800)}
.table th{
  font-family:var(--font-mono);font-size:var(--t-micro);letter-spacing:var(--tr-mono);text-transform:uppercase;
  color:var(--obsidian-300);background:var(--obsidian-850);font-weight:500;
}
.table tr:last-child td{border-bottom:0}
/* a table wider than its container scrolls in its wrapper; the type never shrinks to fit */
.table-scroll{overflow-x:auto;max-width:100%}
/* a row that holds a .table-row-link is the link: the anchor's hit area covers the row */
.table tbody tr:has(.table-row-link){position:relative;cursor:pointer;transition:background var(--d-quick) var(--ease-standard)}
.table tbody tr:has(.table-row-link):hover{background:var(--obsidian-850)}
.table tbody tr:has(.table-row-link):active{background:var(--obsidian-800)}
.table-row-link{color:inherit;text-decoration:none}
.table-row-link::after{content:"";position:absolute;inset:0}
.table-row-link:focus-visible{outline:none}
.table tbody tr:has(.table-row-link:focus-visible){outline:var(--focus-width) solid var(--obsidian-100);outline-offset:calc(-1 * var(--focus-width));box-shadow:var(--ring-halo)}
.table code{font-family:var(--font-mono);font-size:var(--t-caption);color:var(--primary-400);background:var(--obsidian-850);padding:var(--s-0-5) var(--s-1);border-radius:var(--r-sm);letter-spacing:var(--tr-mono)}
.table .muted{color:var(--obsidian-300)}
/* Sortable header (§ 3.39). The button fills the cell, so the whole header is the target. The driver th carries
   aria-sort, one per table, a step lighter. The button holds both drawings and the header shows one: ascending until
   the column drives descending. Colour is inherited. No transition: the sort is a state, not a move. */
.table th:has(> .table-sort){padding:0}
.table th[aria-sort]{background:var(--obsidian-800);color:var(--obsidian-200)}
.table-sort{display:flex;align-items:center;gap:var(--s-2);width:100%;padding:var(--s-3) var(--s-4);background:transparent;border:0;font:inherit;letter-spacing:inherit;text-transform:inherit;text-align:inherit;color:inherit;cursor:pointer}
.table-sort:hover{color:var(--obsidian-200)}
.table-sort:focus-visible{outline:var(--focus-width) solid var(--obsidian-100);outline-offset:calc(-1 * var(--s-0-5));box-shadow:var(--ring-halo)}
.table-sort-desc,.table th[aria-sort="descending"] .table-sort-asc{display:none}
.table th[aria-sort="descending"] .table-sort-desc{display:inline-block}

/* ─────────── SPACING RULER ─────────── */

/* ─────────── BUTTONS (the component itself) ─────────── */
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:var(--s-2);
  font-family:var(--font-sans);font-size:var(--t-body);font-weight:500;
  letter-spacing:var(--tr-snug);line-height:1;
  min-height:var(--s-10);padding:0 var(--s-6);border-radius:var(--r-full);
  transition:all var(--d-quick) var(--ease-standard);
  border:var(--bw-1) solid transparent;
  white-space:nowrap;
}
/* Floating (§ 3.6): a button that stays on screen while its content scrolls, translucent so the content reads through.
   Sticky on --z-sticky at --float-top; the negative bottom margin gives its height back, so it floats over what follows
   instead of pushing it down. Label --t-small, inline padding --s-4 on both sides (§ Size › Inline symmetry). */
.btn-floating{display:flex;width:max-content;position:sticky;top:var(--float-top, var(--s-4));z-index:var(--z-sticky);margin-bottom:calc(-1 * var(--s-10));padding:0 var(--s-4);font-size:var(--t-small);background:var(--surface-glass);border-color:var(--border);color:var(--obsidian-100);backdrop-filter:blur(var(--blur-glass))}
.btn-floating:hover{border-color:var(--border-strong)}
.btn:disabled{opacity:var(--opacity-disabled);cursor:not-allowed}
.btn .icon{width:var(--icon-xs);height:var(--icon-xs)}
.btn-icon .icon{width:var(--icon-sm);height:var(--icon-sm)}  /* an icon-only button keeps the 16 glyph: the 14 is for an icon beside a label */
.btn-primary{background:var(--primary-500);color:var(--obsidian-050);border-color:var(--primary-500);box-shadow:var(--sh-2);transition:all var(--d-quick) var(--ease-standard), transform var(--d-quick) var(--ease-spring)}
.btn-primary:hover{background:var(--primary-500);color:var(--obsidian-050);border-color:var(--primary-500);box-shadow:var(--sh-glow), var(--sh-3)}
.btn-secondary{background:var(--obsidian-800);color:var(--obsidian-100);border-color:var(--obsidian-700)}
.btn-secondary:hover{background:var(--obsidian-700);border-color:var(--obsidian-600)}
.btn-ghost{color:var(--obsidian-100);background:transparent}
.btn-ghost:hover{background:var(--obsidian-800)}
.btn-outline{background:transparent;color:var(--obsidian-100);border-color:var(--obsidian-600)}
.btn-outline:hover{border-color:var(--primary-500);color:var(--primary-400)}
.btn-danger{background:var(--danger);color:var(--obsidian-950)}
.btn-danger:hover{filter:brightness(1.05)}
/* Pressed (v5.0.0): a coloured fill darkens toward --obsidian-950, a neutral fill goes one step past its hover,
   the outline takes the link's pressed magenta. Only the primary moves: it gives under the finger on the spring (L8). */
.btn-primary:active:not(:disabled){background:var(--primary-600);border-color:var(--primary-600);box-shadow:var(--sh-1);transform:scale(.97)}
.btn-secondary:active:not(:disabled){background:var(--obsidian-600);border-color:var(--obsidian-500)}
.btn-ghost:active:not(:disabled){background:var(--obsidian-700)}
.btn-outline:active:not(:disabled){border-color:var(--primary-600);color:var(--primary-500)}
.btn-danger:active:not(:disabled){filter:none;background:color-mix(in srgb, var(--danger) 85%, var(--obsidian-950))}
.btn-floating:active:not(:disabled){border-color:var(--obsidian-500)}
@media (prefers-reduced-motion: reduce){.btn-primary:active:not(:disabled){transform:none}}
.btn-sm{min-height:var(--s-8);padding:0 var(--s-4);font-size:var(--t-small)}
.btn-lg{min-height:var(--s-12);padding:0 var(--s-8)}
/* Icon-only: a square at the size's height. aria-label is mandatory (§ 3.6). */
.btn-icon{width:var(--s-10);padding:0}
.btn-sm.btn-icon{width:var(--s-8)}
.btn-lg.btn-icon{width:var(--s-12)}
/* An icon-only button that ends a row (§ Size › Inline symmetry): its glyph, not its target, sits on the
   padding edge, as far from the right as the row's first mark is from the left; the target reaches into the padding. */
:is(.modal-head,.drawer-head,.list-end) > .btn-icon:last-child,.list-end > .select-wrap:last-child > .btn-icon{margin-inline-end:calc((var(--icon-sm) - var(--s-10)) / 2)}
:is(.modal-head,.drawer-head,.list-end) > .btn-sm.btn-icon:last-child,.list-end > .select-wrap:last-child > .btn-sm.btn-icon{margin-inline-end:calc((var(--icon-sm) - var(--s-8)) / 2)}
:is(.modal-head,.drawer-head,.list-end) > .btn-lg.btn-icon:last-child,.list-end > .select-wrap:last-child > .btn-lg.btn-icon{margin-inline-end:calc((var(--icon-sm) - var(--s-12)) / 2)}
/* Touch: the § 6 floor asks 44x44 on coarse pointers; dense desktop keeps 32. */
@media (pointer:coarse){
  .btn:not(.btn-lg){min-height:var(--target-touch)}
  .btn-icon:not(.btn-lg){min-width:var(--target-touch)}
  :is(.modal-head,.drawer-head,.list-end) > .btn-icon:not(.btn-lg):last-child,.list-end > .select-wrap:last-child > .btn-icon:not(.btn-lg){margin-inline-end:calc((var(--icon-sm) - var(--target-touch)) / 2)}
}

/* ─────────── INPUTS ─────────── */
.field{display:flex;flex-direction:column;gap:var(--s-1)}
.label{font-family:var(--font-mono);font-size:var(--t-micro);letter-spacing:var(--tr-mono);text-transform:uppercase;color:var(--obsidian-300)}
.input,.textarea,.select{
  background:var(--surface-field);
  border:var(--bw-1) solid var(--border-input);
  border-radius:var(--r-md);
  color:var(--obsidian-100);
  min-height:var(--s-10);padding:var(--s-2) var(--s-3);
  font-family:var(--font-sans);font-size:var(--t-small);
  outline:none;transition:all var(--d-quick) var(--ease-standard);
  width:100%;
}
.select{
  appearance:none;-webkit-appearance:none;-moz-appearance:none;
  padding-right:var(--s-8);
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%238A94A3' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 6l5 5 5-5'/%3E%3C/svg%3E");
  background-repeat:no-repeat;
  background-position:right var(--s-3) center;
  background-size:var(--icon-xs) var(--icon-xs);
}
.select-wrap{position:relative;width:100%}
.select-trigger{
  display:flex;align-items:center;justify-content:flex-start;
  text-align:left;cursor:pointer;
  width:100%;
}
.select-trigger[aria-expanded="true"]{border-color:var(--primary-500);box-shadow:var(--ring-field)}
.select-value{flex:1;color:var(--obsidian-100)}
.select-menu{
  position:absolute;top:calc(100% + var(--s-1));left:0;right:0;
  margin:0;padding:var(--s-1);list-style:none;
  background:var(--obsidian-850);
  border:var(--bw-1) solid var(--obsidian-700);
  border-radius:var(--r-md);
  box-shadow:var(--sh-menu);
  z-index:var(--z-menu);max-height:240px;overflow:auto;
}
.select-menu[hidden]{display:none}
/* Viewport-aware placement (§ Dropdown / Select, variant B): the script fixes the
   menu to the trigger's rect and writes top, left, width and max-height inline at
   open, corrected for a transformed ancestor. right:auto releases the absolute
   default. */
.select-menu.is-fixed{position:fixed;right:auto}
/* The floating layer (v5.3.0, RIGID): every panel that floats over the page rides the top layer, lifted there by the
   page's float helper (a manual popover, showPopover). The panel drops the UA popover box and is placed by script in
   viewport coordinates, so no card, overflow or transformed ancestor can cover it or cut it. Without the Popover API
   the panel stays absolute in its wrap, on --z-menu or --z-popover. */
:is(.select-menu,.dp-popover,.tp-popover,.tooltip).is-floating{position:fixed;inset:auto;margin:0}
.tooltip.is-floating{transform:none}
.select-option{
  display:flex;align-items:center;gap:var(--s-2);min-width:0;
  padding:var(--s-2);border-radius:calc(var(--r-md) - var(--r-xs));
  font-family:var(--font-sans);font-size:var(--t-small);color:var(--obsidian-100);
  cursor:pointer;transition:background var(--d-quick) var(--ease-standard);
}
.select-option[hidden]{display:none}   /* an option on offer later (the add chip's Menu) */
.select-option:hover,.select-option:focus-visible{background:var(--obsidian-800);outline:none}
.select-option[aria-selected="true"]{color:var(--primary-400)}
/* Select · Menu (v5.0.0, § 3.11). One panel and one row for three uses: a value
   chosen from a list (variant B, listbox), a number set on a Slider (variant C,
   dialog) and an action run from a Menu (variant D, menu). The row: a leading
   icon, the label (one line, ellipsis), then a check that follows the text
   (variant B) or a shortcut (variant D). The check's room is reserved on every
   row so labels never move when the choice changes. */
.select-option-label{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.select-option > .icon{width:var(--icon-xs);height:var(--icon-xs);color:var(--obsidian-300)}
.select-check{width:var(--icon-xs);height:var(--icon-xs);visibility:hidden}
.select-option > .select-check{color:inherit}
.select-option[aria-selected="true"] .select-check{visibility:visible}
.select-kbd{font-family:var(--font-mono);font-size:var(--t-caption);letter-spacing:var(--tr-mono);color:var(--obsidian-300)}
.select-group{padding:var(--s-2) var(--s-2) var(--s-1);font-family:var(--font-mono);font-size:var(--t-micro);letter-spacing:var(--tr-mono);text-transform:uppercase;color:var(--obsidian-300);cursor:default}
.select-divider{height:var(--bw-1);margin:var(--s-1) calc(-1 * var(--s-1));padding:0;background:var(--obsidian-700);list-style:none}
.select-option-danger,.select-option-danger > .icon{color:var(--danger)}
.select-option[aria-disabled="true"]{opacity:var(--opacity-disabled);cursor:not-allowed}
.select-option[aria-disabled="true"]:hover{background:transparent}
/* Variant D: the Menu grows to its longest item, from the trigger (at least
   --s-32) to the drawer menu's measure, then truncates. */
.select-menu-actions{width:max-content;min-width:var(--s-32);max-width:calc(30ch + 2 * var(--s-1))}
/* Variant C: one Slider (§ 3.9), single or range, the width of the field. The
   label and the value stay in the field; the panel holds the track and the scale. */
.select-menu-slider{padding:var(--s-3) var(--s-4) var(--s-2)}
.select-menu-slider .slider{gap:var(--s-1)}
/* Native select placement, progressive enhancement (v4.2.2). Where the
   customizable select ships (Chromium 135+), the picker is a styleable popover
   anchored to the control: it opens below and flips above when the bottom edge
   would clip it, the same rule variant B implements in script. Elsewhere the OS
   popup stays. Scoped to select.select so the variant B trigger (button.select)
   is untouched; the closed control keeps its background chevron. */
@supports (appearance: base-select){
  select.select,select.select::picker(select){appearance:base-select}
  select.select{line-height:normal;align-items:center}   /* base-select sets its own; normal gives the 40px box of .input and the variant B trigger.
     base-select makes the control a flex box that stretches its value to the top: centre it, as the trigger does (v5.3.0) */
  select.select::picker-icon{display:none}
  select.select::picker(select){
    position-try-order:normal;   /* the UA default picks the roomier side; the contract opens below unless it does not fit */
    position-try-fallbacks:flip-block;
    margin-block:var(--s-1);padding:var(--s-1);
    max-height:240px;overflow:auto;
    background:var(--obsidian-850);
    border:var(--bw-1) solid var(--obsidian-700);
    border-radius:var(--r-md);
    box-shadow:var(--sh-menu);
  }
  select.select option{
    padding:var(--s-2);border-radius:calc(var(--r-md) - var(--r-xs));
    font-family:var(--font-sans);font-size:var(--t-small);color:var(--obsidian-100);
    cursor:pointer;transition:background var(--d-quick) var(--ease-standard);
  }
  select.select option::checkmark{display:none}
  select.select option:hover,select.select option:focus-visible{background:var(--obsidian-800);outline:none}
  select.select option:checked{color:var(--primary-400)}
}
.input:hover:not(:focus):not(:disabled):not([readonly]):not([aria-invalid="true"]),.textarea:hover:not(:focus):not(:disabled):not([readonly]):not([aria-invalid="true"]),.select:hover:not(:focus):not(:disabled):not([aria-invalid="true"]){border-color:var(--obsidian-300)}
.input:focus,.textarea:focus,.select:focus{border-color:var(--primary-500);box-shadow:var(--ring-field)}
.input[aria-invalid="true"],.textarea[aria-invalid="true"],.select[aria-invalid="true"]{border-color:var(--danger)}
.input[aria-invalid="true"]:focus,.textarea[aria-invalid="true"]:focus,.select[aria-invalid="true"]:focus{border-color:var(--danger);box-shadow:var(--ring-field-danger)}
.input:disabled,.textarea:disabled,.select:disabled{opacity:var(--opacity-disabled);cursor:not-allowed}
.input[readonly],.textarea[readonly]{background:var(--obsidian-900);color:var(--obsidian-300)}
.input::placeholder,.textarea::placeholder{color:var(--obsidian-300)}
.input-wrap{position:relative;width:100%}
.input-wrap > .icon{position:absolute;left:var(--s-3);top:50%;transform:translateY(-50%);color:var(--obsidian-300);pointer-events:none}
.input-wrap:has(> .icon) .input{padding-left:var(--s-8)}
.input-wrap:has(> .input-action) .input{padding-right:var(--s-10)}
.input[type="search"]::-webkit-search-cancel-button,.input[type="search"]::-webkit-search-decoration{-webkit-appearance:none;appearance:none}  /* one clear button, ours */
.help{font-size:var(--t-caption);color:var(--obsidian-300)}
.help.error{color:var(--danger)}

/* ─────────── DATE PICKER ─────────── */
/* ─────────── INPUT ACTION ─────────── */
/* A button inside the field, on the right: open a calendar, clear the value. A 32px target in the 40px field. */
.input-action{
  position:absolute;right:var(--s-1);top:50%;transform:translateY(-50%);
  display:grid;place-items:center;
  width:var(--s-8);height:var(--s-8);border:0;background:transparent;cursor:pointer;
  color:var(--obsidian-300);border-radius:var(--r-sm);
  transition:color var(--d-quick) var(--ease-standard), background var(--d-quick) var(--ease-standard);
}
.input-action:hover{color:var(--obsidian-100);background:var(--obsidian-800)}
.input-action:focus-visible{
  outline:var(--focus-width) solid var(--obsidian-100);outline-offset:var(--s-px);
  box-shadow:var(--ring-halo);color:var(--obsidian-100);
}
.input:placeholder-shown ~ .input-action[data-input-clear],.input[readonly] ~ .input-action[data-input-clear],.input:disabled ~ .input-action{visibility:hidden}  /* nothing to clear, or nothing to edit */

/* Popover */
.dp-wrap{position:relative}
.dp-popover{
  position:absolute;top:calc(100% + var(--s-1));left:0;
  width:280px;
  background:var(--obsidian-900);
  border:var(--bw-1) solid var(--obsidian-700);
  border-radius:var(--r-lg);
  box-shadow:var(--sh-3);
  padding:var(--s-3);
  z-index:var(--z-popover);
  font-family:var(--font-sans);
  opacity:0;transform:translateY(-4px);pointer-events:none;
  transition:opacity var(--d-quick) var(--ease-accel), transform var(--d-quick) var(--ease-accel);
}
.dp-popover.is-open{opacity:1;transform:translateY(0);pointer-events:auto;transition:opacity var(--d-quick) var(--ease-decel), transform var(--d-quick) var(--ease-decel)}
.dp-popover[hidden]{display:none}

/* Header */
.dp-header{
  display:flex;align-items:center;justify-content:space-between;
  padding:var(--s-1) var(--s-1) var(--s-2);
}
.dp-title{
  flex:1;display:flex;align-items:center;justify-content:center;gap:var(--s-1);
  background:transparent;border:0;cursor:pointer;
  font-family:var(--font-sans);font-size:var(--t-small);font-weight:600;
  color:var(--obsidian-100);letter-spacing:var(--tr-snug);
  padding:var(--s-1) var(--s-2);border-radius:var(--r-sm);
  transition:background var(--d-quick) var(--ease-standard);
}
.dp-title:hover{background:var(--obsidian-800)}
.dp-title:focus-visible{outline:var(--focus-width) solid var(--obsidian-100);outline-offset:var(--s-px);box-shadow:var(--ring-halo)}
.dp-title svg{width:var(--icon-xs);height:var(--icon-xs);color:var(--obsidian-400);transition:transform var(--d-quick) var(--ease-standard)}
.dp-popover[data-mode="years"] .dp-title svg{transform:rotate(180deg)}
.dp-nav{
  display:grid;place-items:center;
  width:28px;height:28px;padding:0;border:0;background:transparent;cursor:pointer;
  color:var(--obsidian-300);border-radius:var(--r-sm);
  transition:color var(--d-quick) var(--ease-standard), background var(--d-quick) var(--ease-standard);
}
.dp-nav:hover:not(:disabled){color:var(--obsidian-100);background:var(--obsidian-800)}
.dp-nav:disabled{color:var(--obsidian-500);cursor:not-allowed}
.dp-nav:focus-visible{outline:var(--focus-width) solid var(--obsidian-100);outline-offset:var(--s-px);box-shadow:var(--ring-halo)}
.dp-nav svg{width:var(--icon-xs);height:var(--icon-xs)}

/* Day-of-week header */
.dp-dow{
  display:grid;grid-template-columns:repeat(7,1fr);
  font-family:var(--font-mono);font-size:var(--t-micro);letter-spacing:var(--tr-mono);
  color:var(--obsidian-500);text-align:center;
  padding:var(--s-1) 0;margin-bottom:var(--s-0-5);
}
.dp-dow span{padding:var(--s-1) 0}

/* Day grid */
.dp-grid{display:grid;grid-template-columns:repeat(7,1fr);gap:var(--s-0-5)}
.dp-day{
  display:grid;place-items:center;
  height:var(--s-8);padding:0;border:0;background:transparent;cursor:pointer;
  font-family:var(--font-sans);font-size:var(--t-small);font-variant-numeric:tabular-nums;
  color:var(--obsidian-100);border-radius:var(--r-sm);
  transition:background var(--d-quick) var(--ease-standard), color var(--d-quick) var(--ease-standard);
}
.dp-day:hover:not(:disabled):not(.is-selected):not(.is-range-start):not(.is-range-end):not(.is-in-range):not(.is-range-preview){background:var(--obsidian-800)}
.dp-day:focus-visible{outline:var(--focus-width) solid var(--obsidian-100);outline-offset:calc(-1 * var(--s-0-5));box-shadow:var(--ring-halo)}
.dp-day.is-outside{color:var(--obsidian-500)}
.dp-day.is-today:not(.is-selected){
  color:var(--primary-400);font-weight:600;
  background:color-mix(in srgb, var(--primary-500) calc(var(--tint-fill) * 100%), transparent);
  box-shadow:inset 0 0 0 2px color-mix(in srgb, var(--primary-500) calc(var(--tint-edge) * 100%), transparent);
}
.dp-day.is-selected{
  background:var(--primary-500);color:var(--obsidian-950);font-weight:600;
}
.dp-day:disabled{color:var(--obsidian-600);cursor:not-allowed;background:transparent}

/* Range states */
.dp-day.is-in-range{background:color-mix(in srgb, var(--primary-500) calc(var(--tint-fill-deep) * 100%), transparent);border-radius:0;color:var(--obsidian-100)}
.dp-day.is-range-preview{background:color-mix(in srgb, var(--primary-500) calc(var(--tint-faint) * 100%), transparent);border-radius:0;color:var(--obsidian-100)}
.dp-day.is-range-start{background:var(--primary-500);color:var(--obsidian-950);font-weight:600;border-radius:var(--r-sm) 0 0 var(--r-sm)}
.dp-day.is-range-end{background:var(--primary-500);color:var(--obsidian-950);font-weight:600;border-radius:0 var(--r-sm) var(--r-sm) 0}
.dp-day.is-range-start.is-range-end{border-radius:var(--r-sm)}
.dp-day.is-range-start.is-today,.dp-day.is-range-end.is-today{box-shadow:none}

/* Range popover layout: 580px desktop, two months side-by-side */
.dp-popover.dp-range{width:580px}
.dp-range .dp-months{display:grid;grid-template-columns:1fr 1fr;gap:var(--s-5)}
.dp-range .dp-month-title{
  text-align:center;font-family:var(--font-sans);font-size:var(--t-small);font-weight:600;
  color:var(--obsidian-100);padding:var(--s-1) 0 var(--s-2);
}
.dp-range .dp-presets{
  display:grid;grid-template-columns:repeat(4,1fr);gap:var(--s-1);
  padding:var(--s-2) 0 var(--s-1);margin-top:var(--s-2);border-top:var(--bw-1) solid var(--obsidian-800);
}
.dp-preset{
  font-family:var(--font-mono);font-size:var(--t-micro);letter-spacing:var(--tr-mono);
  text-transform:uppercase;color:var(--obsidian-300);
  background:transparent;border:0;cursor:pointer;
  padding:var(--s-2) var(--s-1);border-radius:var(--r-sm);
  transition:color var(--d-quick) var(--ease-standard), background var(--d-quick) var(--ease-standard);
}
.dp-preset:hover{color:var(--obsidian-100);background:var(--obsidian-800)}
.dp-preset:focus-visible{outline:var(--focus-width) solid var(--obsidian-100);outline-offset:var(--s-px);box-shadow:var(--ring-halo)}

@media (max-width:480px){
  .dp-popover.dp-range{width:280px}
  .dp-range .dp-months{grid-template-columns:1fr;gap:var(--s-2)}
  .dp-range .dp-presets{grid-template-columns:repeat(2,1fr)}
}

/* Year-jump view */
.dp-year-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--s-1);padding:var(--s-1) var(--s-0-5)}
.dp-year{
  height:36px;display:grid;place-items:center;
  border:0;background:transparent;cursor:pointer;
  font-family:var(--font-sans);font-size:var(--t-small);
  color:var(--obsidian-100);border-radius:var(--r-sm);
  transition:background var(--d-quick) var(--ease-standard), color var(--d-quick) var(--ease-standard);
}
.dp-year:hover:not(:disabled):not(.is-selected){background:var(--obsidian-800)}
.dp-year:focus-visible{outline:var(--focus-width) solid var(--obsidian-100);outline-offset:calc(-1 * var(--s-0-5));box-shadow:var(--ring-halo)}
.dp-year.is-outside{color:var(--obsidian-500)}
.dp-year.is-current{color:var(--primary-400);box-shadow:inset 0 0 0 1px var(--obsidian-700)}
.dp-year.is-selected{background:var(--primary-500);color:var(--obsidian-950);font-weight:600}
.dp-year:disabled{color:var(--obsidian-600);cursor:not-allowed}

/* Footer */
.dp-footer{
  display:flex;justify-content:flex-end;
  margin-top:var(--s-1);padding:var(--s-1) 0 var(--s-0-5);border-top:var(--bw-1) solid var(--obsidian-800);
}
.dp-today-btn{
  font-family:var(--font-mono);font-size:var(--t-micro);letter-spacing:var(--tr-mono);
  text-transform:uppercase;color:var(--obsidian-300);
  background:transparent;border:0;cursor:pointer;
  padding:var(--s-1) var(--s-2);border-radius:var(--r-sm);
  transition:color var(--d-quick) var(--ease-standard), background var(--d-quick) var(--ease-standard);
}
.dp-today-btn:hover{color:var(--obsidian-100);background:var(--obsidian-800)}
.dp-today-btn:focus-visible{outline:var(--focus-width) solid var(--obsidian-100);outline-offset:var(--s-px);box-shadow:var(--ring-halo)}

/* ─────────── TIME PICKER — iOS-style scroll wheel ─────────── */
.tp-wrap{position:relative}
.tp-popover{
  position:absolute;top:calc(100% + var(--s-1));left:0;
  width:200px;
  background:var(--obsidian-900);
  border:var(--bw-1) solid var(--obsidian-700);
  border-radius:var(--r-lg);
  box-shadow:var(--sh-3);
  padding:var(--s-3);
  z-index:var(--z-popover);
  font-family:var(--font-sans);
  opacity:0;transform:translateY(-4px);pointer-events:none;
  transition:opacity var(--d-quick) var(--ease-accel), transform var(--d-quick) var(--ease-accel);
}
.tp-popover.is-open{opacity:1;transform:translateY(0);pointer-events:auto;transition:opacity var(--d-quick) var(--ease-decel), transform var(--d-quick) var(--ease-decel)}
.tp-popover[hidden]{display:none}

.tp-wheels{
  position:relative;
  display:grid;grid-template-columns:1fr auto 1fr;
  align-items:center;
  height:calc(28px * 7);
  --tp-item-h:28px;
  --tp-visible:7;
  --tp-center:3; /* (visible - 1) / 2 */
}
.tp-sep{
  font-family:var(--font-sans);font-size:var(--t-lead);font-weight:600;color:var(--obsidian-300);
  padding:0 var(--s-1);
}
/* Selection band — magenta highlight on the middle row */
.tp-wheels::before{
  content:"";position:absolute;left:0;right:0;
  top:calc(var(--tp-item-h) * var(--tp-center));
  height:var(--tp-item-h);
  background:color-mix(in srgb, var(--primary-500) calc(var(--tint-fill) * 100%), transparent);
  border-top:var(--bw-1) solid color-mix(in srgb, var(--primary-500) calc(var(--tint-glow) * 100%), transparent);
  border-bottom:var(--bw-1) solid color-mix(in srgb, var(--primary-500) calc(var(--tint-glow) * 100%), transparent);
  pointer-events:none;
  border-radius:var(--r-sm);
}
/* Top + bottom fade gradient over the wheel */
.tp-wheels::after{
  content:"";position:absolute;inset:0;
  background:linear-gradient(180deg,
    var(--obsidian-900) 0%,
    color-mix(in srgb, var(--obsidian-900) calc(var(--tint-strong) * 100%), transparent) 14%,
    transparent 36%,
    transparent 64%,
    color-mix(in srgb, var(--obsidian-900) calc(var(--tint-strong) * 100%), transparent) 86%,
    var(--obsidian-900) 100%);
  pointer-events:none;
  border-radius:var(--r-sm);
}
.tp-wheel{
  height:100%;
  overflow-y:scroll;
  scroll-snap-type:y mandatory;
  scrollbar-width:none;
  -ms-overflow-style:none;
  scroll-behavior:smooth;
}
.tp-wheel::-webkit-scrollbar{display:none}
.tp-wheel-list{
  padding:calc(var(--tp-item-h) * var(--tp-center)) 0;
}
.tp-wheel-item{
  height:var(--tp-item-h);
  display:grid;place-items:center;
  font-family:var(--font-sans);font-size:var(--t-small);font-variant-numeric:tabular-nums;
  color:var(--obsidian-300);
  scroll-snap-align:center;
  scroll-snap-stop:always;
  cursor:pointer;
  transition:color var(--d-quick) var(--ease-standard), font-weight var(--d-quick) var(--ease-standard);
}
.tp-wheel-item.is-active{
  color:var(--obsidian-100);font-weight:600;
}
.tp-wheel:focus-visible{outline:var(--focus-width) solid var(--obsidian-100);outline-offset:calc(-1 * var(--s-0-5));box-shadow:var(--ring-halo);border-radius:var(--r-sm)}
@media (prefers-reduced-motion: reduce){
  .tp-popover,.tp-wheel-item{transition:none}
  .tp-wheel{scroll-behavior:auto}
}

@media (prefers-reduced-motion: reduce){
  .dp-popover,.dp-day,.dp-year,.dp-nav,.dp-title,.dp-today-btn,.input-action{transition:none}
}

/* checkbox & switch */
.check{display:inline-flex;align-items:center;gap:var(--s-2);cursor:pointer;font-size:var(--t-small);color:var(--obsidian-100)}
.check input{appearance:none;width:var(--s-4);height:var(--s-4);border:var(--bw-1) solid var(--border-input);border-radius:var(--r-xs);background:var(--surface-field);display:grid;place-items:center;transition:border-color var(--d-quick) var(--ease-standard), background var(--d-quick) var(--ease-standard)}
.check input:checked{background:var(--primary-500);border-color:var(--primary-500)}
.check input:checked::after{content:"";width:10px;height:6px;border:var(--bw-2) solid var(--obsidian-950);border-top:0;border-right:0;transform:rotate(-45deg) translate(1px,-1px)}
.switch{display:inline-flex;align-items:center;gap:var(--s-2);cursor:pointer;font-size:var(--t-small);color:var(--obsidian-100)}
.switch input{appearance:none;width:var(--s-8);height:calc(var(--s-4) + var(--s-0-5));background:var(--obsidian-700);border-radius:var(--r-full);position:relative;transition:background var(--d-quick) var(--ease-standard)}
.switch input::after{content:"";position:absolute;top:var(--s-0-5);left:var(--s-0-5);width:14px;height:14px;background:var(--obsidian-200);border-radius:var(--r-full);transition:left var(--d-base) var(--ease-standard), background var(--d-quick) var(--ease-standard), transform var(--d-quick) var(--ease-standard)}
.switch input:checked{background:var(--primary-500)}
.switch input:checked::after{left:var(--s-4);background:var(--obsidian-950)}
/* Hover grows the knob one step, 14px to --s-4, as a scale about its centre: never a colour, which on the
   --primary-500 track would vanish (v5.3.0). The scale moves nothing else, so the knob's left keeps its own curve;
   --ease-standard, not the spring: a 2px growth has no room for an overshoot, which under the pointer reads as a
   flicker. A fine pointer only; a disabled switch does not answer. */
@media (hover: hover){
  .switch:hover input:not(:disabled)::after{transform:scale(calc(16 / 14))}
}
@media (prefers-reduced-motion: reduce){.switch input::after{transition:none}}

/* Radio — shape-distinct from the checkbox by contract (§ 6 floor #1:
   meaning is never carried by color alone). Circle + dot, never a tick. */
.radio{display:inline-flex;align-items:center;gap:var(--s-2);cursor:pointer;font-size:var(--t-small);color:var(--obsidian-100)}
.radio input{
  appearance:none;width:var(--s-4);height:var(--s-4);
  border:var(--bw-1) solid var(--border-input);border-radius:var(--r-full);
  background:var(--surface-field);display:grid;place-items:center;
  transition:border-color var(--d-quick) var(--ease-standard), background var(--d-quick) var(--ease-standard);
}
.radio input:checked{border-color:var(--primary-500)}
.radio input:checked::after{content:"";width:8px;height:8px;border-radius:var(--r-full);background:var(--primary-500)}

/* A group of choices (v5.3.0): a fieldset, its legend in the label register, the options --s-3 apart.
   Radios always come in one; checkboxes and switches when there are two or more. */
.choice-group{border:0;margin:0;padding:0;min-inline-size:0;display:flex;flex-direction:column;gap:var(--s-3)}
.choice-group > legend{padding:0;margin-bottom:var(--s-3);font-family:var(--font-mono);font-size:var(--t-micro);letter-spacing:var(--tr-mono);text-transform:uppercase;color:var(--obsidian-300)}

/* Choice controls — shared focus ring and disabled treatment.
   The § 6.2 pressable pattern, applied to the real focus target (the input). */
.check input:focus-visible,
.switch input:focus-visible,
.radio input:focus-visible{
  outline:var(--focus-width) solid var(--obsidian-100);outline-offset:var(--focus-offset);
  box-shadow:var(--ring-halo);
}
.check input:disabled,
.switch input:disabled,
.radio input:disabled{opacity:var(--opacity-disabled);cursor:not-allowed}
.check:has(input:disabled),
.switch:has(input:disabled),
.radio:has(input:disabled){color:var(--obsidian-400);cursor:not-allowed}

/* ─────────── BADGES ─────────── */
/* § 3.14 — status the system computed. Its own register: --t-small, --tr-snug,
   padding --s-2 --s-4, gap --s-1, dot --s-1. The default mixes its deep hue at
   --tint-fill-deep / --tint-edge-deep; the variants at the chip's two strengths,
   --tint-fill and --tint-edge (tokens, v4.3.0). */
.badge{
  --tint-hue:var(--tertiary-500);
  display:inline-flex;align-items:center;gap:var(--s-1);
  font-family:var(--font-sans);font-size:var(--t-small);letter-spacing:var(--tr-snug);
  padding:var(--s-2) var(--s-4);border-radius:var(--r-md);
  border:var(--bw-1) solid color-mix(in srgb, var(--tint-hue) calc(var(--tint-edge-deep) * 100%), transparent);
  color:var(--tertiary-300);
  background:color-mix(in srgb, var(--tint-hue) calc(var(--tint-fill-deep) * 100%), transparent);
  font-weight:500;white-space:nowrap;flex:none;
}
.badge .dot{width:var(--s-1);height:var(--s-1);border-radius:var(--r-full);background:currentColor}
.badge-success,.badge-warn,.badge-danger,.badge-info,.badge-brand{
  border-color:color-mix(in srgb, var(--tint-hue) calc(var(--tint-edge) * 100%), transparent);
  background:color-mix(in srgb, var(--tint-hue) calc(var(--tint-fill) * 100%), transparent);
}
.badge-success{--tint-hue:var(--success);color:var(--success)}
.badge-warn{--tint-hue:var(--warning);color:var(--warning)}
.badge-danger{--tint-hue:var(--danger);color:var(--danger)}
.badge-info{--tint-hue:var(--info);color:var(--info)}
.badge-brand{--tint-hue:var(--primary-500);color:var(--primary-400)}
.badge-solid{background:var(--primary-500);color:var(--obsidian-050);border-color:var(--primary-500)}

/* ─────────── CHIPS ─────────── */
/* § 3.15 — a value a person put there. Status the system computed is a .badge. */
.chip{
  display:inline-flex;align-items:center;gap:var(--s-1);position:relative;
  font-family:var(--font-sans);font-size:var(--t-small);font-weight:500;
  letter-spacing:var(--tr-snug);line-height:var(--lh-snug);white-space:nowrap;
  padding:var(--s-1) var(--s-3);border-radius:var(--r-full);
  border:var(--bw-1) solid var(--obsidian-700);background:var(--obsidian-800);color:var(--obsidian-100);
  transition:border-color var(--d-quick) var(--ease-standard),
             color var(--d-quick) var(--ease-standard),
             background var(--d-quick) var(--ease-standard);
}
/* the 44x44 floor is reached by an inset: the visible box stays on the type scale */
/* Only a target grows: the pressable chip, and the dismiss inside a removable one.
   v4.1.0 had the inset on every .chip with pointer-events:none, which extends
   nothing — a pseudo-element that ignores the pointer is not a hit area. */
button.chip::before,a.chip::before{content:"";position:absolute;top:50%;left:50%;width:max(100%,var(--target-touch));height:var(--target-touch);transform:translate(-50%,-50%)}
.chip .chip-dot{width:var(--s-1);height:var(--s-1);border-radius:var(--r-full);background:currentColor;flex:none}
.chip-dense{font-size:var(--t-micro);padding:var(--s-1) var(--s-2)}
.chip-brand,.chip-success,.chip-warn,.chip-danger,.chip-info{
  border-color:color-mix(in srgb, var(--tint-hue) calc(var(--tint-edge) * 100%), transparent);
  background:color-mix(in srgb, var(--tint-hue) calc(var(--tint-fill) * 100%), transparent);
}
.chip-brand{--tint-hue:var(--primary-500);color:var(--primary-400)}
.chip-success{--tint-hue:var(--success);color:var(--success)}
.chip-warn{--tint-hue:var(--warning);color:var(--warning)}
.chip-danger{--tint-hue:var(--danger);color:var(--danger)}
.chip-info{--tint-hue:var(--info);color:var(--info)}
/* pressable = the whole object is the target. Never combined with a dismiss. */
button.chip,a.chip{cursor:pointer;text-decoration:none}
button.chip:hover,a.chip:hover{border-color:var(--obsidian-600)}
button.chip:active,a.chip:active{background:var(--obsidian-700)}
button.chip[aria-pressed="true"]{border-color:var(--primary-500);color:var(--primary-400)}
button.chip:disabled{opacity:var(--opacity-disabled);cursor:not-allowed}
/* dismissible = the chip is static and the button is the only target */
.chip-dismiss{
  all:unset;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;
  width:var(--icon-xs);height:var(--icon-xs);border-radius:var(--r-full);
  color:var(--obsidian-300);line-height:var(--lh-tight);
  transition:color var(--d-quick) var(--ease-standard);
}
.chip-dismiss{position:relative}
/* The dismiss is the close glyph at --icon-xs, its box the glyph's own square (v5.3.0): the mark ends on the padding
   edge, as the label starts on the other one (§ Size › Inline symmetry). The text × it replaces was narrower than its
   16px box and sat 4px in. */
.chip-dismiss .icon{width:var(--icon-xs);height:var(--icon-xs)}
.chip[hidden]{display:none}   /* a chip behind the +N */
/* The add chip: a round + at the end of a removable collection, the trigger of a Menu of suggestions (v5.3.0). */
.chip-add{justify-content:center;aspect-ratio:1;padding:var(--s-1);color:var(--obsidian-200);cursor:pointer}
.chip-add .icon{width:var(--icon-xs);height:var(--icon-xs)}
.chip-dismiss::before{content:"";position:absolute;top:50%;left:50%;width:var(--target-touch);height:var(--target-touch);transform:translate(-50%,-50%)}
.chip-dismiss:hover{color:var(--obsidian-100)}
.chip-dismiss:focus-visible{
  outline:var(--focus-width) solid var(--obsidian-100);outline-offset:calc(-1 * var(--s-px));
  box-shadow:var(--ring-halo);
}
@media (prefers-reduced-motion: reduce){
  .chip,.chip-dismiss{transition:none}
}

/* ─────────── DATA-VIZ ─────────── */
/* A plot with two drawings: the wide one, and one for small screens with its own proportions, where
   points and labels stay readable instead of shrinking with the width. One shows at a time. */
.chart-plot{position:relative}
.chart-plot > svg{display:block;width:100%;height:auto}
/* Labels of a plot: HTML over the drawing, positioned in % of its viewBox, sized by tokens. The drawing scales with
   the card; the text stays at its token at every width. No <text> inside a plot's svg. */
.chart-label{position:absolute;font-family:var(--font-mono);font-size:var(--t-caption);letter-spacing:var(--tr-mono);line-height:1;white-space:nowrap;translate:0 -50%;pointer-events:none}
.chart-label-axis{color:var(--obsidian-200)}
.chart-label-value{color:var(--obsidian-100)}
.chart-label-center{translate:-50% -50%}
.chart-label-end{translate:-100% -50%}
/* Horizontal bars: the labels take the column their longest needs, the drawing takes what is left, and the last
   column holds the widest value, so a full bar's label still fits. A gutter made of viewBox units shrank with the
   card while the text stayed at its token, and the two met under 330px of plot. */
.chart-bars{display:grid;grid-template-columns:max-content minmax(0,1fr) max-content}
.chart-bars-axis{display:grid;grid-auto-rows:minmax(0,1fr);margin-inline-end:var(--s-3)}
.chart-bars > .chart-bars-reserve,.chart-bars-axis > .chart-label{position:static;translate:none;align-self:center}
.chart-bars > .chart-bars-reserve{visibility:hidden}
/* A bar chart with room reads its labels one step up, --t-small: from --bp-sm of the card's own width, not the
   screen's, so a narrow card on a desktop (the Anatomy sample) keeps --t-caption and its rows their air. */
.chart-card:has(> .chart-bars){container-type:inline-size}
@container (min-width: 480px){.chart-bars .chart-label{font-size:var(--t-small)}}
/* Labels centre with the translate property: [data-fade] owns transform, the two compose.
   Timeline (§ 3.42): the gantt is a plot; under the width its lanes need it scrolls sideways, its labels at their tokens. */
.timeline-scroll{overflow-x:auto;overscroll-behavior-x:contain}
.timeline-plot{min-width:calc(var(--s-32) * 5)}
.timeline-lane{position:absolute;translate:0 -50%;font-size:var(--t-small);font-weight:500;line-height:1;color:var(--obsidian-100);white-space:nowrap}
.timeline-meta{position:absolute;translate:0 -50%;font-family:var(--font-mono);font-size:var(--t-micro);letter-spacing:var(--tr-mono);text-transform:uppercase;line-height:1;color:var(--obsidian-200);white-space:nowrap}
.timeline-bar-label{position:absolute;translate:0 -50%;font-size:var(--t-micro);font-weight:700;line-height:1;color:var(--primary-950);white-space:nowrap}
.timeline-bar-label-dark{color:var(--primary-100)}
.timeline-today{position:absolute;translate:-50% -50%;padding:var(--s-0-5) var(--s-1);border-radius:var(--r-xs);background:var(--primary-200);color:var(--primary-950);font-family:var(--font-mono);font-size:var(--t-micro);font-weight:700;letter-spacing:var(--tr-mono);text-transform:uppercase;line-height:1}
/* Bars keep two columns down to --bp-md (one column at 900 made each bar chart twice its size); under it the labels grow so they stay readable at phone scale. */
@media (max-width: 900px){.grid-2.chart-grid{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media (max-width: 720px){.grid-2.chart-grid{grid-template-columns:1fr}}
.chart-plot-sm{display:none}
@media (max-width: 720px){.chart-plot-lg{display:none}.chart-plot-sm{display:block}}
.chart-card{background:var(--obsidian-800);color:var(--obsidian-100);border:var(--bw-1) solid var(--obsidian-700);border-radius:var(--r-lg);padding:var(--s-6)}
.chart-head{display:flex;align-items:baseline;justify-content:space-between;gap:var(--s-4);margin-bottom:var(--s-5)}
.chart-head > :first-child{min-width:0}
.chart-head .t{font-size:var(--t-body);font-weight:600}
.chart-head .s{font-family:var(--font-mono);font-size:var(--t-caption);letter-spacing:var(--tr-mono);color:var(--obsidian-300);text-transform:uppercase}
.chart-big{font-size:var(--t-h2);font-weight:700;line-height:var(--lh-tight);letter-spacing:var(--tr-tight);font-variant-numeric:tabular-nums;margin:var(--s-2) 0}
.chart-big.accent{background:var(--grad-signal);-webkit-background-clip:text;background-clip:text;color:transparent}
.chart-delta{font-family:var(--font-mono);font-size:var(--t-caption);letter-spacing:var(--tr-mono);color:var(--success)}
.chart-delta.neg{color:var(--danger)}
/* v5.0.0 — the legend of a chart with two or more series: a Swatch (§ 3.36) before each name, under the plot */
.chart-legend{list-style:none;margin:var(--s-3) 0 0;padding:0;display:flex;flex-wrap:wrap;gap:var(--s-4);font-size:var(--t-small);color:var(--obsidian-200)}
.chart-legend li{display:inline-flex;align-items:center;gap:var(--s-2);white-space:nowrap}

/* ─────────── VOICE / TONE ─────────── */
/* A States row (§ 3.0.3, v5.3.0): one control per state, in a row like the button variants, each captioned. A
   caption of two words takes two lines (min-content). Focus and press are forced with data-force, which the page
   script turns into the stylesheet's own :focus-visible and :active rules. */
.states-row{display:flex;flex-wrap:wrap;align-items:flex-start;gap:var(--s-8);padding:var(--s-8)}
.state{display:flex;flex-direction:column;align-items:center;gap:var(--s-3)}
.state-cap{width:min-content;text-align:center;font-family:var(--font-mono);font-size:var(--t-micro);letter-spacing:var(--tr-mono);text-transform:uppercase;line-height:var(--lh-tight);color:var(--obsidian-300)}
.do-dont{display:grid;grid-template-columns:1fr 1fr;gap:var(--s-4)}
.do-dont + .do-dont{margin-top:var(--s-4)}
@media (max-width:900px){.do-dont{grid-template-columns:1fr}}
.do, .dont{border:var(--bw-1) solid var(--obsidian-800);border-radius:var(--r-lg);padding:var(--s-5);background:var(--obsidian-900)}
.do{border-left:var(--bw-2) solid var(--success)}
.dont{border-left:var(--bw-2) solid var(--danger)}
.do .hd, .dont .hd{display:flex;align-items:center;gap:var(--s-2);font-family:var(--font-mono);font-size:var(--t-caption);letter-spacing:var(--tr-mono);text-transform:uppercase;margin-bottom:var(--s-3)}
.do .hd{color:var(--success)}
.dont .hd{color:var(--danger)}
/* Usage — when to use a component, and what to use instead (site chrome, § 3.0.3). Neutral on purpose: it is not a Do / Don't. */
.usage{display:grid;grid-template-columns:1fr 1fr;gap:var(--s-4);margin-bottom:var(--s-16)}
@media (max-width:900px){.usage{grid-template-columns:1fr}}
.usage-col{border:var(--bw-1) solid var(--border-subtle);border-radius:var(--r-lg);padding:var(--s-5);background:var(--surface-sunken)}
.usage .hd{font-family:var(--font-mono);font-size:var(--t-caption);letter-spacing:var(--tr-mono);text-transform:uppercase;color:var(--obsidian-300);margin-bottom:var(--s-3)}
.usage ul{margin:0;padding-left:var(--s-5);display:grid;gap:var(--s-2);color:var(--obsidian-200);font-size:var(--t-body);line-height:var(--lh-normal)}
.usage-flat{margin:var(--s-5) 0 0;gap:var(--s-5)}
.usage-flat .usage-col{border:0;padding:0;background:transparent}
.usage-flat ul{font-size:var(--t-small);color:var(--obsidian-300)}
.table-registry td{vertical-align:top}
.table-registry .muted{font-size:var(--t-caption);margin-top:var(--s-1)}
.table-registry .badge{white-space:nowrap}
.do p, .dont p{margin:0;font-size:var(--t-small);color:var(--obsidian-100);line-height:var(--lh-loose)}

/* ─────────── CASE STUDY APPLIED ─────────── */
/* v5.0.0, aligned to the portfolio that runs it (angelomacaione.com): long reading on the --t-h6 body,
   one centred column for each section's text and figures, real figures under a caption, outcome stat
   cards, a closing note, More cases as linked Cards. The hero keeps the animated mark on its right: a placeholder
   for the project's own object (a render, a 3D scene). */
.cs-hero{
  position:relative;overflow:hidden;
  margin-bottom:var(--s-10);padding:var(--s-16) var(--s-10);
  border:var(--bw-1) solid var(--obsidian-800);border-radius:var(--r-xl);
  background:var(--light-hero), var(--obsidian-900);
  color:var(--obsidian-100);
  --cube:clamp(120px, 26%, 220px); /* the mark scales with the hero; the text column keeps clear of it */
}
.cs-hero .eyebrow{margin:0 0 var(--s-4);font-family:var(--font-mono);font-size:var(--t-caption);letter-spacing:var(--tr-mono);text-transform:uppercase;color:var(--primary-400)}
.cs-hero-title{margin:0 0 var(--s-5);max-width:min(18ch, calc(100% - var(--cube) - var(--s-6)));font-size:var(--t-h2);font-weight:500;line-height:var(--lh-tight);letter-spacing:var(--tr-tight)}
.cs-hero-lede{margin:0;max-width:min(56ch, calc(100% - var(--cube) - var(--s-6)));font-size:var(--t-h6);line-height:var(--lh-normal);color:var(--obsidian-200)}
.cs-hero .cube{
  position:absolute;right:var(--s-10);top:50%;transform:translateY(-50%);
  width:var(--cube);height:auto;aspect-ratio:1;filter:drop-shadow(0 0 48px color-mix(in srgb, var(--primary-500) calc(var(--tint-glow) * 100%), transparent));
}
.cs-meta{position:relative;display:flex;flex-wrap:wrap;gap:var(--s-6) var(--s-10);margin-top:var(--s-6)}
.cs-meta .item{display:flex;flex-direction:column;gap:var(--s-2)}
.cs-meta .k{font-family:var(--font-mono);font-size:var(--t-micro);letter-spacing:var(--tr-mono);text-transform:uppercase;color:var(--obsidian-300)}
.cs-meta .v{font-size:var(--t-small);font-weight:500;color:var(--obsidian-100)}
.cs-meta .tags{display:flex;flex-wrap:wrap;gap:var(--s-2);margin:0;padding:0;list-style:none}
.cs-dossier{
  display:grid;grid-template-columns:repeat(4,1fr);gap:var(--s-4);
  margin:0 0 var(--s-10);padding:var(--s-6);
  background:var(--obsidian-900);border:var(--bw-1) solid var(--obsidian-800);border-radius:var(--r-lg);
}
@media(max-width:900px){.cs-dossier{grid-template-columns:repeat(2,1fr)}}
.cs-dossier .item{display:flex;flex-direction:column;gap:var(--s-1)}
.cs-dossier .k{font-family:var(--font-mono);font-size:var(--t-micro);letter-spacing:var(--tr-mono);text-transform:uppercase;color:var(--obsidian-300)}
.cs-dossier .v{margin:0;font-size:var(--t-small);font-weight:500;color:var(--obsidian-100)}

/* Sections: one centred column, 36em of the --t-h6 body (about 65 characters a line), for eyebrow, title, text and figures. */
.cs-section{margin:0 0 var(--s-12);--cs-col:calc(var(--t-h6) * 36)}
.cs-section > :is(.eyebrow,.cs-section-title,.cs-section-body){max-width:var(--cs-col);margin-left:auto;margin-right:auto}
.cs-section .eyebrow{display:flex;align-items:center;gap:var(--s-2);margin-top:0;margin-bottom:var(--s-2);font-family:var(--font-mono);font-size:var(--t-caption);letter-spacing:var(--tr-mono);text-transform:uppercase;color:var(--primary-400)}
.cs-section .eyebrow::before{content:"";width:20px;height:1px;background:var(--primary-500)}
.cs-section-title{margin:0 0 var(--s-4);font-size:var(--t-h3);font-weight:400;line-height:var(--lh-snug);letter-spacing:var(--tr-snug);color:var(--obsidian-100)}
.cs-section-body{font-size:var(--t-h6);line-height:var(--lh-loose);color:var(--obsidian-100)}
.cs-section-body :is(p,ul,ol){max-width:36em}
.cs-section-body :where(p,ul,ol,figure){margin:0}
.cs-section-body > * + *,.cs-point-body > * + *{margin-top:var(--s-4)}
.cs-section-body :is(* + .cs-figure,.cs-figure + *){margin-top:var(--s-8)}
.cs-section-body strong{font-weight:700}
.cs-pull{
  border-left:var(--bw-2) solid var(--primary-500);padding:var(--s-3) var(--s-6);
  font-size:var(--t-h5);font-weight:500;line-height:var(--lh-snug);letter-spacing:var(--tr-snug);
  color:var(--obsidian-100);max-width:calc(var(--t-h6) * 36);margin:var(--s-8) auto;
}
/* Key points: the dot on the title's line, the text under the title, a Divider (§ 3.34) between points. */
.cs-points{display:flex;flex-direction:column;gap:var(--s-6)}
.cs-section-body > .cs-points{margin-top:var(--s-6)}
.cs-section-body > .cs-points:first-child{margin-top:0}
.cs-point{display:grid;grid-template-columns:var(--s-4) minmax(0,1fr);column-gap:var(--s-4);row-gap:var(--s-2)}
.cs-point::before{content:"";grid-row:1;width:var(--s-4);height:var(--s-4);border-radius:var(--r-full);background:var(--primary-500);align-self:center}
.cs-point-title{grid-column:2;grid-row:1;margin:0;font-size:var(--t-h6);font-weight:700;letter-spacing:var(--tr-snug);line-height:var(--lh-snug);color:var(--obsidian-100)}
.cs-point-body{grid-column:2}
/* Figure: a real image or an inline diagram, never enlarged past its file, opening the Lightbox (§ 3.22).
   The caption sits under it: over a light image an overlaid caption would not read. */
.cs-img{
  position:relative;display:block;width:fit-content;max-width:100%;margin:0 auto;padding:0;
  border:var(--bw-1) solid var(--obsidian-800);border-radius:var(--r-lg);overflow:hidden;
  background:var(--obsidian-900);cursor:zoom-in;font:inherit;color:inherit;
  transition:border-color var(--d-quick) var(--ease-standard), box-shadow var(--d-base) var(--ease-decel);
}
.cs-img img{display:block;max-width:100%;height:auto}
.cs-img > svg{display:block;width:100%;height:auto}
.cs-img:has(> svg){width:100%}
.cs-img:hover,
.cs-img:focus-visible{
  border-color:var(--primary-500);
  box-shadow:var(--sh-glow);
  outline:none;
}
.cs-img-hint{
  position:absolute;top:var(--s-3);right:var(--s-3);
  display:inline-flex;align-items:center;gap:var(--s-1);
  padding:var(--s-1) var(--s-2);
  background:var(--surface-glass);backdrop-filter:blur(var(--blur-glass));
  border:var(--bw-1) solid var(--obsidian-700);border-radius:var(--r-md);
  font-family:var(--font-mono);font-size:var(--t-micro);letter-spacing:var(--tr-mono);color:var(--obsidian-200);
  opacity:0;transform:translateY(-4px);pointer-events:none;
  transition:opacity var(--d-quick) var(--ease-standard), transform var(--d-quick) var(--ease-standard);
}
.cs-img-hint .icon{width:var(--icon-xs);height:var(--icon-xs)}
.cs-img:hover .cs-img-hint,
.cs-img:focus-visible .cs-img-hint{opacity:1;transform:translateY(0)}
.cs-figure-caption{max-width:36em;margin:var(--s-3) auto 0;font-size:var(--t-small);line-height:var(--lh-normal);color:var(--obsidian-300);text-align:center}
.cs-figure-caption .n{margin-right:var(--s-2);font-family:var(--font-mono);font-size:var(--t-caption);letter-spacing:var(--tr-mono);text-transform:uppercase;color:var(--obsidian-300)}
/* Outcome: the numbers as stat cards, before the text. Two or four go two by two, three share a row. */
.cs-stats{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--s-4);margin:0;padding:0;list-style:none}
.cs-section-body .cs-stats{max-width:none}
.cs-stats > .chart-card{display:flex;flex-direction:column;font-size:var(--t-body);line-height:var(--lh-normal)} /* the reading column runs larger; a stat reads the same everywhere */
.cs-stats .chart-delta{margin-top:auto}
.cs-stats[data-count="2"],.cs-stats[data-count="4"]{grid-template-columns:repeat(2,minmax(0,1fr))}
/* Closing note of the Reflection (confidentiality, a source): under a rule, a mono label, small type. */
.cs-note{margin-top:var(--s-10);padding-top:var(--s-5);border-top:var(--bw-1) solid var(--obsidian-700);font-size:var(--t-small);line-height:var(--lh-normal);color:var(--obsidian-300)}
.cs-section-body > .cs-note{margin-top:var(--s-10)}
.cs-note-label{display:block;margin-bottom:var(--s-2);font-family:var(--font-mono);font-size:var(--t-caption);letter-spacing:var(--tr-mono);text-transform:uppercase;color:var(--obsidian-300)}
/* More cases: three project Cards, each one link, as wide as the hero. */
.cs-more{margin-top:var(--s-16)}
.cs-more > :is(.eyebrow,.cs-section-title){max-width:none;margin-left:0;margin-right:0}
.cs-more .eyebrow{display:flex;align-items:center;gap:var(--s-2);margin:0 0 var(--s-2);font-family:var(--font-mono);font-size:var(--t-caption);letter-spacing:var(--tr-mono);text-transform:uppercase;color:var(--primary-400)}
.cs-more .eyebrow::before{content:"";width:20px;height:1px;background:var(--primary-500)}
.cs-more-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--s-4);margin:var(--s-6) 0 0;padding:0;list-style:none}
.cs-card{
  display:flex;flex-direction:column;height:100%;padding:var(--s-6);
  background:var(--obsidian-800);border:var(--bw-1) solid var(--obsidian-700);border-radius:var(--r-lg);color:inherit;text-decoration:none;
  transition:border-color var(--d-quick) var(--ease-standard), box-shadow var(--d-quick) var(--ease-standard);
}
.cs-card:hover{border-color:var(--obsidian-600);box-shadow:var(--sh-2)}
.cs-card:focus-visible{outline:var(--focus-width) solid var(--obsidian-100);outline-offset:var(--focus-offset);box-shadow:var(--ring-halo)}
.cs-card-meta{margin-bottom:var(--s-4);font-family:var(--font-mono);font-size:var(--t-micro);letter-spacing:var(--tr-mono);text-transform:uppercase;color:var(--obsidian-300)}
.cs-card-media{display:block;margin:0 0 var(--s-5);border-radius:var(--r-md);overflow:hidden;aspect-ratio:480 / 315}
.cs-card-media > *{display:block;width:100%;height:100%;object-fit:cover;transition:transform var(--d-slow) var(--ease-decel)}
.cs-card:hover .cs-card-media > *,.cs-card:focus-visible .cs-card-media > *{transform:scale(1.05)}
.cs-card-title{margin:0 0 var(--s-1);font-size:var(--t-lead);font-weight:500;line-height:var(--lh-snug);letter-spacing:var(--tr-snug);color:var(--obsidian-100)}
.cs-card-text{margin:0 0 var(--s-4);font-size:var(--t-small);line-height:var(--lh-loose);color:var(--obsidian-300)}
.cs-card-tags{display:flex;flex-wrap:wrap;gap:var(--s-2);margin:auto 0 0;padding:0;list-style:none}
@media(max-width:900px){.cs-more-grid{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media(max-width:480px){.cs-more-grid,.cs-stats{grid-template-columns:1fr}}
@media(prefers-reduced-motion:reduce){
  .cs-card,.cs-card-media > *{transition:none}
  .cs-card:hover .cs-card-media > *,.cs-card:focus-visible .cs-card-media > *{transform:none}
}

/* ─────────── PIE / DONUT CHART ─────────── */
.pie-wrap{
  display:grid;
  grid-template-columns:minmax(0,1fr) minmax(0,1fr);
  gap:var(--s-6);
  align-items:center;
  margin-top:var(--s-4);
}
.pie-plot{position:relative;width:100%;max-width:220px;margin-inline:auto}
.pie{
  width:100%;
  height:auto;
  display:block;
}
.pie-center{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--s-1);pointer-events:none}
.pie-total{font-size:var(--t-h4);font-weight:700;letter-spacing:var(--tr-tight);line-height:1;color:var(--obsidian-100)}
.pie-caption{font-family:var(--font-mono);font-size:var(--t-micro);letter-spacing:var(--tr-mono);text-transform:uppercase;color:var(--obsidian-300)}
.pie-legend{
  list-style:none;margin:0;padding:0;
  display:flex;flex-direction:column;gap:var(--s-2);
}
.pie-legend li{
  display:grid;
  grid-template-columns:12px 1fr auto;
  align-items:center;
  gap:var(--s-3);
  padding:var(--s-2) var(--s-3);
  border:var(--bw-1) solid var(--obsidian-800);
  border-radius:var(--r-md);
  background:var(--obsidian-850);
  transition:border-color var(--d-quick) var(--ease-standard), background var(--d-quick) var(--ease-standard);
}
.pie-legend li:hover{border-color:var(--obsidian-700);background:var(--obsidian-800)}
.pie-legend .lbl{
  font-size:var(--t-small);color:var(--obsidian-100);letter-spacing:var(--tr-snug);
}
.pie-legend .pct{
  font-family:var(--font-mono);font-size:var(--t-caption);color:var(--obsidian-300);letter-spacing:var(--tr-mono);
}
@media (max-width: 720px){
  .pie-wrap{grid-template-columns:1fr;gap:var(--s-5)}
}

/* ─────────── LIGHTBOX ─────────── */
.lightbox{
  position:fixed;inset:0;z-index:var(--z-overlay);
  display:flex;align-items:center;justify-content:center;
  padding:var(--s-8);
  background:var(--scrim);
  backdrop-filter:blur(var(--blur-veil));
  opacity:0;
  pointer-events:none;
  transition:opacity var(--d-quick) var(--ease-accel);
}
.lightbox.open{opacity:1;pointer-events:auto;transition:opacity var(--d-quick) var(--ease-decel)}
.lightbox-content{
  position:relative;display:flex;flex-direction:column;align-items:center;gap:var(--s-3);max-width:1400px;
  transform:scale(0.96);
  transition:transform var(--d-quick) var(--ease-accel);  /* leaves on the backdrop's clock, like the Modal */
}
.lightbox-img,.lightbox-svg{display:block;max-width:100%;max-height:calc(100vh - var(--s-20) - var(--s-8));width:auto;height:auto;border:var(--bw-1) solid var(--obsidian-700);border-radius:var(--r-lg);background:var(--obsidian-900);box-shadow:var(--sh-4)}
.lightbox-svg svg{display:block;width:min(1000px, calc(100vw - 2 * var(--s-8)));height:auto}
.lightbox-img[hidden],.lightbox-svg[hidden]{display:none}
.lightbox-caption{margin:0;font-size:var(--t-small);color:var(--obsidian-200);text-align:center}
.lightbox.open .lightbox-content{transform:scale(1);transition:transform var(--d-base) var(--ease-decel)}
.lightbox-close{
  position:absolute;top:var(--s-3);right:var(--s-3);
  width:36px;height:36px;padding:0;
  display:inline-flex;align-items:center;justify-content:center;
  border:var(--bw-1) solid var(--obsidian-700);
  border-radius:var(--r-md);
  background:var(--surface-glass);backdrop-filter:blur(var(--blur-glass));
  color:var(--obsidian-100);
  cursor:pointer;
  transition:border-color var(--d-quick) var(--ease-standard), background var(--d-quick) var(--ease-standard);
}
.lightbox-close:hover{border-color:var(--obsidian-600);background:var(--obsidian-800)}
@media (prefers-reduced-motion: reduce){
  .cs-img,.cs-img-hint,.lightbox,.lightbox-content{transition:none}
}

/* ─────────── GRID OVERLAY DEMO ─────────── */
.grid-demo{position:relative;background:var(--obsidian-900);border:var(--bw-1) solid var(--obsidian-800);border-radius:var(--r-lg);padding:var(--s-6);overflow:hidden}
.grid-demo .cols{display:grid;grid-template-columns:repeat(12,1fr);gap:var(--s-3)}
.grid-demo .col{height:80px;background:color-mix(in srgb, var(--primary-500) calc(var(--tint-fill) * 100%), transparent);border:var(--bw-1) dashed color-mix(in srgb, var(--primary-500) calc(var(--tint-edge) * 100%), transparent);border-radius:var(--r-xs);display:grid;place-items:center;font-family:var(--font-mono);font-size:var(--t-micro);color:var(--primary-400);letter-spacing:var(--tr-mono)}

/* ─────────── ALERT — inline, in-flow, never dismissed on a timer ───────────
   The § 6 floor forbids timed dismissal (#6): an alert stays until the
   condition clears or the reader dismisses it. Semantics ride the left
   rule + the icon, never the fill — the surface stays --obsidian-850 in
   every variant so the 85/10/5 budget is untouched. */
.alert{
  display:grid;grid-template-columns:auto minmax(0,1fr);
  column-gap:var(--s-3);row-gap:var(--s-1);align-items:center;
  padding:var(--s-3) var(--s-4);background:var(--obsidian-850);border:var(--bw-1) solid var(--obsidian-800);border-left:var(--bw-2) solid var(--primary-500);
  border-radius:var(--r-md);font-size:var(--t-small);color:var(--obsidian-200);
}
.alert .tag{font-family:var(--font-mono);font-size:var(--t-micro);letter-spacing:var(--tr-mono);color:var(--primary-400);text-transform:uppercase}
.alert-icon{grid-column:1;grid-row:1;width:16px;height:16px;color:var(--primary-400)}
.alert-title{grid-column:2;grid-row:1;font-weight:600;color:var(--obsidian-100);min-width:0}
/* Single-line alert: the body sits beside the icon.
   Titled alert: the body drops to its own row and returns to the icon's
   left edge — the title is what the icon labels, not the paragraph. */
.alert-body{grid-column:2;grid-row:1;min-width:0;overflow-wrap:anywhere}
.alert:has(.alert-title) .alert-body{grid-column:1 / -1;grid-row:2}

/* Entrance — the system's reveal grammar, opt-in via [data-alert-fade] */
[data-alert-fade]{opacity:0;transform:translateY(12px);transition:opacity var(--d-slow) var(--ease-decel), transform var(--d-slow) var(--ease-decel)}
[data-alert-fade].is-in{opacity:1;transform:translateY(0)}
@media (prefers-reduced-motion: reduce){
  [data-alert-fade]{opacity:1;transform:none;transition:none}
}

.alert-success{border-left-color:var(--success)}
.alert-success .alert-icon,.alert-success .tag{color:var(--success)}
.alert-warn{border-left-color:var(--warning)}
.alert-warn .alert-icon,.alert-warn .tag{color:var(--warning)}
.alert-danger{border-left-color:var(--danger)}
.alert-danger .alert-icon,.alert-danger .tag{color:var(--danger)}
.alert-info{border-left-color:var(--info)}
.alert-info .alert-icon,.alert-info .tag{color:var(--info)}



/* ─────────── A11Y: focus visibility + reduced motion ─────────── */
.skip-link{
  position:absolute;top:calc(-1 * var(--s-24));left:var(--s-3);z-index:var(--z-max);
  padding:var(--s-3) var(--s-4);background:var(--primary-500);color:var(--obsidian-950);
  font-family:var(--font-sans);font-weight:600;font-size:var(--t-small);
  border-radius:var(--r-md);text-decoration:none;
}
.skip-link:focus{top:var(--s-3)}
.btn:focus-visible,
.nav-item:focus-visible,
.menu-toggle:focus-visible,
.chip:focus-visible,
.chip-add:focus-visible,
.tab:focus-visible,
.segmented-item:focus-visible,
.select-trigger:focus-visible,
.lightbox-close:focus-visible,
.replay-btn:focus-visible,
.tp-wheel-item:focus-visible {
  outline:var(--focus-width) solid var(--obsidian-100);
  outline-offset:var(--focus-offset);
  box-shadow:var(--ring-halo);
}
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration:0.01ms !important;
    animation-iteration-count:1 !important;
    transition-duration:0.01ms !important;
    scroll-behavior:auto !important;
  }
  /* The select panel's box is measured and written by script at open: it never
     transitions. The 0.01ms above gives every property a transition, and the
     script read the start of one and opened the panel off screen (v5.0.0). */
  .select-menu{transition:none !important}
}


/* ─────────── REPLAY BUTTON ─────────── */
.replay-btn{
  display:inline-flex;align-items:center;gap:var(--s-1);
  font-family:var(--font-sans);font-size:var(--t-caption);font-weight:500;letter-spacing:var(--tr-snug);
  color:var(--obsidian-200);background:var(--obsidian-850);
  border:var(--bw-1) solid var(--obsidian-700);border-radius:var(--r-full);
  padding:var(--s-1) var(--s-3);cursor:pointer;
  transition:all var(--d-quick) var(--ease-standard);
}
.replay-btn:hover{
  color:var(--primary-300);border-color:var(--primary-500);
  background:color-mix(in srgb, var(--primary-500) calc(var(--tint-fill) * 100%), transparent);
}
.replay-btn svg{width:var(--icon-xs);height:var(--icon-xs);transition:transform var(--d-base) var(--ease-standard)}
.replay-btn:hover svg{transform:rotate(-180deg)}
.replay-btn:active svg{transform:rotate(-360deg);transition-duration:var(--d-slow)}


/* ─────────── fade-in-up utility ─────────── */
[data-fade]{opacity:0;transform:translateY(12px);transition:opacity var(--d-slow) var(--ease-decel), transform var(--d-slow) var(--ease-decel)}
[data-fade].is-in{opacity:1;transform:translateY(0)}
@media (prefers-reduced-motion: reduce){
  [data-fade]{opacity:1;transform:none;transition:none}
}

/* ─────────── TABS ─────────── */
.tabs{
  position:relative;display:flex;
  border-bottom:var(--bw-1) solid var(--obsidian-800);
  padding:0 var(--s-4);
}
.tab{
  background:none;border:0;cursor:pointer;
  padding:var(--s-3) var(--s-4);
  font-family:var(--font-sans);font-size:var(--t-small);font-weight:500;
  color:var(--obsidian-300);
  transition:color var(--d-quick) var(--ease-standard);
  position:relative;z-index:1;
}
.tab:hover{color:var(--obsidian-100)}
.tab:active{color:var(--obsidian-300)}
.tab.active{color:var(--obsidian-100);font-weight:600}
.tab-indicator{
  position:absolute;left:0;bottom:calc(-1 * var(--s-px));
  height:2px;width:0;
  background:var(--primary-500);
  transition:transform var(--d-base) var(--ease-decel), width var(--d-base) var(--ease-decel);
  pointer-events:none;
  will-change:transform,width;
}
.tab-panels{position:relative}
.tab-panel{
  display:none;
  padding:var(--s-6);
  color:var(--obsidian-300);font-size:var(--t-small);line-height:1.7;
  opacity:0;transform:translateY(6px);
  transition:opacity var(--d-quick) var(--ease-standard), transform var(--d-quick) var(--ease-standard);
}
.tab-panel.active{display:block}
.tab-panel.is-in{opacity:1;transform:translateY(0)}
@media (prefers-reduced-motion: reduce){
  .tab-indicator{transition:none}
  .tab-panel{transition:none;opacity:1;transform:none}
}

/* ─── § 3.28 Segmented control (v5.0.0): two or three views of one thing, one thumb that travels ─── */
.segmented{
  position:relative;display:inline-flex;align-items:stretch;
  padding:var(--s-1);
  background:var(--surface-sunken);
  border:var(--bw-1) solid var(--border-subtle);
  border-radius:var(--r-full);
}
.segmented-fill{display:flex}
.segmented-item{
  position:relative;z-index:1;
  display:inline-flex;align-items:center;justify-content:center;gap:var(--s-2);
  height:var(--s-10);padding:0 var(--s-4);
  background:transparent;border:none;border-radius:var(--r-full);cursor:pointer;
  font-family:var(--font-sans);font-size:var(--t-small);font-weight:500;line-height:1;white-space:nowrap;
  color:var(--obsidian-300);
  transition:color var(--d-quick) var(--ease-standard);
}
.segmented-fill .segmented-item{flex:1 1 0}
.segmented-item:hover{color:var(--obsidian-100)}
.segmented-item:active{color:var(--obsidian-300)}
.segmented-item[aria-selected="true"]{color:var(--obsidian-100)}
.segmented-thumb{
  position:absolute;top:var(--s-1);bottom:var(--s-1);left:0;width:0;
  background:var(--obsidian-700);
  border:var(--bw-1) solid var(--border-input);
  border-radius:var(--r-full);
  box-shadow:var(--sh-1);
  transition:transform var(--d-base) var(--ease-decel), width var(--d-base) var(--ease-decel);
  pointer-events:none;
  will-change:transform,width;
}
.segmented-panel{
  opacity:0;transform:translateY(6px);
  transition:opacity var(--d-quick) var(--ease-standard), transform var(--d-quick) var(--ease-standard);
}
.segmented-panel.is-in{opacity:1;transform:translateY(0)}
@media (prefers-reduced-motion: reduce){
  .segmented-item,.segmented-thumb{transition:none}
  .segmented-panel{transition:none;opacity:1;transform:none}
}

/* =========================================================
   MOBILE — sidebar becomes a drawer, hamburger in topbar
   ========================================================= */

/* hamburger (hidden on desktop) */
.menu-toggle{
  display:none;
  width:40px;height:40px;
  border:var(--bw-1) solid var(--obsidian-700);
  border-radius:var(--r-md);
  background:var(--obsidian-850);
  padding:0;
  align-items:center;justify-content:center;
  color:var(--obsidian-100);
  cursor:pointer;
  transition:border-color var(--d-quick) var(--ease-standard), background var(--d-quick) var(--ease-standard);
  flex:0 0 auto;
}
.menu-toggle:hover{border-color:var(--primary-500)}
.menu-toggle-bars{
  display:inline-flex;flex-direction:column;gap:var(--s-1);
  width:18px;
}
.menu-toggle-bars span{
  display:block;height:2px;background:currentColor;border-radius:1px;
  transition:transform var(--d-quick) var(--ease-standard), opacity var(--d-quick) var(--ease-standard);
  transform-origin:center;
}
.menu-toggle[aria-expanded="true"] .menu-toggle-bars span:nth-child(1){transform:translateY(6px) rotate(45deg)}
.menu-toggle[aria-expanded="true"] .menu-toggle-bars span:nth-child(2){opacity:0}
.menu-toggle[aria-expanded="true"] .menu-toggle-bars span:nth-child(3){transform:translateY(-6px) rotate(-45deg)}

/* scrim */
.sidebar-scrim{
  display:none;
  position:fixed;inset:0;
  background:var(--scrim);
  backdrop-filter:blur(var(--blur-veil));
  z-index:var(--z-scrim);
  opacity:0;
  transition:opacity var(--d-quick) var(--ease-standard);
}
.sidebar-scrim.open{display:block;opacity:1}

@media (max-width: 900px){
  .app{grid-template-columns:1fr}

  .menu-toggle{display:inline-flex}

  .sidebar{
    position:fixed;top:0;left:0;
    width:min(86vw, 320px);
    height:100vh;
    transform:translateX(-100%);
    transition:transform var(--d-base) var(--ease-decel);
    z-index:var(--z-menu);
    border-right:var(--bw-1) solid var(--obsidian-800);
    box-shadow:8px 0 32px color-mix(in srgb, var(--obsidian-950) calc(var(--tint-edge-deep) * 100%), transparent);
  }
  .sidebar.open{transform:translateX(0)}
  .nav-item.active::after{display:none}

  .topbar{
    padding:var(--s-3) var(--s-5);
    gap:var(--s-3);
  }
  .topbar-actions{display:none}

  .main{--page-gutter:var(--s-5);--topbar-h:calc(var(--s-16) + var(--bw-1))}   /* the bar wraps to two rows here */
  .content{
    padding:var(--s-8) var(--page-gutter) var(--s-16);
  }

  /* collapse grids */
  .grid-2, .grid-3, .grid-4, .grid-6{grid-template-columns:minmax(0,1fr)}

  /* typography scale down */
  .page-title{font-size:var(--t-h1-fluid);max-width:none}
  .page-lede{font-size:var(--t-lead-fluid)}
  .page-header{margin-bottom:var(--s-10)}
  .subsection{margin-bottom:var(--s-12)}
  .subsection-title{font-size:var(--t-h4-fluid)}

  /* page-meta becomes wrap */
  .page-meta{flex-wrap:wrap;gap:var(--s-4)}

  /* tables & horizontal-scroll rescues */
  .table{font-size:var(--t-caption)}
  .table th,.table td{padding:var(--s-2) var(--s-3)}

  /* tabs don't overflow */
  .tabs{overflow-x:auto;scrollbar-width:none}
  .tabs::-webkit-scrollbar{display:none}
  .tab{white-space:nowrap}
}

@media (max-width: 480px){
  .topbar .breadcrumb{font-size:var(--t-micro)}
  .topbar .breadcrumb span:not(.active):not(.sep){display:none}
  .topbar .breadcrumb .sep{display:none}
  .main{--page-gutter:var(--s-4)}
  .content{padding:var(--s-6) var(--page-gutter) var(--s-12)}
  .card{padding:var(--s-5)}
}


/* ============ ACCORDION ============ */
/* Separators only. A border-top with no side borders draws a lid with no
   walls: the radius curves it at the corners and it ends in mid-air. Same
   discipline as § 3.39 Table — the row rule carries the scan. */
.accordion{display:flex;flex-direction:column;border-radius:var(--r-lg);overflow:hidden;background:var(--obsidian-950)}
.acc-item{border-bottom:var(--bw-1) solid var(--obsidian-800);background:transparent;transition:background var(--d-quick) var(--ease-decel)}
.acc-item:last-child{border-bottom:0}
.acc-item.is-open{background:color-mix(in srgb, var(--primary-500) calc(var(--tint-faint) * 100%), transparent)}
.acc-trigger{
  display:grid;
  grid-template-columns:auto minmax(0,1fr) auto;
  align-items:center;
  gap:var(--s-4);
  width:100%;
  min-height:calc(var(--s-12) + var(--s-2));
  padding:var(--s-4) var(--s-6);
  background:transparent;
  border:0;
  color:var(--obsidian-100);
  text-align:left;
  cursor:pointer;
  font:inherit;
  font-size:var(--t-body);
  letter-spacing:var(--tr-snug);
  transition:color var(--d-quick) var(--ease-decel);
}
.acc-trigger:hover{color:var(--obsidian-050)}
.acc-trigger:active{color:var(--obsidian-300)}
.acc-trigger:focus-visible{outline:var(--focus-width) solid var(--obsidian-100);outline-offset:calc(-1 * var(--focus-width));box-shadow:var(--ring-halo)}
.acc-chevron{
  display:inline-flex;align-items:center;justify-content:center;
  width:var(--icon-xs);height:var(--icon-xs);flex:0 0 var(--icon-xs);
  color:var(--obsidian-400);
  transition:transform var(--d-base) var(--ease-standard), color var(--d-quick) var(--ease-standard);
}
.acc-chevron svg{width:var(--icon-xs);height:var(--icon-xs);display:block}
.acc-item.is-open .acc-chevron{transform:rotate(90deg);color:var(--primary-400);transition:transform var(--d-base) var(--ease-decel), color var(--d-quick) var(--ease-standard)}
.acc-label{min-width:0;font-weight:500}
.acc-num{
  font-family:var(--font-mono);font-size:var(--t-caption);letter-spacing:var(--tr-mono);
  color:var(--obsidian-500);text-transform:uppercase;flex-shrink:0;
}
.acc-item.is-open .acc-num{color:var(--primary-400)}
/* Duration is chosen by distance (§ 09.3). --acc-d is set on the item by the
   controller from the measured panel height, picking one of the existing
   duration tokens — never a computed value. The fallback below is the middle
   bucket, so the component still behaves without JS.
   Direction decides the curve: the resting rule is the CLOSING ride
   (user-triggered → --ease-standard, per the § 09.3 pairing), the .is-open
   rule is the OPENING ride (system revealing → --ease-decel). --ease-accel is
   wrong here: it holds for 150ms then drops, which reads as lag, not leaving. */
.acc-panel{
  display:grid;
  grid-template-rows:0fr;
  transition:grid-template-rows var(--acc-d, var(--d-slow)) var(--ease-standard);
}
.acc-item.is-open .acc-panel{
  grid-template-rows:1fr;
  transition:grid-template-rows var(--acc-d, var(--d-slow)) var(--ease-decel);
}
.acc-panel-inner{overflow:hidden;min-height:0}
.acc-panel-body{
  padding:0 var(--s-6) var(--s-6) calc(var(--s-6) + var(--icon-xs) + var(--s-4));  /* the body starts under the label: trigger padding, chevron, gap */
  color:var(--obsidian-300);line-height:1.7;font-size:var(--t-small);
  opacity:0;transition:opacity var(--d-quick) var(--ease-decel) var(--d-instant);
}
.acc-item.is-open .acc-panel-body{opacity:1}
.acc-panel-body p{margin:0 0 var(--s-3)}
.acc-panel-body p:last-child{margin-bottom:0}
@media (prefers-reduced-motion: reduce){
  .acc-trigger,.acc-chevron,.acc-panel,.acc-panel-body,.acc-item{transition:none}
}


/* ============ A11Y FLOOR (rule cards) ============ */
.a11y-floor{
  display:grid;
  grid-template-columns:repeat(auto-fill, minmax(260px, 1fr));
  gap:var(--s-4);
}
.a11y-rule{
  position:relative;
  display:grid;
  grid-template-columns:auto minmax(0,1fr);
  gap:var(--s-4);
  align-items:start;
  padding:var(--s-6);
  background:var(--obsidian-950);
  border:var(--bw-1) solid var(--obsidian-800);
  border-radius:var(--r-md);
  transition:border-color var(--d-quick) var(--ease-decel), background var(--d-quick) var(--ease-decel);
}
.a11y-rule:hover{border-color:var(--obsidian-700);background:var(--obsidian-900)}
.a11y-rule .n{
  font-family:var(--font-mono);
  font-size:var(--t-caption);
  letter-spacing:var(--tr-mono);
  color:var(--primary-400);
  font-weight:500;
  line-height:1;
  padding-top:var(--s-1);
  flex-shrink:0;
}
.a11y-rule p{
  margin:0;
  color:var(--obsidian-200);
  font-size:var(--t-small);
  line-height:1.6;
  letter-spacing:var(--tr-snug);
}
.a11y-rule p code{
  font-family:var(--font-mono);
  font-size:var(--t-caption);
  letter-spacing:var(--tr-mono);
  color:var(--primary-300);
  background:var(--obsidian-850);
  padding:var(--s-px) var(--s-1);
  border-radius:var(--r-sm);
}
@media (prefers-reduced-motion: reduce){
  .a11y-rule{transition:none}
}


/* ============ FOCUS / KEYBOARD DEMO (§ 21.2) ============ */
.focus-row{
  margin-top:var(--s-5);
  display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--s-4);
}
.focus-demo{
  background:var(--obsidian-900);
  border:var(--bw-1) solid var(--obsidian-800);
  border-radius:var(--r-md);
  padding:var(--s-8) var(--s-6) var(--s-5);
  display:flex;flex-direction:column;align-items:flex-start;gap:var(--s-4);
  min-width:0;
}
.focus-cap{
  font-family:var(--font-mono);font-size:var(--t-micro);letter-spacing:var(--tr-mono);
  text-transform:uppercase;color:var(--obsidian-300);
}
.btn.is-focus{
  outline:var(--focus-width) solid var(--obsidian-100);
  outline-offset:var(--focus-offset);
  box-shadow:var(--ring-halo);
}
.input-focus-demo{
  background:var(--obsidian-850);
  border:var(--bw-1) solid var(--primary-500);
  border-radius:var(--r-md);
  padding:var(--s-2) var(--s-3);
  display:flex;align-items:center;gap:var(--s-1);
  width:100%;
  box-shadow:var(--ring-field);
  font-size:var(--t-small);color:var(--obsidian-100);
}
.input-focus-demo .lbl{
  font-family:var(--font-mono);font-size:var(--t-micro);letter-spacing:var(--tr-mono);
  text-transform:uppercase;color:var(--obsidian-300);margin-right:var(--s-1);
}
.input-focus-demo .val{flex:1}
.input-focus-demo .caret{
  width:1px;height:14px;background:var(--primary-400);
  animation:a11y-caret 1s steps(1) infinite;
}
@keyframes a11y-caret{50%{opacity:0}}
@media(max-width:720px){
  .focus-row{grid-template-columns:1fr}
}
@media (prefers-reduced-motion: reduce){
  .input-focus-demo .caret{animation:none;opacity:1}
}


/* spec card stacks vertically on mobile */
@media (max-width: 720px){
  .spec-card{
    grid-template-columns:1fr !important;
    text-align:center;
    gap:var(--s-5) !important;
    justify-items:center;
  }
  .spec-card > div:first-child{margin-inline:auto}
  .spec-card .btn{width:100%;justify-content:center}
}

/* Documentation install rows + DTCG row: collapse the mono-label / body
   two-column grid to a single column on mobile so copy isn't crammed
   into a ~120px right rail. */
@media (max-width: 720px){
  .doc-row{
    grid-template-columns:1fr !important;
    gap:var(--s-3) !important;
    padding:var(--s-5) !important;
  }
  /* Picker card buttons (03.1) go full-width — matches .spec-card behavior */
  #documentation .grid-2 > .card .btn{ width:100%; justify-content:center }
}


/* Case study under 720px: the floating Back sits over the hero, so the top padding clears it; the reading scale steps down. */
@media (max-width: 720px){
  .cs-hero{padding:calc(var(--s-10) + var(--s-6)) var(--s-6) var(--s-6)}
  .cs-hero-title{max-width:none;font-size:var(--t-h4)}
  .cs-hero-lede{max-width:none;font-size:var(--t-lead)}
  .cs-hero .cube{position:static;transform:none;width:120px;height:120px;margin:var(--s-5) 0 0;display:block}
  .cs-section-title{font-size:var(--t-h4)}
  .cs-section-body{font-size:var(--t-lead)}
}








/* ─────────── 85/10/5 LAW · INFOGRAPHIC CARD ─────────── */
.law-card{
  display:grid;
  gap:var(--s-10);
  margin-top:var(--s-8);
}

/* Scroll-in reveal: bar wipes L→R (obsidian → magenta → semantic, in segment order),
   then legend rows and rule fade up in sequence. Triggered by .is-revealed on .law-card. */
.law-card .law-card-bar{
  clip-path:inset(0 100% 0 0);
  transition:clip-path var(--d-draw) var(--ease-standard);
  will-change:clip-path;
}
.law-card .law-row,
.law-card .law-rule{
  opacity:0;
  transform:translateY(10px);
  transition:opacity var(--d-slow) var(--ease-decel),
    transform var(--d-slow) var(--ease-decel);
}
.law-card.is-revealed .law-card-bar{ clip-path:inset(0 0 0 0); }
.law-card.is-revealed .law-row,
.law-card.is-revealed .law-rule{ opacity:1; transform:none; }
/* Stagger begins just before the bar finishes, for overlap */
.law-card.is-revealed .law-row:nth-child(1){ transition-delay:calc(9 * var(--d-instant)); }
.law-card.is-revealed .law-row:nth-child(2){ transition-delay:calc(11 * var(--d-instant)); }
.law-card.is-revealed .law-row:nth-child(3){ transition-delay:calc(13 * var(--d-instant)); }
.law-card.is-revealed .law-rule{ transition-delay:calc(15 * var(--d-instant)); }

@media (prefers-reduced-motion: reduce){
  .law-card .law-card-bar,
  .law-card .law-row,
  .law-card .law-rule{
    transition:none;
    transform:none;
    clip-path:none;
    opacity:1;
  }
}

/* striped bar — flat colors only, hatch on obsidian */
.law-card-bar{
  display:flex;
  height:96px;
  border-radius:var(--r-md);
  overflow:hidden;
  background:var(--obsidian-950);
  border:var(--bw-1) solid var(--obsidian-800);
}
.law-seg{position:relative; height:100%}
.law-seg-obsidian{
  background-image:repeating-linear-gradient(135deg,
      color-mix(in srgb, var(--obsidian-050) calc(var(--tint-faint) * 100%), transparent) 0 1px,
      transparent 1px 8px);
  background-color:var(--obsidian-950);
}
.law-seg-brand{background:var(--primary-500)}
.law-seg-semantic{background:var(--success)}

.law-legend{
  display:grid;
  grid-template-columns:repeat(3, minmax(0,1fr));
  gap:var(--s-6);
  padding-bottom:var(--s-3);
}
.law-row{display:grid;gap:var(--s-2)}
.law-row-head{
  display:flex;
  align-items:center;
  gap:var(--s-3);
  margin-bottom:var(--s-2);
}

.law-pct-mono{
  font-family:var(--font-mono);
  font-size:var(--t-caption);
  letter-spacing:var(--tr-mono);
  font-weight:500;
  color:var(--primary-400);
}
.law-label{
  font-size:var(--t-lead);
  font-weight:700;
  color:var(--obsidian-100);
  letter-spacing:var(--tr-snug);
}
.law-note{
  font-family:var(--font-mono);
  font-size:var(--t-micro);
  letter-spacing:var(--tr-mono);
  color:var(--obsidian-300);
  text-transform:uppercase;
}

.law-rule{
  margin:0;
  padding:var(--s-8) var(--s-10);
  border:var(--bw-1) solid var(--obsidian-800);
  border-left:var(--bw-2) solid var(--primary-400);
  border-radius:var(--r-md);
  display:grid;
  gap:var(--s-6);
  background:var(--obsidian-950);
}
.law-rule-mark{
  font-family:var(--font-mono);
  font-size:var(--t-micro);
  letter-spacing:var(--tr-mono);
  color:var(--primary-400);
  text-transform:uppercase;
  white-space:nowrap;
  padding:var(--s-1) var(--s-2);
  border:var(--bw-1) solid color-mix(in srgb, var(--primary-500) calc(var(--tint-edge) * 100%), transparent);
  border-radius:var(--r-sm);
  justify-self:start;
}
.law-rule p{
  margin:0;
  color:var(--obsidian-100);
  font-size:var(--t-lead);
  line-height:1.55;
  letter-spacing:var(--tr-snug);
}

@media (max-width: 720px){
  .law-card-bar{height:64px}
  .law-legend{grid-template-columns:repeat(3, minmax(0,1fr)); gap:var(--s-3)}
  .law-row{gap:var(--s-1)}
  .law-row-head{margin-bottom:var(--s-1); gap:var(--s-1)}
  .law-pct-mono{font-size:var(--t-micro)}
  .law-label{font-size:var(--t-small)}
  .law-note{font-size:var(--t-micro)}
  .law-rule p{font-size:var(--t-small)}
  .law-rule{padding:var(--s-6) var(--s-8); gap:var(--s-4)}
}


/* ─────────── TYPE · MOBILE OVERFLOW PROTECTION ─────────── */
@media (max-width: 720px){
  /* clamp display sizes so they never overflow */
  .ty-display{font-size:var(--t-display-fluid)}
  .ty-h1{font-size:var(--t-h1-fluid)}
  .ty-h2{font-size:var(--t-h2-fluid)}
  .ty-h3{font-size:var(--t-h3-fluid)}
  .ty-h4{font-size:var(--t-h4-fluid)}
  .ty-h5{font-size:var(--t-h5-fluid)}
}




/* ─────────── GRID DEMO · BREAKPOINT META ─────────── */
.grid-demo-card .tab-panel{padding:var(--s-6)}
.grid-demo-meta{
  display:flex;
  gap:var(--s-2);
  align-items:center;
  font-family:var(--font-mono);
  font-size:var(--t-micro);
  letter-spacing:var(--tr-mono);
  color:var(--obsidian-300);
  text-transform:uppercase;
  margin-bottom:var(--s-5);
}
.grid-demo-meta-sep{color:var(--obsidian-700)}
.grid-demo-card .cols-tablet{grid-template-columns:repeat(8, 1fr)}
.grid-demo-card .cols-mobile{grid-template-columns:repeat(4, 1fr)}
/* The gutter the meta line states: 24 desktop, 20 tablet, 16 mobile (v5.3.0). */
.grid-demo-card .cols-desktop{gap:var(--s-6)}
.grid-demo-card .cols-tablet{gap:var(--s-5)}
.grid-demo-card .cols-mobile{gap:var(--s-4)}
/* Morph between breakpoints: the panel swaps at once, the columns carry the change (v5.3.0). */
[data-grid-morph] .tab-panel{transition:none;opacity:1;transform:none}
.grid-demo .col-ghost{position:absolute;margin:0;pointer-events:none}




/* ─────────── DEVICE PREVIEW · FIXED WIDTHS WITH SCALING ─────────── */
.device-preview{
  position:relative;
  width:100%;
  overflow:hidden;
  border-radius:var(--r-md);
}
.device-preview-inner{
  transform-origin:top left;
  /* fixed device width — JS scales it down to fit container */
}
.device-preview[data-device="desktop"] .device-preview-inner{width:1280px}
.device-preview[data-device="tablet"]  .device-preview-inner{width:768px}
.device-preview[data-device="mobile"]  .device-preview-inner{width:380px}
/* the global reduced-motion rule gives every property a near-zero transition, and the frame measured
   after a device change still read the old width: the frame width never transitions */
@media (prefers-reduced-motion: reduce){ .device-preview-inner{transition:none !important} }


/* ─────────── AI RULES LIST · § 20.4 ─────────── */
.ai-rules{
  margin:0;
  padding-left:var(--s-6);
  display:flex;
  flex-direction:column;
  gap:var(--s-4);
  color:var(--obsidian-200);
  font-size:var(--t-body);
  line-height:1.65;
}
.ai-rules li{padding-left:var(--s-2)}
.ai-rules li::marker{color:var(--primary-400); font-family:var(--font-mono); font-size:var(--t-small)}
.ai-rules em{font-style:italic; color:var(--obsidian-100)}

/* ─────────── AI CARD · § 20.4 (do/dont visual language) ─────────── */
.ai-card{
  border:var(--bw-1) solid var(--obsidian-800);
  border-left:var(--bw-2) solid var(--primary-500);
  border-radius:var(--r-lg);
  padding:var(--s-5);
  background:var(--obsidian-900);
}
.ai-card .hd{
  display:flex; align-items:center; gap:var(--s-2);
  font-family:var(--font-mono); font-size:var(--t-caption);
  letter-spacing:var(--tr-mono); text-transform:uppercase;
  margin-bottom:var(--s-3);
  color:var(--primary-400);
}
.ai-card-lede{
  margin:0 0 var(--s-4);
  font-size:var(--t-small);
  color:var(--obsidian-100);
  line-height:var(--lh-loose);
}
.ai-card .ai-rules{
  font-size:var(--t-small);
  color:var(--obsidian-100);
  line-height:var(--lh-loose);
  gap:var(--s-3);
}


/* italic emphasis inside do/dont cards */
.do em, .dont em{font-style:italic; color:var(--obsidian-100); font-weight:500}


/* ─────────── CHAT / MESSAGING · § 19 ─────────── */
/* Conversation surface — fixed height, bottom-aligned, bubbles push up */
.chat-stage{
  display:flex;
  flex-direction:column;
  justify-content:flex-end;
  gap:var(--s-2);
  height:480px;
  padding:var(--s-6);
  background:var(--obsidian-900);
  border:var(--bw-1) solid var(--obsidian-800);
  border-radius:var(--r-lg);
  overflow:hidden;
  position:relative;
}
.chat-stage-head{
  position:absolute; top:0; left:0; right:0;
  display:flex; align-items:center; gap:var(--s-3);
  padding:var(--s-4) var(--s-6);
  border-bottom:var(--bw-1) solid var(--obsidian-800);
  background:linear-gradient(to bottom, var(--obsidian-900) 60%, transparent);
  z-index:2;
}
.chat-stage-head .chat-avatar{ width:28px; height:28px; font-size:var(--t-micro) }
.chat-stage-head-title{
  font-size:var(--t-small); font-weight:600;
  color:var(--obsidian-100); letter-spacing:var(--tr-snug);
}
.chat-stage-head-status{
  font-family:var(--font-mono);
  font-size:var(--t-micro); letter-spacing:var(--tr-mono);
  color:var(--obsidian-300); text-transform:uppercase;
  margin-left:auto;
  display:flex; align-items:center; gap:var(--s-2);
}
.chat-stage-head-status::before{
  content:""; width:6px; height:6px; border-radius:50%;
  background:var(--success); flex-shrink:0;
}
.chat-stage-scroll{
  display:flex; flex-direction:column; gap:var(--s-3);
  padding-top:var(--s-12);
  margin-top:auto;
}

/* Day separator */
.chat-day{
  display:flex; align-items:center; gap:var(--s-3);
  margin:var(--s-3) 0 var(--s-1);
}
.chat-day::before, .chat-day::after{
  content:""; flex:1; height:1px; background:var(--obsidian-800);
}
.chat-day-label{
  font-family:var(--font-mono);
  font-size:var(--t-micro); letter-spacing:var(--tr-mono);
  color:var(--obsidian-300); text-transform:uppercase;
}

/* Message row — sender side defines column direction */
.chat-msg{
  display:flex; align-items:flex-end; gap:var(--s-3);
  max-width:84%;
}
.chat-msg-bot{ align-self:flex-start }
.chat-msg-own{ align-self:flex-end; flex-direction:row-reverse }

/* Avatar (initials or image) — only on first bubble of a bot streak */
.chat-avatar{
  width:32px; height:32px; border-radius:50%;
  flex-shrink:0;
  background:var(--obsidian-700);
  color:var(--obsidian-100);
  display:flex; align-items:center; justify-content:center;
  font-family:var(--font-mono);
  font-size:var(--t-caption); font-weight:600;
  letter-spacing:var(--tr-mono);
  text-transform:uppercase;
}
.chat-avatar-bot{
  background:var(--obsidian-800);
  color:var(--primary-400);
  border:var(--bw-1) solid var(--obsidian-700);
}
.chat-avatar-spacer{ width:32px; height:32px; flex-shrink:0; visibility:hidden }

/* Bubble stack column (bubble + meta below) */
.chat-stack{
  display:flex; flex-direction:column;
  gap:var(--s-1);
  min-width:0;
}
.chat-msg-own .chat-stack{ align-items:flex-end }

/* Meta row above first bubble of a streak */
.chat-meta{
  display:flex; align-items:baseline; gap:var(--s-2);
  margin-bottom:var(--s-0-5);
  padding:0 var(--s-2);
}
.chat-meta-name{
  font-size:var(--t-caption);
  font-weight:600;
  color:var(--obsidian-200);
  letter-spacing:var(--tr-snug);
}
.chat-meta-time{
  font-family:var(--font-mono);
  font-size:var(--t-micro);
  letter-spacing:var(--tr-mono);
  color:var(--obsidian-300);
}

/* Bubble — uniform --r-lg radius on all corners (system-like, no tail) */
.chat-bubble{
  padding:var(--s-3) var(--s-4);
  border-radius:var(--r-lg);
  font-size:var(--t-body);
  line-height:var(--lh-normal);
  letter-spacing:var(--tr-snug);
  word-wrap:break-word;
  overflow-wrap:anywhere;
}
.chat-bubble-bot{
  background:var(--obsidian-800);
  color:var(--obsidian-100);
  border:var(--bw-1) solid var(--obsidian-700);
}
/* Own bubble — deep magenta (--primary-700), reserved brand accent.
   The bright --primary-500 stays for CTAs / focus rings only.
   Text uses --obsidian-050 for max contrast (6.26:1 — AA, near AAA). */
.chat-bubble-own{
  background:var(--primary-700);
  color:var(--obsidian-050);
}

/* Screen-reader-only utility for sender prefix inside bubbles + typing label */
.chat-sr-only{
  position:absolute;
  width:1px; height:1px;
  padding:0; margin:calc(-1 * var(--s-px));
  overflow:hidden;
  clip:rect(0,0,0,0);
  white-space:nowrap;
  border:0;
}

/* Focus visibility — dual-ring per § 6.2 (outline + magenta halo) */
.chat-composer-attach:focus-visible,
.chat-composer-send:focus-visible,
.chat-demo-replay:focus-visible{
  outline:var(--focus-width) solid var(--obsidian-100);
  outline-offset:var(--focus-offset);
  box-shadow:var(--ring-halo);
}

/* Status ticks row under own bubble */
.chat-status{
  display:flex; align-items:center; gap:var(--s-1);
  padding:0 var(--s-2);
  font-family:var(--font-mono);
  font-size:var(--t-micro);
  letter-spacing:var(--tr-mono);
  color:var(--obsidian-300);
  text-transform:uppercase;
}
.chat-tick{
  display:inline-flex; align-items:center;
  color:var(--obsidian-400);
  transition:color var(--d-quick) var(--ease-standard);
}
.chat-tick svg{ width:14px; height:14px; display:block }
.chat-status.is-read .chat-tick{ color:var(--primary-400) }
.chat-status-label{ margin-left:var(--s-0-5) }

/* Typing indicator — lives inside a bot bubble */
.chat-bubble-typing{
  padding:var(--s-3) var(--s-4);
  min-height:36px;
}
.chat-typing{
  display:inline-flex; align-items:center;
  gap:var(--s-1); height:14px;
}
.chat-dot{
  width:6px; height:6px; border-radius:50%;
  background:var(--obsidian-300);
  animation:chat-dot-wave var(--d-slow) var(--ease-standard) infinite;
  transform-origin:center;
  will-change:transform, opacity;
}
.chat-dot:nth-child(2){ animation-delay:calc(2 * var(--d-instant)) }
.chat-dot:nth-child(3){ animation-delay:calc(4 * var(--d-instant)) }
@keyframes chat-dot-wave{
  0%, 60%, 100% { transform:translateY(0); opacity:0.3 }
  30%           { transform:translateY(-4px); opacity:1 }
}

/* Media attachment (image preview inside a bot bubble) */
.chat-bubble-media{ padding:0; overflow:hidden }
.chat-media{
  display:block; width:280px; max-width:100%;
  aspect-ratio:16 / 10;
  background:repeating-linear-gradient(135deg,
      var(--obsidian-700) 0 1px,
      transparent 1px 10px),
    var(--obsidian-800);
  position:relative;
}
.chat-media-tag{
  position:absolute; left:var(--s-3); top:var(--s-3);
  font-family:var(--font-mono);
  font-size:var(--t-micro); letter-spacing:var(--tr-mono);
  text-transform:uppercase;
  padding:var(--s-1) var(--s-2);
  background:var(--surface-glass);backdrop-filter:blur(var(--blur-glass));
  border:var(--bw-1) solid var(--obsidian-700);
  border-radius:var(--r-sm);
  color:var(--obsidian-200);
}
.chat-media-caption{
  padding:var(--s-3) var(--s-4);
  font-size:var(--t-small);
  color:var(--obsidian-300);
  border-top:var(--bw-1) solid var(--obsidian-700);
}

/* Link preview card embedded inside a bubble */
.chat-linkprev{
  display:grid;
  grid-template-columns:56px 1fr;
  gap:var(--s-3);
  padding:var(--s-3);
  margin-top:var(--s-2);
  background:var(--obsidian-850);
  border:var(--bw-1) solid var(--obsidian-700);
  border-radius:var(--r-md);
}
.chat-linkprev-thumb{
  width:56px; height:56px;
  border-radius:var(--r-sm);
  background:repeating-linear-gradient(135deg,
      var(--obsidian-700) 0 1px,
      transparent 1px 6px),
    var(--obsidian-800);
}
.chat-linkprev-body{ display:flex; flex-direction:column; gap:var(--s-0-5); min-width:0 }
.chat-linkprev-domain{
  font-family:var(--font-mono);
  font-size:var(--t-micro);
  letter-spacing:var(--tr-mono);
  text-transform:uppercase;
  color:var(--primary-400);
}
.chat-linkprev-title{
  font-size:var(--t-small);
  font-weight:600;
  color:var(--obsidian-100);
  letter-spacing:var(--tr-snug);
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
.chat-linkprev-desc{
  font-size:var(--t-micro);
  color:var(--obsidian-300);
  overflow:hidden;
  display:-webkit-box;
  -webkit-line-clamp:2;
  -webkit-box-orient:vertical;
}

/* Voice message — duration + waveform */
.chat-bubble-voice{
  padding:var(--s-3) var(--s-4);
  min-width:220px;
}
.chat-voice{
  display:flex; align-items:center; gap:var(--s-3);
}
.chat-voice-play{
  width:28px; height:28px;
  border-radius:50%;
  background:var(--obsidian-700);
  display:flex; align-items:center; justify-content:center;
  flex-shrink:0;
  color:var(--obsidian-100);
}
.chat-bubble-own .chat-voice-play{
  background:var(--primary-800);
  color:var(--obsidian-100);
}
.chat-voice-play svg{ width:12px; height:12px; display:block }
.chat-waveform{
  display:flex; align-items:center;
  gap:var(--s-0-5); flex:1;
  height:22px;
}
.chat-waveform .bar{
  flex:1;
  background:var(--obsidian-400);
  border-radius:var(--r-full);
  min-height:4px;
}
.chat-bubble-own .chat-waveform .bar{ background:color-mix(in srgb, var(--obsidian-100) calc(var(--tint-edge) * 100%), transparent) }
.chat-bubble-own .chat-waveform .bar.played{ background:var(--obsidian-100) }
.chat-bubble-bot .chat-waveform .bar.played{ background:var(--primary-400) }
.chat-voice-time{
  font-family:var(--font-mono);
  font-size:var(--t-micro);
  letter-spacing:var(--tr-mono);
  color:var(--obsidian-300);
  text-transform:uppercase;
  flex-shrink:0;
}
.chat-bubble-own .chat-voice-time{ color:color-mix(in srgb, var(--obsidian-100) calc(var(--tint-strong) * 100%), transparent) }

/* ─── Bubble entry choreography ───
   Two-stage: container scales+fades in with a subtle spring overshoot
   (--d-base / --ease-spring), then the inner content fades up after
   --d-instant (--d-quick / --ease-standard). Exit: opacity + slight rise,
   --d-quick / --ease-accel.
*/
.chat-msg .chat-bubble,
.chat-msg .chat-status,
.chat-msg .chat-avatar,
.chat-msg .chat-meta{
  opacity:0;
  transform:scale(0.92);
  transition:opacity var(--d-base) var(--ease-standard),
    transform var(--d-base) var(--ease-spring);
}
.chat-msg-own .chat-bubble{ transform-origin:bottom right }
.chat-msg-bot .chat-bubble{ transform-origin:bottom left }
.chat-msg .chat-avatar,
.chat-msg .chat-meta{ transform:translateY(4px) scale(1) }

.chat-msg.is-in .chat-bubble,
.chat-msg.is-in .chat-status,
.chat-msg.is-in .chat-avatar,
.chat-msg.is-in .chat-meta{
  opacity:1;
  transform:none;
}

/* Stage 2: content inside the bubble (text, media, voice) fades --d-instant behind */
.chat-bubble-content{
  opacity:0;
  transform:translateY(3px);
  transition:opacity var(--d-quick) var(--ease-standard),
    transform var(--d-quick) var(--ease-standard);
}
.chat-msg.is-in .chat-bubble-content{
  opacity:1;
  transform:none;
  transition-delay:var(--d-instant);
}

/* Re-cool the hot bubble: keep the hot-cold transition (color only) intact */
/* (defined above on .chat-bubble-own) */

/* Exit (roll-off): older messages fade up + collapse vertically */
.chat-msg.is-out{
  opacity:0;
  transform:translateY(-8px);
  max-height:0;
  margin-top:calc(var(--s-3) * -1);
  pointer-events:none;
  transition:opacity var(--d-quick) var(--ease-accel),
    transform var(--d-quick) var(--ease-accel),
    max-height var(--d-base) var(--ease-accel),
    margin-top var(--d-base) var(--ease-accel);
}

/* ─── Composer ─── */
.chat-composer{
  display:flex; align-items:flex-end; gap:var(--s-3);
  padding:var(--s-3);
  background:var(--obsidian-850);
  border:var(--bw-1) solid var(--obsidian-700);
  border-radius:var(--r-lg);
  transition:border-color var(--d-quick) var(--ease-standard),
              box-shadow var(--d-quick) var(--ease-standard);
}
.chat-composer:focus-within{
  border-color:var(--primary-500);
  box-shadow:var(--ring-field);
}
.chat-composer-attach,
.chat-composer-send{
  width:36px; height:36px;
  flex-shrink:0;
  border-radius:50%;
  display:flex; align-items:center; justify-content:center;
  padding:0;
  border:var(--bw-1) solid transparent;
  background:transparent;
  color:var(--obsidian-300);
  cursor:pointer;
  transition:background var(--d-quick) var(--ease-standard),
    color var(--d-quick) var(--ease-standard),
    border-color var(--d-quick) var(--ease-standard),
    transform var(--d-quick) var(--ease-standard);
}
.chat-composer-attach svg,
.chat-composer-send svg{ width:16px; height:16px; display:block }
.chat-composer-attach:hover{
  background:var(--obsidian-800);
  color:var(--obsidian-100);
}
.chat-composer-send{
  background:var(--obsidian-700);
  color:var(--obsidian-400);
}
.chat-composer.is-ready .chat-composer-send{
  background:var(--primary-500);
  color:var(--obsidian-950);
}
.chat-composer.is-ready .chat-composer-send:hover{
  transform:scale(1.04);
}
.chat-composer-textarea{
  flex:1;
  min-height:36px;
  max-height:132px;
  resize:none;
  background:transparent;
  border:none;
  outline:none;
  color:var(--obsidian-100);
  font-family:var(--font-sans);
  font-size:var(--t-body);
  line-height:var(--lh-normal);
  letter-spacing:var(--tr-snug);
  padding:var(--s-2) var(--s-2);
}
.chat-composer-textarea::placeholder{ color:var(--obsidian-300) }
.chat-composer-hint{
  font-family:var(--font-mono);
  font-size:var(--t-micro);
  letter-spacing:var(--tr-mono);
  color:var(--obsidian-300);
  text-transform:uppercase;
  margin-top:var(--s-2);
  display:flex; align-items:center; gap:var(--s-2);
}
.chat-composer-hint kbd{
  font-family:var(--font-mono);
  font-size:var(--t-micro);
  padding:var(--s-0-5) var(--s-1);
  background:var(--obsidian-800);
  border:var(--bw-1) solid var(--obsidian-700);
  border-radius:var(--r-xs);
  color:var(--obsidian-200);
}

/* ─── Anatomy diagram (§ 19.1) ─── */
.chat-anatomy{
  display:grid;
  grid-template-columns:minmax(280px, 380px) 1fr;
  gap:var(--s-10);
  padding:var(--s-8);
  background:var(--obsidian-900);
  border:var(--bw-1) solid var(--obsidian-800);
  border-radius:var(--r-lg);
  align-items:center;
}
.chat-anatomy-canvas{
  display:flex; flex-direction:column; gap:var(--s-3);
  padding:var(--s-6) var(--s-4);
  background:var(--obsidian-950);
  border:var(--bw-1) solid var(--obsidian-800);
  border-radius:var(--r-md);
}
.chat-anatomy-canvas .chat-msg{ opacity:1; max-width:100% }
.chat-anatomy-canvas .chat-msg .chat-bubble,
.chat-anatomy-canvas .chat-msg .chat-avatar,
.chat-anatomy-canvas .chat-msg .chat-status,
.chat-anatomy-canvas .chat-msg .chat-meta,
.chat-anatomy-canvas .chat-msg .chat-bubble-content{
  opacity:1; transform:none; transition:none;
}
.chat-anatomy-legend{ display:grid; gap:var(--s-3) }
.chat-anatomy-row{
  display:grid;
  grid-template-columns:28px 1fr auto;
  gap:var(--s-3);
  align-items:baseline;
  padding-bottom:var(--s-3);
  border-bottom:var(--bw-1) solid var(--obsidian-800);
}
.chat-anatomy-row:last-child{ border-bottom:none; padding-bottom:0 }
.chat-anatomy-num{
  font-family:var(--font-mono);
  font-size:var(--t-micro);
  letter-spacing:var(--tr-mono);
  color:var(--primary-400);
  padding-top:var(--s-0-5);
}
.chat-anatomy-label{ font-size:var(--t-small); color:var(--obsidian-100); font-weight:500 }
.chat-anatomy-value{
  font-family:var(--font-mono);
  font-size:var(--t-micro);
  letter-spacing:var(--tr-mono);
  color:var(--obsidian-300);
  text-transform:uppercase;
}

/* ─── Live demo wrapper (§ 19.2) — replay button + chat-stage ─── */
.chat-demo{ display:grid; gap:var(--s-4) }
.chat-demo-head{
  display:flex; align-items:center; gap:var(--s-3);
}
.chat-demo-head-title{
  font-family:var(--font-mono);
  font-size:var(--t-micro); letter-spacing:var(--tr-mono);
  color:var(--obsidian-300); text-transform:uppercase;
}
.chat-demo-head-spacer{ flex:1 }
.chat-demo-replay{
  font-family:var(--font-mono);
  font-size:var(--t-micro);
  letter-spacing:var(--tr-mono);
  text-transform:uppercase;
  padding:var(--s-1) var(--s-3);
  background:transparent;
  border:var(--bw-1) solid var(--obsidian-700);
  border-radius:var(--r-sm);
  color:var(--obsidian-200);
  cursor:pointer;
  display:inline-flex; align-items:center; gap:var(--s-1);
  transition:border-color var(--d-quick) var(--ease-standard),
              color var(--d-quick) var(--ease-standard);
}
.chat-demo-replay:hover{
  border-color:var(--primary-500);
  color:var(--primary-400);
}
.chat-demo-replay svg{ width:var(--icon-xs); height:var(--icon-xs); display:block }

/* ─── Reduced motion: kill all chat motion ─── */
@media (prefers-reduced-motion: reduce){
  .chat-msg .chat-bubble,
  .chat-msg .chat-avatar,
  .chat-msg .chat-meta,
  .chat-msg .chat-bubble-content,
  .chat-composer,
  .chat-composer-attach,
  .chat-composer-send,
  .chat-tick,
  .chat-msg.is-out{
    transition:none !important;
    transform:none !important;
    opacity:1 !important;
  }
  .chat-msg.is-out{ opacity:0 !important; max-height:0 !important }
  .chat-dot{ animation:none !important; opacity:1 !important }
}

/* ─── Mobile ─── */
@media (max-width: 720px){
  .chat-stage{ height:420px; padding:var(--s-4) }
  .chat-msg{ max-width:92% }
  .chat-anatomy{
    grid-template-columns:1fr;
    gap:var(--s-6);
    padding:var(--s-5);
  }
  .chat-media{ width:100% }
  /* Touch targets — § 6 floor #7 (44×44 minimum on mobile) */
  .chat-composer-attach,
  .chat-composer-send{ width:44px; height:44px }
}


/* ─────────── LOADER · § 20 ─────────── */
/* Brand logo Lottie at four sizes. Under reduced motion: SVG ring spinner. */

.loader{
  display:inline-flex;
  align-items:center;
  justify-content:center;
  position:relative;
  flex-shrink:0;
  vertical-align:middle;
  line-height:1;
}

/* Size scale — controls both the lottie box and the fallback ring */
.loader-xs{ width:var(--loader-xs); height:var(--loader-xs) }
.loader-sm{ width:var(--loader-sm); height:var(--loader-sm) }
.loader-md{ width:var(--loader-md); height:var(--loader-md) }
.loader-lg{ width:var(--loader-lg); height:var(--loader-lg) }

/* The Lottie canvas — fills the loader box */
.loader-anim{
  display:block;
  width:100%;
  height:100%;
  object-fit:contain;
  pointer-events:none;
  transition:opacity var(--d-quick) var(--ease-standard),
    transform var(--d-quick) var(--ease-standard);
}

/* CSS ring spinner — fallback shown under prefers-reduced-motion */
.loader-fallback{
  position:absolute;
  inset:0;
  display:none;
  align-items:center;
  justify-content:center;
}
.loader-fallback svg{
  width:100%;
  height:100%;
  display:block;
}
.loader-fallback circle{
  fill:none;
  stroke:var(--primary-500);
  stroke-width:2.5;
  stroke-linecap:round;
  stroke-dasharray:60 60;
  stroke-dashoffset:30;
  transform-origin:center;
  animation:loader-spin 1400ms linear infinite;
}
.loader-xs .loader-fallback circle{ stroke-width:2 }
.loader-lg .loader-fallback circle{ stroke-width:3 }
@keyframes loader-spin{
  to { transform:rotate(360deg) }
}

/* Layout: with label below (vertical stack) */
.loader-with-label{
  display:inline-flex;
  flex-direction:column;
  align-items:center;
  gap:var(--s-3);
  width:auto; height:auto;
}
.loader-with-label .loader-anim,
.loader-with-label .loader-fallback{ position:relative }
.loader-with-label > .loader-anim,
.loader-with-label > .loader-fallback{
  width:var(--loader-md);
  height:var(--loader-md);
  position:relative;
}
.loader-with-label.loader-sm > .loader-anim,
.loader-with-label.loader-sm > .loader-fallback{ width:var(--loader-sm); height:var(--loader-sm) }
.loader-with-label.loader-lg > .loader-anim,
.loader-with-label.loader-lg > .loader-fallback{ width:var(--loader-lg); height:var(--loader-lg) }

/* Layout: inline (label to the right) — used for input validating, chat hints */
.loader-inline{
  display:inline-flex;
  flex-direction:row;
  align-items:center;
  gap:var(--s-2);
  width:auto; height:auto;
}
.loader-inline > .loader-anim,
.loader-inline > .loader-fallback{
  width:var(--loader-xs);
  height:var(--loader-xs);
  position:relative;
}
.loader-inline.loader-sm > .loader-anim,
.loader-inline.loader-sm > .loader-fallback{ width:var(--loader-sm); height:var(--loader-sm) }

.loader-label{
  font-size:var(--t-body);
  color:var(--obsidian-200);
  letter-spacing:var(--tr-snug);
  white-space:nowrap;
}
.loader-inline .loader-label{ font-size:var(--t-small); color:var(--obsidian-300) }

/* Success state — Lottie fades out, checkmark scales in with spring */
.loader-check{
  position:absolute;
  inset:0;
  display:flex;
  align-items:center;
  justify-content:center;
  opacity:0;
  transform:scale(0.5);
  transition:opacity var(--d-quick) var(--ease-standard),
    transform var(--d-base) var(--ease-spring);
  pointer-events:none;
}
.loader-check svg{ width:60%; height:60%; color:var(--success) }
[data-loader-state="success"] .loader-anim,
[data-loader-state="success"] .loader-fallback{
  opacity:0;
  transform:scale(0.7);
}
[data-loader-state="success"] .loader-check{
  opacity:1;
  transform:scale(1);
}

/* Inside a button: replaces label, button stays the same size */
.btn.is-loading{
  position:relative;
  pointer-events:none;
  color:transparent !important;
}
.btn.is-loading > .loader{
  position:absolute;
  top:50%; left:50%;
  transform:translate(-50%, -50%);
}
/* Anything composed inside .btn-primary wears the label's colour.
   The label is near-white on magenta (--obsidian-050, ratified § 6.3); a loader
   that stays dark puts two opposite treatments in one button. Cyan on magenta
   stays off-system either way, and at this size the cube detail isn't legible,
   so the mark collapses to a flat near-white silhouette. Applies at rest and
   while loading — the contract holds before the trigger fires too. */
.btn-primary.is-loading .loader-fallback circle{ stroke:var(--obsidian-050) }
.btn-primary.is-loading .loader-check svg{ color:var(--obsidian-050) }
.btn-primary .loader-anim{
  filter:brightness(0) invert(1);
}

/* Section overlay variant — sits over a card/region, dims the parent */
.loader-overlay{
  position:absolute;
  inset:0;
  display:flex;
  align-items:center;
  justify-content:center;
  background:var(--scrim);
  backdrop-filter:blur(var(--blur-veil));
  z-index:5;
  width:auto; height:auto;
  border-radius:inherit;
  opacity:0;
  pointer-events:none;
  transition:opacity var(--d-quick) var(--ease-standard);
}
.loader-overlay.is-active{
  opacity:1;
  pointer-events:auto;
}

/* Full-page variant — covers the viewport (or a relative ancestor) */
.loader-page{
  position:absolute;
  inset:0;
  display:flex;
  flex-direction:column;
  align-items:center;
  justify-content:center;
  gap:var(--s-5);
  background:var(--obsidian-950);
  z-index:var(--z-sticky);
}

/* ─── § 3.20 Skeleton — the shape of content that has not arrived ─── */
.skeleton-stack{
  display:grid;
  gap:var(--s-3);
  width:100%;
}
.skeleton-line,
.skeleton-circle,
.skeleton-block{
  position:relative;
  overflow:hidden;
  background:var(--obsidian-700);
}
.skeleton-line{
  height:var(--s-3);
  border-radius:var(--r-sm);
}
.skeleton-circle{
  --size:var(--s-8);
  flex:none;
  width:var(--size);
  height:var(--size);
  border-radius:var(--r-full);
}
.skeleton-block{
  width:100%;
  height:var(--s-24);
  border-radius:var(--r-md);
}
.skeleton-line::after,
.skeleton-circle::after,
.skeleton-block::after{
  content:"";
  position:absolute; inset:0;
  background:linear-gradient(
    90deg,
    transparent 0,
    color-mix(in srgb, var(--primary-500) calc(var(--tint-fill) * 100%), transparent) 50%,
    transparent 100%
  );
  animation:skeleton-shimmer 1600ms linear infinite;
}
@keyframes skeleton-shimmer{
  from{ transform:translateX(-100%) }
  to  { transform:translateX(100%) }
}

/* ─── § 3.23 Popover — anchored, richer than a tooltip, opened by a click ───
   The native Popover API does the dismissal (click outside, Escape on an
   auto popover) and the top layer; the position is CSS anchor positioning
   from the invoker (popovertarget). --z-popover does not apply: a popover
   in the top layer sits above every z-index. */
.popover{
  margin:0; inset:auto;
  position-area:bottom span-right;
  position-try-fallbacks:flip-block, flip-inline;
  margin-block:var(--s-1);
  width:max-content;
  min-width:var(--w-popover-min); max-width:min(var(--w-popover), calc(100vw - var(--s-8)));
  padding:var(--s-4);
  background:var(--obsidian-900);
  color:var(--obsidian-100);
  border:var(--bw-1) solid var(--obsidian-700);
  border-radius:var(--r-lg);
  box-shadow:var(--sh-3);
  font-family:var(--font-sans); font-size:var(--t-small); line-height:var(--lh-snug);
  /* it grows from 0.96 out of the corner that touches its trigger, and shrinks back into it (v5.3.0) */
  opacity:0; transform:scale(0.96); transform-origin:top left;
  transition:opacity var(--d-quick) var(--ease-accel), transform var(--d-quick) var(--ease-accel), overlay var(--d-quick) var(--ease-accel) allow-discrete, display var(--d-quick) var(--ease-accel) allow-discrete;
}
.popover:popover-open{opacity:1; transform:none; transition-timing-function:var(--ease-decel)}
@starting-style{ .popover:popover-open{opacity:0; transform:scale(0.96)} }
.popover-top{position-area:top span-right; transform-origin:bottom left}
.popover-end{position-area:right span-bottom; margin-block:0; margin-inline:var(--s-1)}
/* a narrow screen has no room at the side: it opens below, like the default */
@media (max-width:480px){
  .popover-end{position-area:bottom span-right; margin-block:var(--s-1); margin-inline:0}
}
.popover-head{display:flex;align-items:center;justify-content:space-between;gap:var(--s-4);margin-bottom:var(--s-3)}
.popover-head .btn-icon{flex:none}
.popover-title{margin:0;font-size:var(--t-body);font-weight:700;line-height:var(--lh-snug)}
.popover-body{display:grid;gap:var(--s-3);color:var(--obsidian-200)}
.popover-foot{display:flex;justify-content:flex-end;gap:var(--s-2);margin-top:var(--s-4)}

/* ─── § 3.24 Drawer — a modal anchored to a side: a menu or text, flush with the edge ───
   A <dialog> opened with showModal(): the modal's surface and scrim, no radius, the shadow one
   step below the modal's (so no edge), the width a readable line. .drawer-nav is the side menu. */
.drawer{
  --pad:var(--s-6);
  position:fixed; inset:0 0 0 auto; margin:0; padding:0;
  width:min(100%, calc(45ch + 2 * var(--pad))); max-width:100%; height:100%; max-height:none;
  flex-direction:column; overflow:hidden;
  background:var(--obsidian-800); color:var(--obsidian-100);
  border:0; border-radius:0; box-shadow:var(--sh-3);
  font-family:var(--font-sans); font-size:var(--t-body);
  transform:translateX(100%);
  transition:transform var(--d-base) var(--ease-accel), overlay var(--d-base) var(--ease-accel) allow-discrete, display var(--d-base) var(--ease-accel) allow-discrete;
}
.drawer[open]{display:flex; transform:none; transition-timing-function:var(--ease-decel)}
@starting-style{ .drawer[open]{transform:translateX(100%)} }
.drawer-start{inset:0 auto 0 0; transform:translateX(-100%)}
@starting-style{ .drawer-start[open]{transform:translateX(-100%)} }
.drawer-wide{width:min(100%, calc(60ch + 2 * var(--pad)))}
.drawer-nav{--pad:var(--s-4); width:min(100%, calc(30ch + 2 * var(--pad))); font-size:var(--t-lead)}
.drawer::backdrop{
  background:transparent;
  transition:background var(--d-base) var(--ease-accel), overlay var(--d-base) var(--ease-accel) allow-discrete, display var(--d-base) var(--ease-accel) allow-discrete;
}
.drawer[open]::backdrop{background:var(--scrim);backdrop-filter:blur(var(--blur-veil)); transition-timing-function:var(--ease-decel)}
@starting-style{ .drawer[open]::backdrop{background:transparent} }
.drawer-head{flex:none; display:flex; align-items:center; justify-content:space-between; gap:var(--s-4); padding:var(--pad) var(--pad) var(--s-4)}
.drawer-head .btn-icon{flex:none}
.drawer-head .btn-icon:focus-visible{outline-offset:calc(-1 * var(--focus-width)); box-shadow:none}
.drawer-title{margin:0; font-size:var(--t-h6); font-weight:700; line-height:var(--lh-snug)}
.drawer-body{flex:1; min-height:0; overflow:auto; padding:0 var(--pad) var(--pad); display:grid; gap:var(--s-4); align-content:start; color:var(--obsidian-200); font-size:var(--t-body)}
.drawer-body > p{margin:0}
.drawer-nav .drawer-body{gap:var(--s-2)}
.drawer-body > .list{margin-inline:calc(-1 * var(--pad))}
.drawer-body > .list .list-item{padding-inline:var(--pad)}
.drawer-nav .list-title{font-size:var(--t-lead)}
.drawer .list-item[aria-current="page"]{background:var(--obsidian-700); font-weight:600; cursor:default}
.drawer-label{margin:var(--s-4) 0 0; font-family:var(--font-mono); font-size:var(--t-micro); letter-spacing:var(--tr-mono); text-transform:uppercase; color:var(--obsidian-300)}
.drawer-label:first-child{margin-top:0}
.drawer-foot{flex:none; display:flex; justify-content:flex-end; flex-wrap:wrap; gap:var(--s-2); padding:var(--s-4) var(--pad); border-top:var(--bw-1) solid var(--obsidian-700)}
body:has(.drawer:modal){overflow:hidden}  /* as the modal: only one opened with showModal() locks the page */
@media (max-width:480px){ .drawer{width:100%} .drawer-foot .btn{flex:1 1 100%} }
@media (prefers-reduced-motion:reduce){
  .drawer,.drawer[open],.drawer-start,.drawer-start[open]{transition:none; transform:none}
  .drawer::backdrop,.drawer[open]::backdrop{transition:none}
}
/* the anatomy frame on the documentation site: a page behind a scrim, the drawer held inside it */
.drawer-demo{position:relative;overflow:hidden;overflow:clip;min-height:var(--s-24);height:480px;background:var(--obsidian-950);border:var(--bw-1) solid var(--obsidian-800);border-radius:var(--r-lg)}
.drawer-demo::before{content:"";position:absolute;inset:0;background:var(--scrim);backdrop-filter:blur(var(--blur-veil));z-index:1}
.drawer-demo .drawer{position:absolute;inset-block:0;z-index:2}
.drawer-demo .drawer[open]{display:flex}
.drawer-demo .drawer{width:min(72%, calc(45ch + 2 * var(--pad)))}
.drawer-demo .drawer-nav{width:min(62%, calc(30ch + 2 * var(--pad)))}
.drawer-demo.is-closed::before{display:none}
.drawer-demo-open{position:absolute;inset:0;z-index:0;display:flex;align-items:center;justify-content:center}
.drawer-demo > .drawer-demo-open{align-items:flex-end;padding:var(--s-6)}
.drawer-demo-page{padding:var(--s-6)}
.drawer-demo-row{display:flex;justify-content:space-between;padding-block:var(--s-3);border-bottom:var(--bw-1) solid var(--obsidian-800);color:var(--obsidian-300)}
.drawer-demo .drawer[open]{transition:none;animation:drawer-demo-in var(--d-base) var(--ease-decel)}
.drawer-demo .drawer-start[open]{animation-name:drawer-demo-in-start}
@keyframes drawer-demo-in{from{transform:translateX(100%)}to{transform:none}}
@keyframes drawer-demo-in-start{from{transform:translateX(-100%)}to{transform:none}}
@media (prefers-reduced-motion:reduce){.drawer-demo .drawer[open]{animation:none}}

/* ─── § 3.26 Navigation · top bar — brand, destinations, one action. Flat, flush, items as tall as the bar ───
   The bar is its own container: at 720px of its OWN width or less the list and the action leave and the
   toggle opens the Drawer menu, on the toggle's side. One markup, whatever the frame or the page. */
.navbar{
  container-type:inline-size;
  position:sticky; top:0; z-index:var(--z-sticky);
  display:flex; align-items:stretch; gap:var(--s-8);
  min-block-size:var(--s-12);
  padding-inline:0;
  background:transparent;
  border-radius:0;
  color:var(--obsidian-100);
}
/* The Bar material with a fading edge (v5.0.0): fill and blur reach --s-6 below the bar and fade out, so the
   bar ends in a mist, not a line. */
.navbar::before{
  content:""; position:absolute; inset:0 0 calc(-1 * var(--s-6)); z-index:-1; pointer-events:none;
  background:linear-gradient(var(--surface-bar), transparent);
  backdrop-filter:blur(var(--blur-bar)); -webkit-backdrop-filter:blur(var(--blur-bar));
  -webkit-mask-image:linear-gradient(black 55%, transparent); mask-image:linear-gradient(black 55%, transparent);
}
.navbar-brand{padding-inline-start:var(--s-6); display:flex; align-items:center; gap:var(--s-3); flex:none; color:var(--obsidian-100); font-size:var(--t-body); font-weight:700; letter-spacing:var(--tr-snug); text-decoration:none}
.navbar-brand .brand-mark{width:var(--s-8); height:var(--s-8)}
.navbar-brand .brand-mark img{width:var(--s-6); height:var(--s-6)}
.navbar-nav{display:flex; align-items:stretch}
.navbar-list{display:flex; align-items:stretch; margin:0; padding:0; list-style:none}
.navbar-list > li{display:flex}
.navbar-item{
  display:inline-flex; flex-direction:column; justify-content:center; align-items:center;
  padding-inline:var(--s-4);
  color:var(--obsidian-200); font-size:var(--t-small); font-weight:500; text-decoration:none; white-space:nowrap;
  cursor:pointer;
  transition:color var(--d-quick) var(--ease-standard);
}
/* the label's bold width is reserved, so selecting an item never moves its neighbours */
.navbar-item::after{content:attr(data-label); height:0; overflow:hidden; visibility:hidden; font-weight:600; pointer-events:none}
.navbar-item:hover{color:var(--obsidian-050)}
.navbar-item:active{color:var(--obsidian-300)}
.navbar-item[aria-current="page"]{color:var(--primary-400); font-weight:600}
.navbar-item[aria-current="page"]:hover{color:var(--primary-400)}
.navbar-item:focus-visible{outline:var(--focus-width) solid var(--obsidian-100); outline-offset:calc(-1 * var(--focus-width)); box-shadow:var(--ring-halo)}  /* inside the item, as the List's row: the bar clips nothing */
.navbar-end{padding-inline-end:var(--s-6); display:flex; align-items:center; gap:var(--s-3); margin-left:auto; flex:none}
.navbar-toggle{display:none}
/* the glyph, not the button, sits on the bar's inset: the button is pulled out by the space around its 16px glyph,
   so the icon lines up with the brand's edge */
.navbar-end > .navbar-toggle{margin-inline-end:calc((var(--icon-sm) - var(--s-10)) / 2)}
@media (pointer:coarse){ .navbar-end > .navbar-toggle{margin-inline-end:calc((var(--icon-sm) - var(--target-touch)) / 2)} }
@container (max-width: 720px){
  .navbar-nav,.navbar-end > .btn-primary{display:none}
  .navbar-toggle{display:inline-flex}
}
/* § 3.26 Navigation · floating bar (v5.0.0): the Bar material with its line all round, lifted off the page.
   On a wide screen one pill at the top: brand, destinations, action. At --bp-md or less the bar is a plain
   row that scrolls away with the brand and the action, and the destinations float in a pill at the bottom,
   where the thumb is. One markup: the CSS moves the pill, the reading order does not change. */
.navbar-floating{
  container-type:normal;
  top:var(--s-4);
  margin:var(--s-4) auto 0;
  width:max-content; max-width:calc(100% - var(--s-8));
  gap:var(--s-4);
  background:var(--surface-bar);
  backdrop-filter:blur(var(--blur-bar)); -webkit-backdrop-filter:blur(var(--blur-bar));
  border:var(--bw-1) solid var(--border-subtle);
  border-radius:var(--r-full);
  box-shadow:var(--sh-3);
}
.navbar-floating::before{content:none}
.navbar-floating .navbar-brand{padding-inline-start:var(--s-2)}
/* a square tile reads as a stranger in a pill: the mark drops its tile and keeps its glyph and glow */
.navbar-floating .brand-mark{background:transparent;border:0;overflow:visible}
.navbar-floating .navbar-end{padding-inline-end:var(--s-2)}
.navbar-floating .navbar-item{padding-inline:var(--s-3)}
@media (max-width: 720px){
  .navbar-floating{
    position:relative; top:auto; margin:0;
    width:auto; max-width:none;
    background:transparent; backdrop-filter:none; -webkit-backdrop-filter:none;
    border:0; border-radius:0; box-shadow:none;
  }
  .navbar-floating .navbar-brand{padding-inline-start:var(--s-4)}
  .navbar-floating .navbar-end{padding-inline-end:var(--s-4)}
  .navbar-floating .navbar-nav{
    position:fixed; z-index:var(--z-sticky);
    left:0; right:0; bottom:var(--s-4); margin:0 auto env(safe-area-inset-bottom);
    width:max-content; max-width:calc(100% - var(--s-8));
    min-block-size:var(--s-12); padding-inline:var(--s-2);
    background:var(--surface-bar);
    backdrop-filter:blur(var(--blur-bar)); -webkit-backdrop-filter:blur(var(--blur-bar));
    border:var(--bw-1) solid var(--border-subtle);
    border-radius:var(--r-full);
    box-shadow:var(--sh-3);
  }
  body:has(.navbar-floating){padding-bottom:calc(var(--s-12) + var(--s-8))}
}

/* site chrome, § 30.1: the bar alone in the tab card, and a page below it that follows the tab — its width,
   its sticky bar, its Drawer menu. Only the page's toggle opens the menu; the card's bar is a specimen. */
.navbar-demo-strip{background:var(--surface);border:var(--bw-1) solid var(--border-subtle)}
.navbar-demo-strip .navbar{position:relative}
.navbar-demo-stage{margin-top:var(--s-6)}
.navbar-demo-frame{display:block;width:100%;height:calc(var(--s-24) * 4);border:var(--bw-1) solid var(--border-subtle);border-radius:var(--r-md);background:var(--surface)}
.navbar-demo-frame-phone{width:calc(var(--s-24) * 4);max-width:100%;height:calc(var(--s-24) * 6)}
.navbar-demo-frames{display:grid;gap:var(--s-6);justify-items:start}
/* § 30.4: the floating bar's frames sit in a device preview, as the Top navigation's strips do (v5.3.0): the bar only,
   in a band as tall as the top bar's strip; on a phone the band holds the top row and the pill at the bottom. Each frame
   is its own viewport, so the phone layout is real. */
.device-preview .navbar-demo-frame{width:100%;border:0;border-radius:0}
.navbar-demo-frame-strip{height:calc(var(--s-12) + var(--s-px) * 2)}
.device-preview[data-device="mobile"] .navbar-demo-frame-strip{height:calc(var(--s-24) + var(--s-6))}
/* the page below: as tall as the Top navigation's, with its frame */
.device-preview .navbar-demo-frame-page{height:calc(9 * var(--s-10));border:var(--bw-1) solid var(--border-subtle);border-radius:var(--r-md)}
.device-preview[data-device="mobile"] .navbar-demo-frame-page{height:calc(14 * var(--s-10))}
.navbar-demo-stage .grid-demo-meta{margin-bottom:var(--s-3)}
.navbar-demo{position:relative;overflow:hidden;overflow:clip;height:calc(9 * var(--s-10));background:var(--surface);border:var(--bw-1) solid var(--border-subtle);border-radius:var(--r-md)}
.device-preview[data-device="mobile"] .navbar-demo{height:calc(14 * var(--s-10))}
.navbar-demo-page{height:100%;overflow-y:auto;overscroll-behavior:contain;scrollbar-width:thin;scrollbar-color:var(--obsidian-700) transparent}
.navbar-demo-body{padding:var(--s-8) var(--s-6) var(--s-16);display:grid;gap:var(--s-4)}
.navbar-demo-title{margin:0;color:var(--obsidian-100);font-size:var(--t-h4);font-weight:700;letter-spacing:var(--tr-snug)}
.navbar-demo-row{display:flex;justify-content:space-between;gap:var(--s-4);padding-block:var(--s-4);border-bottom:var(--bw-1) solid var(--border-subtle);color:var(--obsidian-300);font-size:var(--t-small)}
.navbar-demo::before{content:"";position:absolute;inset:0;background:var(--scrim);backdrop-filter:blur(var(--blur-veil));z-index:var(--z-scrim);opacity:0;pointer-events:none;transition:opacity var(--d-base) var(--ease-accel)}
.navbar-demo.is-open::before{opacity:1;pointer-events:auto;transition-timing-function:var(--ease-decel)}
.navbar-demo .drawer{position:absolute;inset-block:0;z-index:var(--z-menu);width:min(86%, calc(30ch + 2 * var(--pad)))}
.navbar-demo .drawer[open]{display:flex;transition:none;animation:drawer-demo-in var(--d-base) var(--ease-decel)}
@media (prefers-reduced-motion:reduce){.navbar-demo .drawer[open]{animation:none}.navbar-demo::before{transition:none}}

/* ─── Loader compositions (§ 20.3) — frames for the demo cards ─── */
.loader-comp{
  display:flex;
  flex-direction:column;
  background:var(--obsidian-900);
  border:var(--bw-1) solid var(--obsidian-800);
  border-radius:var(--r-lg);
  overflow:hidden;
  min-height:220px;
}
.loader-comp-head{
  display:flex; align-items:center; gap:var(--s-3);
  padding:var(--s-4) var(--s-5);
  border-bottom:var(--bw-1) solid var(--obsidian-800);
}
.loader-comp-eyebrow{
  font-family:var(--font-mono);
  font-size:var(--t-micro);
  letter-spacing:var(--tr-mono);
  color:var(--primary-400);
  text-transform:uppercase;
}
.loader-comp-title{
  font-size:var(--t-small);
  font-weight:600;
  color:var(--obsidian-100);
  letter-spacing:var(--tr-snug);
}
.loader-comp-body{
  flex:1;
  display:flex;
  align-items:center;
  justify-content:center;
  padding:var(--s-6);
  position:relative;
}
.loader-comp-actions{
  display:flex;
  gap:var(--s-3);
  padding:var(--s-3) var(--s-5);
  border-top:var(--bw-1) solid var(--obsidian-800);
  background:var(--obsidian-850);
}
.loader-comp-actions .btn{ font-size:var(--t-micro) }

/* Device-frame composition body (full-page loader inside an iframe-like) */
.loader-device{
  width:100%;
  height:240px;
  background:var(--obsidian-950);
  border:var(--bw-1) solid var(--obsidian-800);
  border-radius:var(--r-md);
  position:relative;
  overflow:hidden;
}
.loader-device-bar{
  display:flex; align-items:center; gap:var(--s-1);
  padding:var(--s-2) var(--s-3);
  border-bottom:var(--bw-1) solid var(--obsidian-800);
  background:var(--obsidian-900);
}
.loader-device-bar .dot{
  width:9px; height:9px;
  border-radius:50%;
  background:var(--obsidian-700);
}
.loader-device-bar .url{
  margin-left:var(--s-3);
  flex:1;
  height:14px;
  background:var(--obsidian-850);
  border-radius:var(--r-sm);
}

/* Tiny chat-composer-style strip for the cross-component composition */
.loader-mini-composer{
  display:flex;
  align-items:center;
  gap:var(--s-3);
  padding:var(--s-3);
  background:var(--obsidian-850);
  border:var(--bw-1) solid var(--obsidian-700);
  border-radius:var(--r-lg);
}
.loader-mini-composer .text{
  flex:1;
  font-size:var(--t-small);
  color:var(--obsidian-300);
}
.loader-mini-bubble{
  align-self:flex-start;
  margin-bottom:var(--s-3);
  padding:var(--s-3) var(--s-4);
  background:var(--obsidian-800);
  border:var(--bw-1) solid var(--obsidian-700);
  border-radius:var(--r-lg);
  display:inline-flex;
  align-items:center;
  gap:var(--s-3);
  font-size:var(--t-small);
  color:var(--obsidian-200);
}

/* ─── Scale subsection (§ 20.1) — the four sizes side-by-side ─── */
.loader-scale{
  display:grid;
  grid-template-columns:repeat(4, 1fr);
  gap:var(--s-4);
}
.loader-scale-cell{
  display:flex;
  flex-direction:column;
  align-items:center;
  gap:var(--s-4);
  padding:var(--s-6) var(--s-4);
  background:var(--obsidian-900);
  border:var(--bw-1) solid var(--obsidian-800);
  border-radius:var(--r-md);
  min-height:180px;
  justify-content:center;
}
.loader-scale-cell .loader-anim{ position:relative }
.loader-scale-cell .loader-fallback{ position:absolute; inset:0 }
.loader-scale-cell .meta{
  display:flex;
  flex-direction:column;
  align-items:center;
  gap:var(--s-0-5);
  margin-top:auto;
}
.loader-scale-cell .token{
  font-family:var(--font-mono);
  font-size:var(--t-micro);
  letter-spacing:var(--tr-mono);
  color:var(--primary-400);
  text-transform:uppercase;
}
.loader-scale-cell .value{
  font-family:var(--font-mono);
  font-size:var(--t-micro);
  letter-spacing:var(--tr-mono);
  color:var(--obsidian-300);
}

/* ─── Variants subsection (§ 20.2) — five labeled specimens ─── */
.loader-variants{
  display:grid;
  grid-template-columns:repeat(5, minmax(0, 1fr));
  gap:var(--s-4);
}
.loader-variant-cell{
  display:flex;
  flex-direction:column;
  align-items:center;
  justify-content:center;
  gap:var(--s-4);
  padding:var(--s-6) var(--s-4);
  background:var(--obsidian-900);
  border:var(--bw-1) solid var(--obsidian-800);
  border-radius:var(--r-md);
  min-height:220px;
  position:relative;
}
.loader-variant-cell .caption{
  position:absolute;
  bottom:var(--s-3);
  left:0; right:0;
  text-align:center;
  font-family:var(--font-mono);
  font-size:var(--t-micro);
  letter-spacing:var(--tr-mono);
  color:var(--obsidian-300);
  text-transform:uppercase;
}

/* ─── Anatomy diagram (§ 20.4) — annotated specimen ─── */
.loader-anatomy{
  display:grid;
  grid-template-columns:minmax(280px, 380px) 1fr;
  gap:var(--s-10);
  padding:var(--s-8);
  background:var(--obsidian-900);
  border:var(--bw-1) solid var(--obsidian-800);
  border-radius:var(--r-lg);
  align-items:center;
}
.loader-anatomy-canvas{
  display:flex;
  flex-direction:column;
  align-items:center;
  gap:var(--s-4);
  padding:var(--s-8);
  background:var(--obsidian-950);
  border:var(--bw-1) solid var(--obsidian-800);
  border-radius:var(--r-md);
}
.loader-anatomy-canvas .loader-anim{ position:relative }
.loader-anatomy-canvas .loader-fallback{ position:absolute; inset:0 }
.loader-anatomy-legend{ display:grid; gap:var(--s-3) }
.loader-anatomy-row{
  display:grid;
  grid-template-columns:28px 1fr auto;
  gap:var(--s-3);
  align-items:baseline;
  padding-bottom:var(--s-3);
  border-bottom:var(--bw-1) solid var(--obsidian-800);
}
.loader-anatomy-row:last-child{ border-bottom:none; padding-bottom:0 }
.loader-anatomy-num{
  font-family:var(--font-mono);
  font-size:var(--t-micro);
  letter-spacing:var(--tr-mono);
  color:var(--primary-400);
}
.loader-anatomy-label{ font-size:var(--t-small); color:var(--obsidian-100); font-weight:500 }
.loader-anatomy-value{
  font-family:var(--font-mono);
  font-size:var(--t-micro);
  letter-spacing:var(--tr-mono);
  color:var(--obsidian-300);
  text-transform:uppercase;
}

/* ─── Reduced motion: hide Lottie, show CSS ring ─── */
@media (prefers-reduced-motion: reduce){
  .loader-anim{ display:none !important }
  .loader-fallback{ display:flex }
  .loader-check{ transition:none }
  .skeleton-line::after,
  .skeleton-circle::after,
  .skeleton-block::after{ animation:none; opacity:0 }
  .popover,.popover-top,.popover-end{ transition:none; transform:none }
}

/* Mobile */
@media (max-width: 720px){
  .loader-scale{ grid-template-columns:repeat(2, 1fr) }
  .loader-variants{ grid-template-columns:repeat(2, 1fr) }
  .loader-anatomy{ grid-template-columns:1fr; padding:var(--s-5); gap:var(--s-6) }
}


/* ─────────── DIAGRAMS · § 21 ─────────── */
/* Auto-layout flow/architecture diagrams (Mermaid, theme base) themed entirely
   from tokens read at runtime. The figure chrome is coherent with .card (§ 12):
   --obsidian-900 surface, --obsidian-700 border, --r-lg, --s-6 padding. */
.diagram{
  margin:0;
  display:flex;
  flex-direction:column;
  gap:var(--s-5);
  padding:var(--s-6);
  background:var(--obsidian-900);
  border:var(--bw-1) solid var(--obsidian-700);
  border-radius:var(--r-lg);
}
/* Render target — the Mermaid SVG is injected here. role="img" + aria-label. */
.diagram-canvas{
  display:flex;
  justify-content:center;
  align-items:center;
  min-height:140px;
  padding:var(--s-4) var(--s-2);
  overflow-x:auto;
}
.diagram-canvas svg{
  max-width:100%;
  height:auto;
  display:block;
}
/* Mermaid's label classes (.nodeLabel / .edgeLabel / .cluster-label) are unique
   to diagrams. Neutralize them GLOBALLY — not just inside .diagram-canvas — so
   Mermaid's off-screen width-measurement pass matches the render. Otherwise the
   design system's global `.label` rule (mono, uppercase, tracked) uppercases the
   measured text and inflates every node box. These classes never appear in any
   design-system component, so the global scope is safe. */
.nodeLabel, .edgeLabel, .cluster-label,
.diagram-canvas .label{
  font-family:var(--font-sans);
  font-weight:400;
  letter-spacing:var(--tr-normal);
  text-transform:none;
}
.nodeLabel, .cluster-label{ font-size:var(--t-small) }
.edgeLabel{ font-size:var(--t-caption) }
.diagram-canvas .nodeLabel{ fill:var(--obsidian-100); color:var(--obsidian-100) }
.diagram-canvas .edgeLabel{ fill:var(--obsidian-300); color:var(--obsidian-300) }
.diagram-canvas .cluster-label{ fill:var(--obsidian-200); color:var(--obsidian-200) }
/* Safety net: label content is flex-centered via JS, so any residual overflow
   spills symmetrically and never reaches the node border (16px padding). */
.diagram-canvas foreignObject{ overflow:visible }
/* Edges a touch thicker (arrowheads inherit lineColor from themeVariables). */
.diagram-canvas .edgePaths path,
.diagram-canvas path.flowchart-link{ stroke-width:2px }
/* Edge labels (yes / no) get an opaque chip applied via JS on the label div
   (Mermaid paints it at 0.5 alpha through an id-scoped rule). Just reset margins. */
.diagram-canvas .edgeLabel p,
.diagram-canvas .edgeLabel .nodeLabel{ margin:0 }
/* Node radius → --r-md. rx is a geometry property Mermaid leaves unset on
   default rectangles, so this applies without !important (no inline override). */
.diagram-canvas .node rect,
.diagram-canvas .node .basic{ rx:var(--r-md); ry:var(--r-md) }
/* Subgraph / cluster box radius → --r-lg, matching panels. */
.diagram-canvas .cluster rect{ rx:var(--r-lg); ry:var(--r-lg) }
/* Caption — mono micro, echoes .card-meta. "FIG-NN · title". */
.diagram-caption{
  font-family:var(--font-mono);
  font-size:var(--t-micro);
  letter-spacing:var(--tr-mono);
  text-transform:uppercase;
  color:var(--obsidian-300);
}
.diagram-caption .num{ color:var(--primary-400) }

/* Legend — only for semantic-state diagrams. Color is never alone: each row
   pairs a shape token + a written label (§ 6 floor #1). */
.diagram-legend{
  display:flex;
  flex-wrap:wrap;
  gap:var(--s-3) var(--s-5);
  padding-top:var(--s-4);
  border-top:var(--bw-1) solid var(--obsidian-800);
}
.diagram-legend-item{
  display:flex;
  align-items:center;
  gap:var(--s-2);
  font-size:var(--t-small);
  color:var(--obsidian-200);
}
.diagram-legend-swatch{
  width:20px;
  height:20px;
  flex-shrink:0;
  background:var(--obsidian-800);
  border:var(--bw-1) solid var(--obsidian-600);
}
.diagram-legend-swatch.is-focus{ border-color:var(--primary-500); border-radius:var(--r-md) }
.diagram-legend-swatch.is-ok{ border-color:var(--success); border-radius:var(--r-full) }
.diagram-legend-swatch.is-warn{ border-color:var(--warning); transform:rotate(45deg) }
.diagram-legend-swatch.is-bad{ border-color:var(--danger); border-radius:var(--r-md) }
.diagram-legend-meta{
  font-family:var(--font-mono);
  font-size:var(--t-micro);
  letter-spacing:var(--tr-mono);
  text-transform:uppercase;
  color:var(--obsidian-300);
}

/* ─── Entrance: opacity-only cascade (§ 7.3 — never transform the SVG groups) ───
   JS sets opacity:0 + per-element transition-delay after Mermaid's async render
   resolves, then flips opacity:1 on scroll-in. Reduced motion renders straight
   to the resolved state (handled in JS — no hidden initial state is ever set). */
.diagram-canvas svg .node,
.diagram-canvas svg .cluster,
.diagram-canvas svg .edgePath,
.diagram-canvas svg .edgePaths path,
.diagram-canvas svg .edgeLabel{
  will-change:opacity;
}

/* Mobile */
@media (max-width: 720px){
  .diagram{ padding:var(--s-5) }
  .diagram-canvas{ padding:var(--s-2) 0 }
}


/* =========================================================
   TOAST — transient, stacked, bottom-right
   The § 6 floor forbids auto-advancing content (#6). A toast may
   auto-dismiss only when it carries no action and no error: the
   dismissal is the reader's by default, `data-autohide` is opt-in
   and never applies to `.toast-danger`.
   ========================================================= */
.toast-region{
  position:fixed;right:var(--s-6);bottom:var(--s-6);
  z-index:var(--z-toast);
  display:flex;flex-direction:column;gap:var(--s-3);
  width:min(var(--w-toast), calc(100vw - var(--s-8)));
  pointer-events:none;
}
.toast{
  pointer-events:auto;
  display:grid;grid-template-columns:auto minmax(0,1fr) auto;
  column-gap:var(--s-3);row-gap:var(--s-1);align-items:center;
  padding:var(--s-4);
  background:var(--obsidian-850);
  border:var(--bw-1) solid var(--obsidian-700);
  border-left:var(--bw-2) solid var(--primary-500);
  border-radius:var(--r-md);
  box-shadow:var(--sh-3);
  font-size:var(--t-small);color:var(--obsidian-200);
  opacity:0;transform:translateX(24px);
  transition:opacity var(--d-base) var(--ease-decel), transform var(--d-base) var(--ease-decel);
}
.toast.is-in{opacity:1;transform:translateX(0)}
.toast.is-out{
  opacity:0;transform:translateX(24px);
  transition:opacity var(--d-quick) var(--ease-accel), transform var(--d-quick) var(--ease-accel);
}
/* Collapse — the stack closes the gap the dismissed toast leaves, it never
   snaps shut. Two moves: the fade and slide go first (that is the exit, and
   exits ride --ease-accel), then the box collapses.
   The collapse rides --ease-decel, not --ease-accel: it is not the exit of
   this toast, it is the REPOSITIONING of the ones below it. They are not
   leaving — they are settling into a new place, which is a system-triggered
   state change. `--s-3` is the region gap; the negative margin eats it so
   nothing is left behind. */
.toast.is-collapsing{
  /* max-height is driven inline by the controller — an inline start value
     outranks a class end value, so both ends have to live in the same place. */
  padding-block:0;border-block-width:0;
  margin-bottom:calc(-1 * var(--s-3));
  overflow:hidden;
  transition:max-height var(--d-base) var(--ease-decel),
             padding var(--d-base) var(--ease-decel),
             margin var(--d-base) var(--ease-decel),
             border-width var(--d-base) var(--ease-decel);
}
@media (prefers-reduced-motion: reduce){
  .toast.is-collapsing{transition:none}
}
.toast-icon{grid-column:1;grid-row:1;width:var(--icon-sm);height:var(--icon-sm);color:var(--primary-400)}
.toast-title{grid-column:2;grid-row:1;font-weight:600;color:var(--obsidian-100);min-width:0}
.toast-body{grid-column:2;grid-row:1;min-width:0;overflow-wrap:anywhere}
.toast:has(.toast-title) .toast-body{grid-column:1 / -1;grid-row:2}
.toast-action{
  font-family:var(--font-mono);font-size:var(--t-micro);letter-spacing:var(--tr-mono);text-transform:uppercase;
  color:var(--primary-400);background:transparent;border:0;cursor:pointer;
  padding:var(--s-1) 0;margin-top:var(--s-2);
  transition:color var(--d-quick) var(--ease-standard);
}
.toast-action:hover{color:var(--primary-300)}
.toast-action:focus-visible{outline:var(--focus-width) solid var(--obsidian-100);outline-offset:var(--focus-offset);box-shadow:var(--ring-halo)}
.toast-dismiss{
  grid-column:3;grid-row:1;display:grid;place-items:center;width:var(--s-5);height:var(--s-5);padding:0;
  margin-inline-end:calc((var(--icon-xs) - var(--s-5)) / 2);  /* padding:0 or the browser's button padding squeezes the glyph; the glyph, not the target, sits on the padding edge */
  color:var(--obsidian-400);border-radius:var(--r-sm);background:transparent;border:0;cursor:pointer;
  transition:color var(--d-quick) var(--ease-standard), background var(--d-quick) var(--ease-standard);
}
.toast-dismiss:hover{color:var(--obsidian-100);background:var(--obsidian-800)}
.toast-dismiss:focus-visible{outline:var(--focus-width) solid var(--obsidian-100);outline-offset:var(--s-px);box-shadow:var(--ring-halo)}
.toast-dismiss svg{width:var(--icon-xs);height:var(--icon-xs)}

.toast-success{border-left-color:var(--success)}
.toast-success .toast-icon{color:var(--success)}
.toast-warn{border-left-color:var(--warning)}
.toast-warn .toast-icon{color:var(--warning)}
.toast-danger{border-left-color:var(--danger)}
.toast-danger .toast-icon{color:var(--danger)}

@media (max-width:480px){
  .toast-region{left:var(--s-4);right:var(--s-4);bottom:var(--s-4);width:auto}
}


/* =========================================================
   TOOLTIP — label only, never the sole carrier of meaning
   Never contains interactive content: the § 6 floor requires the
   information to survive without hover (#1, #5). Anchored, no arrow.
   ========================================================= */
.tooltip-wrap{position:relative;display:inline-flex}
.tooltip{
  position:absolute;bottom:calc(100% + var(--s-1));left:50%;
  transform:translateX(-50%);
  z-index:var(--z-popover);
  max-width:var(--w-tooltip);width:max-content;
  padding:var(--s-1) var(--s-2);
  background:var(--obsidian-800);
  border:var(--bw-1) solid var(--obsidian-700);
  border-radius:var(--r-sm);
  box-shadow:var(--sh-2);
  font-family:var(--font-sans);font-size:var(--t-caption);line-height:var(--lh-snug);
  color:var(--obsidian-100);
  opacity:0;pointer-events:none;
  transition:opacity var(--d-quick) var(--ease-standard);  /* a fade where it stands, no travel (v5.3.0) */
}
/* Open state is a class, never :hover — the RIGID single-open rule
   (§ 3.25) cannot be expressed in CSS alone. The controller opens on
   pointerenter and focusin and closes every other tooltip first. */
.tooltip.is-open{opacity:1}
.tooltip-bottom{bottom:auto;top:calc(100% + var(--s-1))}
/* near the end edge the bubble aligns its end to the anchor's end, instead of centring past the screen */
.tooltip-end{left:auto;right:0;transform:none}

/* § 24.1 — a swatch (§ 3.36) beside each token name in the contrast pairs (v5.0.0): the pair reads at a glance.
   Swatch and name are one unit that never breaks across lines. */
.table-contrast .tok{display:inline-flex;align-items:center;gap:var(--s-1);white-space:nowrap}

/* § 3.7 — Link (v5.0.0): inline text link, underlined at rest (WCAG 1.4.1 — the colour alone is 2.1:1 against the body text).
   Rest 1px, hover 2px + lighter; pressed --primary-500; the pressable ring on focus-visible; no visited state. */
.link{
  color:var(--primary-400);
  text-decoration:underline;text-decoration-thickness:var(--bw-1);text-underline-offset:var(--s-1);
  border-radius:var(--r-sm);cursor:pointer;
  transition:color var(--d-quick) var(--ease-standard),text-decoration-thickness var(--d-quick) var(--ease-standard);
}
.link:hover{color:var(--primary-300);text-decoration-thickness:var(--bw-2)}
.link:active{color:var(--primary-500)}
.link:focus-visible{outline:var(--focus-width) solid var(--obsidian-100);outline-offset:var(--focus-offset);box-shadow:var(--ring-halo)}
.link[aria-disabled="true"]{color:var(--obsidian-400);text-decoration-thickness:var(--bw-1);cursor:not-allowed}

/* § 3.7 — Link, quiet variant (v5.0.0): no underline at rest. For a standalone link only (menu, footer, list of links),
   where the context already says it is a link. In running text it fails WCAG 1.4.1 — the colour is 2.1:1 against the text. */
.link-quiet{
  color:var(--primary-400);
  text-decoration:underline;text-decoration-color:transparent;text-decoration-thickness:var(--bw-1);text-underline-offset:var(--s-1);
  border-radius:var(--r-sm);cursor:pointer;
  transition:color var(--d-quick) var(--ease-standard),text-decoration-color var(--d-quick) var(--ease-standard);
}
.link-quiet:hover,.link-quiet:focus-visible{color:var(--primary-300);text-decoration-color:currentColor}
.link-quiet:active{color:var(--primary-500);text-decoration-color:currentColor}
.link-quiet:focus-visible{outline:var(--focus-width) solid var(--obsidian-100);outline-offset:var(--focus-offset);box-shadow:var(--ring-halo)}
.link-quiet[aria-disabled="true"]{color:var(--obsidian-400);text-decoration-color:transparent;cursor:not-allowed}

/* § 3.21 — Modal (v5.0.0): a native <dialog> opened with showModal(). The panel is the card's surface and radius, the top
   step of the shadow scale, over --scrim. Opens on opacity + a scale from 0.96 about its centre; closes on opacity + the
   same scale, faster: the Lightbox's entrance, so the two centred overlays arrive alike (v5.3.0). */
.modal{
  width:calc(100% - var(--s-8));max-width:var(--w-modal);max-height:calc(100vh - var(--s-8));overflow:auto;
  /* centred on the viewport's own middle, 50vw · 50vh, which a classic scrollbar does not move: the scroll lock hides
     the scrollbar while the modal is open and it comes back as the panel fades, so a panel centred in the narrower
     box slid 5px on close (v5.3.0). The scale of the motion stays on transform; the centring is on translate. */
  inset:auto;left:50vw;top:50vh;translate:-50% -50%;margin:0;padding:var(--s-6);
  background:var(--obsidian-800);color:var(--obsidian-100);
  border:var(--bw-1) solid var(--obsidian-700);border-radius:var(--r-lg);box-shadow:var(--sh-4);
  font-family:var(--font-sans);
  opacity:0;transform:scale(0.96);
  transition:opacity var(--d-quick) var(--ease-accel),transform var(--d-quick) var(--ease-accel),
    overlay var(--d-quick) var(--ease-accel) allow-discrete,display var(--d-quick) var(--ease-accel) allow-discrete;
}
.modal-wide{max-width:720px}
.modal[open]{
  opacity:1;transform:none;
  transition:opacity var(--d-quick) var(--ease-decel),transform var(--d-base) var(--ease-decel),
    overlay var(--d-quick) var(--ease-decel) allow-discrete,display var(--d-quick) var(--ease-decel) allow-discrete;
}
@starting-style{.modal[open]{opacity:0;transform:scale(0.96)}}
.modal::backdrop{
  background:transparent;
  transition:background var(--d-quick) var(--ease-accel),overlay var(--d-quick) var(--ease-accel) allow-discrete,display var(--d-quick) var(--ease-accel) allow-discrete;
}
.modal[open]::backdrop{background:var(--scrim);backdrop-filter:blur(var(--blur-veil));transition:background var(--d-quick) var(--ease-decel),overlay var(--d-quick) var(--ease-decel) allow-discrete,display var(--d-quick) var(--ease-decel) allow-discrete}
@starting-style{.modal[open]::backdrop{background:transparent}}
body:has(.modal:modal){overflow:hidden}  /* only a modal opened with showModal() locks the page; the inline demo (static `open`) must not */
.modal-head{display:flex;align-items:center;justify-content:space-between;gap:var(--s-4);margin-bottom:var(--s-4)}
.modal-head .btn-icon{flex:none}  /* the glyph sits on the content edge, level with the title; the 32px target reaches into the padding */
.modal-head .btn-icon:focus-visible{outline-offset:calc(-1 * var(--focus-width));box-shadow:none}  /* the ring stays inside the button, without the halo: the one place the ring leaves the standard offset */
.modal-title{margin:0;font-size:var(--t-h6);font-weight:700;line-height:var(--lh-snug)}
.modal-body{margin:0;color:var(--obsidian-200);font-size:var(--t-body)}
.modal-foot{display:flex;justify-content:flex-end;flex-wrap:wrap;gap:var(--s-2);margin-top:var(--s-6)}
@media (max-width:480px){.modal-foot .btn{flex:1 1 100%}}
@media (prefers-reduced-motion:reduce){
  .modal,.modal[open]{transition:none;transform:none}
  .modal::backdrop,.modal[open]::backdrop{transition:none}
}
/* § 3.37 Avatar — who a person, team or account is. A circle; the name sits on the wrapper (role="img"). */
.avatar{--size:var(--s-8);--fs:var(--t-caption);--dot:var(--s-2);--o:var(--s-2);position:relative;display:inline-flex;align-items:center;justify-content:center;flex:none;box-sizing:border-box;width:var(--size);height:var(--size);padding:0;border:var(--bw-1) solid var(--obsidian-600);border-radius:var(--r-full);background:var(--obsidian-700);color:var(--obsidian-100);font:700 var(--fs)/1 var(--font-sans);text-transform:uppercase;text-decoration:none;vertical-align:middle;user-select:none}
.avatar-sm{--size:var(--s-6);--fs:var(--t-micro);--o:calc(var(--s-1) + var(--s-0-5))}
.avatar-lg{--size:var(--s-10);--fs:var(--t-body);--dot:var(--s-3);--o:var(--s-3)}
.avatar-xl{--size:var(--s-12);--fs:var(--t-lead);--dot:var(--s-3);--o:var(--s-3)}
.avatar-2xl{--size:var(--s-16);--fs:var(--t-h5);--dot:var(--s-4);--o:var(--s-4)}
.avatar-img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;border-radius:inherit}
.avatar>svg{width:60%;height:60%;color:var(--obsidian-300)}
.avatar-mark{background:var(--obsidian-850)}
.avatar-mark>.avatar-img{inset:22%;width:56%;height:56%;object-fit:contain}
.avatar-hue-1,.avatar-hue-2,.avatar-hue-3,.avatar-hue-4,.avatar-hue-5{background:color-mix(in srgb,var(--h) calc(var(--tint-fill-deep) * 100%),var(--obsidian-800));border-color:color-mix(in srgb,var(--h) calc(var(--tint-edge) * 100%),transparent);color:var(--h)}
.avatar-hue-1{--h:var(--primary-300)}
.avatar-hue-2{--h:var(--info)}
.avatar-hue-3{--h:var(--success)}
.avatar-hue-4{--h:var(--warning)}
.avatar-hue-5{--h:var(--tertiary-200)}
.avatar-dot{position:absolute;right:calc(-1 * var(--bw-2));bottom:calc(-1 * var(--bw-2));box-sizing:content-box;width:var(--dot);height:var(--dot);border:var(--bw-2) solid var(--avatar-ring,var(--obsidian-950));border-radius:var(--r-full);background:var(--dc)}
.avatar-dot[data-status="online"]{--dc:var(--success)}
.avatar-dot[data-status="away"]{--dc:var(--warning)}
.avatar-dot[data-status="busy"]{--dc:var(--danger)}
.avatar-dot[data-status="offline"]{--dc:transparent;box-shadow:inset 0 0 0 var(--bw-2) var(--obsidian-400)}
.avatar-group{display:inline-flex;align-items:center}
.avatar-group>.avatar+.avatar{margin-inline-start:calc(-1 * var(--o))}
.avatar-group>.avatar:not(:last-child){--cut:calc(var(--size) / 2 + var(--bw-2));padding-inline-end:calc(var(--o) + var(--bw-2));-webkit-mask:radial-gradient(circle at calc(var(--size) - var(--o) + var(--size) / 2) 50%,transparent var(--cut),black calc(var(--cut) + var(--bw-1) / 2));mask:radial-gradient(circle at calc(var(--size) - var(--o) + var(--size) / 2) 50%,transparent var(--cut),black calc(var(--cut) + var(--bw-1) / 2))}
.avatar-more{background:var(--obsidian-800);color:var(--obsidian-200);font-weight:500}
a.avatar,button.avatar{cursor:pointer;transition:border-color var(--d-quick) var(--ease-standard)}
a.avatar:hover,button.avatar:hover{border-color:var(--primary-400)}
a.avatar:active,button.avatar:active{border-color:var(--primary-500)}
a.avatar:focus-visible,button.avatar:focus-visible{outline:var(--focus-width) solid var(--obsidian-100);outline-offset:var(--focus-offset);box-shadow:var(--ring-halo)}
@media (prefers-reduced-motion:reduce){a.avatar,button.avatar{transition:none}}

/* § 3.1 Icon — one hand: viewBox 16, stroke 1.5 on the grid (so it grows with the size), round ends, outline only. Colour is inherited. */
.icon{width:var(--icon-sm);height:var(--icon-sm);flex:none;fill:none;stroke:currentColor;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;vertical-align:middle}
.icon-xs{width:var(--icon-xs);height:var(--icon-xs)}
.icon-md{width:var(--icon-md);height:var(--icon-md)}
.icon-lg{width:var(--icon-lg);height:var(--icon-lg)}
.icon-muted{color:var(--obsidian-300)}
.icon-fill{fill:currentColor;stroke-width:var(--bw-1)}  /* solid: the same box, filled; the 1px stroke only rounds the corners */

/* § 3.38 List — rows in a column: many things of one kind (.list-item), or the facts of one (.list-summary). Hairlines between rows, nothing around. */
.list{list-style:none;margin:0;padding:0;border-top:var(--bw-1) solid var(--obsidian-700)}
.list > li{border-bottom:var(--bw-1) solid var(--obsidian-700)}
.list-item{display:flex;align-items:center;gap:var(--s-3);box-sizing:border-box;width:100%;min-height:var(--s-12);padding:var(--s-3) var(--s-4);color:var(--obsidian-100);font:inherit;font-size:var(--t-small);text-align:left;text-decoration:none;background:transparent;border:0}
.list-body{flex:1;min-width:0;display:flex;flex-direction:column;gap:var(--s-px)}
.list-title{color:var(--obsidian-100);font-size:var(--t-small)}
.list-meta{color:var(--obsidian-300);font-size:var(--t-caption)}
.list-end{flex:none;display:flex;align-items:center;gap:var(--s-2);margin-left:auto}
a.list-item,button.list-item{cursor:pointer;transition:background var(--d-quick) var(--ease-standard)}
a.list-item:hover,button.list-item:hover{background:var(--obsidian-850)}
a.list-item:focus-visible,button.list-item:focus-visible{outline:var(--focus-width) solid var(--obsidian-100);outline-offset:calc(-1 * var(--focus-width));box-shadow:var(--ring-halo)}  /* inside the row: the list clips nothing, the ring stays on the hairlines */
.list-item[aria-disabled="true"]{opacity:var(--opacity-disabled);cursor:not-allowed}
.list-summary{margin:0;border-top:var(--bw-1) solid var(--obsidian-700)}
.list-summary > div{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,2fr) var(--s-20);align-items:baseline;gap:var(--s-4);padding:var(--s-3) var(--s-4);border-bottom:var(--bw-1) solid var(--obsidian-700)}
.list-key{margin:0;font-family:var(--font-mono);font-size:var(--t-micro);letter-spacing:var(--tr-mono);text-transform:uppercase;color:var(--obsidian-300)}
.list-value{margin:0;min-width:0;color:var(--obsidian-100);font-size:var(--t-small)}
.list-actions{margin:0;display:flex;justify-content:flex-end;gap:var(--s-2)}
@media (max-width:720px){.list-summary > div{grid-template-columns:1fr}}
@media (prefers-reduced-motion:reduce){a.list-item,button.list-item{transition:none}}

/* § 3.30 Pagination — move between pages of similar items. A nav of links: numbered, or compact (previous · status · next). */
.pagination{display:flex;align-items:center;gap:var(--s-1)}
.pagination-list{list-style:none;margin:0;padding:0;display:flex;align-items:center;gap:var(--s-1)}
.pagination-link{display:inline-flex;align-items:center;justify-content:center;gap:var(--s-2);box-sizing:border-box;min-width:var(--s-8);height:var(--s-8);padding:0 var(--s-2);border:var(--bw-1) solid transparent;border-radius:var(--r-md);background:transparent;color:var(--obsidian-300);font:inherit;font-size:var(--t-small);font-variant-numeric:tabular-nums;text-decoration:none;cursor:pointer;transition:background var(--d-quick) var(--ease-standard),color var(--d-quick) var(--ease-standard)}
.pagination-link:hover{background:var(--obsidian-700);color:var(--obsidian-100)}
.pagination-link:focus-visible{outline:var(--focus-width) solid var(--obsidian-100);outline-offset:var(--s-px);box-shadow:var(--ring-halo);color:var(--obsidian-100)}
.pagination-link[aria-current="page"]{background:var(--obsidian-700);border-color:var(--obsidian-500);color:var(--obsidian-100);font-weight:600;cursor:default}
.pagination-link[aria-disabled="true"]{opacity:var(--opacity-disabled);cursor:not-allowed}
.pagination-gap{display:inline-flex;align-items:center;justify-content:center;min-width:var(--s-8);color:var(--obsidian-300);font-size:var(--t-small)}
.pagination-status{padding:0 var(--s-3);color:var(--obsidian-300);font-size:var(--t-small);font-variant-numeric:tabular-nums}
@media (max-width:480px){.pagination{flex-wrap:wrap}.pagination-link > span{display:none}.pagination-gap{min-width:var(--s-6)}}  /* the numbered form still fits: the words drop out and the names stay on aria-label; the compact form is the real answer */
@media (prefers-reduced-motion:reduce){.pagination-link{transition:none}}

/* § 3.9 Slider — a number, or a range of two, chosen by dragging. Native range inputs underneath: keyboard, form value and screen reader come with them. */
.slider{display:flex;flex-direction:column;gap:var(--s-2)}
.slider-head{display:flex;align-items:baseline;justify-content:space-between;gap:var(--s-3)}
.slider-value{color:var(--obsidian-100);font-size:var(--t-small);font-variant-numeric:tabular-nums}
.slider-scale{display:flex;justify-content:space-between;color:var(--obsidian-300);font-size:var(--t-caption);font-variant-numeric:tabular-nums}
.slider-input{-webkit-appearance:none;appearance:none;display:block;width:100%;height:var(--s-8);margin:0;padding:0;background:transparent;cursor:pointer;outline:none}
.slider-input::-webkit-slider-runnable-track{height:var(--s-1);border-radius:var(--r-full);background:linear-gradient(to right,var(--primary-500) var(--slider-fill),var(--obsidian-600) var(--slider-fill))}
.slider-input::-moz-range-track{height:var(--s-1);border-radius:var(--r-full);background:linear-gradient(to right,var(--primary-500) var(--slider-fill),var(--obsidian-600) var(--slider-fill))}
.slider-input::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;box-sizing:border-box;width:var(--s-5);height:var(--s-5);margin-top:calc((var(--s-1) - var(--s-5)) / 2);border:var(--bw-2) solid var(--obsidian-950);border-radius:var(--r-full);background:var(--obsidian-100);box-shadow:var(--sh-1);transition:box-shadow var(--d-quick) var(--ease-standard), transform var(--d-quick) var(--ease-standard)}
.slider-input::-moz-range-thumb{box-sizing:border-box;width:var(--s-5);height:var(--s-5);border:var(--bw-2) solid var(--obsidian-950);border-radius:var(--r-full);background:var(--obsidian-100);box-shadow:var(--sh-1);transition:box-shadow var(--d-quick) var(--ease-standard), transform var(--d-quick) var(--ease-standard)}
/* Hover grows the thumb one step, --s-5 to --s-6, as a scale about its centre on --ease-standard: the same answer
   as the switch's knob (v5.3.0). */
@media (hover: hover){
  .slider-input:not(:disabled):hover::-webkit-slider-thumb{transform:scale(calc(24 / 20))}
  .slider-input:not(:disabled):hover::-moz-range-thumb{transform:scale(calc(24 / 20))}
}
.slider-input:focus-visible::-webkit-slider-thumb{box-shadow:var(--ring-halo)}
.slider-input:focus-visible::-moz-range-thumb{box-shadow:var(--ring-halo)}
.slider-input:active{cursor:grabbing}
.slider-input:disabled{opacity:var(--opacity-disabled);cursor:not-allowed}
/* range: two inputs on one track; the pair draws the track, the inputs pass the pointer through to their thumbs */
.slider-pair{position:relative;height:var(--s-8)}
.slider-pair::before{content:"";position:absolute;left:0;right:0;top:50%;height:var(--s-1);transform:translateY(-50%);border-radius:var(--r-full);background:linear-gradient(to right,transparent var(--lo,0%),var(--primary-500) var(--lo,0%),var(--primary-500) var(--hi,100%),transparent var(--hi,100%)),var(--obsidian-600);z-index:0}
.slider-pair .slider-input{position:absolute;inset:0;z-index:1;pointer-events:none}
.slider-pair .slider-input::-webkit-slider-runnable-track{background:transparent}
.slider-pair .slider-input::-moz-range-track{background:transparent}
.slider-pair .slider-input::-webkit-slider-thumb{pointer-events:auto;cursor:pointer}
.slider-pair .slider-input::-moz-range-thumb{pointer-events:auto;cursor:pointer}
@media (prefers-reduced-motion:reduce){.slider-input::-webkit-slider-thumb,.slider-input::-moz-range-thumb{transition:none}}

/* § 3.34 Divider — a thematic break inside one container. One hairline; the space around it belongs to the container. */
.divider{display:block;width:100%;height:0;margin:0;padding:0;border:0;border-top:var(--bw-1) solid var(--obsidian-700)}
.divider-vertical{align-self:stretch;width:0;height:auto;min-height:var(--s-4);border-top:0;border-left:var(--bw-1) solid var(--obsidian-700)}
.divider-label{display:flex;align-items:center;gap:var(--s-3);width:100%;color:var(--obsidian-300);font-size:var(--t-caption)}
.divider-label::before,.divider-label::after{content:"";flex:1;border-top:var(--bw-1) solid var(--obsidian-700)}

/* site-only: a modal drawn open inside a frame, so the page can show it without taking over the screen */
.modal-demo{position:relative;display:flex;align-items:center;justify-content:center;min-height:var(--s-24);padding:var(--s-8);overflow:hidden;background:var(--obsidian-950);border:var(--bw-1) solid var(--obsidian-800);border-radius:var(--r-lg)}
.modal-demo::before{content:"";position:absolute;inset:0;background:var(--scrim);backdrop-filter:blur(var(--blur-veil));z-index:1;transition:opacity var(--d-quick) var(--ease-decel)}
/* The anatomy frame moves as the real Modal does (v5.3.0): in, the panel grows from 0.96 and fades in over the scrim;
   out, the same on --d-quick · --ease-accel. It plays once when the frame comes into view, and on Open / Close. */
.modal-demo .modal{position:relative;inset:auto;translate:none;margin:0;z-index:2;
  transition:opacity var(--d-quick) var(--ease-accel),transform var(--d-quick) var(--ease-accel),visibility var(--d-quick) var(--ease-accel)}
.modal-demo .modal[open]{opacity:1;transform:none;
  transition:opacity var(--d-quick) var(--ease-decel),transform var(--d-base) var(--ease-decel),visibility var(--d-quick) var(--ease-decel)}
.modal-demo.is-closed::before{opacity:0;transition-timing-function:var(--ease-accel)}
.modal-demo .modal:not([open]){display:block;visibility:hidden}
.modal-demo.is-snap::before,.modal-demo.is-snap .modal{transition:none}
@media (prefers-reduced-motion:reduce){.modal-demo::before,.modal-demo .modal{transition:none}}
.modal-demo > .drawer-demo-open{position:absolute;inset:0;z-index:0;display:flex;align-items:center;justify-content:center}


/* § 3.31 Stepper — the steps of a linear journey: done, current, upcoming. An ordered list; the current step carries aria-current="step".
   Horizontal; vertical below 480px of its own width (container query) or with .stepper-vertical. */
.stepper{--stp-dot:var(--s-6);--stp-cur:var(--s-8);container-type:inline-size}
.stepper-list{list-style:none;margin:0;padding:0;display:flex}
.stepper-step{flex:1 1 0;min-width:0;position:relative;display:flex;flex-direction:column;align-items:center;text-align:center;gap:var(--s-2)}
.stepper-step::after{content:"";position:absolute;top:calc(var(--stp-cur) / 2);left:50%;width:100%;height:var(--bw-2);background:repeating-linear-gradient(90deg,var(--obsidian-300) 0 var(--s-1),transparent var(--s-1) var(--s-2));transform:translateY(-50%)}
.stepper-step:last-child::after{display:none}
.stepper-step.is-done::after{height:var(--bw-2);border:0;border-radius:var(--r-xs);background:var(--grad-progress);box-shadow:var(--sh-glow-soft)}
.stepper-dot{position:relative;z-index:1;width:var(--stp-dot);height:var(--stp-dot);margin:calc((var(--stp-cur) - var(--stp-dot)) / 2) 0;border-radius:var(--r-full);display:grid;place-items:center;font-size:var(--t-caption);font-weight:600;color:var(--obsidian-300);background:var(--obsidian-800);box-shadow:inset 0 0 0 var(--bw-1) var(--obsidian-300)}
.stepper-dot .icon{width:var(--icon-xs);height:var(--icon-xs)}
.stepper-step.is-done .stepper-dot{background:var(--primary-500);box-shadow:none;color:var(--obsidian-950)}
.stepper-step[aria-current="step"] .stepper-dot{width:var(--stp-cur);height:var(--stp-cur);margin:0;background:var(--grad-progress);box-shadow:var(--sh-glow);color:var(--obsidian-950);font-weight:700}
.stepper-step[aria-current="step"] .stepper-dot::after{content:"";position:absolute;inset:calc(-1 * var(--s-1));border-radius:var(--r-full);box-shadow:0 0 0 var(--bw-1) var(--primary-500);animation:stepper-pulse 2400ms var(--ease-standard) infinite}
@keyframes stepper-pulse{0%,100%{transform:scale(1);opacity:0.6}50%{transform:scale(1.33);opacity:0}}
.stepper-text{display:flex;flex-direction:column;align-items:inherit;gap:var(--s-0-5)}
.stepper-sr-only{position:absolute;width:var(--s-px);height:var(--s-px);padding:0;margin:calc(-1 * var(--s-px));overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}
.stepper-label{font-size:var(--t-small);font-weight:400;color:var(--obsidian-300)}
.stepper-meta{font-family:var(--font-mono);font-size:var(--t-micro);letter-spacing:var(--tr-mono);text-transform:uppercase;color:var(--obsidian-300)}
.stepper-step.is-done .stepper-label{font-weight:600;color:var(--obsidian-100)}
.stepper-step[aria-current="step"] .stepper-label{font-weight:700;color:var(--primary-200)}
.stepper-step[aria-current="step"] .stepper-meta{color:var(--primary-200)}
/* reveal on view (site JS adds .is-in): connectors fade, dots spring in, text rises 10px, the done connector draws */
.stepper[data-reveal] .stepper-step::after{opacity:0;transform:translateY(-50%) scaleX(0);transform-origin:left}
.stepper[data-reveal] .stepper-dot{opacity:0;transform:scale(0)}
.stepper[data-reveal] .stepper-text{opacity:0;transform:translateY(var(--s-2))}
/* one ladder, whatever the state: dot i scales in from 500ms + --d-instant·i (--d-slow less one step), connector i draws to the next dot from 600ms + --d-instant·i (--d-slow), both on --d-slow.
   Done or dashed only changes the paint, so adding or removing steps keeps the choreography. */
.stepper[data-reveal].is-in .stepper-step::after{opacity:1;transform:translateY(-50%) scaleX(1);transition:opacity var(--d-quick) var(--ease-decel),transform var(--d-slow) var(--ease-decel);transition-delay:calc(var(--d-slow) + var(--i, 0) * var(--d-instant))}
.stepper[data-reveal].is-in .stepper-dot{opacity:1;transform:none;transition:opacity var(--d-slow) var(--ease-decel),transform var(--d-slow) var(--ease-spring);transition-delay:calc(var(--d-slow) + (var(--i, 0) - 1) * var(--d-instant))}
.stepper[data-reveal].is-in .stepper-text{opacity:1;transform:none;transition:opacity var(--d-slow) var(--ease-decel),transform var(--d-slow) var(--ease-decel);transition-delay:calc(var(--d-slow) + (var(--i, 0) - 1) * var(--d-instant))}
/* vertical: below 480px of its own width, or forced */
.stepper-vertical .stepper-list{flex-direction:column;gap:var(--s-8)}
.stepper-vertical .stepper-step{flex-direction:row;align-items:center;text-align:left;gap:var(--s-3)}
.stepper-vertical .stepper-text{align-items:flex-start}
.stepper-vertical .stepper-dot{margin:0 calc((var(--stp-cur) - var(--stp-dot)) / 2)}
.stepper-vertical .stepper-step::after{top:calc(var(--stp-cur) / 2);left:calc(var(--stp-cur) / 2);width:var(--bw-2);height:calc(100% + var(--s-8));background:repeating-linear-gradient(180deg,var(--obsidian-300) 0 var(--s-1),transparent var(--s-1) var(--s-2));transform:translateX(-50%)}
.stepper-vertical .stepper-step.is-done::after{width:var(--bw-2);border:0;background:linear-gradient(180deg,var(--primary-200),var(--primary-500))}
.stepper-vertical[data-reveal] .stepper-step::after{transform:translateX(-50%) scaleY(0);transform-origin:top}
.stepper-vertical[data-reveal].is-in .stepper-step::after{transform:translateX(-50%) scaleY(1)}
@container (max-width: 480px){
  .stepper-list{flex-direction:column;gap:var(--s-8)}
  .stepper-step{flex-direction:row;align-items:center;text-align:left;gap:var(--s-3)}
  .stepper-text{align-items:flex-start}
  .stepper-dot{margin:0 calc((var(--stp-cur) - var(--stp-dot)) / 2)}
  .stepper-step::after{top:calc(var(--stp-cur) / 2);left:calc(var(--stp-cur) / 2);width:var(--bw-2);height:calc(100% + var(--s-8));background:repeating-linear-gradient(180deg,var(--obsidian-300) 0 var(--s-1),transparent var(--s-1) var(--s-2));transform:translateX(-50%)}
  .stepper-step.is-done::after{width:var(--bw-2);height:calc(100% + var(--s-8));border:0;background:linear-gradient(180deg,var(--primary-200),var(--primary-500))}
  .stepper[data-reveal] .stepper-step::after{transform:translateX(-50%) scaleY(0);transform-origin:top}
  .stepper[data-reveal].is-in .stepper-step::after{transform:translateX(-50%) scaleY(1)}
}
@media (prefers-reduced-motion: reduce){
  .stepper[data-reveal] .stepper-step::after,.stepper[data-reveal] .stepper-dot,.stepper[data-reveal] .stepper-text{opacity:1;transition:none}
  .stepper[data-reveal] .stepper-dot,.stepper[data-reveal] .stepper-text{transform:none}
  .stepper[data-reveal] .stepper-step::after,.stepper[data-reveal].is-in .stepper-step::after{transform:translateY(-50%);transition:none}
  .stepper-vertical[data-reveal] .stepper-step::after,.stepper-vertical[data-reveal].is-in .stepper-step::after{transform:translateX(-50%)}
  .stepper-step[aria-current="step"] .stepper-dot::after{animation:none;transform:none;opacity:var(--opacity-disabled)}
}

/* § 3.18 Progress — how far a task with a known end has come. role="progressbar" with a name, a value, a min and a max.
   8px by default, .progress-sm 4px; the fill animates to its value on --d-scene. */
.progress{display:flex;align-items:center;gap:var(--s-4)}
.progress-label{font-family:var(--font-mono);font-size:var(--t-micro);letter-spacing:var(--tr-mono);text-transform:uppercase;color:var(--obsidian-300)}
.progress-track{flex:1;height:var(--s-2);border-radius:var(--r-full);background:var(--obsidian-700)}
.progress-sm .progress-track{height:var(--s-1)}
.progress-fill{height:100%;width:var(--value, 0%);border-radius:inherit;background:var(--grad-progress);box-shadow:var(--sh-glow-soft);transform-origin:left;transition:width var(--d-scene) var(--ease-decel)}
.progress-value{font-size:var(--t-small);color:var(--obsidian-100);font-variant-numeric:tabular-nums}
.progress[data-reveal] .progress-fill{transform:scaleX(0)}
.progress[data-reveal].is-in .progress-fill{transform:scaleX(1);transition:width var(--d-scene) var(--ease-decel),transform var(--d-scene) var(--ease-decel) calc(7 * var(--d-instant))}
@media (prefers-reduced-motion: reduce){
  .progress-fill{transition:none}
  .progress[data-reveal] .progress-fill,.progress[data-reveal].is-in .progress-fill{transform:none;transition:none}
}

/* ─── § 3.43 Map — the land as a grid of hexes; a cluster of cells is one place, and acts as one ───
   The land is baked (Natural Earth 1:110m), so the page asks nothing at run time. Grey is the land;
   a cluster takes the colour of its state. The sea is never drawn, so it can never take a colour. */
.hexmap{position:relative;border-radius:var(--r-md);overflow:hidden;background:radial-gradient(130% 130% at 50% 38%, var(--obsidian-850) 0%, var(--obsidian-950) 70%)}
.hexmap-svg{display:block;width:100%;height:auto}
.hexmap-svg polygon{fill:var(--obsidian-500);transition:fill var(--d-quick) var(--ease-standard), filter var(--d-quick) var(--ease-standard)}
.hexmap-svg [data-st="primary"]{fill:var(--primary-500)}
.hexmap-svg [data-st="warning"]{fill:var(--warning)}
.hexmap-svg [data-st="danger"]{fill:var(--danger)}
.hexmap-area{position:absolute;min-width:var(--s-6);min-height:var(--s-6);translate:-50% -50%;margin:0;padding:0;border:0;border-radius:var(--r-sm);background:none;cursor:pointer;pointer-events:none}
.hexmap-area:focus-visible{outline:var(--focus-width) solid var(--primary-500);outline-offset:var(--focus-offset)}
@media (max-width: 720px){.hexmap-area{pointer-events:auto}}
@media (prefers-reduced-motion: reduce){.hexmap-svg polygon{transition:none}}
/* a cluster glows in its own colour; grey land lights its country and glows faintly. No scale: the grid never moves. */
.hexmap-svg [data-hot]{filter:drop-shadow(0 0 var(--s-3) var(--glow, transparent))}
.hexmap-svg [data-st="primary"]{--glow:var(--primary-500)}
.hexmap-svg [data-st="warning"]{--glow:var(--warning)}
.hexmap-svg [data-st="danger"]{--glow:var(--danger)}
.hexmap-svg [data-lit]{fill:var(--obsidian-400);filter:drop-shadow(0 0 var(--s-2) var(--obsidian-300))}
.hexmap[data-open] .hexmap-svg polygon:not([data-sel]){fill:var(--obsidian-700)}
/* the legend's hex: a regular hexagon, pointy-top (the map's cell turned 30 degrees), 12 high */
.swatch-hex{width:calc(var(--s-3) * 0.866);border-radius:0;box-shadow:none;clip-path:polygon(50% 0,100% 25%,100% 75%,50% 100%,0 75%,0 25%)}


/* ─── Kit (site chrome, v5.0.0): the Anatomy | Code card of a component page.
   release/kit.py writes the markup from the repo; the stage on the left, the panel on the right ─── */
.kit{
  display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.15fr);
  border:var(--bw-1) solid var(--border-subtle);border-radius:var(--r-lg);
  background:var(--surface-raised);overflow:hidden;
}
.kit + .kit{margin-top:var(--s-6)}  /* two kits on one page (Navigation: Sidebar, Top bar) keep a gap, never one slab */
.kit-stage{
  position:relative;min-width:0;min-height:calc(var(--s-32) * 2.5);
  display:flex;align-items:center;justify-content:center;padding:var(--s-10);
  background-color:var(--obsidian-850);
  background-image:linear-gradient(var(--obsidian-800) var(--bw-1),transparent var(--bw-1)),linear-gradient(90deg,var(--obsidian-800) var(--bw-1),transparent var(--bw-1));
  background-size:var(--s-4) var(--s-4);background-position:center;
}
/* The example sits in the middle; a component that lives on an edge leans on that edge, full height or width */
.kit-stage > *{max-width:100%}
.kit-stage-row{gap:var(--s-3)}
.kit-stage-row > .skeleton-stack{width:calc(var(--s-32) * 1.25)}
.kit-stage-col{flex-direction:column;gap:var(--s-3)}
.kit-stage-col > *{width:min(100%, calc(var(--s-32) * 2.5))}
.kit-stage-left{justify-content:flex-start;align-items:stretch;padding:0}
.kit-stage-right{justify-content:flex-end;align-items:stretch;padding:0}
.kit-stage-top{align-items:flex-start;padding:0}
.kit-stage > p{max-width:28ch;margin:0;color:var(--obsidian-300);font-size:var(--t-body);line-height:var(--lh-loose)}
.kit-stage > .icon{color:var(--obsidian-100)}
.kit-stage > :is(.field,.slider,.progress,.divider-label){width:min(100%, calc(var(--s-32) * 2))}
.kit-stage > :is(.alert,.toast,.modal,.popover,.card,.accordion,.list,.table,.tabs){width:min(100%, calc(var(--s-32) * 2.5))}
.kit-stage > .stepper-vertical{width:calc(var(--s-24) + var(--s-8))}
.kit-stage > .swatch-tile{width:calc(var(--s-32) * 1.5)}
/* What a component keeps closed, hidden or fixed, laid open in place: the menu apart from its field */
.kit-stage :is(.select-menu,.tp-popover,.dp-popover)[hidden]{display:block}
.kit-stage :is(.select-menu,.tp-popover,.dp-popover){position:static;margin-top:var(--s-6);max-height:none;opacity:1;transform:none;pointer-events:auto}
.kit-stage > :is(.modal,.popover){display:block;position:static;inset:auto;translate:none;margin:0;opacity:1;transform:none}
.kit-stage > .tooltip{position:static;transform:none}
:is(.kit-stage-left,.kit-stage-right) > .drawer{display:flex;position:static;width:65%;height:auto;transform:none}
.kit-stage-left > .sidebar{position:static;width:60%;height:auto;transform:none;box-shadow:none;z-index:auto}
.kit-stage-top > .navbar{position:static;width:100%}
.kit-wide{grid-template-columns:1fr}
.kit-wide .kit-panel{border-left:0;border-top:var(--bw-1) solid var(--border-subtle)}
.kit-panel{display:flex;flex-direction:column;min-width:0;background:var(--surface-sunken);border-left:var(--bw-1) solid var(--border-subtle)}
.kit-head{display:flex;align-items:center;padding:var(--s-4);border-bottom:var(--bw-1) solid var(--border-subtle)}
.kit-body{padding:var(--s-4) var(--s-5);overflow:auto;max-height:calc(var(--s-32) * 3)}
/* One height for both views (v5.2.0): the Anatomy view sets it, Code scrolls inside it. The two panels share
   one grid cell; hidden, Anatomy keeps its place without showing, and Code adds no height of its own. */
.kit-panel{display:grid;grid-template-rows:auto minmax(0,1fr)}
.kit-panel > .kit-body{grid-row:2;grid-column:1}
.kit-panel > .kit-body:nth-child(2)[hidden]{display:block;visibility:hidden}
.kit-panel > .kit-body:nth-child(3){contain:size;max-height:none}
.kit-group{display:block;font-family:var(--font-mono);font-size:var(--t-micro);letter-spacing:var(--tr-mono);text-transform:uppercase;color:var(--obsidian-300)}
.kit-part{display:grid;grid-template-columns:var(--s-6) var(--s-16) minmax(0,1fr);gap:var(--s-3);align-items:start;padding:var(--s-3) 0;border-bottom:var(--bw-1) solid var(--border-subtle);font-size:var(--t-small)}
.kit-part:last-child{border-bottom:0}
.kit-num{display:flex;align-items:center;justify-content:center;width:var(--s-5);height:var(--s-5);border:var(--bw-1) solid var(--obsidian-400);border-radius:var(--r-full);font-size:var(--t-micro);color:var(--obsidian-100)}
.kit-label{color:var(--obsidian-300);line-height:var(--s-5)}
.kit-main{font-family:var(--font-mono);color:var(--obsidian-100);line-height:var(--s-5);overflow-wrap:anywhere}
.kit-sub{display:block;font-size:var(--t-caption);color:var(--obsidian-300);line-height:1.5}
.kit-code-bar{display:flex;align-items:center;justify-content:space-between;gap:var(--s-2);margin-bottom:var(--s-3)}
.kit-tools{display:flex;gap:var(--s-1)}
.kit-code{margin:0 0 var(--s-4);font-family:var(--font-mono);font-size:var(--t-caption);line-height:var(--lh-loose);color:var(--obsidian-200);white-space:pre}
.kit-code b{font-weight:500;color:var(--obsidian-050)}
@media (max-width: 720px){
  .kit{grid-template-columns:1fr}
  .kit-stage{padding:var(--s-8)}
  .kit-stage:is(.kit-stage-left,.kit-stage-right,.kit-stage-top){padding:0}
  .kit-panel{border-left:0;border-top:var(--bw-1) solid var(--border-subtle)}
}
