/* Auto-managed: molecule-layer CSS. Button + Tile (Phase 1c — semantic aliases).
 *
 * Token consumption per the runtime contract:
 *   tokens.generated.css   → OKLCH 12-step ladders (raw color steps)
 *   tokens.semantic.css    → semantic alias layer (--accent, --fg-primary,
 *                            --bg-canvas, --border-subtle, --radius-sm,
 *                            --font-sans, --focus-ring, etc.)
 *   primitives.css         → density-aware --ctrl-* tokens
 *
 * Selectors keyed off data-attrs emitted by the runtime components
 * (button.tsx, tile.tsx). This file references SEMANTIC aliases — not raw
 * OKLCH ladder steps — so themes and multi-tenant brand overrides can swap
 * a single alias to re-skin every cell. The one intentional raw-step
 * exception is `var(--focus-ring)`, which is itself a semantic alias for
 * `var(--accent-2-7)` (peri-mid) per the v4 reference convention.
 */

/* ============================================================================
   FINISHING DETAILS — system-wide defaults (H15)
   ========================================================================== */

/* Text selection is the system's, not the browser's. The default selection blue
   is the one piece of foreign chrome that appears on every surface. Peri soft
   (--accent-2-2 via --secondary-soft-bg) is the lightest brand tint that keeps
   --fg-primary comfortably above AA on selected text, and it inverts with the
   OKLCH ladder in dark mode for free. */
::selection {
  background: var(--secondary-soft-bg);
  color: var(--fg-primary);
}

/* Press feedback is already carried by the :active states, so the grey tap flash
   Chrome paints on touch is pure noise — and it lands on top of them. */
.nxt-button,
.nxt-tab,
.nxt-tab-pill,
.nxt-menu-item,
.nxt-nav-item,
.nxt-pagination button,
.nxt-select-control,
.nxt-checkbox,
.nxt-radio,
.nxt-switch,
.nxt-link {
  -webkit-tap-highlight-color: transparent;
}

/* Internal scroll areas wear the system's scrollbar rather than the platform's.
   --border-strong on a transparent track reads as part of the surface at rest.
   (.nxt-docs-chip-nav keeps its own scrollbar-width: none — that strip hides its
   scrollbar deliberately and is not an internal scroll area.) */
.nxt-scroll-area,
.nxt-textarea,
.nxt-menu,
.nxt-select-menu-list,
.nxt-autocomplete-list,
.nxt-command-list,
.nxt-dialog-content,
.nxt-drawer-content,
.nxt-sheet-content,
.nxt-popover-content,
.nxt-data-table-scroll {
  scrollbar-width: thin;
  scrollbar-color: var(--border-strong) transparent;
}

/* An overlay that reaches its end must not hand the rest of the gesture to the
   page behind it: scroll-chaining silently moves the surface the user believes
   is covered. */
.nxt-menu,
.nxt-select-menu-list,
.nxt-autocomplete-list,
.nxt-command-list,
.nxt-dialog-content,
.nxt-drawer-content,
.nxt-sheet-content,
.nxt-popover-content {
  overscroll-behavior: contain;
}

/* ============================================================================
   SHARED VISUAL RECIPES
   ========================================================================== */

.nxt-control-frame {
  display: inline-flex;
  align-items: center;
  gap: var(--ctrl-gap-md);
  min-block-size: var(--ctrl-block-h-md);
  padding-block: var(--ctrl-block-pad-md);
  padding-inline: var(--ctrl-inline-pad-md);
  border: var(--control-frame-border-width) solid transparent;
  border-radius: var(--control-frame-radius);
  outline: none;
}

.nxt-control-frame:focus-visible,
.nxt-control-frame:focus-within {
  box-shadow: var(--control-frame-focus-shadow);
}

.nxt-control-frame[disabled],
.nxt-control-frame[aria-disabled="true"],
.nxt-control-frame[data-disabled] {
  opacity: var(--control-frame-disabled-opacity);
}

.nxt-field-frame {
  color: var(--field-frame-fg, var(--input-fg));
  background: var(--field-frame-bg, var(--input-bg));
  border: var(--field-frame-border-width, var(--input-border-width)) solid var(--field-frame-border, var(--input-border));
  border-radius: var(--field-frame-radius);
}

@media (hover: hover) {
  .nxt-field-frame:hover {
    border-color: var(--field-frame-border-hover, var(--input-border-hover));
  }
}

.nxt-field-frame:focus-visible,
.nxt-field-frame:focus-within {
  border-color: var(--field-frame-border-focus, var(--input-border-focus));
  box-shadow: var(--field-frame-focus-shadow, var(--input-focus-ring));
}

.nxt-field-frame[aria-invalid="true"],
.nxt-field-frame[data-invalid] {
  border-color: var(--field-frame-border-invalid, var(--input-border-invalid));
}

.nxt-field-frame[data-warning] {
  border-color: var(--field-frame-border-warning, var(--input-border-warning));
}

.nxt-field-frame[data-success] {
  border-color: var(--field-frame-border-success, var(--input-border-success));
}

.nxt-field-frame[data-readonly] {
  background: var(--field-frame-bg-readonly, var(--input-bg-readonly));
}

.nxt-field-frame[disabled],
.nxt-field-frame[data-disabled] {
  color: var(--field-frame-fg-disabled, var(--input-fg-disabled));
  background: var(--field-frame-bg-disabled, var(--input-bg-disabled));
  border-color: var(--field-frame-border-disabled, var(--input-border-disabled));
}

.nxt-overlay-panel {
  color: var(--overlay-panel-fg);
  background: var(--overlay-panel-bg);
  border: 1px solid var(--overlay-panel-border);
  border-radius: var(--overlay-panel-radius);
  box-shadow: var(--overlay-panel-shadow);
}

.nxt-nav-item {
  display: inline-flex;
  align-items: center;
  gap: var(--nav-item-gap);
  min-block-size: var(--nav-item-block-size);
  padding-inline: var(--nav-item-padding-inline);
  border-radius: var(--nav-item-radius);
  color: var(--nav-item-fg);
  text-decoration: none;
}

@media (hover: hover) {
  .nxt-nav-item:hover {
    color: var(--nav-item-fg-hover);
    background: var(--nav-item-bg-hover);
  }
}

.nxt-nav-item:focus-visible {
  outline: none;
  box-shadow: var(--nav-item-focus-shadow);
}

.nxt-nav-item[aria-current="page"],
.nxt-nav-item[aria-selected="true"],
.nxt-nav-item[data-active] {
  color: var(--nav-item-fg-active);
  background: var(--nav-item-bg-active);
}

.nxt-surface-frame {
  --focus-ring-gap-color: var(--surface-frame-bg);
  color: var(--surface-frame-fg);
  background: var(--surface-frame-bg);
  border: 1px solid var(--surface-frame-border);
  border-radius: var(--surface-frame-radius);
  box-shadow: var(--surface-frame-shadow);
}

.nxt-surface-frame:focus-visible {
  outline: none;
  box-shadow: var(--surface-frame-focus-shadow);
}

/* Forced colors (Windows High Contrast) strips every box-shadow ring, and the
   per-component `outline: none` resets would otherwise leave keyboard focus
   with no indicator at all. Restore a real outline for every focusable in this
   mode; !important is required to beat those resets and is contained here. */
@media (forced-colors: active) {
  *:focus-visible {
    outline: 2px solid Highlight !important;
    outline-offset: 2px;
  }
}

/* ============================================================================
   SORTABLE LIST
   ========================================================================= */
.nxt-sortable-list {
  display: grid;
  /* Label -> items is a group boundary over rows separated by
     --sortable-list-row-gap, so it tracks that gap one rung up per density
     rather than sitting flat on it. */
  gap: var(--sortable-list-label-gap);
  color: var(--fg-primary);
  font-family: var(--font-sans);
  --sortable-list-row-padding: var(--space-3);
  --sortable-list-row-gap: var(--space-2);
  --sortable-list-label-gap: var(--space-4);
}

.nxt-sortable-list--compact {
  --sortable-list-row-padding: var(--space-2);
  --sortable-list-row-gap: var(--space-2);
  --sortable-list-label-gap: var(--space-4);
}

.nxt-sortable-list--comfortable {
  --sortable-list-row-padding: var(--space-3);
  --sortable-list-row-gap: var(--space-2);
  --sortable-list-label-gap: var(--space-4);
}

.nxt-sortable-list--expanded {
  --sortable-list-row-padding: var(--space-4);
  --sortable-list-row-gap: var(--space-3);
  --sortable-list-label-gap: var(--space-5);
}

.nxt-sortable-list--gigantic {
  --sortable-list-row-padding: var(--space-5);
  --sortable-list-row-gap: var(--space-3);
  --sortable-list-label-gap: var(--space-5);
}

.nxt-sortable-list-label {
  color: var(--fg-primary);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  line-height: var(--lh-tight);
}

.nxt-sortable-list-items {
  display: grid;
  gap: var(--sortable-list-row-gap);
  margin: 0;
  padding: 0;
  list-style: none;
}

.nxt-sortable-list-item {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--sortable-list-row-padding);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-md);
  background: var(--bg-surface);
  transition:
    background-color var(--dur-snap) var(--ease-snap),
    border-color var(--dur-fast) var(--ease-smooth),
    box-shadow var(--dur-fast) var(--ease-smooth),
    transform var(--dur-instant) var(--ease-smooth),
    opacity var(--dur-fast) var(--ease-smooth);
}

@media (hover: hover) {
  .nxt-sortable-list-item:hover {
    border-color: var(--border-strong);
    background: var(--bg-sunken);
  }
}

.nxt-sortable-list-item[data-dragging="true"] {
  border-color: var(--border-strong);
  background: var(--accent-soft-bg);
  box-shadow: 0 0 0 1px var(--border-strong);
}

.nxt-sortable-list-item[data-keyboard-active="true"] {
  box-shadow: 0 0 0 1px var(--focus-ring);
}

.nxt-sortable-list-item[data-drop-before="true"] {
  box-shadow: inset 0 2px 0 0 var(--focus-ring);
}

.nxt-sortable-list-item[data-drop-after="true"] {
  box-shadow: inset 0 -2px 0 0 var(--focus-ring);
}

.nxt-sortable-list-item[data-disabled="true"] {
  opacity: 0.64;
}

.nxt-sortable-list-item-body {
  display: grid;
  gap: var(--space-1);
  min-inline-size: 0;
  flex: 1 1 auto;
}

.nxt-sortable-list-item-copy {
  display: grid;
  gap: var(--space-1);
  min-inline-size: 0;
}

.nxt-sortable-list-item-label {
  color: var(--fg-primary);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  line-height: var(--lh-tight);
  overflow-wrap: anywhere;
}

.nxt-sortable-list-item-description {
  color: var(--fg-secondary);
  font-size: var(--text-xs);
  line-height: var(--lh-snug);
  overflow-wrap: anywhere;
}

.nxt-sortable-list-handle {
  position: relative;
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-inline-size: var(--space-6);
  min-block-size: var(--space-6);
  padding-block: var(--space-1);
  padding-inline: var(--space-2);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-md);
  background: transparent;
  color: var(--fg-tertiary);
  cursor: grab;
  transition:
    background-color var(--dur-snap) var(--ease-snap),
    border-color var(--dur-fast) var(--ease-smooth),
    color var(--dur-fast) var(--ease-smooth),
    box-shadow var(--dur-fast) var(--ease-smooth),
    transform var(--dur-instant) var(--ease-smooth);
}

@media (hover: hover) {
  .nxt-sortable-list-handle:hover:not(:disabled) {
    border-color: var(--border-strong);
    background: var(--bg-sunken);
    color: var(--fg-primary);
    transform: translateY(-1px);
  }
}

.nxt-sortable-list-handle:focus-visible {
  outline: none;
  box-shadow: 0 0 0 2px var(--focus-ring);
}

.nxt-sortable-list-handle:disabled {
  opacity: 0.55;
  cursor: not-allowed;
}

.nxt-sortable-list-item[data-keyboard-active="true"] .nxt-sortable-list-handle,
.nxt-sortable-list-handle[data-keyboard-active="true"] {
  border-color: var(--focus-ring);
  background: var(--accent-soft-bg);
  color: var(--accent-soft-fg);
}

.nxt-sortable-list[data-disabled="true"] {
  opacity: 0.92;
}

/* Touch-target — the 32px grip extends to the 44px touch floor on coarse
 * pointers, matching the Button size=sm pattern. */
@media (hover: none) {
  .nxt-sortable-list-handle:not(:disabled)::before,
  .nxt-kanban-handle:not(:disabled)::before {
    content: "";
    position: absolute;
    inset: var(--drag-handle-hit-target-outset);
  }

  .nxt-kanban-place:not(:disabled) {
    min-block-size: calc(
      var(--space-6) - var(--drag-handle-hit-target-outset) - var(--drag-handle-hit-target-outset)
    );
  }
}

@media (prefers-reduced-motion: reduce) {
  .nxt-sortable-list-item,
  .nxt-sortable-list-handle {
    transition-duration: 1ms;
    transition-delay: 0ms;
  }
}

/* ============================================================================
   BUTTON
   ========================================================================= */

/* ------------------------------------------------------------------ */
/* Base: shared layout, typography, transitions                       */
/* ------------------------------------------------------------------ */
.nxt-button {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--button-gap);
  white-space: nowrap;
  border: var(--control-frame-border-width) solid transparent;
  cursor: pointer;
  user-select: none;
  text-decoration: none;
  touch-action: manipulation;
  font-family: var(--font-sans);
  font-weight: var(--weight-medium);
  letter-spacing: var(--track-normal);
  line-height: var(--lh-tight);
  /* background-color uses --dur-snap / --ease-snap (70ms snap feel for
     hover bg flips). All other animated properties keep the standard
     var(--dur-fast) / var(--dur-instant) smooth-ease cadence. */
  transition:
    background-color var(--dur-snap) var(--ease-snap),
    color            var(--dur-fast) var(--ease-smooth),
    border-color     var(--dur-fast) var(--ease-smooth),
    box-shadow       var(--dur-fast) var(--ease-smooth),
    transform        var(--dur-instant) var(--ease-smooth),
    opacity          var(--dur-fast) var(--ease-smooth);
}

/* ------------------------------------------------------------------ */
/* Size                                                                */
/* ------------------------------------------------------------------ */
.nxt-button[data-size="sm"] {
  block-size: var(--ctrl-block-h-sm);
  padding-block: var(--ctrl-block-pad-sm);
  padding-inline: var(--ctrl-inline-pad-sm);
  gap: var(--ctrl-gap-sm);
  font-size: var(--text-sm);
}
.nxt-button[data-size="md"] {
  block-size: var(--ctrl-block-h-md);
  padding-block: var(--ctrl-block-pad-md);
  padding-inline: var(--ctrl-inline-pad-md);
  gap: var(--ctrl-gap-md);
  font-size: var(--text-base);
  letter-spacing: 0;
}
.nxt-button[data-size="lg"] {
  block-size: var(--ctrl-block-h-lg);
  padding-block: var(--ctrl-block-pad-lg);
  padding-inline: var(--ctrl-inline-pad-lg);
  gap: var(--ctrl-gap-lg);
  font-size: var(--text-md);
}
.nxt-button[data-size="xl"] {
  block-size: var(--ctrl-block-h-xl);
  padding-block: var(--ctrl-block-pad-xl);
  padding-inline: var(--ctrl-inline-pad-xl);
  gap: var(--ctrl-gap-xl);
  font-size: var(--text-lg);
}
.nxt-button[data-size="2xl"] {
  block-size: var(--ctrl-block-h-2xl);
  padding-block: var(--ctrl-block-pad-2xl);
  padding-inline: var(--ctrl-inline-pad-2xl);
  gap: var(--ctrl-gap-2xl);
  font-size: var(--text-xl);
}

/* ------------------------------------------------------------------ */
/* Shape                                                               */
/* ------------------------------------------------------------------ */
/* Rectangular = radius-sm (2px, v4 reference); pill = full round. */
.nxt-button[data-shape="rectangular"] { border-radius: var(--control-frame-radius); }
.nxt-button[data-shape="pill"],
.nxt-button[data-shape="circle"]      { border-radius: var(--radius-full); }

/* ------------------------------------------------------------------ */
/* Intent × Solid (default)                                            */
/* ------------------------------------------------------------------ */
.nxt-button[data-intent="neutral"][data-emphasis="solid"] {
  background: var(--neutral-fill);
  color: var(--neutral-fill-fg);
  border-color: var(--neutral-fill);
}
.nxt-button[data-intent="hero"][data-emphasis="solid"] {
  background: var(--accent);
  color: var(--accent-fg);
  border-color: var(--accent-press);
}
.nxt-button[data-intent="accent"][data-emphasis="solid"] {
  background: var(--secondary);
  color: var(--secondary-fg);
  border-color: var(--secondary);
}
.nxt-button[data-intent="danger"][data-emphasis="solid"] {
  background: var(--danger);
  color: var(--danger-fg);
  border-color: var(--danger);
}

/* ------------------------------------------------------------------ */
/* Intent × Outline                                                    */
/* ------------------------------------------------------------------ */
.nxt-button[data-emphasis="outline"] { background: transparent; }
.nxt-button[data-intent="neutral"][data-emphasis="outline"] {
  color: var(--fg-primary); border-color: var(--control-frame-muted-fill);
}
.nxt-button[data-intent="hero"][data-emphasis="outline"] {
  color: var(--accent-outline); border-color: var(--accent-outline);
}
.nxt-button[data-intent="accent"][data-emphasis="outline"] {
  color: var(--secondary-outline); border-color: var(--secondary-outline);
}
.nxt-button[data-intent="danger"][data-emphasis="outline"] {
  color: var(--danger-outline); border-color: var(--danger-outline);
}

/* ------------------------------------------------------------------ */
/* Intent × Soft (v3.2 — tinted bg, no border, no-collide with outline hover) */
/* ------------------------------------------------------------------ */
.nxt-button[data-emphasis="soft"] { border-color: transparent; }
.nxt-button[data-intent="neutral"][data-emphasis="soft"] {
  background: var(--neutral-soft-bg); color: var(--neutral-soft-fg);
}
.nxt-button[data-intent="hero"][data-emphasis="soft"] {
  background: var(--accent-soft-bg); color: var(--accent-soft-fg);
}
.nxt-button[data-intent="accent"][data-emphasis="soft"] {
  background: var(--secondary-soft-bg); color: var(--secondary-soft-fg);
}
.nxt-button[data-intent="danger"][data-emphasis="soft"] {
  background: var(--danger-soft-bg); color: var(--danger-soft-fg);
}

/* ------------------------------------------------------------------ */
/* Intent × Ghost                                                      */
/* ------------------------------------------------------------------ */
.nxt-button[data-emphasis="ghost"] {
  background: transparent;
  border-color: transparent;
}
.nxt-button[data-intent="neutral"][data-emphasis="ghost"] { color: var(--fg-primary); }
.nxt-button[data-intent="hero"][data-emphasis="ghost"]    { color: var(--accent-outline); }
.nxt-button[data-intent="accent"][data-emphasis="ghost"]  { color: var(--secondary); }
.nxt-button[data-intent="danger"][data-emphasis="ghost"]  { color: var(--danger); }

/* ------------------------------------------------------------------ */
/* Bordered — opt-in 1.5px contrasting stroke on solid fills            */
/* ------------------------------------------------------------------ */
.nxt-button[data-bordered] { border-width: var(--border-width-strong); }
.nxt-button[data-intent="neutral"][data-emphasis="solid"][data-bordered] {
  border-color: var(--fg-inverse);
}
.nxt-button[data-intent="hero"][data-emphasis="solid"][data-bordered] {
  border-color: var(--accent-outline);
}
.nxt-button[data-intent="accent"][data-emphasis="solid"][data-bordered] {
  border-color: var(--secondary-press);
}
.nxt-button[data-intent="danger"][data-emphasis="solid"][data-bordered] {
  border-color: var(--danger-press);
}

/* ------------------------------------------------------------------ */
/* Icon companions                                                     */
/* ------------------------------------------------------------------ */
.nxt-button > svg { width: var(--ctrl-icon-md); height: var(--ctrl-icon-md); flex-shrink: 0; }
.nxt-button[data-size="sm"]  > svg { width: var(--ctrl-icon-sm); height: var(--ctrl-icon-sm); }
.nxt-button[data-size="lg"]  > svg { width: var(--ctrl-icon-lg); height: var(--ctrl-icon-lg); }
.nxt-button[data-size="xl"]  > svg { width: var(--ctrl-icon-xl); height: var(--ctrl-icon-xl); }
.nxt-button[data-size="2xl"] > svg { width: var(--ctrl-icon-2xl); height: var(--ctrl-icon-2xl); }

/* Optical inset so a leading/trailing glyph aligns to the label, not the edge */
.nxt-button > svg:first-child:not(:only-child) { margin-inline-start: var(--button-icon-leading-nudge-inline); }
.nxt-button > svg:last-child:not(:only-child)  { margin-inline-end: var(--button-icon-trailing-nudge-inline); }

/* Icon-only — square footprint keyed to the density block size */
.nxt-button[data-icon-only] { padding-inline: 0; inline-size: var(--ctrl-block-h-md); }
.nxt-button[data-icon-only][data-size="sm"]  { inline-size: var(--ctrl-block-h-sm); }
.nxt-button[data-icon-only][data-size="lg"]  { inline-size: var(--ctrl-block-h-lg); }
.nxt-button[data-icon-only][data-size="xl"]  { inline-size: var(--ctrl-block-h-xl); }
.nxt-button[data-icon-only][data-size="2xl"] { inline-size: var(--ctrl-block-h-2xl); }
.nxt-button[data-icon-only] > svg { margin-inline: 0; }

/* ------------------------------------------------------------------ */
/* Hover — intent-specific ladder-step deepening                       */
/* ------------------------------------------------------------------ */
@media (hover: hover) {
  .nxt-button[data-intent="neutral"][data-emphasis="solid"]:hover:not([disabled]):not([data-loading="true"]),
  .nxt-button[data-intent="neutral"][data-emphasis="solid"].force-hover {
    background: var(--neutral-fill-hover); border-color: var(--neutral-fill-hover);
  }
  .nxt-button[data-intent="hero"][data-emphasis="solid"]:hover:not([disabled]):not([data-loading="true"]),
  .nxt-button[data-intent="hero"][data-emphasis="solid"].force-hover {
    background: var(--accent-hover);
  }
  .nxt-button[data-intent="accent"][data-emphasis="solid"]:hover:not([disabled]):not([data-loading="true"]),
  .nxt-button[data-intent="accent"][data-emphasis="solid"].force-hover {
    background: var(--secondary-hover); border-color: var(--secondary-hover);
  }
  .nxt-button[data-intent="danger"][data-emphasis="solid"]:hover:not([disabled]):not([data-loading="true"]),
  .nxt-button[data-intent="danger"][data-emphasis="solid"].force-hover {
    background: var(--danger-hover); border-color: var(--danger-hover);
  }

  /* Outline hover — fills with the intent's solid color (Polestar convention) */
  .nxt-button[data-intent="neutral"][data-emphasis="outline"]:hover:not([disabled]):not([data-loading="true"]),
  .nxt-button[data-intent="neutral"][data-emphasis="outline"].force-hover {
    background: var(--neutral-fill); color: var(--neutral-fill-fg); border-color: var(--neutral-fill);
  }
  .nxt-button[data-intent="hero"][data-emphasis="outline"]:hover:not([disabled]):not([data-loading="true"]),
  .nxt-button[data-intent="hero"][data-emphasis="outline"].force-hover {
    background: var(--accent-soft-bg);
  }
  .nxt-button[data-intent="accent"][data-emphasis="outline"]:hover:not([disabled]):not([data-loading="true"]),
  .nxt-button[data-intent="accent"][data-emphasis="outline"].force-hover {
    background: var(--secondary-soft-bg);
  }
  .nxt-button[data-intent="danger"][data-emphasis="outline"]:hover:not([disabled]):not([data-loading="true"]),
  .nxt-button[data-intent="danger"][data-emphasis="outline"].force-hover {
    background: var(--danger-soft-bg);
  }

  /* Soft hover — filter brightness so all intents darken proportionally */
  .nxt-button[data-emphasis="soft"]:hover:not([disabled]):not([data-loading="true"]),
  .nxt-button[data-emphasis="soft"].force-hover {
    filter: brightness(0.96);
  }

  /* Ghost hover — subtle neutral tint */
  .nxt-button[data-emphasis="ghost"]:hover:not([disabled]):not([data-loading="true"]),
  .nxt-button[data-emphasis="ghost"].force-hover {
    background: var(--border-subtle);
  }
}

/* ------------------------------------------------------------------ */
/* Active — scale(0.97) per brand/profile.json visualStance.do press rule */
/* ------------------------------------------------------------------ */
.nxt-button:active:not([data-loading="true"]):not([disabled]):not([aria-disabled="true"]),
.nxt-button.force-active {
  transform: scale(0.97);
}
.nxt-button[data-motion="static"]:active {
  transform: none;
}
.nxt-button[data-intent="hero"][data-emphasis="solid"]:active:not([data-loading="true"]):not([disabled]):not([aria-disabled="true"]),
.nxt-button[data-intent="hero"][data-emphasis="solid"].force-active {
  background: var(--accent-press);
  border-color: var(--accent-press);
}
.nxt-button[data-intent="accent"][data-emphasis="solid"]:active:not([data-loading="true"]):not([disabled]):not([aria-disabled="true"]),
.nxt-button[data-intent="accent"][data-emphasis="solid"].force-active {
  background: var(--secondary-press);
  border-color: var(--secondary-press);
}
.nxt-button[data-intent="danger"][data-emphasis="solid"]:active:not([data-loading="true"]):not([disabled]):not([aria-disabled="true"]),
.nxt-button[data-intent="danger"][data-emphasis="solid"].force-active {
  background: var(--danger-press);
  border-color: var(--danger-press);
}

/* ------------------------------------------------------------------ */
/* Focus-visible — doubled ring (canvas gap + accent halo)             */
/* ------------------------------------------------------------------ */
.nxt-button:focus-visible,
.nxt-button.force-focus {
  outline: none;
  box-shadow: var(--control-frame-focus-shadow);
}

/* ------------------------------------------------------------------ */
/* Disabled                                                            */
/* ------------------------------------------------------------------ */
.nxt-button:disabled,
.nxt-button[aria-disabled="true"] {
  opacity: var(--control-frame-disabled-opacity);
  cursor: not-allowed;
  pointer-events: none;
}

/* ------------------------------------------------------------------ */
/* Loading — preserve outer dimensions, show centered spinner          */
/* ------------------------------------------------------------------ */
.nxt-button[data-loading="true"] { cursor: progress; pointer-events: none; }
.nxt-button[data-loading="true"] > * { visibility: hidden; }
/* Bare text labels are text nodes — `> *` cannot hide them. text-fill keeps
 * the label transparent (width reserved) while currentColor still paints
 * the ::after spinner. */
.nxt-button[data-loading="true"] { -webkit-text-fill-color: transparent; }
.nxt-button[data-loading="true"]::after {
  content: "";
  position: absolute;
  width: var(--ctrl-icon-md);
  height: var(--ctrl-icon-md);
  border: 2px solid currentColor;
  border-top-color: transparent;
  border-radius: var(--radius-full);
  animation: nxt-button-spin 650ms linear infinite;
  visibility: visible;
}
.nxt-button[data-size="sm"][data-loading="true"]::after {
  width: var(--ctrl-icon-sm); height: var(--ctrl-icon-sm);
}
.nxt-button[data-size="lg"][data-loading="true"]::after {
  width: var(--ctrl-icon-lg); height: var(--ctrl-icon-lg);
}
.nxt-button[data-size="xl"][data-loading="true"]::after {
  width: var(--ctrl-icon-xl); height: var(--ctrl-icon-xl);
}
.nxt-button[data-size="2xl"][data-loading="true"]::after {
  width: var(--ctrl-icon-2xl); height: var(--ctrl-icon-2xl);
}

@keyframes nxt-button-spin {
  to { transform: rotate(360deg); }
}

/* ------------------------------------------------------------------ */
/* Container-attached — full-width Button flush with a container edge  */
/* ------------------------------------------------------------------ */
.nxt-button[data-attached] {
  width: 100%;
  flex-shrink: 0;
  border-left: none;
  border-right: none;
}
.nxt-button[data-attached="bottom"] {
  border-radius: 0 0 var(--radius-sm) var(--radius-sm);
  border-top: 1px solid;
  border-bottom: none;
}
.nxt-button[data-attached="top"] {
  border-radius: var(--radius-sm) var(--radius-sm) 0 0;
  border-bottom: 1px solid;
  border-top: none;
}

/* Container-radius inheritance — match common container radii. */
.nxt-button[data-attached][data-container-radius="sm"][data-attached="bottom"] {
  border-radius: 0 0 var(--radius-sm) var(--radius-sm);
}
.nxt-button[data-attached][data-container-radius="sm"][data-attached="top"] {
  border-radius: var(--radius-sm) var(--radius-sm) 0 0;
}
.nxt-button[data-attached][data-container-radius="md"][data-attached="bottom"] {
  border-radius: 0 0 var(--radius-md) var(--radius-md);
}
.nxt-button[data-attached][data-container-radius="md"][data-attached="top"] {
  border-radius: var(--radius-md) var(--radius-md) 0 0;
}
.nxt-button[data-attached][data-container-radius="lg"][data-attached="bottom"] {
  border-radius: 0 0 var(--radius-lg) var(--radius-lg);
}
.nxt-button[data-attached][data-container-radius="lg"][data-attached="top"] {
  border-radius: var(--radius-lg) var(--radius-lg) 0 0;
}

/* Attached separator border color per intent */
.nxt-button[data-attached][data-intent="neutral"][data-emphasis="solid"] {
  border-color: var(--neutral-fill-hover);
}
.nxt-button[data-attached][data-intent="hero"][data-emphasis="solid"] {
  border-color: var(--accent-outline);
}
.nxt-button[data-attached][data-intent="accent"][data-emphasis="solid"] {
  border-color: var(--secondary-press);
}
.nxt-button[data-attached][data-intent="danger"][data-emphasis="solid"] {
  border-color: var(--danger-press);
}
.nxt-button[data-attached][data-emphasis="outline"] {
  border-color: inherit;
}
.nxt-button[data-attached][data-emphasis="soft"] {
  border-color: transparent;
}
.nxt-button[data-attached][data-emphasis="ghost"] {
  border-color: var(--border-subtle);
}

/* Attached buttons NEVER use pill — force rectangular at the attached edge */
.nxt-button[data-attached][data-shape="pill"] { border-radius: 0; }
.nxt-button[data-attached="bottom"][data-shape="pill"] {
  border-radius: 0 0 var(--radius-sm) var(--radius-sm);
}
.nxt-button[data-attached="top"][data-shape="pill"] {
  border-radius: var(--radius-sm) var(--radius-sm) 0 0;
}

/* No scale on active for attached */
.nxt-button[data-attached]:active:not([disabled]):not([data-loading="true"]),
.nxt-button[data-attached].force-active {
  transform: none;
}

/* ------------------------------------------------------------------ */
/* Touch-target — size=sm on touch devices extends hit area to 44x44    */
/* ------------------------------------------------------------------ */
@media (hover: none) {
  .nxt-button[data-size="sm"]:not([data-loading="true"])::before {
    content: "";
    position: absolute;
    inset: var(--button-sm-hit-target-outset);
  }
}

/* ------------------------------------------------------------------ */
/* Reduced motion                                                      */
/* ------------------------------------------------------------------ */
@media (prefers-reduced-motion: reduce) {
  .nxt-button { transition-duration: 0ms; }
  .nxt-button:active:not([data-loading="true"]):not([disabled]) {
    transform: none;
    opacity: 0.85;
  }
  .nxt-button[data-loading="true"]::after { animation: none; }
}

/* ============================================================================
   SPLIT BUTTON
   ========================================================================== */

.nxt-split-button {
  position: relative;
  display: inline-flex;
  align-items: stretch;
  vertical-align: middle;
}

.nxt-split-button .nxt-button {
  border-radius: 0;
}

.nxt-split-button .nxt-button[data-split-segment="primary"] {
  min-inline-size: 0;
}

.nxt-split-button .nxt-button[data-split-segment="trigger"] {
  margin-inline-start: calc(var(--control-frame-border-width) * -1);
  flex: 0 0 auto;
}

.nxt-split-button[data-emphasis="solid"] .nxt-button[data-split-segment="primary"] {
  border-inline-end: 0;
}

.nxt-split-button[data-emphasis="solid"] .nxt-button[data-split-segment="trigger"] {
  margin-inline-start: 0;
  border-inline-start-width: var(--control-frame-border-width);
  border-inline-start-style: solid;
}

.nxt-split-button[data-emphasis="solid"][data-intent="neutral"] .nxt-button[data-split-segment="trigger"] {
  border-inline-start-color: var(--neutral-fill-hover);
}

.nxt-split-button[data-emphasis="solid"][data-intent="hero"] .nxt-button[data-split-segment="trigger"] {
  border-inline-start-color: var(--accent-outline);
}

.nxt-split-button[data-emphasis="solid"][data-intent="accent"] .nxt-button[data-split-segment="trigger"] {
  border-inline-start-color: var(--secondary-press);
}

.nxt-split-button[data-emphasis="solid"][data-intent="danger"] .nxt-button[data-split-segment="trigger"] {
  border-inline-start-color: var(--danger-press);
}

.nxt-split-button[data-shape="rectangular"] .nxt-button[data-split-segment="primary"] {
  border-start-start-radius: var(--control-frame-radius);
  border-end-start-radius: var(--control-frame-radius);
}

.nxt-split-button[data-shape="rectangular"] .nxt-button[data-split-segment="trigger"] {
  border-start-end-radius: var(--control-frame-radius);
  border-end-end-radius: var(--control-frame-radius);
}

.nxt-split-button[data-shape="pill"] .nxt-button[data-split-segment="primary"] {
  border-start-start-radius: var(--radius-full);
  border-end-start-radius: var(--radius-full);
}

.nxt-split-button[data-shape="pill"] .nxt-button[data-split-segment="trigger"] {
  border-start-end-radius: var(--radius-full);
  border-end-end-radius: var(--radius-full);
}

.nxt-split-button .nxt-button[data-split-segment="trigger"]:focus-visible {
  z-index: 1;
}

.nxt-split-button-menu {
  position: absolute;
  z-index: var(--z-overlay);
  inset-block-start: 100%;
  inset-inline-start: 0;
  display: grid;
  inline-size: max(100%, var(--split-button-menu-min-inline-size));
  min-inline-size: max(100%, var(--split-button-menu-min-inline-size));
  padding: var(--space-1);
  border: 1px solid var(--border-default);
  border-start-start-radius: 0;
  border-start-end-radius: 0;
  border-end-start-radius: var(--control-frame-radius);
  border-end-end-radius: var(--control-frame-radius);
  border-color: var(--border-default);
  background: var(--overlay-panel-bg);
  color: var(--overlay-panel-fg);
  box-shadow: var(--elevation-floating);
  transform-origin: top right;
}

.nxt-split-button-menu button {
  display: inline-flex;
  align-items: center;
  justify-content: flex-start;
  min-block-size: var(--ctrl-block-h-md);
  inline-size: 100%;
  padding-block: var(--space-2);
  padding-inline: var(--nav-item-padding-inline);
  border: 0;
  border-radius: var(--nav-item-radius);
  background: transparent;
  color: var(--nav-item-fg);
  cursor: pointer;
  font: inherit;
  text-align: start;
  transition:
    background-color var(--dur-snap) var(--ease-snap),
    color var(--dur-snap) var(--ease-snap),
    transform var(--dur-instant) var(--ease-smooth);
}

.nxt-split-button-menu button + button {
  margin-block-start: var(--split-button-menu-item-gap);
}

.nxt-split-button-menu button:first-child {
  border-start-start-radius: 0;
  border-start-end-radius: 0;
}

@media (hover: hover) {
  .nxt-split-button-menu button:hover:not(:disabled) {
    background: var(--nav-item-bg-hover);
    color: var(--nav-item-fg-hover);
  }
}

.nxt-split-button-menu button:active:not(:disabled) {
  transform: scale(0.97);
}

.nxt-split-button-menu button:focus-visible {
  outline: 2px solid var(--focus-ring);
  outline-offset: 2px;
}

.nxt-split-button-menu button:disabled {
  cursor: not-allowed;
  opacity: var(--control-frame-disabled-opacity);
}

.nxt-split-button-menu button[data-destructive="true"] {
  color: var(--danger);
}

@media (prefers-reduced-motion: reduce) {
  .nxt-split-button-menu button {
    transition-duration: 0ms;
  }

  .nxt-split-button-menu button:active:not(:disabled) {
    transform: none;
  }
}

/* ============================================================================
   TILE — Section Tile (sibling component, not a Button variant)
   ========================================================================= */

.nxt-tile {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  width: 100%;
  cursor: pointer;
  user-select: none;
  touch-action: manipulation;
  font-family: var(--font-sans);
  background: transparent;
  border: 1px solid transparent;
  /* Tile uses the same hover-bg snap as Button so the catalog reads as
     one motion family across both components. Border / color / box-shadow
     keep the var(--dur-fast) smooth-ease so the inversion to active state still
     feels deliberate. */
  transition:
    background   var(--dur-snap) var(--ease-snap),
    border-color var(--dur-fast) var(--ease-smooth),
    color        var(--dur-fast) var(--ease-smooth),
    transform    var(--dur-instant) var(--ease-smooth),
    box-shadow   var(--dur-fast) var(--ease-smooth);
}

/* Tile shape */
.nxt-tile[data-shape="rectangular"] { border-radius: var(--surface-frame-radius); }
.nxt-tile[data-shape="pill"]        { border-radius: var(--radius-xl); }

/* Tile aspect ratio — wide 16:9 (default) | standard 4:3 */
.nxt-tile[data-ratio="wide"]     { aspect-ratio: var(--ratio-tile-wide); }
.nxt-tile[data-ratio="standard"] { aspect-ratio: var(--ratio-tile-standard); }

/* Wide tiles: tighter vertical padding, horizontal padding stays generous */
.nxt-tile[data-ratio="wide"][data-size="sm"] { padding: var(--space-3) var(--space-5); }
.nxt-tile[data-ratio="wide"][data-size="md"] { padding: var(--space-4) var(--space-5); }
.nxt-tile[data-ratio="wide"][data-size="lg"] { padding: var(--space-5) var(--space-6); }

/* Square tiles: equal padding for symmetry */
.nxt-tile[data-ratio="standard"][data-size="sm"] { padding: var(--space-4); }
.nxt-tile[data-ratio="standard"][data-size="md"] { padding: var(--space-5); }
.nxt-tile[data-ratio="standard"][data-size="lg"] { padding: var(--space-6); }

/* Gap between icon and label */
.nxt-tile[data-ratio="wide"][data-size="sm"]   { gap: var(--space-2); }
.nxt-tile[data-ratio="wide"][data-size="md"]   { gap: var(--space-3); }
.nxt-tile[data-ratio="wide"][data-size="lg"]   { gap: var(--tile-wide-lg-gap); }
.nxt-tile[data-ratio="standard"][data-size="sm"] { gap: var(--space-3); }
.nxt-tile[data-ratio="standard"][data-size="md"] { gap: var(--space-4); }
.nxt-tile[data-ratio="standard"][data-size="lg"] { gap: var(--space-5); }

/* Optical vertical centering — icon mass sits visually lower than the
   label's cap-height; nudge the content group up by an extra padding-bottom. */
.nxt-tile { padding-bottom: calc(var(--tile-pb-extra, 4px) + 0px); }
.nxt-tile[data-ratio="wide"]   { --tile-pb-extra: 2px; }
.nxt-tile[data-ratio="standard"] { --tile-pb-extra: 4px; }

/* Tile icon sizing */
.nxt-tile > svg { flex-shrink: 0; }
.nxt-tile[data-ratio="standard"][data-size="sm"] > svg { width: 28px; height: 28px; }
.nxt-tile[data-ratio="standard"][data-size="md"] > svg { width: 36px; height: 36px; }
.nxt-tile[data-ratio="standard"][data-size="lg"] > svg { width: 44px; height: 44px; }
.nxt-tile[data-ratio="wide"][data-size="sm"] > svg   { width: 22px; height: 22px; }
.nxt-tile[data-ratio="wide"][data-size="md"] > svg   { width: 28px; height: 28px; }
.nxt-tile[data-ratio="wide"][data-size="lg"] > svg   { width: 36px; height: 36px; }

/* Tile label — uppercase, tracked, font-size scales per size */
.nxt-tile-label {
  font-weight: var(--weight-medium);
  letter-spacing: var(--track-caps-x);
  text-transform: uppercase;
}
.nxt-tile[data-size="sm"] .nxt-tile-label { font-size: var(--text-2xs); }
.nxt-tile[data-size="md"] .nxt-tile-label { font-size: var(--text-xs); }
.nxt-tile[data-size="lg"] .nxt-tile-label { font-size: var(--text-sm); }

/* Tile intent — default (resting) state */
.nxt-tile[data-intent="neutral"] {
  background: var(--surface-frame-muted-bg);
  color: var(--fg-secondary);
  border-color: var(--surface-frame-border);
}
.nxt-tile[data-intent="hero"] {
  background: var(--accent-soft-bg);
  color: var(--accent-soft-fg);
  border-color: var(--accent-1-4);
}
.nxt-tile[data-intent="accent"] {
  background: var(--secondary-soft-bg);
  color: var(--secondary-soft-fg);
  border-color: var(--accent-2-4);
}
.nxt-tile[data-intent="danger"] {
  background: var(--danger-soft-bg);
  color: var(--danger-soft-fg);
  border-color: var(--semantic-error-4);
}

/* Tile active/selected state — inverts to solid intent fill */
.nxt-tile[data-active][data-intent="neutral"] {
  background: var(--neutral-fill); color: var(--neutral-fill-fg); border-color: var(--neutral-fill);
}
.nxt-tile[data-active][data-intent="hero"] {
  background: var(--accent); color: var(--accent-fg); border-color: var(--accent-outline);
}
.nxt-tile[data-active][data-intent="accent"] {
  background: var(--secondary); color: var(--secondary-fg); border-color: var(--secondary-hover);
}
.nxt-tile[data-active][data-intent="danger"] {
  background: var(--danger); color: var(--danger-fg); border-color: var(--danger-press);
}

/* Tile hover — resting deepens, active darkens one rung */
@media (hover: hover) {
  .nxt-tile[data-intent="neutral"]:not([data-active]):hover {
    background: var(--surface-frame-bg); border-color: var(--surface-frame-border-hover);
  }
  .nxt-tile[data-intent="hero"]:not([data-active]):hover {
    background: var(--accent-1-3); border-color: var(--accent-outline);
  }
  .nxt-tile[data-intent="accent"]:not([data-active]):hover {
    background: var(--accent-2-3); border-color: var(--secondary);
  }
  .nxt-tile[data-intent="danger"]:not([data-active]):hover {
    background: var(--semantic-error-3); border-color: var(--danger);
  }
  .nxt-tile[data-active][data-intent="neutral"]:hover {
    background: var(--neutral-fill-hover);
  }
  .nxt-tile[data-active][data-intent="hero"]:hover {
    background: var(--accent-hover);
  }
  .nxt-tile[data-active][data-intent="accent"]:hover {
    background: var(--secondary-hover);
  }
  .nxt-tile[data-active][data-intent="danger"]:hover {
    background: var(--danger-hover);
  }
}

/* Tile active press */
.nxt-tile:active:not([disabled]):not([aria-disabled="true"]) { transform: scale(0.96); }

/* Tile focus */
.nxt-tile:focus-visible {
  outline: none;
  border-color: var(--fg-primary);
  box-shadow: var(--surface-frame-focus-shadow);
}

/* Tile disabled */
.nxt-tile:disabled,
.nxt-tile[aria-disabled="true"] {
  opacity: var(--control-frame-disabled-opacity); cursor: not-allowed; pointer-events: none;
}

@media (prefers-reduced-motion: reduce) {
  .nxt-tile { transition-duration: 0ms; }
  .nxt-tile:active { transform: none; }
}

.nxt-card,
.nxt-card-group {
  box-sizing: border-box;
}

.nxt-card {
  --focus-ring-gap-color: var(--card-bg);
  --card-bg: var(--surface-frame-bg);
  --card-border: var(--border-subtle);
  --card-fg: var(--fg-primary);
  --card-fg-secondary: var(--fg-secondary);
  --card-fg-tertiary: var(--fg-tertiary);
  --card-padding: var(--space-5);
  --card-heading-gap: var(--stack-gap-heading);
  --card-content-gap: var(--stack-gap-content);
  /* BOUNDARY, not an alias of the interior. --card-gap separates the card's own
     header / content / footer; --card-content-gap separates the content slot's
     children. While --card-gap aliased --card-content-gap the two sides of that
     relationship were ONE token, so boundary == interior by construction at every
     value and no rung could satisfy the 2x floor (ADR 155 amendment 3). The roles
     are split: the boundary takes `related`, one rung above the `content` interior
     it separates. See ADR 155 amendment 5 (DR-013). */
  --card-gap: var(--stack-gap-related);
  --card-title-gap: var(--card-heading-gap);
  --card-shadow: var(--elevation-flat);
  --card-hover-shadow: var(--elevation-raised);
  display: flex;
  flex-direction: column;
  gap: var(--card-gap);
  inline-size: 100%;
  max-inline-size: var(--card-measure);
  padding: var(--card-padding);
  border: 1px solid var(--card-border);
  border-radius: var(--surface-frame-radius);
  background: var(--card-bg);
  color: var(--card-fg);
  box-shadow: var(--card-shadow);
  text-decoration: none;
  transition:
    border-color var(--dur-fast) var(--ease-smooth),
    box-shadow var(--dur-fast) var(--ease-smooth),
    transform var(--dur-fast) var(--ease-smooth),
    background-color var(--dur-fast) var(--ease-smooth);
}

.nxt-card[data-density="compact"] {
  --card-padding: var(--space-3);
}

.nxt-card[data-density="comfortable"] {
  --card-padding: var(--space-5);
}

.nxt-card[data-surface="sunken"] {
  --card-bg: var(--bg-sunken);
  --card-border: var(--border-subtle);
}

.nxt-card[data-surface="solid"],
.nxt-card[data-surface="inverse"] {
  --card-bg: var(--neutral-fill);
  --card-border: var(--neutral-fill);
  --card-fg: var(--neutral-fill-fg);
  --card-fg-secondary: var(--neutral-fill-fg);
  --card-fg-tertiary: var(--neutral-fill-fg);
}

.nxt-card[data-surface="accent"] {
  --card-bg: var(--accent-bold-bg);
  --card-border: var(--accent-outline);
  --card-fg: var(--neutral-1);
  --card-fg-secondary: var(--neutral-1);
  --card-fg-tertiary: var(--neutral-1);
}

.nxt-card[data-surface="secondary"] {
  --card-bg: var(--secondary);
  --card-border: var(--secondary);
  --card-fg: var(--secondary-fg);
  --card-fg-secondary: var(--secondary-fg);
  --card-fg-tertiary: var(--secondary-fg);
}

.nxt-card[data-surface="danger"] {
  --card-bg: var(--danger);
  --card-border: var(--danger);
  --card-fg: var(--danger-fg);
  --card-fg-secondary: var(--danger-fg);
  --card-fg-tertiary: var(--danger-fg);
}

.nxt-card[data-surface="success"] {
  --card-bg: var(--success);
  --card-border: var(--success);
  --card-fg: var(--success-fg);
  --card-fg-secondary: var(--success-fg);
  --card-fg-tertiary: var(--success-fg);
}

.nxt-card[data-surface="warning"] {
  --card-bg: var(--warning);
  --card-border: var(--warning);
  --card-fg: var(--neutral-fill-fg);
  --card-fg-secondary: var(--neutral-fill-fg);
  --card-fg-tertiary: var(--neutral-fill-fg);
}

.nxt-card[data-surface="info"] {
  --card-bg: var(--info);
  --card-border: var(--info);
  --card-fg: var(--info-fg);
  --card-fg-secondary: var(--info-fg);
  --card-fg-tertiary: var(--info-fg);
}

.nxt-card[data-fluid="true"] {
  max-inline-size: none;
}

.nxt-card[data-raised="true"] {
  border-color: var(--border-strong);
  box-shadow: var(--card-hover-shadow);
}

.nxt-card[data-interactive="true"] {
  cursor: pointer;
}

@media (hover: hover) and (pointer: fine) {
  .nxt-card[data-interactive="true"]:hover {
    border-color: var(--border-strong);
    box-shadow: var(--card-hover-shadow);
    transform: translateY(-1px);
  }
}

.nxt-card[data-interactive="true"]:focus-visible {
  outline: none;
  box-shadow: var(--surface-frame-focus-shadow);
}

.nxt-card-header {
  display: flex;
  flex-direction: column;
  gap: var(--card-title-gap);
}

.nxt-card-eyebrow {
  /* Colour stays on the card-local alias so ink-surface cards can invert it;
     it resolves to --fg-tertiary (the eyebrow role's ink) on default surfaces. */
  color: var(--card-fg-tertiary);
  font-family: var(--eyebrow-font);
  font-size: var(--eyebrow-size);
  font-weight: var(--eyebrow-weight);
  letter-spacing: var(--eyebrow-tracking);
}

.nxt-card-title {
  margin: 0;
  color: var(--card-fg);
  font-size: var(--text-lg);
  font-weight: var(--weight-medium);
  line-height: var(--lh-heading);
  text-wrap: balance;
}

.nxt-card-description {
  color: var(--card-fg-secondary);
  font-size: var(--text-sm);
  line-height: var(--lh-relaxed);
  text-wrap: pretty;
}

.nxt-card-footer {
  color: var(--card-fg-secondary);
  font-size: var(--text-sm);
  line-height: var(--lh-normal);
  text-wrap: pretty;
}

.nxt-card[data-interactive="true"]:where([data-surface="default"], [data-surface="sunken"]) .nxt-card-footer {
  color: var(--secondary);
  font-weight: var(--weight-medium);
}

.nxt-card[data-interactive="true"] .nxt-card-footer svg {
  flex: 0 0 auto;
  transition: transform var(--dur-fast) var(--ease-smooth);
}

@media (hover: hover) and (pointer: fine) {
  .nxt-card[data-interactive="true"]:hover .nxt-card-footer svg {
    transform: translateX(3px);
  }
}

/* Card separates its own header/content/footer at --card-gap, but the content
   slot accepts arbitrary children and owned no rhythm for them, so anything
   stacked inside it touched -- measured on /preview/patterns as time-picker +
   button and skeleton-stack + progress, both at 0px. Same fail-closed fallback
   as `.nxt-form-layout > * + *`. minmax(0, 1fr) keeps grid items from refusing
   to shrink below min-content, which is what overflowed /preview/chart when
   .nxt-cv-block-body became a grid. */
.nxt-card-content {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  row-gap: var(--card-content-gap);
  color: var(--card-fg);
  font-size: var(--text-md);
  line-height: var(--lh-relaxed);
  text-wrap: pretty;
}

.nxt-card-media {
  display: grid;
  place-items: center;
  overflow: hidden;
  inline-size: 100%;
  border-radius: var(--surface-frame-media-radius);
  background:
    linear-gradient(135deg, color-mix(in srgb, var(--bg-canvas) 68%, white), var(--bg-canvas));
  border: 1px solid color-mix(in srgb, var(--border-default) 72%, transparent);
}

.nxt-card-media img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  outline: var(--image-outline);
  outline-offset: -1px;
}

.nxt-card-demo-media {
  display: flex;
  align-items: center;
  justify-content: center;
  inline-size: 100%;
  block-size: 100%;
  min-block-size: var(--card-demo-media-min-block-size);
  padding: var(--space-4);
  color: var(--fg-secondary);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
}

.nxt-card-group {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
  gap: var(--space-4);
  align-items: start;
}

.nxt-card-stack {
  display: flex;
  flex-direction: column;
  gap: 0;
  overflow: clip;
  border: 1px solid var(--surface-frame-border);
  border-radius: var(--surface-frame-radius);
  background: var(--surface-frame-bg);
  color: var(--surface-frame-fg);
}

.nxt-card-stack > * {
  border: 0;
  border-radius: 0;
  max-inline-size: none;
}

.nxt-card-stack > *:not(:last-child) {
  border-block-end: 1px solid var(--surface-frame-border);
}

@media (prefers-reduced-motion: reduce) {
  .nxt-card,
  .nxt-card[data-interactive="true"] .nxt-card-footer svg {
    transition-duration: 0ms;
  }

  .nxt-card[data-interactive="true"]:hover,
  .nxt-card[data-interactive="true"]:hover .nxt-card-footer svg {
    transform: none;
  }
}

.nxt-tournament-card {
  --tournament-card-bg: var(--surface-frame-bg);
  --tournament-card-border: var(--surface-frame-border);
  --tournament-card-fg: var(--surface-frame-fg);
  --tournament-card-muted: var(--fg-secondary);
  --tournament-card-subtle: var(--fg-tertiary);
  --tournament-card-accent: var(--accent-outline);
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: var(--space-4);
  align-items: stretch;
  inline-size: 100%;
  max-inline-size: var(--tournament-card-measure-md);
  padding: var(--space-4);
  border: 1px solid var(--tournament-card-border);
  border-radius: var(--surface-frame-radius);
  background: var(--tournament-card-bg);
  color: var(--tournament-card-fg);
  box-shadow: var(--surface-frame-shadow);
  text-decoration: none;
  transition:
    border-color var(--dur-fast) var(--ease-smooth),
    box-shadow var(--dur-fast) var(--ease-smooth),
    transform var(--dur-fast) var(--ease-smooth);
}

.nxt-tournament-card[data-size="sm"] {
  max-inline-size: var(--tournament-card-measure-sm);
  padding: var(--space-3);
  gap: var(--space-3);
}

.nxt-tournament-card[data-size="lg"] {
  max-inline-size: var(--tournament-card-measure-lg);
  padding: var(--space-5);
  gap: var(--space-5);
}

.nxt-tournament-card[data-surface="accent"] {
  --tournament-card-bg: var(--accent-soft-bg);
  --tournament-card-border: var(--accent-outline);
  --tournament-card-accent: var(--accent-outline);
}

.nxt-tournament-card[data-surface="inverse"] {
  --tournament-card-bg: var(--neutral-fill);
  --tournament-card-border: var(--neutral-fill);
  --tournament-card-fg: var(--neutral-fill-fg);
  --tournament-card-muted: var(--neutral-fill-fg);
  --tournament-card-subtle: var(--neutral-fill-fg);
  --tournament-card-accent: var(--neutral-fill-fg);
}

.nxt-tournament-card[data-interactive="true"] {
  cursor: pointer;
}

@media (hover: hover) and (pointer: fine) {
  .nxt-tournament-card[data-interactive="true"]:hover {
    border-color: var(--surface-frame-border-hover);
    transform: translateY(-1px);
  }
}

.nxt-tournament-card:focus-visible {
  outline: none;
  box-shadow: var(--surface-frame-focus-shadow);
}

.nxt-tournament-card[data-disabled="true"] {
  cursor: not-allowed;
  opacity: 0.68;
}

.nxt-tournament-card-main {
  display: flex;
  min-inline-size: 0;
  flex-direction: column;
  gap: var(--space-4);
}

.nxt-tournament-card-header {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}

.nxt-tournament-card-kicker {
  color: var(--eyebrow-fg);
  font-family: var(--eyebrow-font);
  font-size: var(--eyebrow-size);
  font-weight: var(--eyebrow-weight);
  letter-spacing: var(--eyebrow-tracking);
  line-height: var(--lh-normal);
}

.nxt-tournament-card-title {
  margin: 0;
  color: var(--tournament-card-fg);
  font-size: var(--text-xl);
  font-weight: var(--weight-medium);
  line-height: var(--lh-snug);
  text-wrap: balance;
}

.nxt-tournament-card-course {
  color: var(--tournament-card-muted);
  font-size: var(--text-sm);
  line-height: var(--lh-normal);
  text-wrap: pretty;
}

.nxt-tournament-card-meta {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-2);
  margin: 0;
}

.nxt-tournament-card-meta div {
  min-inline-size: 0;
}

.nxt-tournament-card-meta dt,
.nxt-tournament-card-score-label {
  color: var(--tournament-card-subtle);
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
  line-height: var(--lh-normal);
}

.nxt-tournament-card-meta dd {
  margin: 0;
  color: var(--tournament-card-fg);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  font-variant-numeric: tabular-nums;
  line-height: var(--lh-normal);
}

.nxt-tournament-card-score {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-3);
  padding-block-start: var(--space-3);
  border-block-start: 1px solid var(--tournament-card-border);
}

.nxt-tournament-card-score-value {
  color: var(--tournament-card-fg);
  font-size: var(--text-2xl);
  font-weight: var(--weight-medium);
  font-variant-numeric: tabular-nums;
  line-height: var(--lh-tight);
}

.nxt-tournament-card-cta {
  color: var(--tournament-card-accent);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  text-decoration: underline;
  text-underline-offset: 0.18em;
}

.nxt-tournament-card-qr {
  display: grid;
  place-items: center;
  align-self: stretch;
  min-inline-size: var(--tournament-card-qr-min-inline-size);
  padding: var(--space-2);
  border: 1px solid var(--tournament-card-border);
  border-radius: calc(var(--surface-frame-radius) - 2px);
  background: var(--bg-canvas);
}

.nxt-tournament-card-qr-code {
  display: block;
  inline-size: var(--tournament-card-qr-size);
  block-size: var(--tournament-card-qr-size);
  color: var(--neutral-fill);
}

@media (max-width: 767px) {
  .nxt-tournament-card {
    grid-template-columns: 1fr;
  }

  .nxt-tournament-card-qr {
    justify-self: start;
  }
}

@media (prefers-reduced-motion: reduce) {
  .nxt-tournament-card {
    transition-duration: 0ms;
  }

  .nxt-tournament-card[data-interactive="true"]:hover {
    transform: none;
  }
}

.nxt-kbd,
.nxt-kbd-group {
  box-sizing: border-box;
}

.nxt-kbd-group {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
}

.nxt-kbd {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-inline-size: var(--kbd-min-inline-size);
  padding: var(--kbd-padding);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-sm);
  background: var(--bg-canvas);
  color: var(--fg-primary);
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  line-height: var(--lh-snug);
  white-space: nowrap;
}

.nxt-kbd[data-size="sm"] {
  min-inline-size: var(--kbd-sm-min-inline-size);
  padding: var(--kbd-sm-padding);
  font-size: var(--text-xs);
}

.nxt-kbd[data-variant="muted"] {
  background: var(--bg-sunken);
  color: var(--fg-secondary);
}

.nxt-kbd[data-variant="inverse"] {
  background: var(--bg-inverse);
  color: var(--fg-inverse);
}

.nxt-kbd-separator {
  color: var(--fg-secondary);
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
}

.nxt-empty-state {
  box-sizing: border-box;
  display: grid;
  justify-items: center;
  gap: var(--surface-frame-title-gap);
  inline-size: 100%;
  max-inline-size: var(--empty-state-measure);
  padding: var(--space-6);
  color: var(--surface-frame-fg);
  font-family: var(--font-sans);
  text-align: center;
}

.nxt-empty-state[data-size="sm"] { max-inline-size: var(--progress-measure); padding: var(--space-5); }
.nxt-empty-state[data-size="lg"] { max-inline-size: 42rem; padding: var(--space-7); }

.nxt-empty-state-icon {
  display: inline-grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border-radius: var(--radius-full);
  color: var(--neutral-fill);
  background: var(--neutral-4);
}

.nxt-empty-state-copy {
  display: grid;
  /* Title and description are one voice -- the `heading` role. At --space-2 the
     copy's own rhythm equalled the icon/copy/actions boundary around it. */
  gap: var(--stack-gap-heading);
  justify-items: center;
}

.nxt-empty-state-title {
  margin: 0;
  color: var(--fg-primary);
  font-size: var(--text-lg);
  font-weight: var(--weight-medium);
  line-height: var(--lh-snug);
  text-wrap: balance;
}

.nxt-empty-state-description {
  max-inline-size: var(--empty-state-description-measure);
  margin: 0;
  color: var(--fg-secondary);
  font-size: var(--text-sm);
  line-height: var(--lh-normal);
  text-wrap: pretty;
}

.nxt-empty-state-actions {
  display: inline-flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
}

.nxt-aspect-ratio {
  position: relative;
  display: block;
  overflow: hidden;
  inline-size: 100%;
  border-radius: var(--radius-sm);
}

.nxt-aspect-ratio-content {
  display: block;
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
}

.nxt-aspect-ratio-content:not(img):not(video):not(canvas):not(iframe) {
  display: grid;
  place-items: center;
  color: var(--fg-secondary);
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
}

.nxt-container {
  box-sizing: border-box;
  inline-size: 100%;
  padding-inline: var(--space-4);
}

.nxt-container[data-bleed="true"] { padding-inline: 0; }
.nxt-container[data-align="center"] { margin-inline: auto; }
.nxt-container[data-align="left"] { margin-inline: 0 auto; }
.nxt-container[data-size="sm"] { max-inline-size: var(--container-measure-sm); }
.nxt-container[data-size="md"] { max-inline-size: var(--container-measure-md); }
.nxt-container[data-size="lg"] { max-inline-size: var(--container-measure-lg); }
.nxt-container[data-size="xl"] { max-inline-size: var(--container-measure-xl); }
.nxt-container[data-size="prose"] { max-inline-size: var(--measure-prose); }
.nxt-container[data-size="full"] { max-inline-size: none; }

/* ── Layout primitives — Stack / Cluster / Switcher / Grid (decision 127) ──
 * Every-Layout subset. The primitives own inter-child spacing (children stay
 * margin-free) and adapt to their *container*, never the viewport: the
 * Switcher flip and Grid column count derive from the element's own width
 * via flex-basis / auto-fit math, so no width @media appears here. The
 * shared data-gap map binds --layout-gap to the spacing scale. */

:is(.nxt-stack, .nxt-cluster, .nxt-switcher, .nxt-grid, .nxt-masonry-grid)[data-gap="0"] { --layout-gap: var(--space-0); }
:is(.nxt-stack, .nxt-cluster, .nxt-switcher, .nxt-grid, .nxt-masonry-grid)[data-gap="1"] { --layout-gap: var(--space-1); }
:is(.nxt-stack, .nxt-cluster, .nxt-switcher, .nxt-grid, .nxt-masonry-grid)[data-gap="2"] { --layout-gap: var(--space-2); }
:is(.nxt-stack, .nxt-cluster, .nxt-switcher, .nxt-grid, .nxt-masonry-grid)[data-gap="3"] { --layout-gap: var(--space-3); }
:is(.nxt-stack, .nxt-cluster, .nxt-switcher, .nxt-grid, .nxt-masonry-grid)[data-gap="4"] { --layout-gap: var(--space-4); }
:is(.nxt-stack, .nxt-cluster, .nxt-switcher, .nxt-grid, .nxt-masonry-grid)[data-gap="5"] { --layout-gap: var(--space-5); }
:is(.nxt-stack, .nxt-cluster, .nxt-switcher, .nxt-grid, .nxt-masonry-grid)[data-gap="6"] { --layout-gap: var(--space-6); }
:is(.nxt-stack, .nxt-cluster, .nxt-switcher, .nxt-grid, .nxt-masonry-grid)[data-gap="7"] { --layout-gap: var(--space-7); }
.nxt-stack[data-gap="micro"] { --layout-gap: var(--stack-gap-micro); }
.nxt-stack[data-gap="heading"] { --layout-gap: var(--stack-gap-heading); }
.nxt-stack[data-gap="content"] { --layout-gap: var(--stack-gap-content); }
.nxt-stack[data-gap="related"] { --layout-gap: var(--stack-gap-related); }
.nxt-stack[data-gap="section"] { --layout-gap: var(--stack-gap-section); }

/* List-form usage (as="ul"/"ol") sheds list chrome — the primitive is layout,
 * not typography. */
:is(.nxt-stack, .nxt-cluster, .nxt-switcher, .nxt-grid, .nxt-masonry-grid):is(ul, ol) {
  list-style: none;
  margin-block: 0;
  padding-inline-start: 0;
}

.nxt-stack {
  --layout-gap: var(--space-4);
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: var(--layout-gap);
  min-inline-size: 0;
}

.nxt-stack[data-align="start"] { align-items: flex-start; }
.nxt-stack[data-align="center"] { align-items: center; }
.nxt-stack[data-align="end"] { align-items: flex-end; }

.nxt-cluster {
  --layout-gap: var(--space-3);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-start;
  gap: var(--layout-gap);
  min-inline-size: 0;
}

.nxt-cluster[data-justify="center"] { justify-content: center; }
.nxt-cluster[data-justify="end"] { justify-content: flex-end; }
.nxt-cluster[data-justify="between"] { justify-content: space-between; }
.nxt-cluster[data-align="start"] { align-items: flex-start; }
.nxt-cluster[data-align="end"] { align-items: flex-end; }
.nxt-cluster[data-align="baseline"] { align-items: baseline; }
.nxt-cluster[data-align="stretch"] { align-items: stretch; }

.nxt-switcher {
  --layout-gap: var(--space-4);
  --switcher-threshold: var(--bp-sm);
  display: flex;
  flex-wrap: wrap;
  gap: var(--layout-gap);
  /* .nxt-switcher must be allowed to shrink when nested in another layout. */
  min-inline-size: 0;
}

.nxt-switcher[data-threshold="md"] { --switcher-threshold: var(--bp-md); }
.nxt-switcher[data-threshold="lg"] { --switcher-threshold: var(--bp-lg); }

/* The flip: when the container is narrower than the threshold the basis
 * goes hugely positive (each child claims a full row); wider, it goes
 * negative and clamps to content, so children share the row. Container-
 * relative by construction — no @media, no @container. */
.nxt-switcher > * {
  flex-grow: 1;
  flex-basis: calc((var(--switcher-threshold) - 100%) * 999);
  min-inline-size: 0;
}

.nxt-grid {
  --grid-min: 16rem;
  --layout-gap: var(--space-4);
  display: grid;
  gap: var(--layout-gap);
  grid-template-columns: repeat(auto-fit, minmax(min(var(--grid-min), 100%), 1fr));
  /* .nxt-grid must be allowed to shrink when nested in another layout. */
  min-inline-size: 0;
}

.nxt-grid[data-min="sm"] { --grid-min: 12rem; }
.nxt-grid[data-min="lg"] { --grid-min: 20rem; }

.nxt-masonry-grid {
  --layout-gap: var(--space-4);
  --masonry-col: 2;
  --masonry-gap: var(--layout-gap);
  display: flex;
  flex-flow: wrap;
  align-items: flex-start;
  justify-content: flex-start;
  gap: var(--masonry-gap);
  inline-size: 100%;
  min-inline-size: 0;
  position: relative;
}

.nxt-masonry-grid > * {
  inline-size: calc(((100% - 1px) - (var(--masonry-col) - 1) * var(--masonry-gap)) / var(--masonry-col));
}

.nxt-masonry-grid__visual {
  inline-size: 100%;
  overflow: hidden;
  border-radius: var(--surface-frame-media-radius);
  background: var(--bg-sunken);
}

.nxt-masonry-grid__visual[data-aspect="square"] { aspect-ratio: 1; }
.nxt-masonry-grid__visual[data-aspect="wide"] { aspect-ratio: 3 / 2; }
.nxt-masonry-grid__visual[data-aspect="tall"] { aspect-ratio: 2 / 3; }

.nxt-masonry-grid__image {
  display: block;
  block-size: 100%;
  inline-size: 100%;
  object-fit: cover;
}

@media (min-width: 768px) {
  .nxt-masonry-grid {
    --masonry-col: 3;
  }
}

@media (min-width: 960px) {
  .nxt-masonry-grid {
    --masonry-col: 4;
  }
}

.nxt-breadcrumb {
  color: var(--fg-secondary);
  font-family: var(--font-sans);
  font-size: var(--text-sm);
}

.nxt-breadcrumb[data-size="sm"] { font-size: var(--text-xs); }

.nxt-breadcrumb-list {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-1);
  padding: 0;
  margin: 0;
  list-style: none;
}

.nxt-breadcrumb-item {
  display: inline-flex;
  min-width: 0;
  align-items: center;
  gap: var(--space-1);
}

.nxt-breadcrumb-link {
  color: var(--fg-secondary);
  text-decoration: underline;
  text-underline-offset: 0.18em;
  transition: color var(--dur-snap) var(--ease-snap);
}

.nxt-breadcrumb-link:hover {
  color: var(--fg-primary);
}

.nxt-breadcrumb-link:focus-visible {
  outline: 2px solid var(--focus-ring);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

.nxt-breadcrumb-current {
  color: var(--fg-primary);
  font-weight: var(--weight-medium);
}

.nxt-breadcrumb-separator {
  color: var(--fg-tertiary);
}

.nxt-spinner {
  display: inline-grid;
  place-items: center;
  width: var(--spinner-size-md);
  height: var(--spinner-size-md);
  color: var(--neutral-fill);
}

.nxt-spinner[data-size="sm"] { width: 16px; height: 16px; }
.nxt-spinner[data-size="lg"] { width: 28px; height: 28px; }

.nxt-spinner-ring {
  display: block;
  width: 100%;
  height: 100%;
  border: var(--border-width-strong) solid color-mix(in srgb, currentColor 18%, transparent);
  border-top-color: currentColor;
  border-radius: var(--radius-full);
  animation: nxt-spinner-rotate 700ms linear infinite;
}

@keyframes nxt-spinner-rotate {
  to { transform: rotate(360deg); }
}

.nxt-progress {
  display: grid;
  gap: var(--space-2);
  inline-size: 100%;
  max-inline-size: var(--progress-measure);
  color: var(--fg-primary);
  font-family: var(--font-sans);
}

.nxt-progress-header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-3);
}

.nxt-progress-label {
  color: var(--field-label-fg);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  line-height: var(--lh-normal);
}

.nxt-progress-value {
  color: var(--fg-secondary);
  font-size: var(--text-xs);
  font-variant-numeric: tabular-nums;
  line-height: var(--lh-normal);
}

.nxt-progress-track {
  overflow: hidden;
  block-size: var(--progress-track-block-size);
  background: var(--neutral-4);
  border-radius: var(--radius-full);
}

.nxt-progress[data-size="sm"] .nxt-progress-track { block-size: var(--preloader-block-size); }
.nxt-progress[data-size="lg"] .nxt-progress-track { block-size: var(--progress-lg-block-size); }

.nxt-progress-fill {
  display: block;
  block-size: 100%;
  background: var(--neutral-fill);
  border-radius: inherit;
  transition: inline-size var(--dur-fast) var(--ease-smooth);
}

.nxt-progress[data-indeterminate="true"] .nxt-progress-fill {
  inline-size: 40% !important;
  animation: nxt-progress-indeterminate 900ms var(--ease-smooth) infinite;
}

@keyframes nxt-progress-indeterminate {
  0% { transform: translateX(-120%); }
  100% { transform: translateX(260%); }
}

/* ── Circular variant ─────────────────────────────────────────────────────
   Determinate ring. Reuses the linear track/fill colours and the linear track
   thicknesses (--progress-*-block-size) for cross-variant consistency; only
   the ring diameter is new. Stroke is non-scaling so thickness stays exact in
   px while the viewBox scales. */
.nxt-progress[data-variant="circular"] {
  display: inline-grid;
  justify-items: center;
  gap: var(--space-2);
  inline-size: auto;
  max-inline-size: none;
}

.nxt-progress-circular-ring {
  position: relative;
  inline-size: var(--progress-circular-md-size);
  block-size: var(--progress-circular-md-size);
}

.nxt-progress[data-size="sm"] .nxt-progress-circular-ring {
  inline-size: var(--progress-circular-sm-size);
  block-size: var(--progress-circular-sm-size);
}

.nxt-progress[data-size="lg"] .nxt-progress-circular-ring {
  inline-size: var(--progress-circular-lg-size);
  block-size: var(--progress-circular-lg-size);
}

.nxt-progress-circular-svg {
  display: block;
  inline-size: 100%;
  block-size: 100%;
  transform: rotate(-90deg);
}

.nxt-progress-circular-track,
.nxt-progress-circular-indicator {
  fill: none;
  /* intentional: progress ring thickness mirrors linear track, not UI glyph */
  stroke-width: var(--progress-track-block-size);
}

.nxt-progress[data-size="sm"] .nxt-progress-circular-track,
.nxt-progress[data-size="sm"] .nxt-progress-circular-indicator {
  /* intentional: same token the linear sm track uses, so both variants' sm thickness
     stay locked together rather than coincidentally equal. */
  stroke-width: var(--preloader-block-size);
}

.nxt-progress[data-size="lg"] .nxt-progress-circular-track,
.nxt-progress[data-size="lg"] .nxt-progress-circular-indicator {
  /* intentional: progress ring thickness mirrors linear track, not UI glyph */
  stroke-width: var(--progress-lg-block-size);
}

.nxt-progress-circular-track {
  stroke: var(--neutral-4);
}

.nxt-progress-circular-indicator {
  stroke: var(--neutral-fill);
  stroke-linecap: round;
  transition: stroke-dashoffset var(--dur-fast) var(--ease-smooth);
}

.nxt-progress-circular-value {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  color: var(--fg-secondary);
  font-size: var(--text-xs);
  font-variant-numeric: tabular-nums;
  line-height: var(--lh-normal);
}

.nxt-progress-circular-label {
  color: var(--field-label-fg);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  line-height: var(--lh-normal);
  text-align: center;
}

@media (prefers-reduced-motion: reduce) {
  .nxt-spinner-ring,
  .nxt-progress[data-indeterminate="true"] .nxt-progress-fill {
    animation: none;
  }

  .nxt-progress-fill,
  .nxt-progress-circular-indicator {
    transition: none;
  }
}

/* ============================================================================
   TEXT-INPUT (single-line) + TEXTAREA (multi-line)
   ========================================================================= */

.nxt-input,
.nxt-textarea {
  display: block;
  width: 100%;
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  line-height: var(--lh-normal);
  color: var(--field-frame-fg);
  background: var(--field-frame-bg);
  border: var(--field-frame-border-width) solid var(--field-frame-border);
  border-radius: var(--field-frame-radius);
  appearance: none;
  outline: none;
  transition:
    background-color var(--dur-snap) var(--ease-snap),
    border-color     var(--dur-fast) var(--ease-smooth),
    box-shadow       var(--dur-fast) var(--ease-smooth),
    color            var(--dur-fast) var(--ease-smooth);
}

.nxt-input::placeholder,
.nxt-textarea::placeholder {
  color: var(--field-frame-placeholder, var(--input-placeholder));
}

/* ── Size — single-line input (fixed height) ─────────────────────────── */
.nxt-input[data-size="sm"] {
  block-size: var(--ctrl-block-h-sm);
  padding-block: var(--ctrl-block-pad-sm);
  padding-inline: var(--field-inline-pad-sm);
  font-size: var(--text-sm);
}
.nxt-input[data-size="md"] {
  block-size: var(--ctrl-block-h-md);
  padding-block: var(--ctrl-block-pad-md);
  padding-inline: var(--field-inline-pad-md);
  font-size: var(--text-base);
}
.nxt-input[data-size="lg"] {
  block-size: var(--ctrl-block-h-lg);
  padding-block: var(--ctrl-block-pad-lg);
  padding-inline: var(--field-inline-pad-lg);
  font-size: var(--text-md);
}
.nxt-input[data-size="xl"] {
  block-size: var(--ctrl-block-h-xl);
  padding-block: var(--ctrl-block-pad-xl);
  padding-inline: var(--ctrl-inline-pad-xl);
  font-size: var(--text-lg);
}
.nxt-input[data-size="2xl"] {
  block-size: var(--ctrl-block-h-2xl);
  padding-block: var(--ctrl-block-pad-2xl);
  padding-inline: var(--ctrl-inline-pad-2xl);
  font-size: var(--text-xl);
}

/* ── Size — textarea (min-height, padding scales) ────────────────────── */
.nxt-textarea {
  min-block-size: calc(var(--ctrl-block-h-md) * 2);
  resize: vertical;
}
.nxt-textarea[data-size="sm"] {
  padding-block: var(--ctrl-block-pad-sm);
  padding-inline: var(--field-inline-pad-sm);
  font-size: var(--text-sm);
  min-block-size: calc(var(--ctrl-block-h-sm) * 2);
}
.nxt-textarea[data-size="md"] {
  padding-block: var(--ctrl-block-pad-md);
  padding-inline: var(--field-inline-pad-md);
  font-size: var(--text-base);
}
.nxt-textarea[data-size="lg"] {
  padding-block: var(--ctrl-block-pad-lg);
  padding-inline: var(--field-inline-pad-lg);
  font-size: var(--text-md);
  min-block-size: calc(var(--ctrl-block-h-lg) * 2.5);
}
.nxt-textarea[data-resize="none"]     { resize: none; }
.nxt-textarea[data-resize="vertical"] { resize: vertical; }
.nxt-textarea[data-resize="auto"]     { resize: vertical; field-sizing: content; }

/* ── Intent / validation state ───────────────────────────────────────── */
.nxt-input[data-intent="invalid"],
.nxt-textarea[data-intent="invalid"] {
  border-color: var(--field-frame-border-invalid);
}
.nxt-input[data-intent="warning"],
.nxt-textarea[data-intent="warning"] {
  border-color: var(--field-frame-border-warning);
}
.nxt-input[data-intent="success"],
.nxt-textarea[data-intent="success"] {
  border-color: var(--field-frame-border-success);
}

/* ── Hover ───────────────────────────────────────────────────────────── */
@media (hover: hover) {
  .nxt-input:not(:disabled):not([data-readonly]):hover,
  .nxt-textarea:not(:disabled):not([data-readonly]):hover {
    border-color: var(--field-frame-border-hover);
  }
}

/* ── Focus-visible (replaces native outline with a doubled ring) ─────── */
.nxt-input:focus-visible,
.nxt-textarea:focus-visible {
  border-color: var(--field-frame-border-focus);
  box-shadow: var(--field-frame-focus-shadow);
}
.nxt-input[data-intent="invalid"]:focus-visible,
.nxt-textarea[data-intent="invalid"]:focus-visible {
  box-shadow:
    0 0 0 2px var(--bg-canvas),
    0 0 0 4px var(--field-frame-border-invalid);
}

/* ── Disabled ────────────────────────────────────────────────────────── */
.nxt-input:disabled,
.nxt-textarea:disabled,
.nxt-input[data-disabled],
.nxt-textarea[data-disabled] {
  background: var(--field-frame-bg-disabled);
  color: var(--field-frame-fg-disabled);
  border-color: var(--field-frame-border-disabled);
  cursor: not-allowed;
}

/* ── Read-only (visually distinct from disabled — content is selectable) */
.nxt-input[data-readonly],
.nxt-textarea[data-readonly] {
  background: var(--field-frame-bg-readonly);
  cursor: default;
}

/* ── LINE chrome — underline-only editorial form variant ─────────────────
 * Removes the box border / bg / radius and renders a single-pixel bottom
 * border. Matches the reference's LINE editorial layout (no enclosing box,
 * just a thin baseline that thickens on focus). Padding tightens because
 * there's no left/right chrome to push against.
 * ─────────────────────────────────────────────────────────────────────── */
.nxt-input[data-chrome="line"] {
  background: transparent;
  border: 0;
  border-bottom: var(--field-frame-border-width) solid var(--field-frame-border);
  border-radius: 0;
  padding-inline: 0;
}
.nxt-input[data-chrome="line"]:focus-visible {
  background: transparent;
  border-bottom: 2px solid var(--field-frame-border-focus);
  box-shadow: none;
  /* Compensate for the +1px border so the input doesn't jump. */
  padding-block-end: calc(var(--ctrl-block-pad-md) - 1px);
}
.nxt-input[data-chrome="line"][data-size="sm"]:focus-visible {
  padding-block-end: calc(var(--ctrl-block-pad-sm) - 1px);
}
.nxt-input[data-chrome="line"][data-size="lg"]:focus-visible {
  padding-block-end: calc(var(--ctrl-block-pad-lg) - 1px);
}
.nxt-input[data-chrome="line"][data-size="xl"]:focus-visible {
  padding-block-end: calc(var(--ctrl-block-pad-xl) - 1px);
}
.nxt-input[data-chrome="line"][data-size="2xl"]:focus-visible {
  padding-block-end: calc(var(--ctrl-block-pad-2xl) - 1px);
}
.nxt-input[data-chrome="line"][data-intent="invalid"] {
  border-bottom-color: var(--field-frame-border-invalid);
}
.nxt-input[data-chrome="line"][data-intent="warning"] {
  border-bottom-color: var(--field-frame-border-warning);
}
.nxt-input[data-chrome="line"][data-intent="success"] {
  border-bottom-color: var(--field-frame-border-success);
}
.nxt-input[data-chrome="line"]:disabled,
.nxt-input[data-chrome="line"][data-disabled] {
  background: transparent;
  border-bottom-color: var(--field-frame-border-disabled);
}
.nxt-input[data-chrome="line"][data-readonly] {
  background: transparent;
}

/* Same chrome=line treatment on the slot wrapper so prefix/suffix sit on a
 * shared underline (used by the LINE+icon LABELED affixes in the reference). */
.nxt-input-slot[data-chrome="line"] {
  background: transparent;
  border: 0;
  border-bottom: var(--field-frame-border-width) solid var(--field-frame-border);
  border-radius: 0;
}
.nxt-input-slot[data-chrome="line"]:focus-within {
  background: transparent;
  border-bottom: 2px solid var(--field-frame-border-focus);
  box-shadow: none;
}
.nxt-input-slot[data-chrome="line"][data-intent="invalid"] { border-bottom-color: var(--field-frame-border-invalid); }
.nxt-input-slot[data-chrome="line"][data-intent="warning"] { border-bottom-color: var(--field-frame-border-warning); }
.nxt-input-slot[data-chrome="line"][data-intent="success"] { border-bottom-color: var(--field-frame-border-success); }

/* ── Validation suffix icons — green ✓ / red ⊘ rendered via affix slot ─
 * Consumers pass a <svg> as `suffix` when they want the visual; the affix
 * tone follows intent automatically. */
/* Affix glyph scales with the control size token instead of a fixed 16px, so
 * the icon keeps a proportional rhythm across sm→2xl (md is the default).
 * Direct-child only: scales the affix's own icon, not icons nested inside a
 * composed control (e.g. the clear Button), which keep their own sizing. */
.nxt-input-slot .nxt-input-affix > svg { display: block; width: var(--ctrl-icon-md); height: var(--ctrl-icon-md); }
.nxt-input-slot[data-size="sm"] .nxt-input-affix > svg { width: var(--ctrl-icon-sm); height: var(--ctrl-icon-sm); }
.nxt-input-slot[data-size="lg"] .nxt-input-affix > svg { width: var(--ctrl-icon-lg); height: var(--ctrl-icon-lg); }
.nxt-input-slot[data-size="xl"] .nxt-input-affix > svg { width: var(--ctrl-icon-xl); height: var(--ctrl-icon-xl); }
.nxt-input-slot[data-size="2xl"] .nxt-input-affix > svg { width: var(--ctrl-icon-2xl); height: var(--ctrl-icon-2xl); }
.nxt-input-slot[data-intent="invalid"] .nxt-input-affix--suffix { color: var(--field-frame-border-invalid); }
.nxt-input-slot[data-intent="warning"] .nxt-input-affix--suffix { color: var(--field-frame-border-warning); }
.nxt-input-slot[data-intent="success"] .nxt-input-affix--suffix { color: var(--field-frame-border-success); }

/* ── Slot host (prefix / suffix wrapper) ─────────────────────────────── */
.nxt-input-slot {
  display: inline-flex;
  align-items: center;
  width: 100%;
  background: var(--field-frame-bg);
  border: var(--field-frame-border-width) solid var(--field-frame-border);
  border-radius: var(--field-frame-radius);
  overflow: hidden;
  transition:
    background-color var(--dur-snap) var(--ease-snap),
    border-color     var(--dur-fast) var(--ease-smooth),
    box-shadow       var(--dur-fast) var(--ease-smooth);
}
.nxt-input-slot[data-intent="invalid"] { border-color: var(--field-frame-border-invalid); }
.nxt-input-slot[data-intent="warning"] { border-color: var(--field-frame-border-warning); }
.nxt-input-slot[data-intent="success"] { border-color: var(--field-frame-border-success); }
.nxt-input-slot:focus-within {
  border-color: var(--field-frame-border-focus);
  box-shadow: var(--field-frame-focus-shadow);
}
.nxt-input-slot > .nxt-input {
  border: none;
  background: transparent;
  border-radius: 0;
  flex: 1;
  min-inline-size: 0;
}
.nxt-input-slot > .nxt-input:focus-visible {
  box-shadow: none;     /* parent slot carries the ring */
  border: none;
}
.nxt-input-slot > .nxt-input-affix--prefix + .nxt-input {
  padding-inline-start: var(--space-2);
}
.nxt-input-slot:has(> .nxt-input + .nxt-input-affix--suffix) > .nxt-input {
  padding-inline-end: var(--space-2);
}
.nxt-input-affix {
  display: inline-flex;
  align-items: center;
  padding-inline: var(--field-inline-pad-md);
  color: var(--fg-tertiary);
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  user-select: none;
  flex-shrink: 0;
}
.nxt-input-affix--prefix { padding-inline-end: 0; }
.nxt-input-affix--suffix { padding-inline-start: 0; }
.nxt-input-slot[data-size="sm"] .nxt-input-affix { padding-inline: var(--field-inline-pad-sm); }
.nxt-input-slot[data-size="lg"] .nxt-input-affix { padding-inline: var(--field-inline-pad-lg); }
.nxt-input-slot[data-size="xl"] .nxt-input-affix { padding-inline: var(--ctrl-inline-pad-xl); }
.nxt-input-slot[data-size="2xl"] .nxt-input-affix { padding-inline: var(--ctrl-inline-pad-2xl); }

@media (prefers-reduced-motion: reduce) {
  .nxt-input,
  .nxt-textarea,
  .nxt-input-slot { transition-duration: 0ms; }
}

/* ============================================================================
   FIELD (label + description + control + counter + message composite)
   ========================================================================= */

/* Field gap tokens are local aliases of the shared relational rhythm. */
.nxt-field {
  --field-description-gap: var(--stack-gap-heading);
  /* FP-1: label, input, helper and error sit 4px apart so they read as one
     perceptual unit. This was bound to --stack-gap-content (8px), the group
     boundary, which put it in FP-1's stated anti-pattern band and made FP-2's
     ratio Check fail: dist(field,field) >= 4*dist(label,input) was 16 >= 32. */
  --field-control-gap: var(--stack-gap-heading);
  --field-message-gap: var(--stack-gap-heading);
  --field-inline-gap: var(--space-4);
  --field-label-counter-gap: var(--space-3);
  --field-inline-label-pad: var(--ctrl-block-pad-md);

  display: flex;
  flex-direction: column;
  gap: 0;
  font-family: var(--font-sans);
}
.nxt-field[data-layout="inline"] {
  flex-direction: row;
  align-items: baseline;
  gap: var(--field-inline-gap);
}
.nxt-field[data-layout="inline"][data-size="sm"] { --field-inline-label-pad: var(--ctrl-block-pad-sm); }
.nxt-field[data-layout="inline"][data-size="md"] { --field-inline-label-pad: var(--ctrl-block-pad-md); }
.nxt-field[data-layout="inline"][data-size="lg"] { --field-inline-label-pad: var(--ctrl-block-pad-lg); }
.nxt-field[data-layout="inline"] .nxt-field-header {
  flex-shrink: 0;
  min-inline-size: var(--field-min-inline-size);
  padding-block-start: var(--field-inline-label-pad); /* align label baseline to control top padding */
}
.nxt-field[data-layout="inline"] .nxt-field-control {
  flex: 1;
}

/* Width — constrains the control wrapper to an expected-content step.
 * Tokens live in tokens.semantic.css; full=100% spans the field. */
.nxt-field[data-width="short"]  .nxt-field-control { max-inline-size: var(--field-w-short); }
.nxt-field[data-width="medium"] .nxt-field-control { max-inline-size: var(--field-w-medium); }
.nxt-field[data-width="long"]   .nxt-field-control { max-inline-size: var(--field-w-long); }
.nxt-field[data-width="full"]   .nxt-field-control { max-inline-size: var(--field-w-full); }

.nxt-field-header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--field-label-counter-gap);
  margin: 0;
}
.nxt-field-label {
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  color: var(--field-label-fg);
  line-height: var(--lh-snug);
}
.nxt-field-required {
  color: var(--field-label-required);
  margin-inline-start: var(--field-required-gap);
}
.nxt-field-counter {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--field-counter-fg);
  letter-spacing: var(--track-wide);
  flex-shrink: 0;
}
.nxt-field[data-intent="invalid"] .nxt-field-counter {
  color: var(--field-counter-invalid);
}
.nxt-field-description {
  font-size: var(--text-xs);
  color: var(--field-description-fg);
  line-height: var(--lh-normal);
  margin: 0;
}
.nxt-field-control {
  display: block;
  margin-block-start: 0;
}
.nxt-field-message {
  font-size: var(--text-xs);
  line-height: var(--lh-normal);
  margin: 0;
}
.nxt-field:not([data-layout="inline"]) .nxt-field-description {
  margin-block-start: var(--field-description-gap);
}
.nxt-field:not([data-layout="inline"]) .nxt-field-control {
  margin-block-start: var(--field-control-gap);
}
.nxt-field:not([data-layout="inline"]) .nxt-field-message {
  margin-block-start: var(--field-message-gap);
}
.nxt-field-message[data-kind="error"]   { color: var(--field-message-error-fg); }
.nxt-field-message[data-kind="warning"] { color: var(--field-message-warning-fg); }
.nxt-field-message[data-kind="success"] { color: var(--field-message-success-fg); }
.nxt-field-message[data-kind="info"]    { color: var(--field-message-info-fg); }

/* Disabled field — dim the header (control is dimmed via the control's own state). */
.nxt-field[data-disabled] .nxt-field-label,
.nxt-field[data-disabled] .nxt-field-description {
  opacity: 0.55;
}

/* Size — adjusts label/description scale. */
.nxt-field[data-size="lg"] .nxt-field-label { font-size: var(--text-md); }
.nxt-field[data-size="lg"] .nxt-field-description,
.nxt-field[data-size="lg"] .nxt-field-message,
.nxt-field[data-size="lg"] .nxt-field-counter { font-size: var(--text-sm); }
.nxt-field[data-size="sm"] .nxt-field-label { font-size: var(--text-xs); }

/* ============================================================================
 * Checkbox + CheckboxGroup
 *
 * Radix Checkbox.Root is visually hidden behind a custom .nxt-checkbox-box.
 * Tick + dash drawn via inline SVG using stroke-dasharray so checked/indeterminate
 * states can be CSS-driven without JS state. Click target is the wrapping <label>;
 * focus ring lives on the .nxt-checkbox-box (mirroring Button + input focus shape).
 * Radix inserts a hidden BubbleInput sibling after the Root for form semantics, so
 * state selectors use general sibling combinators instead of adjacent siblings.
 * ============================================================================ */

.nxt-checkbox {
  display: inline-flex;
  align-items: flex-start;
  gap: var(--checkbox-gap);
  min-block-size: var(--checkbox-min-block-size);
  cursor: pointer;
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  line-height: var(--lh-normal);
  color: var(--field-label-fg);
}
.nxt-checkbox[data-disabled] {
  cursor: not-allowed;
  opacity: 0.55;
}
.nxt-checkbox-input {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: var(--sr-only-offset);
  overflow: hidden; clip: rect(0,0,0,0);
  white-space: nowrap; border: 0;
}
.nxt-checkbox-box {
  flex: 0 0 auto;
  position: relative;
  display: inline-grid;
  place-items: center;
  background: var(--bg-surface);
  border: var(--border-width-strong) solid var(--input-border);
  border-radius: var(--radius-sm);
  width: var(--selection-box-size); height: var(--selection-box-size);
  transition: background-color var(--dur-snap) var(--ease-snap),
              border-color var(--dur-snap) var(--ease-snap),
              transform var(--dur-fast) var(--ease-smooth);
}
.nxt-checkbox[data-size="sm"] .nxt-checkbox-box { width: 16px; height: 16px; }
.nxt-checkbox[data-intent="invalid"] .nxt-checkbox-box {
  border-color: var(--input-border-invalid);
}
.nxt-checkbox-input:focus-visible ~ .nxt-checkbox-box {
  box-shadow: var(--focus-ring-shadow-gap);
  border-color: var(--input-border-focus);
}
.nxt-checkbox-input[data-state="checked"] ~ .nxt-checkbox-box,
.nxt-checkbox-input[data-state="indeterminate"] ~ .nxt-checkbox-box {
  /* On-state uses the neutral solid fill. Lime remains reserved for the
   * single hero CTA per view, never ordinary selection controls. */
  background: var(--neutral-fill);
  border-color: var(--neutral-fill);
}
.nxt-checkbox-check {
  width: 72%; height: 72%;
  fill: none;
  stroke: var(--neutral-fill-fg);
  /* intentional: optical weight at 18px box */
  stroke-width: 2.1;
  stroke-linecap: round;
  stroke-linejoin: round;
  pointer-events: none;
  opacity: 0;
  transition: opacity var(--dur-instant) var(--ease-smooth);
}
.nxt-checkbox[data-size="sm"] .nxt-checkbox-check {
  width: 12px; height: 12px;
  /* intentional: optical weight at 18px box */
  stroke-width: 2;
}
.nxt-checkbox-input[data-state="checked"] ~ .nxt-checkbox-box .nxt-checkbox-check,
.nxt-checkbox-input[data-state="indeterminate"] ~ .nxt-checkbox-box .nxt-checkbox-check {
  opacity: 1;
}
.nxt-checkbox-tick {
  display: block;
  opacity: 0;
  stroke-dasharray: 16;
  stroke-dashoffset: 16;
  transition:
    opacity var(--dur-instant) var(--ease-smooth),
    stroke-dashoffset var(--dur-quick) var(--ease-smooth) 60ms;
}
.nxt-checkbox-dash {
  display: block;
  opacity: 0;
  stroke-dasharray: 9;
  stroke-dashoffset: 9;
  transition:
    opacity var(--dur-instant) var(--ease-smooth),
    stroke-dashoffset var(--dur-quick) var(--ease-smooth);
}
.nxt-checkbox-input[data-state="checked"] ~ .nxt-checkbox-box .nxt-checkbox-tick {
  opacity: 1;
  stroke-dashoffset: 0;
}
.nxt-checkbox-input[data-state="indeterminate"] ~ .nxt-checkbox-box .nxt-checkbox-dash {
  opacity: 1;
  stroke-dashoffset: 0;
}
.nxt-checkbox-content {
  display: inline-flex;
  flex-direction: column;
  gap: var(--checkbox-content-gap);
  padding-top: 1px;
}
.nxt-checkbox-label { font-weight: var(--weight-medium, 500); }
.nxt-checkbox-description {
  font-size: var(--text-xs);
  color: var(--field-description-fg);
  line-height: var(--lh-normal);
}
@media (hover: none) {
  .nxt-checkbox-box::before {
    content: "";
    position: absolute;
    inset: var(--selection-hit-target-outset);
  }
}
@media (prefers-reduced-motion: reduce) {
  .nxt-checkbox-box,
  .nxt-checkbox-check,
  .nxt-checkbox-tick,
  .nxt-checkbox-dash { transition: none; }
  .nxt-checkbox:hover:not([data-disabled]) .nxt-checkbox-box { transform: none; }
}

/* CheckboxGroup — fieldset wrapper with legend, vertical/horizontal stack. */
.nxt-checkbox-group {
  border: 0;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: var(--checkbox-group-gap);
  min-width: 0;
}
.nxt-checkbox-group-legend {
  padding: 0;
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium, 500);
  color: var(--field-label-fg);
  line-height: var(--lh-heading);
}
.nxt-checkbox-group-required { color: var(--field-label-required); }
.nxt-checkbox-group-description {
  font-size: var(--text-xs);
  color: var(--field-description-fg);
  line-height: var(--lh-normal);
  margin: 0;
}
.nxt-checkbox-group-items {
  display: flex;
  flex-direction: column;
  gap: var(--checkbox-group-items-gap);
  margin-top: var(--checkbox-group-items-margin-block-start);
}
.nxt-checkbox-group[data-orientation="horizontal"] .nxt-checkbox-group-items {
  flex-direction: row;
  flex-wrap: wrap;
  gap: var(--checkbox-group-horizontal-gap);
}
.nxt-checkbox-group-message {
  font-size: var(--text-xs);
  line-height: var(--lh-normal);
  margin: 0;
}
.nxt-checkbox-group-message[data-kind="error"] { color: var(--field-message-error-fg); }
.nxt-checkbox-group-message[data-kind="info"]  { color: var(--field-message-info-fg); }

/* ============================================================================
 * Switch
 *
 * Radix Switch.Root is the visible control; the custom thumb slides via
 * data-state="checked" / "unchecked" while Radix preserves switch semantics.
 * ============================================================================ */

.nxt-switch {
  --nxt-switch-thumb-travel: 20px;

  display: inline-flex;
  align-items: flex-start;
  gap: var(--switch-gap);
  min-block-size: var(--radio-min-block-size);
  cursor: pointer;
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  line-height: var(--lh-normal);
  color: var(--field-label-fg);
}
.nxt-switch[data-disabled] {
  cursor: not-allowed;
  opacity: 0.55;
}
.nxt-switch[data-size="sm"] { --nxt-switch-thumb-travel: 16px; }
.nxt-switch-control {
  appearance: none;
  flex: 0 0 auto;
  position: relative;
  display: inline-flex;
  align-items: center;
  width: 44px; height: 24px;
  padding-inline: var(--switch-control-padding-inline);
  background-color: var(--input-border);
  border: var(--border-width-strong) solid var(--input-border);
  border-radius: 9999px;
  cursor: pointer;
  transition: background-color var(--dur-snap) var(--ease-snap),
              border-color var(--dur-snap) var(--ease-snap),
              transform var(--dur-fast) var(--ease-smooth);
}
.nxt-switch[data-disabled] .nxt-switch-control { cursor: not-allowed; }
.nxt-switch[data-invalid] .nxt-switch-control { border-color: var(--input-border-invalid); }
.nxt-switch[data-size="sm"] .nxt-switch-control { width: 36px; height: 20px; }
.nxt-switch-thumb {
  position: absolute;
  top: 50%;
  left: var(--switch-thumb-left);
  display: inline-grid;
  place-items: center;
  width: 18px; height: 18px;
  background: var(--bg-canvas);
  border: 0;
  border-radius: 9999px;
  box-shadow: var(--selection-indicator-shadow);
  transform: translate3d(0, -50%, 0);
  transform-origin: center;
  transition: transform var(--dur-fast) var(--ease-bouncy),
              width var(--dur-snap) var(--ease-snap),
              background-color var(--dur-snap) var(--ease-snap),
              border-color var(--dur-snap) var(--ease-snap);
  will-change: transform;
}
.nxt-switch[data-size="sm"] .nxt-switch-thumb { width: 14px; height: 14px; }
.nxt-switch:hover:not([data-disabled]) .nxt-switch-control {
  background-color: var(--control-frame-muted-hover-fill);
  border-color: var(--control-frame-muted-hover-fill);
}
.nxt-switch-control:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring-shadow-gap);
  border-color: var(--input-border-focus);
}
.nxt-switch-control[data-state="checked"] {
  background-color: var(--neutral-fill);
  border-color: var(--neutral-fill);
}
.nxt-switch-control[data-state="checked"] .nxt-switch-thumb {
  background: var(--neutral-fill-fg);
  color: var(--neutral-fill);
  transform: translate3d(var(--nxt-switch-thumb-travel), -50%, 0);
}
.nxt-switch-control:active .nxt-switch-thumb {
  transform: translate3d(0, -50%, 0) scale(0.96);
}
.nxt-switch-control[data-state="checked"]:active .nxt-switch-thumb {
  transform: translate3d(var(--nxt-switch-thumb-travel), -50%, 0) scale(0.96);
}
.nxt-switch-content {
  display: inline-flex;
  flex-direction: column;
  gap: var(--switch-content-gap);
  padding-top: 1px;
}
@media (hover: none) {
  .nxt-switch-control::before {
    content: "";
    position: absolute;
    inset-block: var(--selection-hit-target-outset);
    inset-inline: 0;
  }
}
.nxt-switch-label { font-weight: var(--weight-medium, 500); }
.nxt-switch-description {
  font-size: var(--text-xs);
  color: var(--field-description-fg);
  line-height: var(--lh-normal);
}
@media (prefers-reduced-motion: reduce) {
  .nxt-switch-control,
  .nxt-switch-thumb { transition: none; }
  .nxt-switch:hover:not([data-disabled]) .nxt-switch-control { transform: none; }
  .nxt-switch-control:active .nxt-switch-thumb {
    transform: translate3d(0, -50%, 0);
  }
  .nxt-switch-control[data-state="checked"]:active .nxt-switch-thumb {
    transform: translate3d(var(--nxt-switch-thumb-travel), -50%, 0);
  }
}

/* ============================================================================
 * RadioGroup + Radio
 *
 * Radix RadioGroup emits button-based radio items plus hidden form inputs.
 * Visual state keys off Radix's data-state on .nxt-radio; group lives
 * inside <fieldset> with <legend>. role="radiogroup" reinforces the
 * relationship for AT.
 * ============================================================================ */

.nxt-radio-group {
  border: 0; padding: 0; margin: 0;
  display: flex; flex-direction: column; gap: var(--radio-group-gap); min-width: 0;
}
.nxt-radio-group[data-variant="card"][data-fluid="true"] {
  inline-size: 100%;
}
.nxt-radio-group-legend {
  padding: 0;
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium, 500);
  color: var(--field-label-fg);
  line-height: var(--lh-heading);
}
.nxt-radio-group-required { color: var(--field-label-required); }
.nxt-radio-group-description {
  font-size: var(--text-xs);
  color: var(--field-description-fg);
  line-height: var(--lh-normal);
  margin: 0;
}
.nxt-radio-group-items {
  display: flex; flex-direction: column; gap: var(--radio-group-items-gap); margin-top: var(--space-1);
}
.nxt-radio-group[data-orientation="horizontal"] .nxt-radio-group-items {
  flex-direction: row; flex-wrap: wrap; gap: var(--space-3) var(--space-5);
}
.nxt-radio-group[data-variant="card"] .nxt-radio-group-items {
  gap: var(--hole-chart-legend-gap);
  margin-top: 6px; /* intentional: off-grid — equidistant from the heading and content rungs; snapping either way is a visible move */
}
.nxt-radio-group[data-variant="card"][data-orientation="horizontal"] .nxt-radio-group-items {
  align-items: stretch;
  gap: var(--oklch-picker-header-gap);
}
.nxt-radio-group-message {
  font-size: var(--text-xs); line-height: var(--lh-normal); margin: 0;
}
.nxt-radio-group-message[data-kind="error"] { color: var(--field-message-error-fg); }
.nxt-radio-group-message[data-kind="info"]  { color: var(--field-message-info-fg); }

.nxt-radio {
  display: inline-flex;
  align-items: flex-start;
  gap: var(--radio-gap);
  min-block-size: var(--switch-min-block-size);
  padding: 0;
  border: 0;
  background: transparent;
  cursor: pointer;
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  line-height: var(--lh-normal);
  text-align: start;
  color: var(--field-label-fg);
}
.nxt-radio[data-disabled] { cursor: not-allowed; opacity: 0.55; }
.nxt-radio[data-variant="card"] {
  align-items: center;
  min-block-size: var(--radio-card-min-block-size);
  min-inline-size: 0;
  padding: var(--radio-card-padding);
  border: var(--border-width-strong) solid var(--input-border);
  border-radius: var(--surface-frame-radius);
  background: var(--bg-surface);
  color: var(--field-label-fg);
  font-size: var(--text-base);
  line-height: var(--lh-heading);
  user-select: none;
  transition:
    background-color var(--dur-snap) var(--ease-snap),
    border-color var(--dur-snap) var(--ease-snap),
    color var(--dur-snap) var(--ease-snap),
    box-shadow var(--dur-snap) var(--ease-snap),
    transform var(--dur-fast) var(--ease-smooth);
}
.nxt-radio-group[data-variant="card"][data-orientation="horizontal"] .nxt-radio {
  flex: 0 1 280px;
}
.nxt-radio-group[data-variant="card"][data-orientation="horizontal"][data-fluid="true"] .nxt-radio {
  flex: 1 1 240px;
}
.nxt-radio[data-variant="card"][data-size="sm"] {
  min-block-size: var(--ctrl-block-h-lg);
  padding-inline: var(--radio-card-sm-padding-inline);
  font-size: var(--text-sm);
}
.nxt-radio-circle {
  flex: 0 0 auto;
  position: relative;
  display: inline-grid; place-items: center;
  width: var(--selection-box-size); height: var(--selection-box-size);
  background-color: var(--bg-surface);
  border: var(--border-width-strong) solid var(--input-border);
  border-radius: 9999px;
  transition: background-color var(--dur-snap) var(--ease-snap),
              border-color var(--dur-snap) var(--ease-snap),
              transform var(--dur-fast) var(--ease-smooth);
}
.nxt-radio[data-size="sm"] .nxt-radio-circle { width: 16px; height: 16px; }
.nxt-radio[data-intent="invalid"] .nxt-radio-circle { border-color: var(--input-border-invalid); }
.nxt-radio[data-variant="card"][data-intent="invalid"] {
  border-color: var(--input-border-invalid);
}
.nxt-radio:focus-visible {
  outline: none;
}
.nxt-radio:focus-visible .nxt-radio-circle {
  box-shadow: var(--focus-ring-shadow-gap);
  border-color: var(--input-border-focus);
}
.nxt-radio[data-variant="card"]:focus-visible {
  border-color: var(--input-border-focus);
  box-shadow: var(--focus-ring-shadow-gap);
}
.nxt-radio[data-variant="card"]:focus-visible .nxt-radio-circle {
  box-shadow: none;
}
.nxt-radio:active:not([data-disabled]) .nxt-radio-circle {
  transform: scale(0.96);
}
.nxt-radio[data-variant="card"]:active:not([data-disabled]) {
  transform: scale(0.99);
}
.nxt-radio-dot {
  display: block;
  position: relative;
  z-index: 1;
  width: 40%; height: 40%;
  border-radius: 9999px;
  background: var(--neutral-fill-fg);
  opacity: 0;
  transform: scale(0);
  transition: opacity var(--dur-snap) var(--ease-snap),
              transform var(--dur-fast) var(--ease-bouncy);
}
.nxt-radio[data-size="sm"] .nxt-radio-dot { width: 6px; height: 6px; }
.nxt-radio[data-state="checked"] .nxt-radio-circle {
  border-color: var(--neutral-fill);
  background-color: var(--neutral-fill);
}
.nxt-radio[data-state="checked"] .nxt-radio-circle .nxt-radio-dot {
  opacity: 1;
  transform: scale(1);
}
.nxt-radio[data-variant="card"][data-state="checked"] {
  border-color: var(--neutral-fill);
  background: var(--neutral-fill);
  color: var(--neutral-fill-fg);
}
.nxt-radio[data-variant="card"][data-state="checked"] .nxt-radio-circle {
  border-color: var(--neutral-fill-fg);
  background-color: var(--neutral-fill-fg);
}
.nxt-radio[data-variant="card"][data-state="checked"] .nxt-radio-dot {
  background: var(--neutral-fill);
}
.nxt-radio-content {
  display: inline-flex; flex-direction: column; gap: var(--radio-content-gap); padding-top: 1px;
}
.nxt-radio[data-variant="card"] .nxt-radio-content {
  min-width: 0;
  padding-top: 0;
}
.nxt-radio-label { font-weight: var(--weight-medium, 500); }
.nxt-radio[data-variant="card"] .nxt-radio-label {
  overflow-wrap: anywhere;
}
.nxt-radio-description {
  font-size: var(--text-xs); color: var(--field-description-fg); line-height: var(--lh-normal);
}
.nxt-radio[data-variant="card"][data-state="checked"] .nxt-radio-description {
  color: currentColor;
  opacity: 0.78;
}
@media (hover: hover) {
  .nxt-radio[data-variant="card"]:hover:not([data-disabled]) {
    border-color: var(--neutral-fill-hover);
  }
  .nxt-radio[data-variant="card"][data-state="checked"]:hover:not([data-disabled]) {
    border-color: var(--neutral-fill-hover);
    background: var(--neutral-fill-hover);
  }
}
@media (hover: none) {
  .nxt-radio-circle::before {
    content: "";
    position: absolute;
    inset: var(--selection-hit-target-outset);
  }
}
@media (prefers-reduced-motion: reduce) {
  .nxt-radio[data-variant="card"],
  .nxt-radio-circle,
  .nxt-radio-dot { transition: none; }
  .nxt-radio:hover:not([data-disabled]) .nxt-radio-circle { transform: none; }
  .nxt-radio:active:not([data-disabled]) .nxt-radio-circle { transform: none; }
  .nxt-radio[data-variant="card"]:active:not([data-disabled]) { transform: none; }
}

/* ============================================================================
 * Select
 *
 * react-select-backed single-select shell. The wrapper keeps the system API
 * stable while the visible control, menu, and option states are styled from
 * DS tokens and shared surface patterns. A hidden native <select> mirrors the
 * current value for form submission and ref compatibility.
 * ============================================================================ */

.nxt-select {
  position: relative;
  display: block;
  width: 100%;
  min-width: 0;
  font-family: var(--font-sans);
}
.nxt-select[data-size="sm"] {
  --nxt-select-height: var(--ctrl-block-h-sm);
  --nxt-select-pad-x: var(--field-inline-pad-sm);
  --nxt-select-pad-y: var(--ctrl-block-pad-sm);
  --nxt-select-font-size: var(--text-sm);
}
.nxt-select[data-size="md"] {
  --nxt-select-height: var(--ctrl-block-h-md);
  --nxt-select-pad-x: var(--field-inline-pad-md);
  --nxt-select-pad-y: var(--ctrl-block-pad-md);
  --nxt-select-font-size: var(--text-sm);
}
.nxt-select[data-size="lg"] {
  --nxt-select-height: var(--ctrl-block-h-lg);
  --nxt-select-pad-x: var(--field-inline-pad-lg);
  --nxt-select-pad-y: var(--ctrl-block-pad-lg);
  --nxt-select-font-size: var(--text-md);
}
.nxt-select-native-mirror {
  position: absolute;
  inset: 0;
  width: var(--sr-only-size);
  height: var(--sr-only-size);
  margin: 0;
  padding: 0;
  border: 0;
  opacity: 0;
  pointer-events: none;
  clip-path: inset(50%);
  overflow: hidden;
  white-space: nowrap;
}
.nxt-select-control {
  display: flex;
  align-items: center;
  min-height: var(--nxt-select-height);
  background: var(--field-frame-bg);
  color: var(--field-frame-fg);
  border: var(--field-frame-border-width) solid var(--field-frame-border);
  border-radius: var(--field-frame-radius);
  cursor: pointer;
  box-shadow: none;
  transition:
    background-color var(--dur-snap) var(--ease-snap),
    border-color var(--dur-snap) var(--ease-snap),
    box-shadow var(--dur-fast) var(--ease-smooth);
}
.nxt-select:hover .nxt-select-control:not([aria-disabled="true"]) {
  border-color: var(--field-frame-border-hover);
}
.nxt-select:focus-within .nxt-select-control {
  border-color: var(--field-frame-border-focus);
  box-shadow: var(--field-frame-focus-shadow);
}
.nxt-select[data-intent="invalid"] .nxt-select-control { border-color: var(--field-frame-border-invalid); }
.nxt-select[data-intent="warning"] .nxt-select-control { border-color: var(--field-frame-border-warning); }
.nxt-select[data-intent="success"] .nxt-select-control { border-color: var(--field-frame-border-success); }
.nxt-select[data-disabled="true"] .nxt-select-control {
  background: var(--field-frame-bg-disabled);
  color: var(--field-frame-fg-disabled);
  border-color: var(--field-frame-border-disabled);
  cursor: not-allowed;
  box-shadow: none;
}
.nxt-select-value-container {
  display: flex;
  align-items: center;
  gap: 0;
  min-height: calc(var(--nxt-select-height) - 2px);
  padding-inline-start: var(--nxt-select-pad-x);
  padding-inline-end: 0;
}
.nxt-select-single-value,
.nxt-select-placeholder,
.nxt-select-input {
  color: inherit;
  font-size: var(--nxt-select-font-size);
  line-height: var(--lh-normal);
}
.nxt-select-single-value {
  margin: 0;
}
.nxt-select-placeholder {
  color: var(--field-frame-placeholder);
}
.nxt-select-input {
  margin: 0;
  padding: 0;
}
.nxt-select-input input {
  color: inherit;
  font: inherit;
  margin: 0;
}
.nxt-select-indicators {
  display: inline-flex;
  align-items: center;
  align-self: stretch;
  padding-inline: var(--select-indicators-padding-inline);
  color: var(--fg-tertiary);
}
.nxt-select-dropdown-indicator {
  padding: 0;
  color: inherit;
}
.nxt-select-dropdown-indicator:hover {
  color: var(--fg-primary);
}
.nxt-select-menu {
  margin-top: var(--space-1);
  overflow: hidden;
  border: 1px solid var(--overlay-panel-border);
  border-radius: var(--overlay-panel-radius);
  background: var(--overlay-panel-bg);
  color: var(--overlay-panel-fg);
  box-shadow: var(--overlay-panel-shadow);
}
.nxt-select-portal {
  z-index: var(--z-tooltip);
}
.nxt-select-menu-list {
  max-height: 18rem;
  padding: var(--select-menu-list-padding);
}
.nxt-select-option {
  padding: var(--select-option-padding);
  color: var(--overlay-panel-fg);
  background: transparent;
  cursor: pointer;
  /* Highlight reuses the shared selection-indicator recipe (Menu pill, Tabs)
   * so the dropdown's focus/selection language matches the rest of the system
   * — neutral fills, never accent. The global prefers-reduced-motion rule
   * (globals.css) zeroes this transition. */
  border-radius: var(--selection-indicator-radius);
  transition:
    background-color var(--selection-indicator-duration) var(--selection-indicator-ease),
    color var(--selection-indicator-duration) var(--selection-indicator-ease);
}
.nxt-select-option.is-focused {
  background: var(--selection-indicator-muted-bg);
}
.nxt-select-option.is-selected {
  background: var(--selection-indicator-bg);
  color: var(--neutral-fill-fg);
}
.nxt-select-option.is-disabled {
  color: var(--fg-tertiary);
  cursor: not-allowed;
}
.nxt-select-group-heading {
  padding: var(--select-group-heading-padding);
  color: var(--eyebrow-fg);
  font-family: var(--eyebrow-font);
  font-size: var(--eyebrow-size);
  font-weight: var(--eyebrow-weight);
  letter-spacing: var(--eyebrow-tracking);
}
.nxt-select-no-options {
  padding: var(--select-no-options-padding);
  color: var(--fg-secondary);
}

/* react-select capability rendering: colour swatches, option icons, multi tags.
 * The doubled class (`.nxt-select-option.nxt-select__option`) outranks
 * react-select's runtime-injected emotion class, which sets `display: block`
 * on the option at equal specificity but later in the cascade — without this,
 * the flex layout (gap + vertical centring of the adornments) is silently lost. */
.nxt-select-option.nxt-select__option { display: flex; align-items: center; gap: var(--space-2); }
.nxt-select-single-value.nxt-select__single-value { display: inline-flex; align-items: center; gap: var(--space-2); min-width: 0; }
.nxt-select-swatch {
  flex: none;
  display: inline-block;
  /* Dot and count badge share one hardcoded 18px height (and the dot is a
   * square -> circle). Hardcoded, not a token, so the two stay identical and
   * editable without the swatch/count tokens drifting apart. */
  width: var(--select-swatch-size);
  height: var(--select-swatch-size);
  border-radius: var(--radius-full);
}
.nxt-select-count {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: var(--select-count-block-size);
  height: var(--select-count-block-size);
  padding-inline: var(--space-1);
  border-radius: var(--radius-full);
  background: var(--neutral-soft-bg);
  color: var(--neutral-soft-fg);
  font-size: var(--select-count-font-size);
  font-weight: var(--weight-medium);
  font-variant-numeric: tabular-nums;
}
.nxt-select-option-icon {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--space-4);
  height: var(--space-4);
  color: var(--fg-secondary);
}
.nxt-select-option-label,
.nxt-select-value-label,
.nxt-select-tag-label {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* Multi-select: wrapped removable tags */
.nxt-select[data-multi] .nxt-select-value-container { flex-wrap: wrap; gap: var(--space-1); }
.nxt-select-multi-value {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  padding: var(--select-multi-value-padding);
  background: var(--neutral-soft-bg);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-sm);
  font-size: var(--text-xs);
}
.nxt-select-multi-value-label { display: inline-flex; align-items: center; gap: var(--space-2); }
.nxt-select-multi-value-remove {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--select-multi-remove-size);
  height: var(--select-multi-remove-size);
  border-radius: var(--radius-sm);
  color: var(--fg-tertiary);
  cursor: pointer;
}
.nxt-select-multi-value-remove:hover { background: var(--neutral-fill); color: var(--neutral-fill-fg); }
.nxt-select-clear-indicator {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: var(--select-clear-indicator-padding);
  color: var(--fg-tertiary);
  cursor: pointer;
}
.nxt-select-clear-indicator:hover { color: var(--fg-secondary); }

/* ============================================================================
 * NumberField (extends TextInput with stepper buttons)
 * ============================================================================ */

.nxt-number-field {
  display: inline-flex;
  align-items: stretch;
}
.nxt-number-field-input {
  text-align: right;
  font-variant-numeric: tabular-nums;
  /* Hide native spinner — replaced by our stepper or omitted entirely */
  -moz-appearance: textfield;
}
.nxt-number-field-input::-webkit-outer-spin-button,
.nxt-number-field-input::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}
.nxt-number-field-steppers {
  display: inline-flex;
  flex-direction: row;
  border-inline-start: var(--field-frame-border-width) solid var(--field-frame-border);
}
/* Steppers laid out HORIZONTALLY so each button gets the full --ctrl-block-h
 * height (= 44px at md) instead of half. WCAG 2.5.5 requires 24×24 minimum
 * target size; stacked vertically the steppers fell to 28×21.5 and tripped
 * axe's target-size rule. Horizontal row gives 28×44 — comfortably above
 * the floor and easier to hit on touch. */
.nxt-number-field-step {
  display: inline-grid;
  place-items: center;
  width: 28px;
  height: 100%;
  min-width: var(--ctrl-hit-min-compact);
  min-height: var(--ctrl-hit-min-compact);
  background: var(--bg-sunken);
  color: var(--fg-secondary);
  border: 0;
  font-size: var(--text-sm);
  line-height: var(--lh-none);
  cursor: pointer;
  transition: background-color var(--dur-snap) var(--ease-snap);
}
.nxt-number-field-step + .nxt-number-field-step {
  border-inline-start: var(--field-frame-border-width) solid var(--field-frame-border);
}
.nxt-number-field-step:hover:not(:disabled) {
  background: var(--neutral-fill-hover, var(--bg-sunken));
}
.nxt-number-field-step:disabled { opacity: 0.45; cursor: not-allowed; }

/* ============================================================================
 * ErrorSummary
 *
 * Block-level focusable region. role="alert" announces on mount; tabIndex=-1
 * lets post-submit focus management land here. Links inside jump to fields.
 * ============================================================================ */

.nxt-error-summary {
  padding: var(--error-summary-padding);
  border: var(--border-width-strong) solid var(--field-frame-border-invalid);
  border-radius: var(--field-frame-radius);
  background: var(--bg-canvas);
  outline: 0;
}
.nxt-error-summary:focus-visible {
  box-shadow: var(--focus-ring-shadow);
}
.nxt-error-summary-title {
  font-family: var(--font-sans);
  /* `md` (16px) is EXACTLY body size, so this h2 did not read as a heading. This file is
     unlayered and therefore beats the `@layer base` ramp that would otherwise give an h2
     --text-2xl, which is how a heading ended up at body size behind green gates. `lg`
     (18px) clears the 1.1x type floor (17.6px) by the smallest step on the scale, which
     suits a compact summary box better than a full ramp step would. Found by the
     composition sweep's TYPE-FLOOR rule; same failure mode as nxt-kanban-column-title. */
  font-size: var(--text-lg);
  font-weight: var(--weight-medium, 500);
  color: var(--field-message-error-fg);
  margin: var(--error-summary-title-margin);
  line-height: var(--lh-heading);
}
.nxt-error-summary-list {
  margin: 0; padding: 0; list-style: none;
}
.nxt-error-summary-list > li + li { margin-top: var(--space-1); }
.nxt-error-summary-link {
  color: var(--field-message-error-fg);
  text-decoration: underline;
  text-underline-offset: 3px;
}
.nxt-error-summary-link:hover { text-decoration-thickness: 2px; }

/* ============================================================================
 * CharacterCount
 *
 * Inline tabular-numerals counter. Color flips when over the limit; aria-live
 * polite so the count is announced without interrupting current speech.
 * ============================================================================ */

.nxt-character-count {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-variant-numeric: tabular-nums;
  color: var(--field-counter-fg);
}
.nxt-character-count[data-state="over"] {
  color: var(--field-counter-invalid);
}

/* ============================================================================
 * Range / Slider
 *
 * Layout (Radix Slider primitive, Tier 2 per MANIFIESTO §11):
 *   .nxt-range                          ← grid wrapper for endpoints + readout
 *     .nxt-range-root  [Slider.Root]    ← horizontal slider region (44px hit zone)
 *       .nxt-range-track  [Slider.Track]   ← unfilled bar (--range-bg)
 *         .nxt-range-ticks                  → step tick marks (when showTicks)
 *         .nxt-range-fill  [Slider.Range]   ← filled portion (--range-fill); Radix
 *                                             computes width = (value-min)/(max-min)
 *       .nxt-range-thumb  [Slider.Thumb]   ← draggable handle; Radix computes
 *                                             left = thumb-inset-adjusted position,
 *                                             which is exactly where Slider.Range ends
 *         .nxt-range-tooltip                → floating value bubble (when showTooltip)
 *     .nxt-range-endpoints               → min/max labels (when showEndpoints)
 *     .nxt-range-readout                 → inline value readout (when showValue)
 *
 * The hand-rolled v1 painted the fill via a linear-gradient stop at raw `value%`
 * while the native input thumb sat at thumb_width/2 + value × (track − thumb).
 * They aligned only at 50%. Radix's Slider.Range and Slider.Thumb compute the
 * same inset, so they always agree — slice 2.2 of the visual-quality plan.
 *
 * Accent: neutral (default) fills with --neutral-fill (warm near-black).
 * accent="peri" swaps to --secondary (peri family) for the focused/accented
 * surfaces in the reference. Never lime — accent-restraint principle.
 * ============================================================================ */

.nxt-range {
  position: relative;
  display: grid;
  grid-template-columns: 1fr auto;
  grid-template-rows: auto 1fr auto;
  align-items: center;
  column-gap: var(--range-column-gap);
  row-gap: var(--oklch-picker-value-row-gap);
  min-width: 200px;
  min-block-size: var(--ctrl-block-h-md);
  --range-fill: var(--neutral-fill);
  --range-bg: var(--neutral-soft-bg);
  --range-thumb-bg: var(--bg-canvas);
  --range-thumb-border: var(--neutral-fill);
  /* Visible thumb diameter — sm 20 / md 24 / lg 28 px. */
  --range-thumb-size: 24px;
  /* Track stroke (height of the visible bar). */
  --range-track-h: 4px;
  --range-start-pct: 0;
  --range-end-pct: var(--range-value-pct, 0);
  --range-value-left-0: 0%;
  --range-value-left-1: var(--range-value-left-0);
}
.nxt-range[data-size="sm"] { --range-thumb-size: 20px; --range-track-h: 3px; }
.nxt-range[data-size="lg"] { --range-thumb-size: 28px; --range-track-h: 6px; }
.nxt-range[data-accent="peri"] {
  --range-fill: var(--secondary);
  --range-thumb-border: var(--secondary);
}

/* Radix Slider.Root — horizontal slider. relative-positioned so child Range and
 * Thumb anchor against it. Row 2 of the wrapper grid. */
.nxt-range-root {
  position: relative;
  grid-row: 2;
  grid-column: 1;
  display: flex;
  align-items: center;
  width: 100%;
  height: var(--ctrl-block-h-md); /* 44px hit zone for WCAG 2.5.5 Target Size */
  touch-action: none;      /* recommended by Radix for drag interactions */
  user-select: none;
  -webkit-user-select: none;
}

/* Track — unfilled bar. Radix gives it position:relative; data-orientation,
 * data-disabled. Its width is 100% of the Root. */
.nxt-range-track {
  position: relative;
  flex-grow: 1;
  height: var(--range-track-h);
  background: var(--range-bg);
  border-radius: 9999px;
  overflow: visible;       /* let ticks paint below; Range stays clipped via its own radius */
}

/* Filled portion — Radix Slider.Range. Radix positions it `left: 0; right: (100-value)%`
 * against the Root, which is raw value% wide — but Radix positions the Thumb at
 * `(value)% + thumb_half × (0.5 - value/100) × 2` so the Thumb stays inside the
 * Root's bounds at the extremes. The two don't agree.
 *
 * Bridge: shift the Range's right edge by the same thumb-in-bounds offset using
 * the live --range-value-pct (set inline in range.tsx). At value=0 we extend the
 * fill by +thumb_half (so it reaches the thumb center at left+thumb_half); at
 * value=100 we pull it in by -thumb_half (so it stops at width-thumb_half); at
 * value=50 the adjustment is zero and Radix's raw 50% lines up naturally. */
.nxt-range-fill {
  position: absolute;
  height: 100%;
  background: var(--range-fill);
  border-radius: 9999px;
  /* (value/100 - 0.5) × thumb_size  — negative at low values (extend right edge
   * outward, making fill longer), positive at high values (pull right edge in,
   * making fill shorter). Zero at midpoint where Radix already aligns. */
  margin-right: calc((var(--range-value-pct, 0) / 100 - 0.5) * var(--range-thumb-size));
}
.nxt-range[data-variant="dual"] .nxt-range-fill {
  margin-left: calc((0.5 - var(--range-start-pct, 0) / 100) * var(--range-thumb-size));
  margin-right: calc((var(--range-end-pct, 0) / 100 - 0.5) * var(--range-thumb-size));
}
.nxt-range[data-intent="invalid"] .nxt-range-fill {
  background: var(--input-border-invalid);
}

/* Multi-handle variant — N-1 colored segments fill the spaces between adjacent
 * thumbs. Default Slider.Range is hidden because it only covers min(values) to
 * max(values), so it would over-paint the outer ends. Each segment uses an
 * absolute-positioned span sized from the thumb-percentage CSS vars set by the
 * runtime. Segment colors cycle through 6 keys before repeating, scoped by
 * data-segment-index so theming can override on a per-segment basis if needed. */
.nxt-range[data-variant="multi"] .nxt-range-fill {
  display: none;
}
.nxt-range-segments {
  position: absolute;
  inset: 0;
  pointer-events: none;
}
.nxt-range-segment {
  position: absolute;
  top: 0;
  bottom: 0;
  background: var(--seg-color, var(--range-fill));
  border-radius: 9999px;
}
.nxt-range[data-variant="multi"] .nxt-range-segment[data-segment-index="0"] { --seg-color: var(--accent); }
.nxt-range[data-variant="multi"] .nxt-range-segment[data-segment-index="1"] { --seg-color: var(--secondary); }
.nxt-range[data-variant="multi"] .nxt-range-segment[data-segment-index="2"] { --seg-color: var(--accent-hover); }
.nxt-range[data-variant="multi"] .nxt-range-segment[data-segment-index="3"] { --seg-color: var(--secondary-hover); }
.nxt-range[data-variant="multi"] .nxt-range-segment[data-segment-index="4"] { --seg-color: var(--accent-outline); }
.nxt-range[data-variant="multi"] .nxt-range-segment[data-segment-index="5"] { --seg-color: var(--secondary-press); }
.nxt-range[data-variant="multi"] .nxt-range-segment[data-segment-index="6"] { --seg-color: var(--accent); }
.nxt-range[data-variant="multi"] .nxt-range-segment[data-segment-index="7"] { --seg-color: var(--secondary); }
.nxt-range[data-variant="multi"] .nxt-range-segment[data-segment-index="8"] { --seg-color: var(--accent-hover); }
.nxt-range[data-variant="multi"][data-intent="invalid"] .nxt-range-segment {
  --seg-color: var(--input-border-invalid);
}

/* Thumb — visible affordance. Radix absolute-positions it; we style the
 * surface, border, focus ring, hover/active feedback. */
.nxt-range-thumb {
  display: block !important;
  width: var(--range-thumb-size);
  height: var(--range-thumb-size);
  background: var(--range-thumb-bg);
  border: 2px solid var(--range-thumb-border);
  border-radius: 9999px;
  cursor: grab;
  outline: none;
  box-shadow: none;
  transition:
    transform 120ms cubic-bezier(0.2, 0, 0.38, 0.9),
    box-shadow var(--dur-fast) var(--ease-smooth);
}

/* Radix Slider SSR emits an inline wrapper at left:0 with the Thumb initially
 * display:none. Hydration corrects it in the app, but the static catalog and
 * SSR screenshots need the same position before JS runs. */
.nxt-range-root > span:has(> .nxt-range-thumb):nth-of-type(2) {
  left: var(--range-value-left-0, 0%) !important;
  z-index: 2;
}
.nxt-range-root > span:has(> .nxt-range-thumb):nth-of-type(3) {
  left: var(--range-value-left-1, var(--range-value-left-0, 0%)) !important;
  z-index: 3;
}
.nxt-range[data-intent="invalid"] .nxt-range-thumb {
  border-color: var(--input-border-invalid);
}

/* Hover — deepen the elevation. Skipped on touch. */
@media (hover: hover) {
  .nxt-range-thumb:hover:not([data-disabled]) {
    box-shadow: 0 0 0 6px color-mix(in oklch, var(--range-thumb-border) 8%, transparent);
  }
}

/* Focus — keyboard-only doubled ring (Radix sets :focus-visible on the thumb). */
.nxt-range-thumb:focus-visible {
  box-shadow:
    0 0 0 2px var(--bg-canvas),
    0 0 0 6px var(--focus-ring),
    0 4px 8px rgba(0, 0, 0, 0.10);
}

/* Active (press) — same tactile scale as the rest of the system. */
.nxt-range-thumb:active {
  cursor: grabbing;
  transform: scale(0.96);
  box-shadow:
    0 1px 2px rgba(0, 0, 0, 0.10),
    0 4px 8px rgba(0, 0, 0, 0.08),
    0 0 0 6px color-mix(in oklch, var(--range-thumb-border) 12%, transparent);
}

/* Disabled — Radix puts data-disabled on Root + Track + Thumb when the Slider
 * is disabled. We dim the fill + thumb border to --border-default. */
.nxt-range[data-disabled] {
  --range-fill: var(--border-default);
  --range-thumb-border: var(--border-default);
}
.nxt-range-root[data-disabled] {
  cursor: not-allowed;
}
.nxt-range-thumb[data-disabled] {
  cursor: not-allowed;
}
.nxt-range[data-disabled] .nxt-range-tooltip,
.nxt-range[data-disabled] .nxt-range-endpoints,
.nxt-range[data-disabled] .nxt-range-readout {
  opacity: 0.72;
}

/* OKLCH color picker — pointer plane plus accessible DS range/number controls. */
.nxt-oklch-picker {
  display: grid;
  gap: var(--switch-gap);
  min-width: 0;
}
.nxt-oklch-picker-header {
  display: flex;
  align-items: start;
  justify-content: space-between;
  gap: var(--oklch-picker-header-gap);
}
.nxt-oklch-picker-title {
  display: grid;
  flex: 1 1 var(--oklch-picker-title-width, 18ch);
  width: var(--oklch-picker-title-width, 18ch);
  min-width: var(--oklch-picker-title-width, 18ch);
  max-width: min(100%, var(--oklch-picker-title-width, 18ch));
  gap: var(--select-multi-value-gap);
}
.nxt-oklch-picker-label {
  color: var(--fg-primary);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  line-height: var(--lh-snug);
}
.nxt-oklch-picker-value-row {
  display: flex;
  align-items: center;
  gap: var(--oklch-picker-value-row-gap);
  min-width: 0;
}
.nxt-oklch-picker-value {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  color: var(--fg-secondary);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  line-height: var(--lh-heading);
  text-overflow: ellipsis;
  white-space: nowrap;
}
.nxt-oklch-picker-value-row .nxt-button {
  flex: 0 0 auto;
}
.nxt-oklch-picker-swatch {
  display: inline-flex;
  flex: 0 0 auto;
  width: 44px;
  height: var(--oklch-picker-swatch-block-size);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-sm);
  box-shadow: inset 0 0 0 1px color-mix(in oklab, var(--bg-canvas) 70%, transparent);
}
.nxt-oklch-picker-fixed {
  display: grid;
  gap: var(--oklch-picker-fixed-option-gap);
  grid-template-columns: repeat(auto-fit, minmax(132px, 1fr));
}
.nxt-oklch-picker-fixed-option {
  display: flex;
  align-items: center;
  gap: var(--oklch-picker-fixed-option-gap);
  width: 100%;
  min-width: 0;
  border: 1px solid var(--border-default);
  border-radius: var(--radius-sm);
  background: var(--bg-canvas);
  color: var(--fg-primary);
  padding: var(--oklch-picker-fixed-option-padding);
  text-align: left;
  cursor: pointer;
  transition:
    background-color var(--dur-snap) var(--ease-snap),
    border-color var(--dur-fast) var(--ease-smooth),
    transform var(--dur-instant) var(--ease-smooth);
}
.nxt-oklch-picker-fixed-option:hover {
  background: var(--neutral-soft-bg);
}
.nxt-oklch-picker-fixed-option[aria-checked="true"] {
  border-color: var(--fg-primary);
  background: color-mix(in oklab, var(--neutral-soft-bg) 70%, var(--bg-canvas));
}
.nxt-oklch-picker-fixed-option:focus-visible {
  outline: 2px solid var(--focus-ring);
  outline-offset: 2px;
}
.nxt-oklch-picker-fixed-option:active {
  transform: scale(0.98);
}
.nxt-oklch-picker-fixed-swatch {
  flex: 0 0 auto;
  width: var(--oklch-picker-fixed-swatch-size);
  height: var(--oklch-picker-fixed-swatch-size);
  border: 1px solid var(--border-default);
  border-radius: 9999px;
}
.nxt-oklch-picker-fixed-label {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: var(--text-sm);
  line-height: var(--lh-snug);
}
.nxt-oklch-picker-plane {
  position: relative;
  height: var(--oklch-picker-plane-block-size);
  overflow: hidden;
  border: 1px solid var(--border-default);
  border-radius: var(--radius-sm);
  cursor: crosshair;
  touch-action: none;
  user-select: none;
}
.nxt-oklch-picker-plane::after {
  position: absolute;
  inset: 0;
  content: "";
  pointer-events: none;
  background:
    linear-gradient(to top, color-mix(in oklab, var(--fg-primary) 18%, transparent), transparent 36%),
    linear-gradient(to bottom, color-mix(in oklab, var(--bg-canvas) 24%, transparent), transparent 42%);
}
.nxt-oklch-picker-plane-thumb {
  position: absolute;
  z-index: 1;
  width: var(--oklch-picker-thumb-size);
  height: var(--oklch-picker-thumb-size);
  border: 2px solid var(--bg-canvas);
  border-radius: 9999px;
  box-shadow: 0 0 0 1px var(--fg-primary);
  pointer-events: none;
  transform: translate(-50%, -50%);
}
.nxt-oklch-picker-controls {
  display: grid;
  gap: var(--oklch-picker-controls-gap);
}
.nxt-oklch-picker-range {
  min-width: 0;
}
.nxt-oklch-picker-range--hue .nxt-range-track {
  background: linear-gradient(
    to right,
    oklch(0.72 0.16 0),
    oklch(0.72 0.16 45),
    oklch(0.72 0.16 90),
    oklch(0.72 0.16 135),
    oklch(0.72 0.16 180),
    oklch(0.72 0.16 225),
    oklch(0.72 0.16 270),
    oklch(0.72 0.16 315),
    oklch(0.72 0.16 360)
  );
}
.nxt-oklch-picker-range--hue .nxt-range-fill {
  background: transparent;
}
.nxt-oklch-picker-range--chroma .nxt-range-track {
  background: linear-gradient(
    to right,
    oklch(0.72 0 var(--oklch-picker-hue)),
    var(--oklch-picker-preview)
  );
}
.nxt-oklch-picker-range--hue,
.nxt-oklch-picker-range--chroma {
  --range-fill: transparent;
  --range-thumb-border: var(--fg-primary);
}
.nxt-oklch-picker-fields {
  display: grid;
  gap: var(--oklch-picker-fields-gap);
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

/* Step ticks — pinned below the track. */
.nxt-range-ticks {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 1;
}
.nxt-range-tick {
  position: absolute;
  top: 100%;
  width: 1px;
  height: var(--range-tick-size);
  margin-top: var(--stack-gap-micro);
  background: var(--fg-tertiary);
  transform: translateX(-50%);
}

/* Floating value tooltip above the thumb. Now a child of .nxt-range-thumb,
 * so it tracks the thumb's horizontal position automatically — no inline
 * left% needed. */
/* Reserve room above the track for the floating value bubble so it stays
   inside the component box and does not clip against a short container. */
.nxt-range:has(.nxt-range-tooltip) {
  padding-block-start: var(--space-6);
}
.nxt-range-tooltip {
  position: absolute;
  bottom: var(--range-tooltip-bottom);
  left: 50%;
  transform: translateX(-50%);
  padding: var(--range-tooltip-padding);
  background: var(--bg-canvas);
  border-radius: var(--radius-sm);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-variant-numeric: tabular-nums;
  color: var(--fg-secondary);
  white-space: nowrap;
  pointer-events: none;
  z-index: 2;
  box-shadow:
    0 1px 2px rgba(0, 0, 0, 0.06),
    0 4px 8px rgba(0, 0, 0, 0.08);
}

/* Endpoints (min/max labels at track ends). */
.nxt-range-endpoints {
  grid-row: 3;
  grid-column: 1;
  display: flex;
  justify-content: space-between;
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--fg-secondary);
}

/* Inline readout (right-side current-value pill). */
.nxt-range-readout {
  grid-row: 2;
  grid-column: 2;
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-variant-numeric: tabular-nums;
  color: var(--field-counter-fg);
  min-width: 4ch;
  text-align: right;
}
.nxt-range[data-variant="dual"] .nxt-range-readout {
  min-width: 10ch;
}

@media (prefers-reduced-motion: reduce) {
  .nxt-range-thumb { transition: none; }
}

/* ============================================================================
 * Input Affix — wrapper that owns the border + focus halo while a child
 * <input> cedes its chrome. Prefix and/or suffix slots ride on the same
 * border with an interior 1px divider stroke.
 *
 * Markup:
 *   <div data-slot="affix" data-size="md" data-state="default">
 *     <span data-slot="affix-slot" data-kind="text" data-position="prefix">https://</span>
 *     <input data-slot="input" type="text" />
 *     <button data-slot="affix-slot" data-kind="button" data-position="suffix">SEND</button>
 *   </div>
 *
 * Wrapper owns: border, focus-within halo, state (default / ok / error /
 * disabled). Slots own: their bg + fg + interior divider. The inner
 * [data-slot="input"] is neutralized via descendant selector — no inline
 * style, no extra class on the input.
 * ============================================================================ */

[data-slot="affix"] {
  display: inline-flex;
  align-items: stretch;
  width: 100%;
  background: var(--field-frame-bg);
  border: var(--field-frame-border-width) solid var(--field-frame-border);
  border-radius: var(--field-frame-radius);
  overflow: hidden;
  font-family: var(--font-sans);
  transition:
    background-color var(--dur-snap) var(--ease-snap),
    border-color     var(--dur-fast) var(--ease-smooth),
    box-shadow       var(--dur-fast) var(--ease-smooth);
}
[data-slot="affix"][data-size="sm"]  { block-size: var(--ctrl-block-h-sm); }
[data-slot="affix"][data-size="md"]  { block-size: var(--ctrl-block-h-md); }
[data-slot="affix"][data-size="lg"]  { block-size: var(--ctrl-block-h-lg); }

@media (hover: hover) {
  [data-slot="affix"]:hover:not([data-disabled]) {
    border-color: var(--field-frame-border-hover);
  }
}
[data-slot="affix"]:focus-within {
  border-color: var(--field-frame-border-focus);
  box-shadow: var(--field-frame-focus-shadow);
}
[data-slot="affix"][data-state="ok"] {
  border-color: var(--field-frame-border-success);
}
[data-slot="affix"][data-state="ok"]:focus-within {
  box-shadow: 0 0 0 2px var(--bg-canvas), 0 0 0 4px var(--field-frame-border-success);
}
[data-slot="affix"][data-state="error"] {
  border-color: var(--field-frame-border-invalid);
}
[data-slot="affix"][data-state="error"]:focus-within {
  box-shadow: 0 0 0 2px var(--bg-canvas), 0 0 0 4px var(--field-frame-border-invalid);
}
[data-slot="affix"][data-disabled] {
  background: var(--field-frame-bg-disabled);
  border-color: var(--field-frame-border-disabled);
  color: var(--field-frame-fg-disabled);
  pointer-events: none;
}

/* Inner input neutralization — single descendant selector. No inline styles,
 * no helper classes on the input. The input loses its border, radius, bg,
 * and shadow when it's inside an affix wrapper. */
[data-slot="affix"] > [data-slot="input"],
[data-slot="affix"] > .nxt-input {
  flex: 1 1 0;
  min-inline-size: 0;
  height: 100%;
  border: 0 !important;
  border-radius: 0;
  background: transparent;
  box-shadow: none !important;
  padding-inline: var(--field-inline-pad-md);
  font-family: inherit;
  font-size: var(--text-sm);
  color: var(--field-frame-fg);
  outline: none;
  -webkit-appearance: none;
  appearance: none;
}
[data-slot="affix"][data-size="sm"] > [data-slot="input"],
[data-slot="affix"][data-size="sm"] > .nxt-input { padding-inline: var(--field-inline-pad-sm); }
[data-slot="affix"][data-size="lg"] > [data-slot="input"],
[data-slot="affix"][data-size="lg"] > .nxt-input { padding-inline: var(--field-inline-pad-lg); font-size: var(--text-md); }
[data-slot="affix"] > [data-slot="input"]:focus,
[data-slot="affix"] > .nxt-input:focus { box-shadow: none !important; }

/* Slot — shared base. Per-kind tone + divider painted below. */
[data-slot="affix-slot"] {
  display: inline-flex;
  align-items: center;
  flex-shrink: 0;
  padding-inline: var(--input-affix-pad-x);
  background: var(--input-affix-bg);
  color: var(--input-affix-fg);
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  user-select: none;
  white-space: nowrap;
}

/* Dividers — color tracks the wrapper's state. Prefix has a right divider;
 * suffix has a left divider. The wrapper border is the outer perimeter. */
[data-slot="affix-slot"][data-position="prefix"] { border-right: var(--field-frame-border-width) solid var(--field-frame-border); }
[data-slot="affix-slot"][data-position="suffix"] { border-left:  var(--field-frame-border-width) solid var(--field-frame-border); }
[data-slot="affix"]:focus-within > [data-slot="affix-slot"][data-position="prefix"] { border-right-color: var(--field-frame-border-focus); }
[data-slot="affix"]:focus-within > [data-slot="affix-slot"][data-position="suffix"] { border-left-color:  var(--field-frame-border-focus); }
[data-slot="affix"][data-state="ok"] > [data-slot="affix-slot"][data-position="prefix"] { border-right-color: var(--field-frame-border-success); }
[data-slot="affix"][data-state="ok"] > [data-slot="affix-slot"][data-position="suffix"] { border-left-color:  var(--field-frame-border-success); }
[data-slot="affix"][data-state="error"] > [data-slot="affix-slot"][data-position="prefix"] { border-right-color: var(--field-frame-border-invalid); }
[data-slot="affix"][data-state="error"] > [data-slot="affix-slot"][data-position="suffix"] { border-left-color:  var(--field-frame-border-invalid); }

/* Slot kinds — bg/fg recipes per the spec table. */
[data-slot="affix-slot"][data-kind="muted"]        { color: var(--input-affix-fg); font-family: var(--font-mono); font-size: var(--text-xs); letter-spacing: 0.01em; }
[data-slot="affix-slot"][data-kind="strong"] { color: var(--fg-primary);    font-weight: var(--weight-medium, 500); }
[data-slot="affix-slot"][data-kind="accent"] { color: var(--accent-soft-fg); font-weight: var(--weight-medium, 500); }

/* Button slot — interactive action. Hover lifts to --bg-raised; active sinks
 * to --bg-sunken. Focus-visible uses --focus-ring (matches Button). */
[data-slot="affix-slot"][data-kind="button"] {
  background: var(--input-affix-bg);
  color: var(--fg-primary);
  font-weight: var(--weight-medium, 500);
  font-size: var(--text-xs);
  letter-spacing: var(--track-wide);
  text-transform: uppercase;
  border: 0;
  cursor: pointer;
  transition:
    background-color var(--dur-snap) var(--ease-snap),
    color            var(--dur-fast) var(--ease-smooth),
    box-shadow       var(--dur-fast) var(--ease-smooth);
}
[data-slot="affix-slot"][data-kind="button"]:hover { background: var(--bg-raised); }
[data-slot="affix-slot"][data-kind="button"]:active { background: var(--bg-sunken); }
[data-slot="affix-slot"][data-kind="button"]:focus-visible {
  outline: 2px solid var(--field-frame-border-focus);
  outline-offset: -2px;
}

/* Select slot — native <select> styled to match the affix surface. Custom
 * caret via inline SVG background-image. */
[data-slot="affix-slot"][data-kind="select"] {
  -webkit-appearance: none;
  appearance: none;
  background-color: var(--input-affix-bg);
  /* UI Exception — svg background-image cannot reference var(); the stroke
   * color is hardcoded to oklch(0.395 0.006 80) which is the resolved value
   * of --fg-secondary in light mode. Re-evaluate when dark-mode catalog
   * baselines land — may need data-color-scheme overrides. */
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23656260' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 6l4 4 4-4'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right calc(var(--input-affix-pad-x) - 2px) center;
  background-size: 14px;
  padding-inline-end: calc(var(--input-affix-pad-x) + 18px);
  color: var(--fg-primary);
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium, 500);
  border: 0;
  cursor: pointer;
}
[data-slot="affix-slot"][data-kind="select"]:focus-visible {
  outline: 2px solid var(--field-frame-border-focus);
  outline-offset: -2px;
}

@media (prefers-reduced-motion: reduce) {
  [data-slot="affix"],
  [data-slot="affix-slot"][data-kind="button"] { transition: none; }
}

/* ============================================================================
 * Input Icon — absolutely-positioned decorative or interactive icons inside
 * an input box. The group is responsible for padding-compensation; the input
 * has no knowledge of the icons.
 *
 * Markup:
 *   <div data-slot="input-icon-group" data-size="md" data-has-left="true">
 *     <span data-slot="input-icon" data-position="left" aria-hidden="true">
 *       <svg>…</svg>
 *     </span>
 *     <input data-slot="input" type="text" />
 *     <button data-slot="input-icon" data-position="right" data-interactive="true"
 *             aria-label="Clear">
 *       <svg>…</svg>
 *     </button>
 *   </div>
 *
 * Decorative icons: pointer-events:none, aria-hidden, var(--input-icon-fg)
 * tone. Interactive icons: <button>, 32×32 hit target, hover lifts.
 * ============================================================================ */

[data-slot="input-icon-group"] {
  position: relative;
  display: inline-block;
  width: 100%;
  font-family: var(--font-sans);
}

/* Padding compensation — both authored (data-has-*) and inferred (:has()). */
[data-slot="input-icon-group"][data-has-left="true"] > [data-slot="input"],
[data-slot="input-icon-group"][data-has-left="true"] > .nxt-input,
[data-slot="input-icon-group"]:has([data-slot="input-icon"][data-position="left"]) > [data-slot="input"],
[data-slot="input-icon-group"]:has([data-slot="input-icon"][data-position="left"]) > .nxt-input {
  padding-inline-start: calc(var(--field-inline-pad-md) + var(--input-icon-pad-extra));
}
[data-slot="input-icon-group"][data-has-right="true"] > [data-slot="input"],
[data-slot="input-icon-group"][data-has-right="true"] > .nxt-input,
[data-slot="input-icon-group"]:has([data-slot="input-icon"][data-position="right"]) > [data-slot="input"],
[data-slot="input-icon-group"]:has([data-slot="input-icon"][data-position="right"]) > .nxt-input {
  padding-inline-end: calc(var(--field-inline-pad-md) + var(--input-icon-pad-extra));
}
[data-slot="input-icon-group"][data-size="sm"][data-has-left="true"] > [data-slot="input"],
[data-slot="input-icon-group"][data-size="sm"]:has([data-slot="input-icon"][data-position="left"]) > .nxt-input {
  padding-inline-start: calc(var(--field-inline-pad-sm) + var(--input-icon-pad-extra));
}
[data-slot="input-icon-group"][data-size="lg"][data-has-left="true"] > [data-slot="input"],
[data-slot="input-icon-group"][data-size="lg"]:has([data-slot="input-icon"][data-position="left"]) > .nxt-input {
  padding-inline-start: calc(var(--field-inline-pad-lg) + var(--input-icon-pad-extra));
}

/* Decorative icon — span, absolutely positioned. */
[data-slot="input-icon"]:not([data-interactive]) {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--input-icon-size);
  height: var(--input-icon-size);
  color: var(--input-icon-fg);
  pointer-events: none;
}
[data-slot="input-icon"][data-position="left"]:not([data-interactive])  { left:  var(--field-inline-pad-md); }
[data-slot="input-icon"][data-position="right"]:not([data-interactive]) { right: var(--field-inline-pad-md); }
[data-slot="input-icon-group"][data-size="sm"] > [data-slot="input-icon"][data-position="left"]:not([data-interactive])  { left:  var(--field-inline-pad-sm); }
[data-slot="input-icon-group"][data-size="sm"] > [data-slot="input-icon"][data-position="right"]:not([data-interactive]) { right: var(--field-inline-pad-sm); }
[data-slot="input-icon-group"][data-size="lg"] > [data-slot="input-icon"][data-position="left"]:not([data-interactive])  { left:  var(--field-inline-pad-lg); }
[data-slot="input-icon-group"][data-size="lg"] > [data-slot="input-icon"][data-position="right"]:not([data-interactive]) { right: var(--field-inline-pad-lg); }

[data-slot="input-icon"] svg {
  width: var(--input-icon-size);
  height: var(--input-icon-size);
  display: block;
}

/* State tints — only on decorative icons (interactive icons keep their
 * default fg + hover treatment for affordance). */
[data-slot="input-icon-group"][data-state="ok"] > [data-slot="input-icon"]:not([data-interactive])    { color: var(--input-icon-fg-ok); }
[data-slot="input-icon-group"][data-state="error"] > [data-slot="input-icon"]:not([data-interactive]) { color: var(--input-icon-fg-error); }

/* Interactive icon — <button> with 32×32 hit target. */
[data-slot="input-icon"][data-interactive="true"] {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border: 0;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--input-icon-fg);
  cursor: pointer;
  transition:
    background-color var(--dur-snap) var(--ease-snap),
    color            var(--dur-fast) var(--ease-smooth);
}
[data-slot="input-icon"][data-interactive="true"][data-position="left"]  { left:  var(--input-icon-interactive-edge-offset); }
[data-slot="input-icon"][data-interactive="true"][data-position="right"] { right: var(--input-icon-interactive-edge-offset); }
[data-slot="input-icon"][data-interactive="true"]:hover {
  color: var(--fg-primary);
  background: var(--neutral-soft-bg);
}
[data-slot="input-icon"][data-interactive="true"]:active {
  background: var(--bg-sunken);
}
[data-slot="input-icon"][data-interactive="true"]:focus-visible {
  outline: 2px solid var(--input-border-focus);
  outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {
  [data-slot="input-icon"][data-interactive="true"] { transition: none; }
}

/* ============================================================================
 * Dialog — modal overlay panel.
 *
 * Wraps @radix-ui/react-dialog. Radix manages focus trap, scroll lock,
 * escape close, click-outside, portal placement, ARIA wiring. We provide the
 * visual treatment via token-driven CSS keyed off Radix's `data-state`
 * attribute (auto-emitted: data-state="open" | "closed").
 * ============================================================================ */

/* Honor the HTML `hidden` attribute on overlay surfaces. Without this,
 * `display: flex/block` on the content/overlay classes wins on specificity
 * over the UA `[hidden] { display: none }` rule, so a `hidden` overlay still
 * paints. The standalone catalog relies on `hidden` for its closed state;
 * the React runtime also benefits when Radix portals attach `hidden` during
 * un-mount transitions. !important guards against descendant overrides
 * (e.g. data-state animations) re-asserting display. */
.nxt-dialog-overlay[hidden],
.nxt-dialog-content[hidden],
.nxt-drawer-overlay[hidden],
.nxt-drawer-content[hidden],
.nxt-popover-content[hidden],
.nxt-tooltip-content[hidden] {
  display: none !important;
}

.nxt-dialog-overlay {
  position: fixed;
  inset: 0;
  background: var(--dialog-scrim);
  z-index: var(--z-overlay);
  animation: nxt-dialog-overlay-in var(--dur-fast) var(--ease-smooth);
}
.nxt-dialog-overlay[data-state="closed"] {
  animation: nxt-dialog-overlay-out 120ms var(--ease-smooth);
}
@keyframes nxt-dialog-overlay-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes nxt-dialog-overlay-out { from { opacity: 1; } to { opacity: 0; } }

.nxt-dialog-content {
  --focus-ring-gap-color: var(--overlay-panel-bg);
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: calc(100vw - 32px);
  max-width: 480px;
  max-height: calc(100vh - 32px);
  overflow: auto;
  z-index: var(--z-overlay-panel);
  display: flex;
  flex-direction: column;
  gap: var(--dialog-content-gap);
  padding: calc(var(--overlay-panel-padding) + var(--space-2));
  background: var(--overlay-panel-bg);
  color: var(--overlay-panel-fg);
  border: 1px solid var(--overlay-panel-border);
  border-radius: var(--dialog-radius);
  box-shadow: var(--dialog-shadow);
  font-family: var(--font-sans);
  outline: none;
  animation: nxt-dialog-content-in 180ms var(--ease-smooth);
}
.nxt-dialog-content[data-size="sm"] { max-width: 360px; }
.nxt-dialog-content[data-size="lg"] { max-width: 640px; }
.nxt-dialog-content[data-state="closed"] {
  animation: nxt-dialog-content-out var(--dur-fast) var(--ease-smooth);
}
@keyframes nxt-dialog-content-in {
  from { opacity: 0; transform: translate(-50%, -48%) scale(0.96); }
  to   { opacity: 1; transform: translate(-50%, -50%) scale(1); }
}
@keyframes nxt-dialog-content-out {
  from { opacity: 1; transform: translate(-50%, -50%) scale(1); }
  to   { opacity: 0; transform: translate(-50%, -48%) scale(0.96); }
}

.nxt-dialog-header { display: flex; flex-direction: column; gap: var(--dialog-header-gap); }
.nxt-dialog-title {
  font-size: var(--text-lg, 18px);
  font-weight: var(--weight-medium, 500);
  line-height: var(--lh-heading);
  margin: 0;
  color: var(--overlay-panel-fg);
  text-wrap: balance;
}
.nxt-dialog-description {
  font-size: var(--text-sm);
  line-height: var(--lh-normal);
  color: var(--fg-secondary);
  margin: 0;
  text-wrap: pretty;
}
.nxt-dialog-footer {
  display: flex;
  flex-direction: row;
  justify-content: flex-end;
  gap: var(--dialog-footer-gap);
  margin-top: var(--stack-gap-content);
}

@media (prefers-reduced-motion: reduce) {
  .nxt-dialog-overlay,
  .nxt-dialog-content { animation: none; }
}

/* ============================================================================
 * Drawer — side sheet built on Radix Dialog. Slides from the named edge
 * (data-side) with the same easing token as Dialog/Popover (var(--ease-smooth))
 * and a slightly longer duration (220ms) to acknowledge the larger travel.
 * Inherits the overlay-panel surface treatment so modal and anchored panels
 * share the same chrome, with scrim kept as the modal-only backdrop.
 * ============================================================================ */

.nxt-drawer-overlay {
  position: fixed;
  inset: 0;
  background: var(--dialog-scrim);
  z-index: var(--z-overlay);
  animation: nxt-drawer-overlay-in 180ms var(--ease-smooth);
}
.nxt-drawer-overlay[data-state="closed"] {
  animation: nxt-drawer-overlay-out var(--dur-fast) var(--ease-smooth);
}
@keyframes nxt-drawer-overlay-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes nxt-drawer-overlay-out { from { opacity: 1; } to { opacity: 0; } }

.nxt-drawer-content {
  --focus-ring-gap-color: var(--overlay-panel-bg);
  position: fixed;
  z-index: var(--z-overlay-panel);
  display: flex;
  flex-direction: column;
  gap: var(--drawer-content-gap);
  padding: calc(var(--overlay-panel-padding) + var(--space-2));
  background: var(--overlay-panel-bg);
  color: var(--overlay-panel-fg);
  border: 1px solid var(--overlay-panel-border);
  box-shadow: var(--overlay-panel-shadow);
  font-family: var(--font-sans);
  outline: none;
  overflow: auto;
}

/* Side-anchored geometry. The non-anchored edge gets the only rounded corners
 * (matches the Dialog small-radius treatment). Cross-axis dimensions are
 * controlled by data-size; main-axis is 100% of the viewport on the anchored axis. */
.nxt-drawer-content[data-side="right"] {
  top: 0; right: 0; bottom: 0;
  border-radius: var(--dialog-radius) 0 0 var(--dialog-radius);
  animation: nxt-drawer-in-right 220ms var(--ease-smooth);
}
.nxt-drawer-content[data-side="right"][data-state="closed"] {
  animation: nxt-drawer-out-right 180ms var(--ease-smooth);
}
.nxt-drawer-content[data-side="left"] {
  top: 0; left: 0; bottom: 0;
  border-radius: 0 var(--dialog-radius) var(--dialog-radius) 0;
  animation: nxt-drawer-in-left 220ms var(--ease-smooth);
}
.nxt-drawer-content[data-side="left"][data-state="closed"] {
  animation: nxt-drawer-out-left 180ms var(--ease-smooth);
}
.nxt-drawer-content[data-side="top"] {
  top: 0; left: 0; right: 0;
  border-radius: 0 0 var(--dialog-radius) var(--dialog-radius);
  animation: nxt-drawer-in-top 220ms var(--ease-smooth);
}
.nxt-drawer-content[data-side="top"][data-state="closed"] {
  animation: nxt-drawer-out-top 180ms var(--ease-smooth);
}
.nxt-drawer-content[data-side="bottom"] {
  bottom: 0; left: 0; right: 0;
  border-radius: var(--dialog-radius) var(--dialog-radius) 0 0;
  animation: nxt-drawer-in-bottom 220ms var(--ease-smooth);
}
.nxt-drawer-content[data-side="bottom"][data-state="closed"] {
  animation: nxt-drawer-out-bottom 180ms var(--ease-smooth);
}

/* Cross-axis size (matters on left/right: width; on top/bottom: height). */
.nxt-drawer-content[data-side="right"][data-size="sm"],
.nxt-drawer-content[data-side="left"][data-size="sm"] { width: 320px; max-width: 90vw; }
.nxt-drawer-content[data-side="right"][data-size="md"],
.nxt-drawer-content[data-side="left"][data-size="md"] { width: 420px; max-width: 90vw; }
.nxt-drawer-content[data-side="right"][data-size="lg"],
.nxt-drawer-content[data-side="left"][data-size="lg"] { width: 560px; max-width: 95vw; }
.nxt-drawer-content[data-side="top"][data-size="sm"],
.nxt-drawer-content[data-side="bottom"][data-size="sm"] { height: 240px; max-height: 60vh; }
.nxt-drawer-content[data-side="top"][data-size="md"],
.nxt-drawer-content[data-side="bottom"][data-size="md"] { height: 360px; max-height: 75vh; }
.nxt-drawer-content[data-side="top"][data-size="lg"],
.nxt-drawer-content[data-side="bottom"][data-size="lg"] { height: 480px; max-height: 85vh; }
/* Full-bleed full-screen sheet — fills the viewport for full-screen mobile flows
   (e.g. mobile signature). Additive modifier, not a size value. */
.nxt-drawer-content[data-side="bottom"][data-fullscreen],
.nxt-drawer-content[data-side="top"][data-fullscreen] {
  height: 100dvh;
  max-height: 100dvh;
  border: 0;
  border-radius: 0;
  padding-inline: 0;
  padding-block-end: 0;
  gap: 0;
  overflow: hidden;
}
/* The signing surface goes edge-to-edge; header + status keep their inset. */
.nxt-drawer-content[data-fullscreen] .nxt-sheet-header,
.nxt-drawer-content[data-fullscreen] .nxt-signature-status {
  padding-inline: var(--space-5);
}

@keyframes nxt-drawer-in-right { from { transform: translateX(100%); } to { transform: translateX(0); } }
@keyframes nxt-drawer-out-right { from { transform: translateX(0); } to { transform: translateX(100%); } }
@keyframes nxt-drawer-in-left { from { transform: translateX(-100%); } to { transform: translateX(0); } }
@keyframes nxt-drawer-out-left { from { transform: translateX(0); } to { transform: translateX(-100%); } }
@keyframes nxt-drawer-in-top { from { transform: translateY(-100%); } to { transform: translateY(0); } }
@keyframes nxt-drawer-out-top { from { transform: translateY(0); } to { transform: translateY(-100%); } }
@keyframes nxt-drawer-in-bottom { from { transform: translateY(100%); } to { transform: translateY(0); } }
@keyframes nxt-drawer-out-bottom { from { transform: translateY(0); } to { transform: translateY(100%); } }

.nxt-drawer-header { display: flex; flex-direction: column; gap: var(--stack-gap-heading); }
.nxt-drawer-title { font-size: var(--text-lg); font-weight: var(--weight-medium); line-height: var(--lh-snug); margin: 0; text-wrap: balance; }
.nxt-drawer-description { color: var(--fg-secondary); font-size: var(--text-sm); line-height: var(--lh-normal); margin: 0; text-wrap: pretty; }
.nxt-drawer-footer { display: flex; flex-direction: row; justify-content: flex-end; gap: var(--action-gap); margin-top: auto; }

@media (prefers-reduced-motion: reduce) {
  .nxt-drawer-overlay,
  .nxt-drawer-content { animation: none; }
}

/* ============================================================================
 * Popover — non-modal overlay anchored to a trigger. No scrim; page below
 * stays interactive. Radix data-side / data-align mirror our variant axes.
 * ============================================================================ */

.nxt-popover-content {
  --focus-ring-gap-color: var(--overlay-panel-bg);
  z-index: var(--z-overlay);
  min-width: 200px;
  max-width: 360px;
  padding: calc(var(--overlay-panel-padding) - var(--space-1)) var(--overlay-panel-padding);
  background: var(--overlay-panel-bg);
  color: var(--overlay-panel-fg);
  border: 1px solid var(--overlay-panel-border);
  border-radius: var(--overlay-panel-radius);
  box-shadow: var(--overlay-panel-shadow);
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  line-height: var(--lh-normal);
  outline: none;
  animation: nxt-popover-in var(--dur-fast) var(--ease-smooth);
}
.nxt-popover-content[data-state="closed"] {
  animation: nxt-popover-out var(--dur-instant) var(--ease-smooth);
}
@keyframes nxt-popover-in {
  from { opacity: 0; transform: translateY(-4px); }
  to   { opacity: 1; transform: translateY(0); }
}
@keyframes nxt-popover-out {
  from { opacity: 1; transform: translateY(0); }
  to   { opacity: 0; transform: translateY(-4px); }
}
@media (prefers-reduced-motion: reduce) { .nxt-popover-content { animation: none; } }

/* ============================================================================
 * Tooltip — supplementary hint overlay. Inverted surface (dark bg / light fg).
 * Pointer-events: none — tooltips never block interaction. Radix singleton
 * mode ensures one tooltip at a time.
 * ============================================================================ */

.nxt-tooltip-content {
  --focus-ring-gap-color: var(--bg-inverse);
  z-index: var(--z-tooltip);
  padding: var(--tooltip-content-padding);
  background: var(--bg-inverse);
  color: var(--fg-inverse);
  border-radius: var(--radius-sm);
  font-family: var(--font-sans);
  font-size: var(--text-xs);
  font-weight: var(--weight-medium, 500);
  line-height: var(--lh-heading);
  max-width: 280px;
  pointer-events: none;
  box-shadow: var(--tooltip-shadow);
  animation: nxt-tooltip-in 120ms var(--ease-smooth);
}
.nxt-tooltip-content[data-state="closed"] {
  animation: nxt-tooltip-out var(--dur-instant) var(--ease-smooth);
}
@keyframes nxt-tooltip-in {
  from { opacity: 0; transform: scale(0.94); }
  to   { opacity: 1; transform: scale(1); }
}
@keyframes nxt-tooltip-out {
  from { opacity: 1; transform: scale(1); }
  to   { opacity: 0; transform: scale(0.94); }
}
@media (prefers-reduced-motion: reduce) { .nxt-tooltip-content { animation: none; } }

/* ============================================================================
 * Avatar — Tier C pure-CSS user mark. Three content modes (image / initials /
 * icon fallback) layered behind the same surface treatment. Five sizes; circle
 * (default) and square shape. Optional corner status dot. AvatarGroup stacks
 * avatars with a slight overlap and an optional "+N" overflow chip.
 * ============================================================================ */

.nxt-avatar {
  /* Optical size ramp — avatar initials are set against a fixed circle, so these
     values are chosen per box rather than from the text scale. Named here so they
     stay auditable; xs/sm coincide with the scale and alias it. */
  --avatar-font-xs: var(--text-2xs);
  --avatar-font-sm: var(--text-xs);
  --avatar-font-md: 14px;
  --avatar-font-lg: var(--text-lg);
  --avatar-font-xl: 22px;
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  color: var(--fg-secondary);
  font-family: var(--font-sans);
  font-weight: var(--weight-medium);
  letter-spacing: var(--track-snug);
  user-select: none;
  vertical-align: middle;
}

/* Content sleeve carries the clipping + fill so the parent can host
 * absolutely-positioned siblings (status dot) that overflow the circle. */
.nxt-avatar-content {
  width: 100%; height: 100%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  background: var(--avatar-bg);
  color: var(--avatar-fg);
  border-radius: inherit;
}

.nxt-avatar[data-shape="circle"] { border-radius: 9999px; }
.nxt-avatar[data-shape="square"] { border-radius: 6px; }

.nxt-avatar[data-size="xs"] { width: 24px; height: 24px; font-size: var(--avatar-font-xs); }
.nxt-avatar[data-size="sm"] { width: 32px; height: 32px; font-size: var(--avatar-font-sm); }
.nxt-avatar[data-size="md"] { width: 40px; height: 40px; font-size: var(--avatar-font-md); }
.nxt-avatar[data-size="lg"] { width: 56px; height: 56px; font-size: var(--avatar-font-lg); }
.nxt-avatar[data-size="xl"] { width: 72px; height: 72px; font-size: var(--avatar-font-xl); }

.nxt-avatar-img {
  width: 100%; height: 100%;
  object-fit: cover; object-position: center;
  display: block;
  outline: var(--image-outline);
  outline-offset: -1px;
}
.nxt-avatar-initials,
.nxt-avatar-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.nxt-avatar-icon { width: 100%; height: 100%; color: var(--fg-tertiary); }

/* Status dot — bottom-right corner. Outer ring is the page bg to lift the dot
 * off the avatar surface when status colors are close to neutral-3. */
.nxt-avatar-status {
  position: absolute;
  bottom: 0; right: 0;
  width: 28%; height: 28%;
  min-width: 8px; min-height: 8px;
  border-radius: 9999px;
  box-shadow: 0 0 0 2px var(--bg-canvas);
}
.nxt-avatar-status[data-status="online"]  { background: var(--success); }
.nxt-avatar-status[data-status="away"]    { background: var(--warning); }
.nxt-avatar-status[data-status="busy"]    { background: var(--danger); }
.nxt-avatar-status[data-status="offline"] { background: var(--fg-muted); }

.nxt-avatar[data-overflow] {
  background: var(--bg-sunken);
  color: var(--fg-secondary);
}

/* AvatarGroup — overlap stack. Hover/focus lifts the targeted avatar slightly
 * off the stack so a hovered item reads cleanly. */
.nxt-avatar-group {
  display: inline-flex;
  align-items: center;
  isolation: isolate;
}
.nxt-avatar-group > .nxt-avatar {
  border: 2px solid var(--bg-canvas);
  margin-left: -8px;
  transition: transform var(--dur-fast) var(--ease-smooth);
}
.nxt-avatar-group > .nxt-avatar:first-child { margin-left: 0; }
.nxt-avatar-group > .nxt-avatar:hover,
.nxt-avatar-group > .nxt-avatar:focus-within {
  transform: translateY(-2px);
  z-index: 1;
}

@media (prefers-reduced-motion: reduce) {
  .nxt-avatar-group > .nxt-avatar { transition: none; }
}

/* ============================================================================
 * Badge — compact, semantic-coloured tag for status / count / label.
 * Tier 1 presentational. Decorative chrome around a piece of text; no
 * keyboard or interaction logic. Three axes:
 * - intent  via data-intent: neutral | accent | success | warning | danger | info
 * - variant via data-variant: soft (default) | outline | solid
 * - size    via data-size:    sm | md (default) | lg
 * Optional .nxt-badge-dot prepends a 6px semantic-coloured dot.
 * All visuals consume the semantic alias layer.
 * ============================================================================ */

.nxt-badge {
  --badge-padding-block: 3px;
  --badge-padding-inline: 10px;
  --badge-font-size: var(--text-xs, 12px);
  display: inline-flex;
  width: fit-content; /* never fluid — shrink-wrap even when stretched by a flex/grid parent */
  align-items: center;
  gap: var(--badge-gap);
  padding: var(--badge-padding-block) var(--badge-padding-inline);
  border-radius: var(--radius-full);
  font-family: var(--font-sans);
  font-size: var(--badge-font-size);
  font-weight: var(--weight-medium, 500);
  font-variant-numeric: tabular-nums;
  line-height: var(--lh-snug);
  white-space: nowrap;
  vertical-align: middle;
  /* faint hard-edge ring for edge definition — the outline variant's
   * --border-default at 60%, so it always reads fainter than outline and
  * stays visible on the neutral-soft fill; inset so it hugs the pill */
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--border-default) 60%, transparent);
}

.nxt-badge[data-size="sm"] {
  --badge-padding-block: var(--space-1);
  --badge-padding-inline: var(--space-2);
  --badge-font-size: var(--text-2xs);
}

.nxt-badge[data-size="md"] {
  --badge-padding-block: var(--space-1);
  --badge-padding-inline: var(--space-3);
  --badge-font-size: var(--text-xs, 12px);
}

.nxt-badge[data-size="lg"] {
  --badge-padding-block: var(--space-2);
  --badge-padding-inline: var(--space-4);
  --badge-font-size: var(--text-sm, 13px);
}

.nxt-badge-dot {
  display: inline-block;
  width: var(--badge-dot-size);
  height: var(--badge-dot-size);
  border-radius: 50%;
  background: currentColor;
  flex: 0 0 auto;
}

/* soft (default) — pale tinted background, deeper text in same family */
.nxt-badge[data-variant="soft"][data-intent="neutral"]  { background: var(--neutral-soft-bg);  color: var(--neutral-soft-fg);  }
.nxt-badge[data-variant="soft"][data-intent="accent"]   { background: var(--accent-soft-bg);   color: var(--accent-soft-fg);   }
.nxt-badge[data-variant="soft"][data-intent="success"]  { background: var(--success-soft-bg);  color: var(--success-soft-fg);  }
.nxt-badge[data-variant="soft"][data-intent="warning"]  { background: var(--warning-soft-bg);  color: var(--warning-soft-fg);  }
.nxt-badge[data-variant="soft"][data-intent="danger"]   { background: var(--danger-soft-bg);   color: var(--danger-soft-fg);   }
.nxt-badge[data-variant="soft"][data-intent="info"]     { background: var(--info-soft-bg);     color: var(--info-soft-fg);     }

/* outline — transparent background, 1px border in the intent colour */
.nxt-badge[data-variant="outline"] { background: transparent; border: 1px solid var(--control-frame-muted-fill); color: var(--fg-secondary); box-shadow: none; /* border IS the boundary — no extra ring */ }
.nxt-badge[data-variant="outline"][data-intent="accent"]   { border-color: var(--accent-outline);  color: var(--accent-soft-fg); }
.nxt-badge[data-variant="outline"][data-intent="success"]  { border-color: var(--success);         color: var(--success-soft-fg); }
.nxt-badge[data-variant="outline"][data-intent="warning"]  { border-color: var(--warning);         color: var(--warning-soft-fg); }
.nxt-badge[data-variant="outline"][data-intent="danger"]   { border-color: var(--danger-outline);  color: var(--danger-soft-fg); }
.nxt-badge[data-variant="outline"][data-intent="info"]     { border-color: var(--info);            color: var(--info-soft-fg); }

/* solid — strong intent fill with foreground-on-fill text */
.nxt-badge[data-variant="solid"][data-intent="neutral"]   { background: var(--neutral-fill);  color: var(--neutral-fill-fg); }
.nxt-badge[data-variant="solid"][data-intent="accent"]    { background: var(--accent);        color: var(--accent-fg);       }
.nxt-badge[data-variant="solid"][data-intent="success"]   { background: var(--success);       color: var(--success-fg);      }
.nxt-badge[data-variant="solid"][data-intent="warning"]   { background: var(--warning);       color: var(--warning-fg);      }
.nxt-badge[data-variant="solid"][data-intent="danger"]    { background: var(--danger);        color: var(--danger-fg);       }
.nxt-badge[data-variant="solid"][data-intent="info"]      { background: var(--info);          color: var(--info-fg);         }

/* ============================================================================
 * Corner label — icon-only folded-corner flag.
 * Tier 1 presentational, overlay only: host must be position:relative
 * (+ overflow:hidden if rounded). A square box (side = --corner-label-size-*)
 * anchored flush to a corner is clipped to a right triangle pointing inward;
 * the icon sits near the outer right-angle vertex. All dimensions/colours are
 * token-backed; the only literals are intrinsic clip-path polygon coordinates.
 * ============================================================================ */
.nxt-corner-label {
  position: absolute;
  inset-block-start: 0;
  inline-size: var(--corner-label-size-md);
  block-size: var(--corner-label-size-md);
  display: block;
  pointer-events: none;
  background: var(--accent);
  color: var(--accent-fg);
}

/* size axis — triangle leg */
.nxt-corner-label[data-size="sm"] { inline-size: var(--corner-label-size-sm); block-size: var(--corner-label-size-sm); }
.nxt-corner-label[data-size="md"] { inline-size: var(--corner-label-size-md); block-size: var(--corner-label-size-md); }
.nxt-corner-label[data-size="lg"] { inline-size: var(--corner-label-size-lg); block-size: var(--corner-label-size-lg); }

/* position axis — flush to a corner, hypotenuse facing inward */
.nxt-corner-label[data-position="top-right"] { inset-inline-end: 0; clip-path: polygon(0 0, 100% 0, 100% 100%); }
.nxt-corner-label[data-position="top-left"]  { inset-inline-start: 0; clip-path: polygon(0 0, 100% 0, 0 100%); }

/* intent axis — solid fill + on-fill foreground (same aliases as badge solid) */
.nxt-corner-label[data-intent="neutral"] { background: var(--neutral-fill); color: var(--neutral-fill-fg); }
.nxt-corner-label[data-intent="accent"]  { background: var(--accent);  color: var(--accent-fg); }
.nxt-corner-label[data-intent="success"] { background: var(--success); color: var(--success-fg); }
.nxt-corner-label[data-intent="warning"] { background: var(--warning); color: var(--warning-fg); }
.nxt-corner-label[data-intent="danger"]  { background: var(--danger);  color: var(--danger-fg); }
.nxt-corner-label[data-intent="info"]    { background: var(--info);    color: var(--info-fg); }

/* icon — sized by token, placed near the outer right-angle vertex.
 * Offsets are per-size calc() on the size token (a fixed icon is a larger
 * fraction of a smaller box; ratios keep the glyph inside the triangle). */
.nxt-corner-label-icon {
  position: absolute;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  inline-size: var(--corner-label-icon-md);
  block-size: var(--corner-label-icon-md);
  color: inherit;
}
.nxt-corner-label[data-size="sm"] .nxt-corner-label-icon { inline-size: var(--corner-label-icon-sm); block-size: var(--corner-label-icon-sm); inset-block-start: calc(var(--corner-label-size-sm) * 0.06); }
.nxt-corner-label[data-size="md"] .nxt-corner-label-icon { inset-block-start: calc(var(--corner-label-size-md) * 0.11); }
.nxt-corner-label[data-size="lg"] .nxt-corner-label-icon { inline-size: var(--corner-label-icon-lg); block-size: var(--corner-label-icon-lg); inset-block-start: calc(var(--corner-label-size-lg) * 0.17); }

.nxt-corner-label[data-size="sm"][data-position="top-right"] .nxt-corner-label-icon { inset-inline-end: calc(var(--corner-label-size-sm) * 0.06); }
.nxt-corner-label[data-size="md"][data-position="top-right"] .nxt-corner-label-icon { inset-inline-end: calc(var(--corner-label-size-md) * 0.11); }
.nxt-corner-label[data-size="lg"][data-position="top-right"] .nxt-corner-label-icon { inset-inline-end: calc(var(--corner-label-size-lg) * 0.17); }
.nxt-corner-label[data-size="sm"][data-position="top-left"]  .nxt-corner-label-icon { inset-inline-start: calc(var(--corner-label-size-sm) * 0.06); }
.nxt-corner-label[data-size="md"][data-position="top-left"]  .nxt-corner-label-icon { inset-inline-start: calc(var(--corner-label-size-md) * 0.11); }
.nxt-corner-label[data-size="lg"][data-position="top-left"]  .nxt-corner-label-icon { inset-inline-start: calc(var(--corner-label-size-lg) * 0.17); }

.nxt-corner-label-icon > svg { inline-size: 100%; block-size: 100%; display: block; }

/* ============================================================================
 * Weather — decorative SVG weather glyph.
 * Tier 1 presentational. Stroke uses currentColor so the consuming context
 * controls the colour. Three axes:
 * - condition via data-condition: sunny | cloudy | partly-cloudy | rain |
 *                                 snow | hail | storm | fog | wind | clear-night
 * - size      via data-size:      sm (16px) | md (24px, default) | lg (32px) | xl (48px)
 * - tone      via data-tone:      inherit (default — no declaration) | accent | muted
 * All visuals consume the semantic alias layer.
 * ============================================================================ */

.nxt-weather {
  display: inline-block;
  flex: 0 0 auto;
  vertical-align: middle;
}
.nxt-weather[data-size="sm"] { width: 16px; height: 16px; }
.nxt-weather[data-size="md"] { width: 24px; height: 24px; }
.nxt-weather[data-size="lg"] { width: 32px; height: 32px; }
.nxt-weather[data-size="xl"] { width: 48px; height: 48px; }

/* tone=inherit declares nothing — currentColor wins. */
.nxt-weather[data-variant="accent"] { color: var(--secondary-press); }
.nxt-weather[data-variant="muted"]  { color: var(--fg-tertiary); }

/* ============================================================================
 * Time — live-updating digital + analog clock primitives.
 * Tier 1 presentational. Two named exports (TimeTile + TimeAnalog) share
 * a colour axis (variant: outline / ink / peri / sand / basic) and a size
 * ladder (xs / sm / md / lg) but emit very different DOM:
 *
 *  - .nxt-time-digital  : Barlow GX 24-hour readout with optional tz label
 *  - .nxt-time-analog   : Mondaine watch face with 4-dot markers + hands
 *
 * Hand rotation in analog mode is driven by an inline --hand-rotation
 * custom property on each .nxt-time-hand element; the React runtime
 * sets it from state, the kitchen-sink hardcodes 10:10 for the static
 * catalog render. All visuals consume the semantic alias layer.
 * ============================================================================ */

.nxt-time {
  position: relative;
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  font-family: "Barlow", var(--font-sans);
  user-select: none;
}

/* ── Shared variant surfaces (digital + analog) ─────────────────────── */
.nxt-time[data-variant="outline"] {
  background: transparent;
  color: var(--fg-primary);
  border: 1px solid var(--border-default);
}
.nxt-time[data-variant="ink"] {
  background: var(--neutral-fill);
  color: var(--neutral-fill-fg);
}
.nxt-time[data-variant="peri"] {
  background: var(--secondary-soft-bg);
  color: var(--secondary-soft-fg);
}
.nxt-time[data-variant="sand"] {
  background: var(--neutral-soft-bg);
  color: var(--neutral-soft-fg);
}
.nxt-time[data-variant="basic"] {
  background: var(--bg-surface);
  color: var(--fg-primary);
  border: 1px solid var(--border-subtle);
}

/* ── Digital style ──────────────────────────────────────────────────── */
.nxt-time-digital {
  border-radius: var(--radius-sm);
  padding: var(--space-3) var(--space-4);
}
.nxt-time-digital[data-size="lg"] { width: 240px; }
.nxt-time-digital[data-size="md"] { width: 176px; padding: var(--space-2) var(--space-3); }
.nxt-time-digital[data-size="sm"] { width: 120px; padding: var(--space-2) var(--space-3); }
.nxt-time-digital[data-size="xs"] { width: 80px;  padding: var(--space-2); }

.nxt-time-digital[data-variant="basic"] {
  /* basic is the minimal-chrome variant — no padding, no border, just type */
  padding: 0;
  border: none;
  background: transparent;
}

.nxt-time-readout {
  /* Optical readout ramp — digit sizes are chosen against each dial's fixed box,
     not from the text scale. Named here so they stay auditable. */
  --time-readout-size-xs: 30px;
  --time-readout-size-sm: 46px;
  --time-readout-size-md: 68px;
  --time-readout-size-lg: 96px;
  display: block;
  font-feature-settings: "tnum" 1;
  font-variant-numeric: tabular-nums;
  font-variation-settings: var(--font-var-time-readout);
  line-height: var(--lh-display);
  letter-spacing: var(--track-tight);
}
.nxt-time-digital[data-size="lg"] .nxt-time-readout { font-size: var(--time-readout-size-lg); }
.nxt-time-digital[data-size="md"] .nxt-time-readout { font-size: var(--time-readout-size-md); }
.nxt-time-digital[data-size="sm"] .nxt-time-readout { font-size: var(--time-readout-size-sm); }
.nxt-time-digital[data-size="xs"] .nxt-time-readout { font-size: var(--time-readout-size-xs); }

.nxt-time-tz {
  display: block;
  margin-top: 6px; /* intentional: off-grid optical gap under the large clock readout */
  font-family: var(--font-mono);
  font-size: var(--text-xs, 12px);
  font-weight: var(--weight-medium, 500);
  letter-spacing: var(--track-caps);
  text-transform: uppercase;
  opacity: 0.75;
}
.nxt-time-digital[data-size="xs"] .nxt-time-tz { font-size: 10px; margin-top: var(--space-1); }

/* ── Analog style ───────────────────────────────────────────────────── */
.nxt-time-analog {
  border-radius: 50%;
  padding: 0;
}
.nxt-time-analog[data-size="lg"] { width: 200px; height: 200px; }
.nxt-time-analog[data-size="md"] { width: 160px; height: 160px; }
.nxt-time-analog[data-size="sm"] { width: 120px; height: 120px; }
.nxt-time-analog[data-size="xs"] { width: 80px;  height: 80px; }

/* basic + analog: keep the circular geometry but drop the surface chrome */
.nxt-time-analog[data-variant="basic"] {
  background: transparent;
  border: 1px solid var(--border-subtle);
}

/* 4-dot markers absolutely positioned around the face. */
.nxt-time-markers {
  position: absolute;
  inset: 0;
  pointer-events: none;
}
.nxt-time-marker {
  position: absolute;
  width: var(--time-marker-size);
  height: var(--time-marker-size);
  border-radius: 50%;
  background: currentColor;
  opacity: 0.85;
  transform: translate(-50%, -50%);
}
.nxt-time-marker[data-pos="12"] { top: 8%;  left: 50%; }
.nxt-time-marker[data-pos="3"]  { top: 50%; left: 92%; }
.nxt-time-marker[data-pos="6"]  { top: 92%; left: 50%; }
.nxt-time-marker[data-pos="9"]  { top: 50%; left: 8%;  }
.nxt-time-analog[data-size="xs"] .nxt-time-marker { width: 5px; height: 5px; }
.nxt-time-analog[data-size="sm"] .nxt-time-marker { width: 6px; height: 6px; }

/* Center pivot dot — sits on top of the hand stack. */
.nxt-time-pivot {
  position: absolute;
  top: 50%;
  left: 50%;
  width: var(--time-pivot-size);
  height: var(--time-pivot-size);
  border-radius: 50%;
  background: currentColor;
  transform: translate(-50%, -50%);
  z-index: 3;
}
.nxt-time-analog[data-size="sm"] .nxt-time-pivot { width: 7px; height: 7px; }
.nxt-time-analog[data-size="xs"] .nxt-time-pivot { width: 5px; height: 5px; }

/* Hands — absolutely centered, rotate around their bottom end (the pivot).
 * Width controls the visual weight: hour 4px, minute 3px, second 2px.
 * The hand "extends upward" from the center; transform-origin is bottom
 * center so rotation pivots at the dial center.
 */
.nxt-time-hand {
  position: absolute;
  left: 50%;
  bottom: 50%;
  transform-origin: 50% 100%;
  transform: translateX(-50%) rotate(var(--hand-rotation, 0deg));
  border-radius: 2px;
  background: currentColor;
}
.nxt-time-hand[data-hand="hour"]   { width: 4px; height: 28%; z-index: 1; }
.nxt-time-hand[data-hand="minute"] { width: 3px; height: 40%; z-index: 2; }
.nxt-time-hand[data-hand="second"] { width: 2px; height: 44%; z-index: 2; background: var(--danger); }
.nxt-time-analog[data-size="xs"] .nxt-time-hand[data-hand="hour"]   { width: 3px; }
.nxt-time-analog[data-size="xs"] .nxt-time-hand[data-hand="minute"] { width: 2px; }
.nxt-time-analog[data-size="xs"] .nxt-time-hand[data-hand="second"] { width: 1px; }

/* Reduced motion: hands snap into their static rotation; no transition
 * to suggest live motion. */
@media (prefers-reduced-motion: reduce) {
  .nxt-time-hand { transition: none; }
}

/* ────────────────────────────────────────────────────────────────────────
 * ButtonGroup — Tier 2 wrapper over @radix-ui/react-toggle-group. Segmented
 * pill row; one item selected (single) or any subset (multiple). Single mode
 * uses useMovingIndicator for the canonical sliding selected segment.
 * ──────────────────────────────────────────────────────────────────────── */
.nxt-button-group {
  display: inline-flex;
  align-items: stretch;
  gap: 0;
  padding: var(--button-group-padding);
  background: var(--selection-indicator-muted-bg);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-md);
  isolation: isolate;
  position: relative;
  /* Runtime bridge vars for the sliding indicator (set by useMovingIndicator). */
  --indicator-x: 0px;
  --indicator-y: 0px;
  --indicator-w: 0px;
  --indicator-h: 0px;
}
/* Sliding indicator — the highlight that travels to the active segment.
 * Decorative (aria-hidden); geometry comes from useMovingIndicator measuring
 * the [data-state="on"] item. Single-select only (data-sliding="true"); in
 * multiple mode each on-item keeps its own static --bg-on (no single target). */
.nxt-button-group-indicator {
  position: absolute;
  left: 0;
  top: 0;
  width: var(--indicator-w, 0px);
  height: var(--indicator-h, 0px);
  transform: translate3d(var(--indicator-x, 0px), var(--indicator-y, 0px), 0);
  border-radius: var(--nav-item-radius);
  background: var(--selection-indicator-surface);
  pointer-events: none;
  z-index: 0;
  transition:
    transform var(--motion-indicator-duration) var(--motion-indicator-ease),
    width var(--motion-indicator-duration) var(--motion-indicator-ease),
    height var(--motion-indicator-duration) var(--motion-indicator-ease),
    background var(--motion-indicator-duration) var(--motion-indicator-ease);
}
@media (prefers-reduced-motion: reduce) {
  .nxt-button-group-indicator { transition: none; }
}
.nxt-button-group-item {
  --bg-on: var(--selection-indicator-surface);
  --fg-on: var(--fg-primary);
  appearance: none;
  -webkit-appearance: none;
  border: 0;
  background: transparent;
  color: var(--nav-item-fg);
  padding: var(--space-2) var(--space-3);
  font-size: var(--text-md);
  font-weight: var(--weight-medium);
  line-height: var(--lh-none);
  cursor: pointer;
  border-radius: var(--nav-item-radius);
  transition:
    background var(--dur-snap) var(--ease-snap),
    color var(--dur-snap) var(--ease-snap);
  min-height: var(--ctrl-block-h-sm);
  position: relative;
  z-index: 1;
}
.nxt-button-group[data-size="sm"] .nxt-button-group-item {
  padding: var(--space-1) var(--space-2);
  font-size: var(--text-sm);
  min-height: var(--ctrl-block-h-sm);
}
.nxt-button-group[data-size="md"] .nxt-button-group-item {
  min-height: var(--ctrl-block-h-md);
}
.nxt-button-group[data-size="lg"] .nxt-button-group-item {
  padding: var(--space-2) var(--space-4, 16px);
  font-size: var(--text-lg);
  min-height: var(--ctrl-block-h-lg);
}
.nxt-button-group-item:hover:not(:disabled):not([data-state="on"]) {
  color: var(--nav-item-fg-hover);
  background: var(--selection-indicator-surface);
}
.nxt-button-group-item:focus-visible {
  outline: 2px solid var(--focus-ring);
  outline-offset: 2px;
}
.nxt-button-group-item[data-state="on"] {
  color: var(--fg-on);
}
/* Multiple-select keeps the static per-item fill (no single slide target).
 * Single-select (data-sliding) lets the travelling indicator show through. */
.nxt-button-group:not([data-sliding="true"]) .nxt-button-group-item[data-state="on"] {
  background: var(--bg-on);
}
.nxt-button-group-item:disabled {
  cursor: not-allowed;
  opacity: 0.5;
}
@media (prefers-reduced-motion: reduce) {
  .nxt-button-group-item { transition: none; }
}
@media (hover: none) {
  .nxt-button-group[data-size="sm"] .nxt-button-group-item::before {
    content: "";
    position: absolute;
    inset-block: var(--button-group-sm-hit-target-outset-block);
    inset-inline: 0;
  }
}

/* ────────────────────────────────────────────────────────────────────────
 * WeatherTile — Tier 2 data-display tile, sibling of Date Tile.
 *
 * Reference: audits/references/weather-tile/project/Weather Component.html
 * (claude.ai/design handoff bundle ingested 2026-05-27).
 *
 * Layout: 3fr numbers / auto hairline / 2fr icon (default variant).
 * Solo variant short-circuits to a single 4:3 landscape row showing only
 * the hero temperature.
 *
 * Typography is BarlowGX (variable font ships at /fonts/BarlowGX.woff2).
 * Axis settings — temp: 'wght' 108, 'wdth' 457; range: 'wght' 111, 'wdth' 457.
 *
 * Colorways translate the bundle's clay-/lime-/peri- raw scale to this
 * project's OKLCH neutral + accent aliases:
 *   - ink      → --neutral-12 (warm near-black surface, white ink)
 *   - ink-lime → ink surface, accent (lime) numerals
 *   - lime     → --accent surface, ink on lime
 *   - peri     → --accent-2 surface, white ink
 *   - sand     → --neutral-11 surface, white ink
 *   - earthy   → --neutral-7 surface, white ink
 *   - outline  → --bg-canvas surface, --border-default 1px, ink on light
 *   - basic    → transparent, no chrome
 * ──────────────────────────────────────────────────────────────────────── */

@font-face {
  font-family: 'BarlowGX';
  src: url('/fonts/BarlowGX.woff2') format('woff2-variations'),
       url('/fonts/BarlowGX.woff2') format('woff2');
  font-weight: 22 188;
  font-stretch: 300% 500%;
  font-style: normal;
  font-display: swap;
}

/* `--surface` is a WeatherTile-scope local custom property used by the
 * inline SVG icon module's cloud-knock-out paths to match the tile's
 * own background colour. The static token-resolve gate needs to see a
 * top-level declaration; the actual value used at render time comes
 * from the .nxt-weather-tile colorway override that cascades into the
 * nested <svg>. Defaulting to --bg-surface is a sensible fallback for
 * any consumer that uses an icon outside a .nxt-weather-tile context. */
:root {
  --surface: var(--bg-surface);
}

.nxt-weather-tile {
  --tile-w: 240px;
  --tile-h: 320px;
  --ink: var(--neutral-1);
  --surface: var(--neutral-12);
  --accent-ink: var(--ink);
  --pad-x: var(--space-5);
  --pad-y: var(--space-4);
  --temp-size: 128px;
  --range-size: 29px;
  --icon-size: 113px;
  --gap-temp-range: 18px;
  --pad-top: 14px;
  --temp-var: var(--font-var-weather-temp);
  --range-var: var(--font-var-weather-range);
  --tile-radius: var(--radius-md);

  display: grid;
  grid-template-rows: 3fr auto 2fr;
  row-gap: 0;
  width: var(--tile-w);
  height: var(--tile-h);
  padding: var(--pad-y) var(--pad-x);
  background: var(--surface);
  color: var(--ink);
  border-radius: var(--tile-radius);
  font-family: 'BarlowGX', 'Barlow', system-ui, sans-serif;
  font-optical-sizing: auto;
  user-select: none;
  box-sizing: border-box;
}

.nxt-weather-tile .top {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding-bottom: var(--pad-top);
}
.nxt-weather-tile .t {
  font-size: var(--temp-size);
  line-height: var(--lh-display);
  font-variation-settings: var(--temp-var);
  letter-spacing: var(--track-snug);
  margin: 0 0 var(--gap-temp-range) 0;
  font-variant-numeric: tabular-nums;
  color: var(--accent-ink);
  display: inline-flex;
  align-items: flex-start;
}
.nxt-weather-tile .t .u {
  /* intentional: relative by design — the unit scales with the temperature digit
     it sits against, so it must not consume a fixed step of the text scale. */
  font-size: 0.36em;
  line-height: var(--lh-none);
  font-variation-settings: var(--range-var);
  margin-top: 0.18em;
  margin-left: 0.04em;
  opacity: 0.55;
}
.nxt-weather-tile .r {
  font-size: var(--range-size);
  line-height: var(--lh-none);
  font-variation-settings: var(--range-var);
  letter-spacing: var(--track-tight);
  margin: 0;
  color: inherit;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  opacity: 0.88;
  display: inline-flex;
  align-items: center;
  gap: var(--weather-tile-gap);
}
.nxt-weather-tile .r .vsep {
  display: inline-block;
  width: 1px;
  height: 0.78em;
  background: currentColor;
  opacity: 0.35;
}

.nxt-weather-tile .rule {
  height: var(--hairline-size);
  width: 100%;
  background: currentColor;
  opacity: 0.18;
}

.nxt-weather-tile .ic {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  color: inherit;
}
.nxt-weather-tile .ic svg {
  width: var(--icon-size);
  height: var(--icon-size);
  display: block;
}

/* ── Colorways ─────────────────────────────────────────────────────────── */
.nxt-weather-tile.ink {
  --ink: var(--neutral-1);
  --surface: var(--neutral-12);
  --accent-ink: var(--ink);
}
.nxt-weather-tile.ink-lime {
  --ink: var(--neutral-1);
  --surface: var(--neutral-12);
  --accent-ink: var(--accent);
}
.nxt-weather-tile.lime {
  --ink: var(--neutral-12);
  --surface: var(--accent);
  --accent-ink: var(--ink);
}
.nxt-weather-tile.peri {
  --ink: var(--neutral-1);
  --surface: var(--secondary);
  --accent-ink: var(--ink);
}
.nxt-weather-tile.sand {
  --ink: var(--neutral-1);
  --surface: var(--neutral-11);
  --accent-ink: var(--ink);
}
.nxt-weather-tile.earthy {
  /* WCAG AA fix: --neutral-7 surface fails 4.5:1 against white text. Per
   * ADR-075 the bundle's earthy colorway ships with marginal contrast
   * (white text on a mid-warm-neutral). We use ink on light here so the
   * tile passes axe-core color-contrast on the range text (21px, normal
   * weight — not "large text" per WCAG). Surface tone stays bundle-true. */
  --ink: var(--neutral-12);
  --surface: var(--neutral-7);
  --accent-ink: var(--ink);
}
.dark .nxt-weather-tile.earthy {
  --ink: var(--neutral-1);
  --accent-ink: var(--ink);
}
.nxt-weather-tile.outline {
  --ink: var(--neutral-12);
  --surface: var(--bg-canvas);
  --accent-ink: var(--ink);
  border: 1px solid var(--border-default);
}
.nxt-weather-tile.basic {
  --ink: var(--neutral-12);
  --surface: transparent;
  --accent-ink: var(--ink);
  border: none;
  --pad-y: var(--space-2);
  padding: var(--pad-y) var(--pad-x);
}

/* ── Size ladder ──────────────────────────────────────────────────────── */
.nxt-weather-tile.md {
  --tile-w: 176px;
  --tile-h: 232px;
  --pad-x: var(--space-4);
  --pad-y: var(--space-3);
  --temp-size: 93px;
  --range-size: 21px;
  --icon-size: 82px;
  --gap-temp-range: 13px;
  --pad-top: 10px;
  --tile-radius: 3px;
}
.nxt-weather-tile.sm {
  --tile-w: 120px;
  --tile-h: 160px;
  --pad-x: var(--space-3);
  --pad-y: var(--space-2);
  --temp-size: 64px;
  --range-size: 15px;
  --icon-size: 57px;
  --gap-temp-range: 9px;
  --pad-top: 7px;
  --tile-radius: var(--radius-sm);
}
.nxt-weather-tile.xs {
  --tile-w: 80px;
  --tile-h: 108px;
  --pad-x: var(--space-2);
  --pad-y: 6px;
  --temp-size: 43px;
  --range-size: 10px;
  --icon-size: 38px;
  --gap-temp-range: 6px;
  --pad-top: var(--tabs-pill-top);
  --tile-radius: var(--radius-sm);
}

/* ── Solo variant (temperature only, 4:3 landscape) ───────────────────── */
.nxt-weather-tile.solo {
  --tile-h: 180px;
  height: var(--weather-tile-solo-block-size-lg);
  grid-template-rows: 1fr;
}
.nxt-weather-tile.solo.md { --tile-h: 132px; height: 132px; }
.nxt-weather-tile.solo.sm { --tile-h: 90px;  height: 90px;  }
.nxt-weather-tile.solo.xs { --tile-h: 60px;  height: 60px;  }
.nxt-weather-tile.solo .top  { padding-bottom: 0; }
.nxt-weather-tile.solo .t    { margin-bottom: 0; }
.nxt-weather-tile.solo .r,
.nxt-weather-tile.solo .rule,
.nxt-weather-tile.solo .ic   { display: none; }

/* ── Verbose variant (editorial weather surface) ───────────────────── */
.nxt-weather-tile.verbose {
  --tile-w: 280px;
  --tile-h: 360px;
  --pad-x: var(--space-5);
  --pad-y: var(--space-5);
  --temp-size: var(--text-5xl);
  --icon-size: var(--space-7);
  --tile-radius: var(--radius-md);
  --tile-shadow: var(--shadow-md);
  --border-width: var(--field-frame-border-width);
  --degree-size: 0.36em;
  --tile-gap: var(--space-4);

  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: var(--tile-gap);
  width: var(--tile-w);
  height: var(--tile-h);
  padding: var(--pad-y) var(--pad-x);
  border-radius: var(--tile-radius);
  box-shadow: var(--tile-shadow);
}

.nxt-weather-tile.verbose.md {
  --tile-w: 232px;
  --tile-h: 300px;
}

.nxt-weather-tile.verbose.sm {
  --tile-w: 200px;
  --tile-h: 260px;
}

.nxt-weather-tile.verbose.xs {
  --tile-w: 168px;
  --tile-h: 208px;
}

.nxt-weather-tile.verbose .eyebrow {
  font-size: var(--text-xs);
  line-height: var(--lh-normal);
  font-variation-settings: var(--font-wght-barlow-semibold);
  font-synthesis: none;
  letter-spacing: var(--track-caps);
  text-transform: uppercase;
  opacity: 0.7;
  margin: 0;
}

.nxt-weather-tile.verbose .hero {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}

.nxt-weather-tile.verbose .vi {
  width: var(--icon-size);
  height: var(--icon-size);
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--accent-ink);
}

.nxt-weather-tile.verbose .tv {
  display: flex;
  flex-direction: column;
}

.nxt-weather-tile.verbose .t {
  font-size: var(--temp-size);
  line-height: var(--lh-tight);
  font-variation-settings: var(--temp-var);
  letter-spacing: var(--track-snug);
  margin: 0;
  font-variant-numeric: tabular-nums;
  color: var(--accent-ink);
  display: inline-flex;
  align-items: flex-start;
}

.nxt-weather-tile.verbose .t .u {
  font-size: var(--degree-size);
  line-height: var(--lh-tight);
  margin-top: 0;
  margin-left: 0;
  opacity: 0.55;
}

.nxt-weather-tile.verbose .cl {
  margin: 0;
  font-size: var(--text-base);
  line-height: var(--lh-tight);
  font-variation-settings: var(--font-wght-barlow-medium);
  font-synthesis: none;
  letter-spacing: var(--track-snug);
  color: var(--ink);
}

.nxt-weather-tile.verbose .rule {
  height: var(--border-width);
  width: 100%;
  opacity: 0.16;
}

.nxt-weather-tile.verbose .ic {
  width: 100%;
  height: 100%;
  color: inherit;
  display: block;
}
.nxt-weather-tile.verbose .ic svg {
  width: 100%;
  height: 100%;
  display: block;
}

.nxt-weather-tile.verbose .metrics {
  display: flex;
  align-items: stretch;
  justify-content: space-between;
  gap: var(--space-4);
}

.nxt-weather-tile.verbose .m {
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}

.nxt-weather-tile.verbose .mk {
  margin: 0;
  font-size: var(--text-xs);
  line-height: var(--lh-normal);
  font-variation-settings: var(--font-wght-barlow-semibold);
  font-synthesis: none;
  letter-spacing: var(--track-caps);
  text-transform: uppercase;
  /* WCAG AA fix: opacity 0.55 de-emphasis blended these 12px labels to 4.41:1
   * on the ink colorway's light panel in dark scheme (brand minimum is 4.5:1).
   * Mixing ink toward surface keeps the same visual register per colorway
   * while the blend stays an explicit, checkable color. */
  color: color-mix(in srgb, var(--ink) 58%, var(--surface));
}

.nxt-weather-tile.verbose .mv {
  margin: 0;
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  line-height: var(--lh-tight);
}

/* Keep verbose colorway behavior identical to default; this rule restores the
   base transparent/chrome handling that colorway classes may change. */
.nxt-weather-tile.verbose.basic,
.nxt-weather-tile.verbose.ink-lime,
.nxt-weather-tile.verbose.lime,
.nxt-weather-tile.verbose.peri,
.nxt-weather-tile.verbose.sand,
.nxt-weather-tile.verbose.earthy,
.nxt-weather-tile.verbose.outline,
.nxt-weather-tile.verbose.ink {
  --pad-y: var(--space-5);
  --pad-x: var(--space-5);
  padding: var(--pad-y) var(--pad-x);
  border: none;
}

.nxt-weather-tile.verbose.outline { border: 1px solid var(--border-default); }

/* ── Icon animations ──────────────────────────────────────────────────── */
@keyframes wi-spin  { to { transform: rotate(360deg); } }
@keyframes wi-bob   { 0%,100% { transform: translateY(0); } 50% { transform: translateY(-1.2px); } }
@keyframes wi-fall  { 0% { transform: translateY(-3px); opacity: 0; } 25% { opacity: 1; } 80% { opacity: 1; } 100% { transform: translateY(9px); opacity: 0; } }
@keyframes wi-flash { 0%,90%,100% { opacity: 1; } 94% { opacity: 0.25; } }
@keyframes wi-flake { 0% { transform: translateY(-3px) rotate(0deg); opacity: 0; } 25% { opacity: 1; } 80% { opacity: 1; } 100% { transform: translateY(9px) rotate(60deg); opacity: 0; } }

.nxt-weather-tile .wi-rays    { transform-origin: 36px 36px; animation: wi-spin 18s linear infinite; }
.nxt-weather-tile .wi-rays-sm { transform-origin: 26px 26px; animation: wi-spin 18s linear infinite; }
.nxt-weather-tile .wi-cloud   { animation: wi-bob 4s ease-in-out infinite; }
.nxt-weather-tile .wi-drop    { animation: wi-fall 1.3s ease-in-out infinite; }
.nxt-weather-tile .wi-bolt    { animation: wi-flash 2.6s ease-in-out infinite; }
.nxt-weather-tile .wi-snow    { animation: wi-flake 2.4s ease-in-out infinite; }

@media (prefers-reduced-motion: reduce) {
  .nxt-weather-tile .wi-rays,
  .nxt-weather-tile .wi-rays-sm,
  .nxt-weather-tile .wi-cloud,
  .nxt-weather-tile .wi-drop,
  .nxt-weather-tile .wi-bolt,
  .nxt-weather-tile .wi-snow { animation: none; }
}

/* ────────────────────────────────────────────────────────────────────────
 * WeatherStripWeek — Tier-2 content surface, sibling of WeatherTile.
 *
 * Reference: _incoming/wheather strip.png (Outline colorway, 6-day strip).
 *
 * Single-row horizontal forecast. N equal columns (driven by --strip-cols
 * inline style on the container), each cell stacks label/icon/max/min.
 * The outer container is the only chrome — cell separation comes from a
 * uniform right-border on every cell except the last.
 *
 * Typography reuses the WeatherTile @font-face block declared above.
 * ──────────────────────────────────────────────────────────────────────── */
.nxt-weather-strip-week {
  --ink: var(--fg-primary);
  --ink-muted: var(--fg-tertiary);
  --surface: var(--bg-canvas);
  --rule: var(--border-default);
  --pad-y: 52px;
  --pad-x: 24px;
  --gap: 12px;
  --label-size: 20px;
  --temp-size: 42px;
  --min-size: 26px;
  --icon-size: 40px;
  --temp-var: var(--font-var-weather-temp);
  --min-var: var(--font-var-weather-min);
  --strip-radius: 4px;
  --cell-min-h: 298px;

  display: grid;
  grid-template-columns: repeat(var(--strip-cols, 7), minmax(118px, 1fr));
  width: 100%;
  max-width: 1040px;
  background: var(--surface);
  color: var(--ink);
  border: 1px solid var(--rule);
  border-radius: var(--strip-radius);
  font-family: 'BarlowGX', 'Barlow', system-ui, sans-serif;
  font-optical-sizing: auto;
  user-select: none;
  overflow: hidden;
  box-sizing: border-box;
}
.nxt-weather-strip-week .cell {
  position: relative;
  display: grid;
  grid-template-rows: auto var(--icon-size) auto auto;
  justify-items: center;
  align-items: start;
  gap: var(--gap);
  padding: var(--pad-y) var(--pad-x) calc(var(--pad-y) + 5px);
  min-width: 0;
  min-height: var(--cell-min-h);
  box-sizing: border-box;
}
.nxt-weather-strip-week .cell:not(:last-child)::after {
  position: absolute;
  top: var(--weather-strip-divider-inset-comfortable);
  right: 0;
  bottom: var(--weather-strip-divider-inset-comfortable);
  width: 1px;
  background: var(--rule);
  content: "";
}
.nxt-weather-strip-week .label {
  font-family: var(--font-mono);
  font-size: var(--label-size);
  line-height: var(--lh-none);
  letter-spacing: var(--track-caps);
  text-transform: uppercase;
  color: var(--ink-muted);
}
.nxt-weather-strip-week .icon {
  display: inline-flex;
  width: var(--icon-size);
  height: var(--icon-size);
  align-items: center;
  justify-content: center;
  color: inherit;
  align-self: center;
}
.nxt-weather-strip-week .icon > svg {
  width: 100%;
  height: 100%;
}
.nxt-weather-strip-week .t {
  font-size: var(--temp-size);
  line-height: var(--lh-display);
  font-variation-settings: var(--temp-var);
  letter-spacing: var(--track-snug);
  font-variant-numeric: tabular-nums;
  color: var(--ink);
  display: inline-flex;
  align-items: flex-start;
  align-self: end;
}
.nxt-weather-strip-week .t .u {
  /* intentional: relative by design — scales with the temperature digit (see
     .nxt-weather-tile .t .u). */
  font-size: 0.74em;
  line-height: var(--lh-none);
  margin-top: 0.02em;
  margin-left: 0.01em;
  opacity: 1;
}
.nxt-weather-strip-week .r {
  font-size: var(--min-size);
  line-height: var(--lh-display);
  font-variation-settings: var(--min-var);
  font-variant-numeric: tabular-nums;
  color: var(--ink-muted);
  align-self: start;
  margin-top: -1px; /* intentional: optical — aligns the glyph to the first text line */
}

/* Outline colorway (default) — already covered by the base block. */
.nxt-weather-strip-week.outline {
  --ink: var(--fg-primary);
  --ink-muted: var(--fg-tertiary);
  --surface: var(--bg-canvas);
  --rule: var(--border-default);
}

/* ────────────────────────────────────────────────────────────────────────
 * Preloader — Tier-2 feedback surface ported from the brand handoff
 * (`_incoming/brand preload.zip` → `<gooey-preloader>`).
 *
 * Composition: the wrapped `<gooey-preloader>` custom element owns the canvas
 * SDF blob renderer and the Nextcaddy mark SVG that fades in. The React runtime
 * owns only the shell/status API; CSS owns layout and colorway.
 *
 * Blob colors travel as bare OKLCH L-C-H triples through component-local
 * vars (--preloader-blob-from, --preloader-blob-to) because the runtime
 * interpolates in OKLab. Mark/status remain ordinary CSS colors so surfaces
 * can swap them without passing through the runtime parser.
 *
 * Supersampling: the wrapped custom element reads --preloader-ss and applies
 * it to the canvas renderer to soften organic shape edges.
 * ──────────────────────────────────────────────────────────────────────── */
.nxt-preloader {
  --preloader-logo: 29px;
  --preloader-ratio: 7.25;
  --preloader-morph: 810ms;
  --preloader-hold: 1210ms;
  --preloader-ease: 0.33, 1, 0.68, 1;
  --preloader-mark-alpha: 0.94;
  --preloader-mark-pow: 3.4;
  --preloader-shape: 1.5;
  --preloader-ss: 3;

  /* Bridge to the wrapped custom element token set. */
  --pre-logo: var(--preloader-logo);
  --pre-ratio: var(--preloader-ratio);
  --pre-morph: var(--preloader-morph);
  --pre-hold: var(--preloader-hold);
  --pre-ease: var(--preloader-ease);
  --pre-mark-alpha: var(--preloader-mark-alpha);
  --pre-mark-pow: var(--preloader-mark-pow);
  --pre-shape: var(--preloader-shape);
  --pre-ss: var(--preloader-ss);
  --pre-status: var(--preloader-status);
  --pre-status-delay: var(--preloader-status-delay);
  --pre-status-interval: var(--preloader-status-interval);
  --pre-status-gap: var(--preloader-status-interval);
  --pre-status-fade: var(--preloader-status-fade);
  --pre-status-size: var(--text-sm);
  --pre-status-weight: 450;
  --pre-status-tracking: var(--track-wide);

  --preloader-blob-from: 0.95 0.2 119;
  --preloader-blob-to: 0.92 0.005 85;
  --preloader-mark: oklab(0 0 0 / 0.47);
  --pre-mark-color: var(--preloader-mark);
  --preloader-status: 0.42 0.013 85;

  --preloader-status-delay: 6s;
  --preloader-status-interval: 2200ms;
  /* Interval between status line swaps — a TIME, not a gap. */
  --preloader-status-interval: 12s;
  --preloader-status-fade: 360ms;

  --_max: calc(var(--preloader-logo) * var(--preloader-ratio));

  display: inline-flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-4);
  contain: layout style;
}

.nxt-preloader .gooey-host {
  display: block;
  color: inherit;
}

/* The wrapped renderer owns WebGL/canvas. In deterministic and reduced-motion
 * contexts it is replaced by the same token-colored brand wordmark seam used
 * by other rich-media fallbacks, avoiding GPU work for a static end state. */
@media (prefers-reduced-motion: reduce) {
  .nxt-preloader .gooey-host {
    inline-size: var(--_max);
    block-size: var(--_max);
    background: currentColor;
    -webkit-mask: url("/brand/nextcaddy-wordmark.svg") center / contain no-repeat;
    mask: url("/brand/nextcaddy-wordmark.svg") center / contain no-repeat;
  }
}
.nxt-preloader .status {
  min-height: 1em;
  color: oklch(var(--preloader-status));
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  font-weight: 450;
  letter-spacing: var(--track-wide);
  opacity: 0;
  transition: opacity var(--preloader-status-fade) var(--ease-smooth);
  user-select: none;
  white-space: nowrap;
  text-rendering: optimizeLegibility;
}

/* Surface palettes — override the blob/mark LCH triples per backdrop. */
.nxt-preloader.ink {
  --preloader-blob-from: 0.95 0.2 119;
  --preloader-blob-to: 0.92 0.005 85;
  --preloader-mark: oklab(0 0 0 / 0.47);
  --pre-grey: var(--preloader-blob-from);
  --pre-ink: var(--preloader-blob-to);
  --pre-mark: 0.985 0.005 85;
  --pre-outline-col: var(--preloader-blob-to);
  /* Source bundle's status gray — AA only against the dark backdrop. */
  --preloader-status: 0.62 0 0;
  /* The dark palette is fixed brand-bundle values, so its backdrop is the
   * matching fixed near-black (warm, neutral-12-light equivalent) rather
   * than a mode-flipping token: the off-white blob and 0.62-gray status
   * text only meet AA contrast against a dark ground in either scheme.
   * Surfaced by the per-example axe scope (status text was 3.43:1 on the
   * light preview canvas). */
  background: oklch(0.12 0.013 85);
  padding: var(--space-6);
}
.nxt-preloader.default {
  --preloader-blob-from: 0.2 0.014 90;
  --preloader-blob-to: 0.95 0.2 119;
  --preloader-mark: oklab(0 0 0 / 0.47);
  --pre-grey: var(--preloader-blob-from);
  --pre-ink: var(--preloader-blob-to);
  --pre-mark: 0.2 0.014 90;
  --pre-outline-col: var(--preloader-blob-to);
}
/* Minimal surface — outline-only blob. The detail axis must not force the
 * filled treatment back on; concise stays outline-only and complete adds only
 * outline satellites. The mark remains a normal CSS color bridge so it stays
 * legible inside the open blob. */
.nxt-preloader.plain {
  --preloader-mark: oklab(0 0 0 / 0.47);
  color: var(--neutral-4, oklch(0.88 0 0));
  background: transparent;
  --pre-grey: 0.2 0.014 90;
  --pre-ink: 0.2 0.014 90;
  --pre-mark: 0.2 0.014 90;
  --pre-fill: 0;
  --pre-outline: 1px;
  --pre-outline-col: 0.2 0.014 90;
  --pre-sat-on: 0;
  --pre-sat-pad: 1;
}

.nxt-preloader[data-detail="concise"] {
  --pre-sat-on: 0;
  --pre-sat-pad: 1;
}

.nxt-preloader:not(.plain)[data-detail="concise"] {
  --pre-fill: 1;
  --pre-outline: 0px;
}

.nxt-preloader[data-detail="complete"] {
  --pre-sat-on: 1;
  --pre-sat-min: 1;
  --pre-sat-max: 3;
  --pre-sat-pad: 2.15;
  --pre-sat-alpha: 0.54;
  --pre-sat-pow: 5;
  --pre-sat-fill: 0;
  --pre-sat-outline: 2.5px;
  --pre-sat-outline-col: var(--pre-status);
  --pre-sat: var(--pre-status);
  --pre-fill: 1;
  --pre-outline: 0px;
  --preloader-satellite-room: calc(var(--_max) * (var(--pre-sat-pad, 2.15) - 1) * 0.5);
  --preloader-status-visual-gap: calc((var(--pre-logo, 29px) * var(--pre-ratio, 7.25)) * 0.45);
  gap: max(var(--space-4), var(--preloader-status-visual-gap));
}

.nxt-preloader[data-detail="complete"] .gooey-host {
  margin: var(--preloader-satellite-room);
}

.nxt-preloader.plain[data-detail] {
  --pre-fill: 0;
  --pre-outline: 1px;
  --pre-outline-col: 0.2 0.014 90;
}

.nxt-preloader.plain[data-detail="concise"] {
  --pre-sat-on: 0;
  --pre-sat-pad: 1;
}

.nxt-preloader.plain[data-detail="complete"] {
  --pre-sat-fill: 0;
  --pre-sat-outline: 1px;
  --pre-sat-outline-col: 0.2 0.014 90;
  --pre-sat: 0.2 0.014 90;
}

.nxt-preloader.three-d {
  --preloader-3d-ink: var(--neutral-12, black);
  display: inline-flex;
  inline-size: var(--preloader-inline-size);
  color: var(--preloader-3d-ink);
}

.nxt-preloader.three-d .stage {
  position: relative;
  inline-size: var(--preloader-three-d-stage-inline-size);
  block-size: auto;
}

.nxt-preloader.three-d .stage::before {
  content: "";
  display: block;
  inline-size: 100%;
  aspect-ratio: var(--ratio-wordmark);
  background: currentColor;
  -webkit-mask: url("/brand/nextcaddy-wordmark.svg") center / contain no-repeat;
  mask: url("/brand/nextcaddy-wordmark.svg") center / contain no-repeat;
}

.nxt-preloader.three-d .logo-canvas {
  position: absolute;
  inset: 0;
  display: block;
  inline-size: 100%;
  block-size: auto;
}

.nxt-preloader.three-d[data-webgl-ready="true"] .stage::before {
  visibility: hidden;
}

.nxt-preloader.three-d .progress-shell {
  inline-size: var(--preloader-three-d-stage-inline-size);
  margin-block-start: var(--space-5);
}

.nxt-preloader.three-d .progress-track {
  position: relative;
  block-size: var(--progress-sm-block-size);
  overflow: hidden;
  background: color-mix(in oklch, var(--preloader-3d-ink), transparent 84%);
}

.nxt-preloader.three-d .progress-fill {
  position: absolute;
  inset: 0 auto 0 0;
  inline-size: 0;
  block-size: 100%;
  background: var(--preloader-3d-ink);
  transition: inline-size 240ms cubic-bezier(0.2, 0, 0.38, 0.9);
}

.nxt-preloader.three-d[data-indeterminate="true"] .progress-fill {
  inline-size: 38%;
  animation: nxt-preloader-3d-sweep 1.9s cubic-bezier(0.2, 0, 0.38, 0.9) infinite;
}

.nxt-preloader.three-d .progress-caption {
  margin-block-start: var(--space-3);
  color: var(--fg-tertiary);
  font-family: var(--font-sans);
  font-size: var(--text-xs);
  font-variant-numeric: tabular-nums;
  letter-spacing: var(--track-wide);
}

@keyframes nxt-preloader-3d-sweep {
  0% { transform: translateX(-110%); }
  100% { transform: translateX(290%); }
}

@media (prefers-reduced-motion: reduce) {
  .nxt-preloader .status {
    opacity: 1;
  }
  .nxt-preloader.three-d .progress-fill {
    transition: none;
  }
  .nxt-preloader.three-d[data-indeterminate="true"] .progress-fill {
    animation: none;
    inline-size: 30%;
    transform: none;
  }
}

/* Ink colorway (inverted, white-on-near-black). */
.nxt-weather-strip-week.ink {
  --ink: var(--neutral-1);
  --ink-muted: color-mix(in oklch, var(--neutral-1), transparent 30%);
  --surface: var(--neutral-12);
  --rule: color-mix(in oklch, var(--neutral-1), transparent 70%);
}
.dark .nxt-weather-strip-week.ink {
  --ink: var(--neutral-12);
  --ink-muted: color-mix(in oklch, var(--neutral-12), transparent 30%);
  --surface: var(--neutral-1);
  --rule: color-mix(in oklch, var(--neutral-12), transparent 70%);
}

@media (max-width: 767px) {
  .nxt-weather-strip-week {
    --pad-y: 28px;
    --pad-x: 14px;
    --gap: 8px;
    --label-size: 12px;
    --temp-size: 32px;
    --min-size: 18px;
    --icon-size: 32px;
    --cell-min-h: 208px;

    grid-template-columns: repeat(var(--strip-cols, 7), minmax(88px, 1fr));
    overflow-x: auto;
  }

  .nxt-weather-strip-week .cell:not(:last-child)::after {
    top: var(--weather-strip-divider-inset-compact);
    bottom: var(--weather-strip-divider-inset-compact);
  }
}

/* ── Size ladder (mirrors WeatherTile lg/md/sm/xs) ─────────────────────────
 * Cells stay 1fr; only per-cell typography, icon, padding, and gap flex.
 * Default rule block above bakes the `md` values; the three siblings below
 * override per-size. */
.nxt-weather-strip-week.lg {
  --pad-y: var(--space-4);
  --pad-x: var(--space-3);
  --gap: var(--radio-group-card-gap);
  --label-size: 12px;
  --temp-size: 40px;
  --min-size: 18px;
  --icon-size: 40px;
  --cell-min-h: auto;
}
.nxt-weather-strip-week.sm {
  --pad-y: var(--space-2);
  --pad-x: 6px;
  --gap: 6px;
  --label-size: 10px;
  --temp-size: 22px;
  --min-size: 12px;
  --icon-size: 22px;
  --cell-min-h: auto;
}
.nxt-weather-strip-week.xs {
  --pad-y: 6px;
  --pad-x: 4px;
  --gap: 4px;
  --label-size: 9px;
  --temp-size: 16px;
  --min-size: 10px;
  --icon-size: 16px;
  --cell-min-h: auto;
}

/* ── Compact variant ───────────────────────────────────────────────────────
 * Suppresses the min temperature row. Cell becomes 3-row: label / icon / max.
 * Composes orthogonally with the size ladder — `compact xs` is the densest
 * possible cell (label + icon + max only, ~16px hero numeral). */
.nxt-weather-strip-week.compact .cell {
  gap: calc(var(--gap) * 0.75);
}
.nxt-weather-strip-week.compact .cell > .r {
  display: none;
}

/* ────────────────────────────────────────────────────────────────────────
 * Essential DS surfaces — conservative token-fed components.
 * These are intentionally flat, semantic-token driven, and interaction-light.
 * ──────────────────────────────────────────────────────────────────────── */
.nxt-pagination,
.nxt-pagination ol {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  margin: 0;
  padding: 0;
  list-style: none;
}

.nxt-pagination {
  color: var(--fg-primary);
}

/* Page numbers align in fixed columns (brand: tabular numerics on data surfaces). */
.nxt-pagination button {
  font-variant-numeric: tabular-nums;
}

.nxt-pagination button,
.nxt-calendar button,
.nxt-toast button,
.nxt-command-list button,
.nxt-dropdown-menu [role="menu"] button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: var(--nav-item-block-size);
  min-height: var(--nav-item-block-size);
  border: 0;
  border-radius: var(--nav-item-radius);
  background: transparent;
  color: var(--nav-item-fg);
  cursor: pointer;
  font: inherit;
  transition:
    background-color var(--dur-snap) var(--ease-snap),
    color var(--dur-snap) var(--ease-snap),
    transform var(--dur-instant) var(--ease-smooth);
  user-select: none;
}

.nxt-pagination button:hover,
.nxt-calendar button:hover,
.nxt-command-list button:hover,
.nxt-dropdown-menu [role="menu"] button:hover {
  background: var(--nav-item-bg-hover);
  color: var(--nav-item-fg-hover);
}

.nxt-pagination button:active,
.nxt-calendar button:active,
.nxt-command-list button:active,
.nxt-dropdown-menu [role="menu"] button:active {
  transform: scale(0.97);
}

.nxt-pagination button:focus-visible,
.nxt-calendar button:focus-visible,
.nxt-toast button:focus-visible,
.nxt-command-list button:focus-visible,
.nxt-dropdown-menu [role="menu"] button:focus-visible,
.nxt-file-input:focus-within,
.nxt-sidebar a:focus-visible,
.nxt-scroll-area:focus-visible,
.nxt-resizable-panel:focus-visible {
  outline: 2px solid var(--focus-ring);
  outline-offset: 2px;
}

.nxt-pagination button[aria-current="page"] {
  background: var(--nav-item-bg-active);
  color: var(--nav-item-fg-active);
}

.nxt-pagination button:disabled,
.nxt-calendar button:disabled {
  cursor: not-allowed;
  opacity: 0.45;
}

.nxt-pagination-ellipsis {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 28px;
  color: var(--fg-tertiary);
}

/* Size axis (sm / md / lg) scales the control hit-area; md is the base. */
.nxt-pagination--sm button {
  min-width: var(--pagination-item-size-sm);
  min-height: var(--pagination-item-size-sm);
}

.nxt-pagination--sm .nxt-pagination-ellipsis {
  min-width: 22px;
}

.nxt-pagination--lg button {
  min-width: 44px;
  min-height: var(--ctrl-block-h-md);
}

.nxt-pagination--lg .nxt-pagination-ellipsis {
  min-width: 34px;
}

.nxt-page {
  --page-region-gap: var(--stack-gap-section);
  --page-heading-gap: var(--stack-gap-heading);
  --page-content-gap: var(--stack-gap-content);
  /* Arbitrary PageBody children — FormLayout-fallback precedent; ADR 155 am.2.
     Density-remapped ONLY UPWARD (expanded 32px, gigantic 48px; see am.3).
     This is NOT the ladder removed earlier: that one moved the body gap DOWN
     (compact 12px) below the 12-16px interiors it bounds. Those interiors
     (--form-field-gap / --form-content-gap / --card-content-gap) resolve
     through fixed :root roles that no density touches, so scaling the page
     family down cannot carry them with it and any downward remap inverts the
     boundary below its interior — which am.2 forbids. Upward remaps keep the
     boundary at or above every interior, so compact and comfortable stay on
     the 16px `related` role and only the two roomier densities move. */
  --page-body-gap: var(--stack-gap-related);
  --page-description-measure: var(--measure-prose);
  display: grid;
  width: 100%;
  max-width: none;
  gap: var(--page-region-gap);
  margin-inline: auto;
  color: var(--fg-primary);
}

.nxt-page[data-density="compact"] {
  --page-heading-gap: var(--page-heading-gap-compact);
  --page-content-gap: var(--page-content-gap-compact);
  --page-region-gap: var(--page-region-gap-compact);
}

.nxt-page[data-density="comfortable"] {
  --page-heading-gap: var(--page-heading-gap-comfortable);
  --page-content-gap: var(--page-content-gap-comfortable);
  --page-region-gap: var(--page-region-gap-comfortable);
}

.nxt-page[data-density="expanded"] {
  --page-heading-gap: var(--page-heading-gap-expanded);
  --page-content-gap: var(--page-content-gap-expanded);
  --page-body-gap: var(--page-body-gap-expanded);
  --page-region-gap: var(--page-region-gap-expanded);
}

.nxt-page[data-density="gigantic"] {
  --page-heading-gap: var(--page-heading-gap-gigantic);
  --page-content-gap: var(--page-content-gap-gigantic);
  --page-body-gap: var(--page-body-gap-gigantic);
  --page-region-gap: var(--page-region-gap-gigantic);
}

.nxt-page[data-width="readable"] {
  max-width: var(--page-description-measure);
}

.nxt-page[data-width="wide"] {
  max-width: min(100%, var(--page-measure-wide));
}

.nxt-page[data-layout-mode="split"] .nxt-page-body,
.nxt-page[data-layout-mode="with-sidebar"] .nxt-page-body {
  display: flex;
  flex-wrap: wrap;
  gap: var(--page-content-gap);
}

.nxt-page[data-layout-mode="split"] .nxt-page-body > *,
.nxt-page[data-layout-mode="with-sidebar"] .nxt-page-body > * {
  flex-basis: calc((var(--page-layout-threshold) - 100%) * 999);
  min-inline-size: 0;
}

.nxt-page[data-layout-mode="split"] .nxt-page-body > :first-child {
  flex-grow: 1;
}

.nxt-page[data-layout-mode="split"] .nxt-page-body > :nth-child(2) {
  flex-grow: 0.48;
  flex-basis: max(var(--page-split-aside-min), calc((var(--page-layout-threshold) - 100%) * 999));
}

.nxt-page[data-layout-mode="with-sidebar"] .nxt-page-body > :first-child {
  flex-grow: 0.28;
  flex-basis: max(var(--page-sidebar-min), calc((var(--page-layout-threshold) - 100%) * 999));
}

.nxt-page[data-layout-mode="with-sidebar"] .nxt-page-body > :nth-child(2) {
  flex-grow: 1;
}

.nxt-page-header,
.nxt-page-footer {
  display: grid;
  gap: 0;
  min-width: 0;
}

.nxt-page-eyebrow,
.nxt-page-title,
.nxt-page-description,
.nxt-page-section-title {
  margin: 0;
}

.nxt-page-eyebrow {
  color: var(--eyebrow-fg);
  font-family: var(--eyebrow-font);
  font-size: var(--eyebrow-size);
  font-weight: var(--eyebrow-weight);
  letter-spacing: var(--eyebrow-tracking);
}

.nxt-page-title {
  color: var(--fg-primary);
  font-size: var(--text-2xl);
  font-weight: var(--weight-medium);
  line-height: var(--lh-tight);
}

.nxt-page-section-title {
  color: var(--fg-primary);
  font-size: var(--text-lg);
  font-weight: var(--weight-medium);
  line-height: var(--lh-tight);
}

.nxt-page-description {
  max-inline-size: var(--page-description-measure);
  color: var(--fg-secondary);
  line-height: var(--lh-relaxed);
}

.nxt-page-body {
  min-width: 0;
}

/* Fail-closed fallback, matching the `.nxt-form-layout > * + *` idiom above: the
   region owns a default separation for every child, and the pairs below tighten
   the fused ones. Previously spacing was an allow-list of enumerated adjacent
   pairs, so any child type nobody had enumerated fell through to zero -- measured
   as `.nxt-page-description + .nxt-toolbar` and `.nxt-toolbar + .nxt-page-actions`
   both at 0px, with .nxt-toolbar carrying no padding or border of its own, so its
   controls touched the description text above. */
.nxt-page-header > * + *,
.nxt-page-footer > * + * {
  margin-block-start: var(--page-content-gap);
}

.nxt-page-header > .nxt-page-eyebrow + :is(.nxt-page-title, .nxt-page-section-title),
.nxt-page-header > :is(.nxt-page-title, .nxt-page-section-title) + .nxt-page-description {
  margin-block-start: var(--page-heading-gap);
}

/* PageBody was the last fail-open Page region: arbitrary children fell through the
   enumerated adjacent pairs below to zero separation. This closes it with the same
   `> * + *` idiom, at `related` (measured PageBody interiors are 12-16px, so the
   boundary must be at least that -- ADR 155 am.2). The CHILD combinator is load
   bearing for the nested docs PageBodys; the two self-rhythmed body classes
   (`.nxt-preview-sections`, `.nxt-system-sections`, `display:grid; row-gap:32px`) are
   excluded by name because 9 of their 10 call sites ARE direct Page children, where a
   margin would stack on top of their own grid gap (measured 32 -> 48px on /components)
   outside every CI clip. Those two classes are the closed set of PageBodys that own
   block-axis rhythm; a body with no owned rhythm must never be added to it.
   Split/with-sidebar bodies are flex two-up regions and own their gap already. */
.nxt-page:where(:not([data-layout-mode="split"])):where(:not([data-layout-mode="with-sidebar"])) > .nxt-page-body:where(:not(.nxt-preview-sections, .nxt-system-sections)) > * + * {
  margin-block-start: var(--page-body-gap);
}

/* Bordered demo-row runs are deliberately flush (padding + rule carry it). */
.nxt-page:where(:not([data-layout-mode="split"])):where(:not([data-layout-mode="with-sidebar"])) > .nxt-page-body > .nxt-page-demo-row + .nxt-page-demo-row {
  margin-block-start: 0;
}

/* The same fused pair inside the body, which the header-scoped rule never
   reached: measured at 0px on /preview/page. */
.nxt-page-body > :is(.nxt-page-title, .nxt-page-section-title) + .nxt-page-description {
  margin-block-start: var(--page-heading-gap);
}

.nxt-page-header > :is(.nxt-page-description, .nxt-page-title, .nxt-page-section-title) + .nxt-page-actions,
.nxt-page-header > .nxt-page-actions + * {
  margin-block-start: var(--page-content-gap);
}

.nxt-page:not([data-layout-mode="split"]):not([data-layout-mode="with-sidebar"]) .nxt-page-body > .nxt-page-section-title + .nxt-page-demo-row,
.nxt-page:not([data-layout-mode="split"]):not([data-layout-mode="with-sidebar"]) .nxt-page-body > .nxt-page-description + .nxt-page-demo-row {
  margin-block-start: var(--page-content-gap);
}

.nxt-page-demo-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  align-items: baseline;
  justify-content: space-between;
  padding-block: var(--space-2);
  border-bottom: 1px solid var(--border-subtle);
}

.nxt-page-actions,
.nxt-sticky-action-region,
.nxt-action-bar,
.nxt-form-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  align-items: center;
}

.nxt-page-actions,
.nxt-form-actions {
  justify-content: flex-end;
}

.nxt-action-bar > [data-zone="danger"],
.nxt-form-actions > [data-zone="danger"] {
  margin-inline-end: auto;
}

.nxt-sticky-action-region,
.nxt-action-bar[data-placement="sticky-bottom"],
.nxt-form-actions[data-placement="sticky-bottom"] {
  position: sticky;
  bottom: max(env(safe-area-inset-bottom, 0px), var(--kb-inset));
  padding-block-start: var(--space-3);
  padding-block-end: calc(var(--space-3) + env(safe-area-inset-bottom, 0px));
  border-top: 1px solid var(--border-subtle);
  background: var(--bg-canvas);
}

/* Full-bleed sticky CTA — the action bar spans edge-to-edge and its attached
   button is squared, for full-screen mobile flows (e.g. mobile signature). */
.nxt-action-bar[data-placement="sticky-bottom"][data-bleed="full"] {
  bottom: var(--kb-inset);
  gap: 0;
  padding-block-start: 0;
  padding-block-end: var(--action-bar-full-bleed-safe-area-padding-block-end);
  padding-inline: 0;
  border-top: 0;
}
.nxt-action-bar[data-placement="sticky-bottom"][data-bleed="full"] .nxt-button[data-attached] {
  border-radius: 0;
}

/* Descriptor-mode FormActions (UI-ACTION-*). Scoped to [data-recipe] so legacy
 * children mode keeps its exact pixels (space-2 gap, no margin). Gaps and the
 * action-area margin use the action tokens only (UI-ACTION-014). Stacking flips
 * container-relative via the Switcher mechanic — no media/container queries, so
 * check-breakpoints stays green. */
.nxt-form-actions[data-recipe="form-actions"] {
  --action-actions-threshold: var(--bp-sm);
  flex-wrap: wrap;
  gap: var(--action-gap);
  margin-block-start: var(--action-area-margin);
}

.nxt-form-actions[data-recipe="form-actions"] > * {
  flex-grow: 1;
  flex-basis: calc((var(--action-actions-threshold) - 100%) * 999);
  min-inline-size: 0;
}

/* default → commit cluster at inline-end; fullPagePrimaryStart → inline-start.
 * Never space-between (UI-ACTION-004). */
.nxt-form-actions[data-recipe="form-actions"][data-variant="default"] {
  justify-content: flex-end;
}

.nxt-form-actions[data-recipe="form-actions"][data-variant="fullPagePrimaryStart"] {
  justify-content: flex-start;
}

/* Component-local aliases, per ADR 155's rule that a foundational layout exposes
   named aliases resolving to a shared token rather than reaching for a primitive
   directly. Toolbar commands are peers in a command cluster, which is exactly
   what --action-gap names, so the alias resolves there rather than restating a
   length. Same 8px as the primitive it replaces -- this formalises the binding,
   it does not move a pixel. */
.nxt-toolbar {
  --toolbar-item-gap: var(--action-gap);
  display: flex;
  flex-wrap: wrap;
  gap: var(--toolbar-item-gap);
  align-items: center;
  min-width: 0;
  color: var(--fg-primary);
}

.nxt-toolbar[data-orientation="vertical"] {
  align-items: stretch;
  flex-direction: column;
}

.nxt-toolbar[data-variant="compact"] {
  gap: var(--space-1);
}

/* Component-local aliases, per ADR 155. The action region's own inset resolves
   to the action-cluster gap rather than restating the primitive, so a change to
   the action rhythm moves the region with it. Same 8px as before. */
.nxt-action-bar {
  --action-bar-padding-block: var(--action-gap);
  justify-content: flex-end;
  min-width: 0;
  padding-block: var(--action-bar-padding-block);
  color: var(--fg-primary);
}

.nxt-action-bar[data-align="start"] {
  justify-content: flex-start;
}

.nxt-action-bar[data-placement="panel-footer"] {
  padding-block: var(--space-3);
  border-top: 1px solid var(--border-subtle);
}

.nxt-form-layout {
  --form-section-gap: var(--stack-gap-major);
  --form-field-gap: var(--stack-gap-related);
  --form-heading-gap: var(--stack-gap-heading);
  /* Heading block -> body. `section` (32px), not `related` (16px): a boundary must
     not be tighter than the gaps inside what it bounds, AND must clear them 2x.
     Amendment 2 moved this off `content` (8px) because the legend bound to the
     first field more strongly than the fields bound to each other; it stopped at
     `related`, where boundary EQUALLED the 16px field rhythm and the heading read
     as one more item in the list. Amendment 4 (DR-010) raised it to 32px so the
     heading block owns its fields. */
  --form-content-gap: var(--stack-gap-section);
  --form-column-gap: var(--space-3);
  --form-columns-threshold: var(--bp-md);
  display: grid;
  gap: 0;
  inline-size: 100%;
  color: var(--fg-primary);
  /* Container context for container-based form responsiveness (UI-FORM-027):
     descendant FieldRow/FieldGroup column behavior keys off this container,
     not the viewport. */
  container-type: inline-size;
  container-name: nxt-form-layout;
}

/* FormLayout accepts arbitrary direct children. The fallback owns their
 * vertical relationship, while the semantic section rule below strengthens
 * section-to-section separation. */
.nxt-form-layout > * + * {
  margin-block-start: var(--form-field-gap);
}

/* A boundary that TOUCHES a form section is a section boundary, whichever side the
   section is on. The section's own interior boundary is --form-content-gap (32px),
   so anything bounding it must clear 64px; --form-field-gap (16px) cannot. Before
   this, a form-level <p> followed by a <fieldset> took the generic 16px child gap
   and inverted against the 32px boundary inside that fieldset -- the exact condition
   ADR 155 amendment 2 forbids. Amendment 4 raised the interior and this rule is what
   moves the boundary with it; without both, the re-scale swaps amendment 3's defect
   for amendment 2's. Measured on 8 pattern parents by the deterministic sweep. */
.nxt-form-layout > * + .nxt-form-section {
  margin-block-start: var(--form-section-gap);
}

.nxt-form-layout > .nxt-form-section + * {
  margin-block-start: var(--form-section-gap);
}

.nxt-form-layout > .nxt-form-actions:not([data-recipe="form-actions"]) {
  margin-block-start: var(--form-section-gap);
}

.nxt-field-group[data-columns="2"],
.nxt-field-group[data-columns="3"],
.nxt-field-group-body[data-columns="2"],
.nxt-field-group-body[data-columns="3"] {
  grid-template-columns: minmax(0, 1fr);
}

.nxt-form-layout[data-columns="2"] {
  display: flex;
  flex-wrap: wrap;
  column-gap: var(--form-column-gap);
  row-gap: var(--form-section-gap);
}

.nxt-form-layout[data-columns="2"] > * {
  flex-grow: 1;
  flex-basis: calc((var(--form-columns-threshold) - 100%) * 999);
  min-inline-size: min(100%, calc((100% - var(--form-column-gap)) / 2));
  margin-block-start: 0;
}

.nxt-form-layout[data-columns="2"] > .nxt-form-actions {
  flex-basis: 100%;
  min-inline-size: 100%;
}

/* Canonical container-based responsiveness (UI-FORM-027): every multi-column
   FieldGroup keys off the FormLayout container, not the viewport, so a group in a
   narrow container stacks even on a wide viewport. FormLayout itself switches
   intrinsically above.

   The legacy alias previously kept a viewport-keyed @media carve-out to preserve
   its established pixel behavior. That behavior was the bug UI-RESP-003 forbids:
   measured across 105 rendered surfaces, three groups were squeezing two columns
   into a narrow parent -- 239px rendering two 113.5px columns, and two 283px
   groups rendering 135.5px columns -- on a 1280px viewport. The same probe found
   12 such groups in total and none outside a FormLayout, so the container is
   always present and the carve-out is removed rather than re-scoped.

   Semantic groups need no exclusion: [data-semantic="true"] is display:block, so
   grid-template-columns is inert on the fieldset and the body below carries it. */
@container nxt-form-layout (min-width: 768px) {
  .nxt-field-group[data-columns="2"],
  .nxt-field-group-body[data-columns="2"] {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
  .nxt-field-group[data-columns="3"],
  .nxt-field-group-body[data-columns="3"] {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

.nxt-form-section {
  min-width: 0;
  /* Strip the UA fieldset margin without clobbering the block-start margin that
     `.nxt-form-layout > * + *` owns. `margin: 0` here ties that fallback on
     specificity (0,1,0) and, being later in the file, silently won -- so the
     first section after any non-section child (a heading, an error summary)
     stacked flush, measured as 0px on /preview/patterns. Section-to-section was
     unaffected because its rule carries higher specificity. */
  margin-inline: 0;
  margin-block-end: 0;
  padding: 0;
  border: 0;
}

.nxt-form-section-legend {
  padding: 0;
  color: var(--fg-primary);
  /* `md` (16px) was EXACTLY body size, so a section legend was distinguished from its own
     description by WEIGHT ALONE. That left 64px of whitespace as the only section cue in a
     form -- spacing carrying hierarchy that typography should carry.
     `xl` (22px), NOT `lg` (18px). 18px clears the 1.1x type floor by 0.4px, but that floor
     is deliberately set BELOW a real ramp step as drift slack (see HEADING_SIZE_RATIO in
     rhythm-sweep.ts), so clearing it is a threshold, not a design target. Chosen on OPTICS:
     against a 16px description on a ~750px measure, 16->18 is barely perceptible on a short
     string, while at 22px the legend unambiguously governs the description beneath it.
     22px is also this scale's `h3` rung; 18px is the body cluster's ceiling and by far its
     most crowded (27 declarations vs 13). */
  font-size: var(--text-xl);
  font-weight: var(--weight-medium);
  line-height: var(--lh-snug);
}

.nxt-form-section-description {
  margin: var(--form-heading-gap) 0 0;
  color: var(--fg-secondary);
}

.nxt-form-section-body,
.nxt-field-group {
  display: grid;
  row-gap: var(--form-field-gap);
  column-gap: var(--form-column-gap);
  min-width: 0;
}

.nxt-form-section-body {
  margin-top: var(--form-content-gap);
}

/* Semantic FieldGroup (fieldset+legend) — a single value split across inputs or
   an option group (UI-FORM-026). The fieldset is normal flow; the body carries
   the grid so legend/hint/error stack above the controls. */
.nxt-field-group[data-semantic="true"] {
  display: block;
  min-width: 0;
  margin: 0;
  padding: 0;
  border: 0;
}

.nxt-field-group-legend {
  padding: 0;
  color: var(--fg-primary);
  font-size: var(--text-md);
  font-weight: var(--weight-medium);
}

.nxt-field-group-hint {
  margin: var(--form-heading-gap) 0 0;
  color: var(--fg-secondary);
}

.nxt-field-group-error {
  margin: var(--form-heading-gap) 0 0;
  color: var(--field-message-error-fg);
}

.nxt-field-group-body {
  display: grid;
  row-gap: var(--form-field-gap);
  column-gap: var(--form-column-gap);
  min-width: 0;
  margin-top: var(--form-content-gap);
}

.nxt-sr-only {
  position: absolute;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  inline-size: var(--sr-only-size);
  block-size: var(--sr-only-size);
  margin: var(--sr-only-offset);
  padding: 0;
  border: 0;
  white-space: nowrap;
}

.nxt-data-table {
  --nxt-data-table-cell-block: var(--space-2);
  --nxt-data-table-cell-inline: var(--space-3);
  --nxt-data-table-row-min: var(--ctrl-block-h-sm);
  display: grid;
  min-inline-size: 0;
  overflow: hidden;
  border: 1px solid var(--border-default);
  border-radius: var(--radius-md);
  background: var(--bg-surface);
  color: var(--fg-primary);
}

.nxt-data-table[data-density="comfortable"] {
  --nxt-data-table-cell-block: var(--space-3);
  --nxt-data-table-cell-inline: var(--space-4);
  --nxt-data-table-row-min: var(--ctrl-block-h-md);
}

.nxt-data-table[data-density="expanded"] {
  --nxt-data-table-cell-block: var(--space-4);
  --nxt-data-table-cell-inline: var(--space-5);
  --nxt-data-table-row-min: var(--ctrl-block-h-lg);
}

.nxt-data-table[data-density="gigantic"] {
  --nxt-data-table-cell-block: var(--space-5);
  --nxt-data-table-cell-inline: var(--space-6);
  --nxt-data-table-row-min: var(--ctrl-block-h-xl);
}

.nxt-data-table-toolbar,
.nxt-data-table-footer {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-3);
  align-items: center;
  padding: var(--space-3);
  background: var(--bg-surface);
}

.nxt-data-table-toolbar {
  justify-content: space-between;
  border-bottom: 1px solid var(--border-subtle);
}

.nxt-data-table-filter {
  display: flex;
  flex: 1 1 calc(var(--ctrl-block-h-md) * 10);
  flex-wrap: wrap;
  gap: var(--space-2);
  align-items: end;
  min-inline-size: 0;
}

.nxt-data-table-filter-label,
.nxt-data-table-page-size-label {
  color: var(--fg-secondary);
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
  line-height: var(--lh-tight);
}

.nxt-data-table-filter-label {
  flex-basis: 100%;
}

.nxt-data-table-filter .nxt-input {
  flex: 1 1 calc(var(--ctrl-block-h-md) * 7);
  min-inline-size: min(100%, calc(var(--ctrl-block-h-md) * 7));
}

.nxt-data-table-status {
  display: inline-flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  align-items: center;
  justify-content: flex-end;
  min-inline-size: 0;
  color: var(--fg-secondary);
  font-size: var(--text-sm);
}

.nxt-data-table-async-status {
  display: flex;
  flex-wrap: wrap;
  /* The cluster wraps, so it has a real block axis: the row gap takes the group
     boundary role and the column gap stays an inline separation. Both resolve to
     the same 8px this cluster shipped with. */
  row-gap: var(--stack-gap-content);
  column-gap: var(--space-2);
  align-items: center;
  padding: var(--space-2) var(--nxt-data-table-cell-inline);
  /* Closed on all four edges over an opaque background, so the cluster is a region
     the reader can see the extent of rather than a band bleeding into the table.
     It also means the seam below it is judged as a region boundary with the
     cluster's own interiors asserted, instead of as loose vertical rhythm. */
  border: 1px solid var(--border-subtle);
  background: var(--bg-sunken);
  color: var(--fg-secondary);
  font-size: var(--text-sm);
}

.nxt-data-table-bulk-actions {
  display: inline-flex;
  gap: var(--space-2);
  align-items: center;
}

.nxt-data-table-scroll {
  min-inline-size: 0;
  overflow-x: auto;
}

/* The scroll viewport carries no border of its own here — .nxt-data-table owns
   the frame — so the edge fades run flush to the viewport box instead of stopping
   short of a hairline that does not exist, and stay square: this viewport is a
   middle band between toolbar and footer, not a rounded corner. */
.nxt-data-table .nxt-scroll-affordance {
  --scroll-affordance-border-inset: 0px;
  --scroll-affordance-radius: 0;
}

.nxt-data-table-scroll:focus-visible {
  outline: 2px solid var(--focus-ring);
  outline-offset: 2px;
}

.nxt-data-table table {
  inline-size: 100%;
  min-inline-size: max(100%, calc(var(--ctrl-block-h-md) * 16));
  border-collapse: collapse;
  color: var(--fg-primary);
  font-size: var(--text-sm);
  line-height: var(--lh-normal);
}

.nxt-data-table caption {
  padding: var(--space-3) var(--nxt-data-table-cell-inline);
  color: var(--fg-tertiary);
  text-align: left;
}

.nxt-data-table th,
.nxt-data-table td {
  /* Row minimum. This is `block-size`, not `min-block-size`, on purpose: table
     layout ignores min-block-size on cells, so the old declaration was dead CSS
     and rows had no floor. On a table cell `block-size` IS a minimum — the used
     height is the greater of it and the content — which is the behaviour that was
     intended all along. */
  block-size: var(--nxt-data-table-row-min);
  padding: var(--nxt-data-table-cell-block) var(--nxt-data-table-cell-inline);
  border-bottom: 1px solid var(--border-subtle);
  text-align: left;
  vertical-align: middle;
}

.nxt-data-table thead th {
  background: var(--bg-sunken);
  color: var(--fg-secondary);
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
  letter-spacing: 0;
}

.nxt-data-table tbody th {
  background: transparent;
  color: var(--fg-primary);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  letter-spacing: 0;
}

.nxt-data-table th[data-align="end"],
.nxt-data-table td[data-align="end"] {
  text-align: right;
}

.nxt-data-table th[data-align="center"],
.nxt-data-table td[data-align="center"] {
  text-align: center;
}

.nxt-data-table th[data-numeric],
.nxt-data-table td[data-numeric] {
  font-variant-numeric: tabular-nums;
}

.nxt-data-table td[data-editable],
.nxt-data-table tbody th[data-editable] {
  padding-block: calc(var(--nxt-data-table-cell-block) / 2);
}

.nxt-data-table-edit-input {
  inline-size: min(100%, calc(var(--ctrl-block-h-md) * 6));
  min-inline-size: min(100%, calc(var(--ctrl-block-h-md) * 4));
}

.nxt-data-table td[data-align="end"] .nxt-data-table-edit-input,
.nxt-data-table tbody th[data-align="end"] .nxt-data-table-edit-input {
  text-align: right;
}

.nxt-data-table td[data-align="center"] .nxt-data-table-edit-input,
.nxt-data-table tbody th[data-align="center"] .nxt-data-table-edit-input {
  text-align: center;
}

.nxt-data-table-selection-cell {
  inline-size: 1%;
  white-space: nowrap;
}

.nxt-data-table-sort {
  display: inline-flex;
  gap: var(--space-1);
  align-items: center;
  justify-content: inherit;
  max-inline-size: 100%;
  padding: 0;
  border: 0;
  border-radius: var(--radius-sm);
  background: transparent;
  color: inherit;
  cursor: pointer;
  font: inherit;
  text-align: inherit;
  transition:
    background-color var(--dur-snap) var(--ease-snap),
    color var(--dur-snap) var(--ease-snap);
}

.nxt-data-table-sort:hover {
  color: var(--fg-primary);
}

.nxt-data-table-sort:focus-visible {
  outline: 2px solid var(--focus-ring);
  outline-offset: var(--space-1);
}

.nxt-data-table-sort-indicator {
  flex: 0 0 auto;
  color: var(--fg-tertiary);
  font-variant-numeric: tabular-nums;
}

.nxt-data-table tbody tr {
  transition: background-color var(--dur-snap) var(--ease-snap);
}

/* Selection is neutral, never accent: lime is reserved for the single hero per
   view, and select, search-box, calendar and checkbox all state the same rule. */
.nxt-data-table tbody tr[data-selected] {
  background: var(--selection-indicator-muted-bg);
}

@media (hover: hover) {
  .nxt-data-table tbody tr:not([data-empty]):not([data-error]):not([data-loading]):hover {
    background: var(--bg-sunken);
  }

  /* Selection must survive hover. The row-hover rule above out-specifies a plain
     tr[data-selected]:hover (its three :not() arguments each count), so this
     repeats the chain to win rather than relying on source order: hovering a
     selected row darkens it one step instead of dropping the state. */
  .nxt-data-table tbody tr[data-selected]:not([data-empty]):not([data-error]):not([data-loading]):hover {
    background: var(--pressed-soft-bg);
  }
}

.nxt-data-table tbody tr:last-child td,
.nxt-data-table tbody tr:last-child th {
  border-bottom: 0;
}

.nxt-data-table-state-cell {
  color: var(--fg-secondary);
  text-align: center;
}

.nxt-data-table-state-cell > strong {
  display: block;
  margin-block-end: var(--space-1);
  color: var(--fg-primary);
  font-weight: var(--weight-medium);
}

/* .nxt-data-table-skeleton-row is gone: it existed to lay its own auto-fit grid
   inside a single colSpan'd cell, which is precisely why the loading state did not
   match the loaded table. The skeleton now emits the table's real cells, so the
   column template and row height come from the table itself. */

.nxt-data-table-skeleton {
  display: block;
  inline-size: 100%;
  block-size: var(--data-table-skeleton-block-size);
  border-radius: var(--radius-sm);
  background: var(--bg-sunken);
}

.nxt-data-table-footer {
  justify-content: flex-end;
  border-top: 1px solid var(--border-subtle);
  color: var(--fg-secondary);
}

.nxt-data-table-page-size {
  flex: 0 0 auto;
  inline-size: auto;
}

.nxt-data-table-page-size .nxt-select-control {
  min-inline-size: var(--data-table-page-size-min-inline-size);
}

.nxt-data-table-page-status {
  color: var(--fg-secondary);
  font-size: var(--text-sm);
  font-variant-numeric: tabular-nums;
}

@media (max-width: 767px) {
  .nxt-data-table-toolbar,
  .nxt-data-table-footer {
    align-items: stretch;
    justify-content: flex-start;
  }

  .nxt-data-table-filter,
  .nxt-data-table-filter .nxt-input,
  .nxt-data-table-status {
    inline-size: 100%;
  }
}

.nxt-toast-stack {
  display: grid;
  gap: var(--space-2);
  width: min(360px, 100%);
}

.nxt-toast {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: var(--space-3);
  align-items: start;
  padding: var(--space-3);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-md);
  background: var(--bg-raised);
  color: var(--fg-primary);
  box-shadow: var(--tooltip-shadow);
}

.nxt-toast strong {
  display: block;
  font-size: var(--text-base);
  line-height: var(--lh-heading);
}

.nxt-toast p {
  margin: var(--toast-margin);
  color: var(--fg-secondary);
  font-size: var(--text-sm);
  line-height: var(--lh-normal);
}

.nxt-toast button {
  min-width: var(--toast-action-min-size);
  min-height: var(--toast-action-min-size);
  color: var(--fg-tertiary);
}

/* Calendar styles live in the react-day-picker block further down (search for
   the nxt-calendar root rule). The pre-ADR-125 hand-rolled calendar CSS that
   lived here was removed — its box chrome (width/padding/border/background) was
   consolidated into that block. The nxt-date-picker-popover layout rule lives
   in the DatePicker popover section further down. */

.nxt-date-picker-popover .nxt-calendar {
  border: 0;
}

.nxt-file-input {
  display: grid;
  place-items: center;
  min-height: var(--file-input-dropzone-min-block-size);
  padding: var(--space-5);
  border: 1px dashed var(--border-default);
  border-radius: var(--radius-md);
  background: var(--bg-surface);
  color: var(--fg-primary);
  text-align: center;
  cursor: pointer;
  transition:
    background-color var(--dur-snap) var(--ease-snap),
    border-color var(--dur-snap) var(--ease-snap);
}

.nxt-file-input:hover {
  border-color: var(--border-strong);
  background: var(--bg-sunken);
}

.nxt-file-input input {
  position: absolute;
  width: var(--sr-only-size);
  height: var(--sr-only-size);
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
}

.nxt-file-input-icon {
  display: grid;
  place-items: center;
  width: 36px;
  height: 36px;
  margin-bottom: var(--space-2);
  border-radius: var(--radius-full);
  background: var(--neutral-soft-bg);
  color: var(--fg-secondary);
}

.nxt-file-input-label {
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
}

.nxt-file-input-description {
  max-width: 34ch;
  margin-top: var(--stack-gap-heading);
  overflow: hidden;
  color: var(--fg-secondary);
  font-size: var(--text-sm);
  line-height: var(--lh-normal);
  text-overflow: ellipsis;
  white-space: nowrap;
}

.nxt-command-palette,
.nxt-dropdown-menu [role="menu"] {
  border: 1px solid var(--overlay-panel-border);
  border-radius: var(--overlay-panel-radius);
  background: var(--overlay-panel-bg);
  color: var(--overlay-panel-fg);
  box-shadow: var(--overlay-panel-shadow);
}

.nxt-command-palette {
  display: grid;
  width: min(520px, 100%);
  overflow: hidden;
}

.nxt-command-search {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: var(--space-2);
  align-items: center;
  padding: var(--space-3);
  border-bottom: 1px solid var(--border-subtle);
  color: var(--fg-tertiary);
}

.nxt-command-search .nxt-input {
  border: 0;
  background: transparent;
  box-shadow: none;
}

.nxt-command-list {
  display: grid;
  max-height: 320px;
  overflow: auto;
  padding: var(--space-2);
}

.nxt-command-list button,
.nxt-dropdown-menu [role="menu"] button {
  justify-content: space-between;
  width: 100%;
  min-height: var(--nav-item-block-size);
  padding-block: var(--space-2);
  padding-inline: var(--nav-item-padding-inline);
  text-align: left;
}

.nxt-command-list strong,
.nxt-command-list small {
  display: block;
}

.nxt-command-list small {
  margin-top: var(--stack-gap-micro);
  color: var(--fg-tertiary);
  font-size: var(--text-xs);
}

.nxt-command-list kbd {
  color: var(--fg-tertiary);
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
}

.nxt-command-list p {
  margin: 0;
  padding: var(--space-4);
  color: var(--fg-tertiary);
  text-align: center;
}

.nxt-sidebar {
  display: grid;
  gap: var(--space-3);
  width: 248px;
  padding: var(--space-3);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-md);
  background: var(--bg-surface);
  color: var(--fg-primary);
}

.nxt-sidebar > strong {
  padding: 0 var(--space-2);
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: var(--track-caps);
  color: var(--fg-tertiary);
}

.nxt-sidebar nav {
  display: grid;
}

.nxt-sidebar-items {
  display: grid;
  gap: var(--space-1);
  margin: 0;
  padding: 0;
  list-style: none;
}

.nxt-sidebar-items > li {
  display: grid;
}

.nxt-sidebar a {
  display: inline-flex;
  align-items: center;
  min-block-size: var(--nav-item-block-size);
  padding-inline: var(--nav-item-padding-inline);
  border-radius: var(--nav-item-radius);
  color: var(--nav-item-fg);
  font-size: var(--text-sm);
  text-decoration: none;
}

.nxt-sidebar a:hover {
  background: var(--nav-item-bg-hover);
  color: var(--nav-item-fg-hover);
}

.nxt-sidebar a[aria-current="page"] {
  background: var(--nav-item-bg-active);
  color: var(--nav-item-fg-active);
}

/* Canonical app-shell starter: relationship-owned layout, no authored utility classes. */
[data-nxt-pattern="app-shell"] {
  display: grid;
  grid-template-columns: minmax(var(--page-sidebar-min), auto) minmax(0, 1fr);
  /* The column gap is structural (inline axis). The row gap only applies below
     the single-column breakpoint, where navigation stacks above the page: that
     is a shell boundary above the page's own region rhythm, which is already
     --stack-gap-section, so it takes the next step rather than sitting flat. */
  column-gap: var(--stack-gap-section);
  row-gap: var(--space-8);
  align-items: start;
}

/* Canonical checkout-payment starter: the two-column FormLayout is a flex track, so
   the page heading claims a full row the same way form actions already do. Keyed on
   the column count so it outweighs the generic two-column child rule. */
[data-nxt-pattern="checkout-payment"][data-columns="2"] > h1 {
  flex-basis: 100%;
  min-inline-size: 100%;
}

/* Section-to-section separation is a stacking rule. Side by side it would offset the
   second column by one section gap, so the container row gap owns the stacked case. */
[data-nxt-pattern="checkout-payment"][data-columns="2"] > .nxt-form-section + .nxt-form-section {
  margin-block-start: 0;
}

/* Canonical login starter: the form measure is owned by the composition rather than
   authored on the starter, which may not carry classes or inline styles. */
[data-nxt-pattern="login"] {
  max-inline-size: var(--field-w-long);
}

/* Canonical empty-state starter: copy to actions is a section boundary, which has to
   read as looser than the title to description relationship inside the copy block. */
[data-nxt-pattern="empty-state"] {
  row-gap: var(--stack-gap-section);
}

@media (max-width: 767px) {
  [data-nxt-pattern="app-shell"] {
    grid-template-columns: minmax(0, 1fr);
  }

  [data-nxt-pattern="app-shell"][data-navigation-open="false"] > .nxt-sidebar {
    display: none;
  }
}

.nxt-dropdown-menu {
  position: relative;
  display: inline-grid;
  gap: var(--space-2);
  justify-items: start;
}

.nxt-dropdown-menu [role="menu"] {
  position: absolute;
  z-index: var(--z-overlay);
  top: calc(100% + var(--space-2));
  left: 0;
  display: grid;
  width: 220px;
  padding: var(--space-2);
}

.nxt-dropdown-menu [data-destructive="true"] {
  color: var(--danger);
}

/* ── Chart — three minimal primitives sharing one attribute API ─────────
 * variant=horizontal-bar / vertical-bar / donut. surface=default/dark/lime
 * shifts the bar fill + label color so the chart reads against the host
 * card. data[].highlight=true promotes a datum to the lime accent.
 *
 * Each chart claims an explicit min-width so it survives the preview
 * shell's flex-wrap container without collapsing to intrinsic content
 * width. The bar variants use CSS grid (label column + bar column) so the
 * value-text inside the bar stays right-anchored at any bar length. */
.nxt-chart {
  --chart-bar-bg: var(--neutral-11);
  --chart-bar-fg: var(--neutral-1);
  --chart-bar-accent: var(--accent);
  --chart-bar-accent-fg: var(--neutral-12);
  --chart-label-fg: var(--fg-secondary);
  --chart-track: var(--border-default);
  --chart-bar-radius: 2px;
  --chart-h-bar-row-h: 32px;
  --chart-v-bar-plot-h: 200px;

  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  width: 100%;
  min-width: min(320px, 100%);
  max-width: 640px;
  color: var(--fg-primary);
  box-sizing: border-box;
}
.nxt-chart[data-surface="ink"] {
  --chart-bar-bg: var(--neutral-1);
  --chart-bar-fg: var(--neutral-12);
  --chart-label-fg: var(--neutral-1);
  background: var(--neutral-12);
  padding: var(--space-5);
  border-radius: var(--radius-md);
}
.nxt-chart[data-surface="accent"] {
  --chart-bar-bg: var(--neutral-12);
  --chart-bar-fg: var(--neutral-1);
  --chart-label-fg: var(--neutral-12);
  background: var(--accent);
  padding: var(--space-5);
  border-radius: var(--radius-md);
}

/* Horizontal bars — `[label-col 1fr bar-col]` rows. Each row has a fixed
 * height; the bar fills its column from the left to `--bar-pct%`. The bar
 * value sits inside the bar at the right edge, falling outside if the bar
 * is too short to fit (see .nxt-chart-bar-value alignment). */
.nxt-chart[data-variant="horizontal-bar"] .nxt-chart-bars {
  display: grid;
  grid-template-columns: minmax(72px, 18%) 1fr;
  column-gap: var(--space-3);
  row-gap: var(--space-2);
  align-items: center;
}
.nxt-chart[data-variant="horizontal-bar"] .nxt-chart-bar {
  grid-column: 2;
  height: var(--chart-h-bar-row-h);
  width: calc(var(--bar-pct, 0) * 1%);
  min-width: 2.5em;
  background: var(--chart-bar-bg);
  color: var(--chart-bar-fg);
  border-radius: var(--chart-bar-radius);
  display: inline-flex;
  align-items: center;
  justify-content: flex-end;
  padding: 0 var(--space-3);
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  font-variant-numeric: tabular-nums;
  font-weight: var(--weight-medium);
  box-sizing: border-box;
  position: relative;
  /* growBar: width 0 → computed, fading in, staggered per index. */
  animation: nxt-chart-grow-bar var(--motion-chart-bar-duration) var(--motion-chart-ease) both;
  animation-delay: calc(var(--motion-chart-delay-bar) + var(--chart-i, 0) * var(--motion-chart-stagger-bar));
}
.nxt-chart[data-variant="horizontal-bar"] .nxt-chart-bar[data-highlight] {
  background: var(--chart-bar-accent);
  color: var(--chart-bar-accent-fg);
}
.nxt-chart[data-variant="horizontal-bar"] .nxt-chart-bar-label {
  grid-column: 1;
  text-align: right;
  color: var(--chart-label-fg);
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  font-weight: var(--weight-regular);
  white-space: nowrap;
  /* Labels sit in column 1 of the same grid row as the bar that follows.
   * Implicit row placement keeps them paired without explicit row indices. */
  --chart-slide-from: 10px;
  animation: nxt-chart-slide-fade-in var(--motion-chart-label-duration) var(--motion-chart-ease) both;
  animation-delay: calc(var(--motion-chart-delay-label) + var(--chart-i, 0) * var(--motion-chart-stagger-bar));
}

/* Vertical bars — fixed-height plot (`--chart-v-bar-plot-h`) with bars
 * rising from a baseline. The plot is a CSS grid: 1 row of bars across the
 * top auto-row, 1 row of labels along the bottom auto-row. Bars fill from
 * the bottom via flex `align-items: flex-end` on the bar wrapper, and bar
 * height is `--bar-pct%` of the plot height so 0..100 maps cleanly. */
.nxt-chart[data-variant="vertical-bar"] .nxt-chart-bars {
  display: grid;
  grid-template-columns: repeat(var(--chart-cols, auto-fill), minmax(0, 1fr));
  grid-auto-rows: var(--chart-v-bar-plot-h) auto;
  column-gap: var(--space-2);
  row-gap: var(--space-2);
  position: relative;   /* anchors the baseline ::after without consuming a cell */
}
.nxt-chart[data-variant="vertical-bar"] .nxt-chart-bar {
  grid-row: 1;
  align-self: end;
  height: max(2em, calc(var(--bar-pct, 0) * 1%));
  background: var(--chart-bar-bg);
  color: var(--chart-bar-fg);
  border-radius: var(--chart-bar-radius);
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding: var(--space-2) var(--space-1);
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  font-variant-numeric: tabular-nums;
  font-weight: var(--weight-medium);
  box-sizing: border-box;
  /* growUp: height 0 → computed, fading in, staggered per index. */
  animation: nxt-chart-grow-up var(--motion-chart-bar-duration) var(--motion-chart-ease) both;
  animation-delay: calc(var(--motion-chart-delay-bar) + var(--chart-i, 0) * var(--motion-chart-stagger-bar));
}
.nxt-chart[data-variant="vertical-bar"] .nxt-chart-bar[data-highlight] {
  background: var(--chart-bar-accent);
  color: var(--chart-bar-accent-fg);
}
/* Hairline the bars rise from; bleeds slightly past the columns like the reference. */
.nxt-chart[data-variant="vertical-bar"] .nxt-chart-bars::after {
  content: "";
  position: absolute;
  left: calc(-1 * var(--space-4));
  right: calc(-1 * var(--space-4));
  top: var(--chart-v-bar-plot-h);   /* bottom edge of the bar plot row */
  height: 1px;
  background: color-mix(in oklch, var(--chart-label-fg) 18%, transparent);
}
.nxt-chart[data-variant="vertical-bar"] .nxt-chart-bar-label {
  grid-row: 2;
  text-align: center;
  color: var(--chart-label-fg);
  font-family: var(--font-sans);
  font-size: var(--text-xs);
  font-weight: var(--weight-regular);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  --chart-slide-from: -6px;
  animation: nxt-chart-slide-fade-in var(--motion-chart-label-duration) var(--motion-chart-ease) both;
  animation-delay: calc(var(--motion-chart-delay-label) + var(--chart-i, 0) * var(--motion-chart-stagger-bar));
}

/* Donut — SVG + legend, side-by-side. The SVG keeps a square aspect via
 * its viewBox; the legend takes remaining width. */
.nxt-chart[data-variant="donut"] {
  flex-direction: row;
  align-items: center;
  gap: var(--space-5);
}
.nxt-chart-donut {
  flex: 0 0 auto;
  width: 240px;
  height: 240px;
  overflow: visible;   /* hover stroke-grow extends past the box */
}
.nxt-chart-donut-track {
  fill: none;
  stroke: var(--chart-track);
}
/* Each segment carries its own rotate() + dash inline. Draw-in animates the
 * dash to 0 (default = drawn, so SSR / reduced-motion show the finished donut);
 * hover re-weights stroke-width and dims siblings via interruptible transitions. */
.nxt-chart-donut-segment {
  fill: none;
  stroke: var(--chart-bar-bg);
  stroke-linecap: butt;
  animation: nxt-chart-draw-seg var(--motion-chart-seg-duration) var(--motion-chart-ease) both;
  animation-delay: calc(var(--motion-chart-delay-seg) + var(--chart-i, 0) * var(--motion-chart-stagger-seg));
  transition:
    stroke-width var(--motion-chart-hover-stroke-duration) var(--motion-chart-hover-ease),
    opacity var(--motion-chart-hover-opacity-duration) var(--motion-chart-hover-ease);
}
.nxt-chart-donut-segment[data-highlight] { stroke: var(--chart-bar-accent); }
.nxt-chart-donut-segment[data-hot] { stroke-width: 32; }   /* intentional: data-viz hover emphasis, not UI glyph */
.nxt-chart-donut-segment[data-dim] { opacity: 0.22; }
.nxt-chart-donut-center {
  font-family: var(--font-display, var(--font-sans));
  font-size: 56px;
  font-weight: var(--weight-regular);
  letter-spacing: var(--track-tight);
  fill: var(--fg-primary);
  opacity: 0;
  transform: translateY(6px);
  animation: nxt-chart-slide-fade-in var(--motion-chart-center-duration) var(--motion-chart-ease)
    var(--motion-chart-delay-center) both;
  transition: fill var(--motion-chart-hover-opacity-duration) var(--motion-chart-hover-ease);
}
.nxt-chart-donut-center-label {
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  letter-spacing: var(--track-caps);
  text-transform: uppercase;
  fill: var(--fg-tertiary);
  opacity: 0;
  transform: translateY(6px);
  animation: nxt-chart-slide-fade-in var(--motion-chart-center-duration) var(--motion-chart-ease)
    var(--motion-chart-delay-eyebrow) both;
}
.nxt-chart[data-surface="ink"] .nxt-chart-donut-center { fill: var(--neutral-1); }
.nxt-chart[data-surface="ink"] .nxt-chart-donut-center-label { fill: var(--neutral-7); }
.nxt-chart[data-surface="accent"] .nxt-chart-donut-center { fill: var(--neutral-12); }
.nxt-chart[data-surface="accent"] .nxt-chart-donut-center-label { fill: var(--neutral-11); }

.nxt-chart-legend {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 0;
  flex: 1 1 auto;
  min-width: 0;
  font-size: var(--text-sm);
  font-variant-numeric: tabular-nums;
}
.nxt-chart-legend li {
  display: grid;
  grid-template-columns: 18px 1fr auto auto;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-2) var(--space-3) var(--space-2) 0;
  border-top: 1px solid color-mix(in oklch, var(--chart-label-fg) 12%, transparent);
  border-radius: var(--radius-sm);
  color: var(--chart-bar-bg);   /* drives the marker (currentColor); overridden inline per datum */
  --chart-slide-from: 8px;
  animation: nxt-chart-slide-fade-in var(--motion-chart-legend-duration) var(--motion-chart-ease) both;
  animation-delay: calc(var(--motion-chart-delay-legend) + var(--chart-i, 0) * var(--motion-chart-stagger-legend));
  transition:
    opacity var(--motion-chart-hover-row-duration) var(--motion-chart-hover-ease),
    background var(--motion-chart-hover-row-duration) var(--motion-chart-hover-ease);
}
.nxt-chart-legend li:first-child { border-top: none; }
.nxt-chart-legend li[data-highlight] { color: var(--chart-bar-accent); }
.nxt-chart-legend[data-dim] li:not([data-hot]) { opacity: 0.42; }
.nxt-chart-legend li[data-hot] { background: color-mix(in oklch, var(--chart-label-fg) 6%, transparent); }
.nxt-chart-legend-swatch {
  width: 18px;
  height: 8px;
  background: currentColor;   /* matches the segment colour via the row's color */
  border-radius: 2px;
  align-self: center;
}
.nxt-chart-legend-label {
  font-family: var(--font-sans);
  color: var(--chart-label-fg);
  /* shrink/ellipsis the label so it never pushes the value+percent off the
     right edge in a narrow card. */
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.nxt-chart-legend-value {
  font-family: var(--font-display, var(--font-sans));
  font-size: var(--text-xl);
  color: var(--fg-primary);
  font-variant-numeric: tabular-nums;
  letter-spacing: var(--track-snug);
}
.nxt-chart-legend-percent {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--fg-tertiary);
  font-variant-numeric: tabular-nums;
}
.nxt-chart[data-surface="ink"] .nxt-chart-legend-value { color: var(--neutral-1); }
.nxt-chart[data-surface="ink"] .nxt-chart-legend-percent { color: var(--neutral-7); }
.nxt-chart[data-surface="accent"] .nxt-chart-legend-value { color: var(--neutral-12); }
.nxt-chart[data-surface="accent"] .nxt-chart-legend-percent { color: var(--neutral-11); }

/* Backwards-compat <dl> kept screen-reader-only on bar variants. */
.nxt-chart dl {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(80px, 1fr));
  gap: var(--space-2);
  margin: 0;
}

/* ── Chart motion — entrance keyframes (one-shot) + reduced-motion rest state.
 * Default (un-animated) styles are the FINAL state, so SSR / no-JS / reduced
 * motion render the finished chart; a keyframe `from` only applies while the
 * animation runs (animation-fill-mode: both holds it through the stagger delay). */
@keyframes nxt-chart-grow-bar { from { width: 0; opacity: 0; } to { opacity: 1; } }
@keyframes nxt-chart-grow-up  { from { height: 0; opacity: 0; } to { opacity: 1; } }
@keyframes nxt-chart-draw-seg { from { stroke-dashoffset: var(--seg-len, 0); } to { stroke-dashoffset: 0; } }
@keyframes nxt-chart-slide-fade-in {
  from { opacity: 0; transform: translateY(var(--chart-slide-from, 6px)); }
  to   { opacity: 1; transform: translateY(0); }
}
@media (prefers-reduced-motion: reduce) {
  .nxt-chart-bar,
  .nxt-chart-bar-label,
  .nxt-chart-donut-segment,
  .nxt-chart-donut-center,
  .nxt-chart-donut-center-label,
  .nxt-chart-legend li { animation: none; opacity: 1; transform: none; }
  .nxt-chart-donut-segment { transition: none; stroke-dashoffset: 0; }
}
/* Reference parity: donut stacks above its legend on narrow viewports. */
@media (max-width: 767px) {
  .nxt-chart[data-variant="donut"] { flex-direction: column; align-items: stretch; }
}

/* ── SwipeConfirm — drag-to-confirm action surface. The track holds a hint
 * line and a draggable handle; release before threshold springs the handle
 * back via a CSS transition (neutralised under prefers-reduced-motion).
 * `data-confirmed` flips the track + handle into the success treatment.
 * Three intents share the same anatomy; size adjusts track height + hint type. */
.nxt-swipe-confirm {
  --sc-track-bg: var(--bg-sunken);
  --sc-track-border: var(--input-border);
  --sc-hint-fg: var(--fg-secondary);
  --sc-fill-bg: var(--danger);
  --sc-handle-bg: var(--neutral-fill);
  --sc-handle-fg: var(--neutral-fill-fg);
  --sc-track-h: 56px;
  --sc-handle-size: 48px;
  --sc-inset: 4px;
  --sc-min-w: 320px;
  --sc-progress: 0;
  --sc-hint-size: var(--text-sm);

  position: relative;
  display: flex;
  align-items: center;
  width: var(--sc-min-w);
  min-width: 320px;
  min-height: var(--sc-track-h);
  padding: var(--sc-inset);
  border: var(--border-width-strong) solid var(--sc-track-border);
  background: var(--sc-track-bg);
  border-radius: var(--radius-full);
  color: var(--sc-hint-fg);
  font-family: var(--font-sans);
  font-size: var(--sc-hint-size);
  font-weight: var(--weight-medium);
  user-select: none;
  overflow: hidden;
  box-sizing: border-box;
  outline: none;
}
.nxt-swipe-confirm:focus-visible {
  box-shadow: var(--focus-ring-shadow-gap);
}
.nxt-swipe-confirm[data-disabled] {
  opacity: 0.55;
  pointer-events: none;
}
.nxt-swipe-confirm[data-intent="danger"] {
  --sc-fill-bg: var(--danger);
  --sc-track-bg: var(--danger-soft-bg);
  --sc-track-border: var(--danger);
  --sc-handle-bg: var(--neutral-fill-fg);
  --sc-handle-fg: var(--danger);
}
.nxt-swipe-confirm[data-intent="accent"] {
  --sc-fill-bg: var(--accent-outline);
  --sc-track-bg: var(--accent-soft-bg);
  --sc-track-border: var(--accent-outline);
}
.nxt-swipe-confirm[data-intent="neutral"] {
  --sc-fill-bg: var(--neutral-fill);
}
.nxt-swipe-confirm[data-size="sm"] {
  --sc-track-h: 48px;
  --sc-handle-size: 40px;
  --sc-min-w: 280px;
  --sc-hint-size: var(--text-xs);
  min-width: 280px;
}
.nxt-swipe-confirm[data-size="lg"] {
  --sc-track-h: 64px;
  --sc-handle-size: 56px;
  --sc-min-w: 360px;
  --sc-hint-size: var(--text-base);
  min-width: 360px;
}
.nxt-swipe-confirm[data-confirmed] {
  --sc-fill-bg: var(--success);
  --sc-track-border: var(--success);
  --sc-hint-fg: var(--success-soft-fg);
}
.nxt-swipe-confirm-fill {
  position: absolute;
  inset-block: var(--sc-inset);
  inset-inline-start: var(--sc-inset);
  width: calc(var(--sc-handle-size) + ((100% - var(--sc-handle-size) - (var(--sc-inset) * 2)) * var(--sc-progress, 0)));
  border-radius: var(--radius-full);
  background: var(--sc-fill-bg);
  pointer-events: none;
  transition:
    width var(--dur-quick) var(--ease-smooth),
    background-color var(--dur-quick) var(--ease-smooth);
  z-index: 0;
}
.nxt-swipe-confirm[data-dragging="true"] .nxt-swipe-confirm-fill {
  transition: none;
}
.nxt-swipe-confirm[data-spring-back="true"] .nxt-swipe-confirm-fill {
  transition: width 280ms cubic-bezier(0.4, 0, 0.2, 1);
}
.nxt-swipe-confirm-hint {
  flex: 1;
  text-align: center;
  margin-inline-start: calc(var(--sc-handle-size) + var(--space-2));
  margin-inline-end: var(--space-2);
  position: relative;
  z-index: 1;
  transition: color var(--dur-quick) var(--ease-smooth);
}
.nxt-swipe-confirm[data-label-inverse="true"] .nxt-swipe-confirm-hint {
  color: var(--neutral-fill-fg);
}
.nxt-swipe-confirm-handle {
  position: absolute;
  inset-block: var(--sc-inset);
  inset-inline-start: var(--sc-inset);
  width: var(--sc-handle-size);
  height: var(--sc-handle-size);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--sc-handle-bg);
  color: var(--sc-handle-fg);
  border-radius: var(--radius-full);
  box-shadow: var(--selection-indicator-shadow);
  cursor: grab;
  touch-action: none;
  z-index: 2;
  /* Rest state has no transition. The runtime toggles data-spring-back
   * on release-without-confirm to enable a one-shot transition back to 0,
   * and data-dragging while a pointer drag is in flight (transition off so
   * the handle tracks the finger pixel-for-pixel). */
  transition: none;
}
.nxt-swipe-confirm-handle:active {
  cursor: grabbing;
}
.nxt-swipe-confirm-handle[data-dragging="true"] {
  transition: none;
}
.nxt-swipe-confirm-handle[data-spring-back="true"] {
  transition: transform 280ms cubic-bezier(0.4, 0, 0.2, 1);
}
@media (prefers-reduced-motion: reduce) {
  .nxt-swipe-confirm-handle[data-spring-back="true"] {
    transition: none;
  }
}

/* ── HoleChart — 18-hole bar distribution + Actual/Propuesto handicap
 * comparison table. Threshold-driven cell coloring uses the success /
 * warning / danger soft-bg pairs from the semantic layer. The chart grid
 * is laid out as `[y-axis | plot]` on row 1 and `[. | x-axis]` on row 2
 * so the Y labels stay aligned with the bar baseline. */
.nxt-hole-chart {
  --hole-chart-bar: var(--neutral-11);
  --hole-chart-min-w: 30rem; /* legible floor for the 18-hole plot before scroll */
  --hole-chart-grid: var(--border-default);
  --hole-chart-axis: var(--fg-tertiary);
  --hole-chart-ink: var(--fg-primary);
  --hole-chart-ink-quiet: var(--fg-secondary);

  display: grid;
  gap: var(--space-5);
  color: var(--hole-chart-ink);
  font-family: var(--font-sans);
  /* scroll (rather than clip holes 16-18) when narrower than the plot; the root
     carries role=group + aria-label + tabindex=0 so the scroll region is
     keyboard-reachable (axe scrollable-region-focusable). No scrollbar once the
     container is wide enough. */
  overflow-x: auto;
}
.nxt-hole-chart:focus-visible {
  outline: 2px solid var(--focus-ring);
  outline-offset: 2px;
}
.nxt-hole-chart[data-surface="ink"] {
  --hole-chart-bar: var(--neutral-1);
  --hole-chart-grid: var(--neutral-7);
  --hole-chart-axis: var(--neutral-1);
  --hole-chart-ink: var(--neutral-1);
  --hole-chart-ink-quiet: var(--neutral-1);
  background: var(--neutral-11);
}

.nxt-hole-chart-legend {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--hole-chart-legend-gap);
  font-size: var(--text-sm);
  color: var(--hole-chart-ink-quiet);
}
.nxt-hole-chart-legend-swatch {
  width: 14px;
  height: 14px;
  background: var(--hole-chart-bar);
  border-radius: 2px;
}

.nxt-hole-chart-chart {
  display: grid;
  grid-template-columns: 96px 1fr;
  grid-template-rows: 1fr 24px;
  height: 320px;
  gap: 0;
  min-inline-size: var(--hole-chart-min-w);
}
.nxt-hole-chart-y-axis {
  grid-column: 1;
  grid-row: 1;
  position: relative;
  height: 100%;
  padding-right: var(--space-3);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--hole-chart-axis);
  font-variant-numeric: tabular-nums;
}
.nxt-hole-chart-y-tick {
  position: absolute;
  right: var(--space-3);
  transform: translateY(-50%);
  line-height: var(--lh-none);
}
.nxt-hole-chart-plot {
  grid-column: 2;
  grid-row: 1;
  position: relative;
  height: 100%;
  border-left: 1px solid var(--hole-chart-grid);
  border-bottom: 1px solid var(--hole-chart-grid);
}
.nxt-hole-chart-grid {
  position: absolute;
  inset: 0;
  pointer-events: none;
}
.nxt-hole-chart-grid-line {
  position: absolute;
  left: 0;
  right: 0;
  height: 1px;
  background: var(--hole-chart-grid);
  opacity: 0.6;
  transform: translateY(-1px);
}
.nxt-hole-chart-bars {
  position: absolute;
  inset: 0;
  display: grid;
  grid-template-columns: repeat(18, 1fr);
  align-items: stretch;
}
.nxt-hole-chart-col {
  display: flex;
  align-items: flex-end;
  justify-content: center;
  height: 100%;
}
.nxt-hole-chart-bar {
  width: 62%;
  background: var(--hole-chart-bar);
}
.nxt-hole-chart-x-axis {
  grid-column: 2;
  grid-row: 2;
  display: grid;
  grid-template-columns: repeat(18, 1fr);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--hole-chart-axis);
  font-variant-numeric: tabular-nums;
  align-items: center;
}
.nxt-hole-chart-x-tick {
  text-align: center;
  line-height: var(--lh-none);
}

.nxt-hole-chart-table {
  width: 100%;
  border-collapse: collapse;
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  font-variant-numeric: tabular-nums;
  border-top: 1px solid var(--hole-chart-grid);
  border-bottom: 1px solid var(--hole-chart-grid);
}
.nxt-hole-chart-table thead th,
.nxt-hole-chart-table tbody td,
.nxt-hole-chart-table tbody th {
  padding: var(--space-2) 0;
  text-align: center;
  border-left: 1px solid var(--hole-chart-grid);
  font-weight: var(--weight-medium);
}
.nxt-hole-chart-table thead th:first-child,
.nxt-hole-chart-table tbody th:first-child {
  text-align: left;
  padding: var(--space-2) var(--space-3);
  border-left: none;
  width: 96px;
}
.nxt-hole-chart-table thead th {
  font-size: var(--text-xs);
  letter-spacing: var(--track-caps);
  color: var(--hole-chart-axis);
  background: var(--bg-canvas);
}
.nxt-hole-chart-table tbody th {
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  color: var(--hole-chart-ink-quiet);
  text-align: left;
}
.nxt-hole-chart-table tbody tr + tr {
  border-top: 1px solid var(--hole-chart-grid);
}
.nxt-hole-chart-table-propuesto td[data-diff="ok"] {
  background: var(--success-soft-bg);
  color: var(--success-soft-fg);
}
.nxt-hole-chart-table-propuesto td[data-diff="warn"] {
  background: var(--warning-soft-bg);
  color: var(--warning-soft-fg);
}
.nxt-hole-chart-table-propuesto td[data-diff="danger"] {
  background: var(--danger-soft-bg);
  color: var(--danger-soft-fg);
}

.nxt-hole-chart-info {
  display: grid;
  grid-template-columns: 24px 1fr;
  gap: var(--space-4);
  padding-top: var(--space-4);
}
.nxt-hole-chart-info-glyph {
  width: 22px;
  height: 22px;
  border: 1.4px solid var(--hole-chart-axis);
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-display, var(--font-sans));
  font-size: var(--text-sm);
  color: var(--hole-chart-axis);
  line-height: var(--lh-none);
}
.nxt-hole-chart-info h3 {
  margin: 0 0 var(--space-1);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  color: var(--hole-chart-ink);
}
.nxt-hole-chart-info p {
  margin: 0;
  font-size: var(--text-sm);
  line-height: var(--lh-relaxed);
  color: var(--hole-chart-ink-quiet);
  max-width: 80ch;
}

.nxt-chart dl div {
  display: grid;
  gap: var(--chart-term-gap);
  padding: var(--space-3);
  border: 1px solid var(--surface-frame-border);
  border-radius: var(--surface-frame-radius);
  background: var(--surface-frame-bg);
}

.nxt-chart dt {
  color: var(--fg-tertiary);
  font-size: var(--text-xs);
}

.nxt-chart dd {
  margin: 0;
  color: var(--fg-primary);
  font-size: var(--text-xl);
  font-variant-numeric: tabular-nums;
  line-height: var(--lh-tight);
}

.nxt-statistic {
  --statistic-value-size: var(--text-3xl);
  --statistic-value-tracking: var(--track-normal);
  --statistic-value-line: 0.92;
  --statistic-prefix-size: var(--text-lg);
  --statistic-suffix-size: var(--text-sm);
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  min-width: 0;
  gap: var(--space-2);
  padding: var(--space-4);
  border: 1px solid var(--surface-frame-border);
  border-radius: var(--surface-frame-radius);
  background: var(--surface-frame-bg);
  color: var(--fg-primary);
}

.nxt-statistic[data-size="sm"] {
  --statistic-value-size: var(--text-2xl);
  --statistic-value-tracking: var(--track-normal);
  --statistic-prefix-size: var(--text-base);
  --statistic-suffix-size: var(--text-xs);
  gap: var(--space-1);
  padding: var(--space-3);
}

.nxt-statistic[data-size="lg"] {
  --statistic-value-size: var(--text-5xl);
  --statistic-prefix-size: var(--text-2xl);
  --statistic-suffix-size: var(--text-lg);
  gap: var(--space-3);
  padding: var(--space-5);
}

.nxt-statistic[data-size="hero"] {
  --statistic-value-size: var(--text-6xl);
  --statistic-value-tracking: var(--track-normal);
  --statistic-prefix-size: var(--text-3xl);
  --statistic-suffix-size: var(--text-xl);
  gap: var(--space-4);
  padding: var(--space-6);
}

.nxt-statistic[data-variant="plain"] {
  padding: 0;
  border-color: transparent;
  border-radius: 0;
  background: transparent;
}

.nxt-statistic[data-variant="ruled"] {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: baseline;
  gap: var(--space-2) var(--space-4);
  align-self: stretch;
  padding: var(--space-3) 0;
  border: 0;
  border-top: 1px solid var(--border-subtle);
  border-radius: 0;
  background: transparent;
}

.nxt-statistic[data-variant="ruled"]:last-child {
  border-bottom: 1px solid var(--border-subtle);
}

.nxt-statistic[data-variant="ruled"] .nxt-statistic-eyebrow,
.nxt-statistic[data-variant="ruled"] .nxt-statistic-delta,
.nxt-statistic[data-variant="ruled"] .nxt-statistic-description,
.nxt-statistic[data-variant="ruled"] .nxt-statistic-comparison {
  grid-column: 1 / -1;
}

.nxt-statistic[data-surface="soft"] {
  border-color: transparent;
  background: var(--bg-sunken);
}

.nxt-statistic[data-surface="ink"] {
  border-color: var(--neutral-fill);
  background: var(--neutral-fill);
  color: var(--neutral-fill-fg);
}

.nxt-statistic-eyebrow {
  color: var(--fg-tertiary);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  line-height: var(--lh-none);
  letter-spacing: var(--track-caps);
  text-transform: uppercase;
}

.nxt-statistic-label {
  color: var(--fg-tertiary);
  font-size: var(--text-sm);
  line-height: var(--lh-normal);
}

.nxt-statistic-value-row {
  display: inline-flex;
  align-items: baseline;
  max-width: 100%;
  min-width: 0;
  gap: var(--statistic-value-row-gap);
  line-height: var(--statistic-value-line);
}

.nxt-statistic-prefix,
.nxt-statistic-value,
.nxt-statistic-suffix {
  font-family: var(--font-ui);
  /* Barlow GX weight channel (BRAND-TYPE-001, ADR 137): weight rides the
     variation axis, never font-weight (which clamps to wght 188). */
  font-variation-settings: var(--font-wght-barlow-regular);
  font-synthesis: none;
  font-variant-numeric: tabular-nums lining-nums;
  font-feature-settings: "tnum", "lnum";
}

.nxt-statistic-prefix {
  color: var(--fg-secondary);
  font-size: var(--statistic-prefix-size);
  line-height: var(--lh-none);
  letter-spacing: var(--track-normal);
}

.nxt-statistic-value {
  min-width: 0;
  margin: 0;
  color: currentColor;
  font-size: var(--statistic-value-size);
  line-height: var(--statistic-value-line);
  letter-spacing: var(--statistic-value-tracking);
}

.nxt-statistic-suffix {
  color: var(--fg-tertiary);
  font-size: var(--statistic-suffix-size);
  line-height: var(--lh-none);
  letter-spacing: var(--track-normal);
}

.nxt-statistic-delta {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  width: fit-content;
  padding: 5px var(--space-2);
  border-radius: var(--radius-sm);
  background: var(--bg-sunken);
  color: var(--fg-secondary);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-style: normal;
  font-weight: var(--weight-medium);
  font-variant-numeric: tabular-nums;
  line-height: var(--lh-none);
  letter-spacing: var(--track-normal);
}

.nxt-statistic-delta svg {
  width: var(--statistic-delta-icon-size);
  height: var(--statistic-delta-icon-size);
  flex-shrink: 0;
}

.nxt-statistic[data-intent="accent"] .nxt-statistic-delta {
  background: var(--accent-soft-bg);
  color: var(--accent-soft-fg);
}

.nxt-statistic[data-intent="success"] .nxt-statistic-delta {
  background: var(--success-soft-bg);
  color: var(--success-soft-fg);
}

.nxt-statistic[data-intent="warning"] .nxt-statistic-delta {
  background: var(--warning-soft-bg);
  color: var(--warning-soft-fg);
}

.nxt-statistic[data-intent="danger"] .nxt-statistic-delta {
  background: var(--danger-soft-bg);
  color: var(--danger-soft-fg);
}

.nxt-statistic[data-intent="info"] .nxt-statistic-delta {
  background: var(--info-soft-bg);
  color: var(--info-soft-fg);
}

.nxt-statistic-description {
  max-width: 36ch;
  color: var(--fg-secondary);
  font-size: var(--text-sm);
  line-height: var(--lh-relaxed);
}

.nxt-statistic-comparison {
  color: var(--fg-tertiary);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-variant-numeric: tabular-nums;
  line-height: var(--lh-normal);
  letter-spacing: var(--track-normal);
}

.nxt-statistic[data-surface="ink"] .nxt-statistic-eyebrow,
.nxt-statistic[data-surface="ink"] .nxt-statistic-label,
.nxt-statistic[data-surface="ink"] .nxt-statistic-suffix,
.nxt-statistic[data-surface="ink"] .nxt-statistic-description,
.nxt-statistic[data-surface="ink"] .nxt-statistic-comparison {
  color: color-mix(in oklch, var(--neutral-fill-fg), transparent 28%);
}

.nxt-statistic[data-surface="ink"] .nxt-statistic-prefix {
  color: color-mix(in oklch, var(--neutral-fill-fg), transparent 18%);
}

.nxt-statistic[data-surface="ink"] .nxt-statistic-delta {
  background: color-mix(in oklch, var(--neutral-fill-fg), transparent 88%);
  color: var(--neutral-fill-fg);
}

.nxt-scroll-area {
  max-height: 220px;
  overflow: auto;
  scrollbar-gutter: stable;
  padding: var(--space-3);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-md);
  background: var(--bg-surface);
}

/* Scroll affordance — decorative edge fades that appear only while content
   is clipped past that edge. The wrapper hosts two pseudo-element overlays
   per axis; `useScrollAffordance` toggles data-overflow-* on the wrapper
   (attribute present = hidden content in that direction), so an exhausted
   edge never shows a fade. Fades are surface-colored gradients inset past
   the viewport border and are purely visual: pointer-events none, no text,
   the scrollable content stays reachable by scroll/keyboard as before. */
/* The wrapper, not the viewport, is now the flex/grid item. A scroll container
   resolves its automatic minimum size to zero, but this wrapper does not scroll,
   so without an explicit min-size it would inherit `min-width: auto` = max-content
   and refuse to shrink — blowing out any flex/grid track that holds a wide
   scrollable child (e.g. a tab strip). Keep the wrapper layout-transparent. */
.nxt-scroll-affordance {
  position: relative;
  min-width: 0;
  min-height: 0;
  /* Concentric inner radius, declared on the wrapper rather than :root so both
     `--radius-md` (density-scoped) and a consumer's `--scroll-affordance-border-inset`
     override resolve against THIS element. A :root declaration would substitute
     both at :root and silently ignore either override. Consumers whose viewport
     is a middle band rather than a rounded corner set this to 0. */
  --scroll-affordance-radius: calc(var(--radius-md) - var(--scroll-affordance-border-inset));
}

.nxt-scroll-affordance::before,
.nxt-scroll-affordance::after {
  content: "";
  position: absolute;
  pointer-events: none;
  opacity: 0;
  transition: opacity var(--dur-quick) var(--ease-smooth);
}

.nxt-scroll-affordance[data-axis="y"]::before,
.nxt-scroll-affordance[data-axis="y"]::after {
  left: var(--scroll-affordance-border-inset);
  right: var(--scroll-affordance-border-inset);
  height: var(--scroll-affordance-extent);
}

.nxt-scroll-affordance[data-axis="y"]::before {
  top: var(--scroll-affordance-border-inset);
  background: linear-gradient(to bottom, var(--bg-surface), transparent);
  border-radius: var(--scroll-affordance-radius) var(--scroll-affordance-radius) 0 0;
}

.nxt-scroll-affordance[data-axis="y"]::after {
  bottom: var(--scroll-affordance-border-inset);
  background: linear-gradient(to top, var(--bg-surface), transparent);
  border-radius: 0 0 var(--scroll-affordance-radius) var(--scroll-affordance-radius);
}

.nxt-scroll-affordance[data-axis="x"]::before,
.nxt-scroll-affordance[data-axis="x"]::after {
  top: var(--scroll-affordance-border-inset);
  bottom: var(--scroll-affordance-border-inset);
  width: var(--scroll-affordance-extent);
}

.nxt-scroll-affordance[data-axis="x"]::before {
  left: var(--scroll-affordance-border-inset);
  background: linear-gradient(to right, var(--bg-surface), transparent);
  border-radius: var(--scroll-affordance-radius) 0 0 var(--scroll-affordance-radius);
}

.nxt-scroll-affordance[data-axis="x"]::after {
  right: var(--scroll-affordance-border-inset);
  background: linear-gradient(to left, var(--bg-surface), transparent);
  border-radius: 0 var(--scroll-affordance-radius) var(--scroll-affordance-radius) 0;
}

.nxt-scroll-affordance[data-axis="y"][data-overflow-top]::before,
.nxt-scroll-affordance[data-axis="y"][data-overflow-bottom]::after,
.nxt-scroll-affordance[data-axis="x"][data-overflow-left]::before,
.nxt-scroll-affordance[data-axis="x"][data-overflow-right]::after {
  opacity: 1;
}

@media (prefers-reduced-motion: reduce) {
  .nxt-scroll-affordance::before,
  .nxt-scroll-affordance::after {
    transition: none;
  }
}

.nxt-resizable-panel {
  /* .nxt-resizable-panel keeps its preferred minimum without escaping a narrow parent. */
  min-inline-size: min(var(--resizable-panel-min-inline-size), 100%);
  min-block-size: var(--resizable-panel-min-block-size);
  max-inline-size: 100%;
  overflow: auto;
  resize: both;
  padding: var(--space-4);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-md);
  background: var(--bg-surface);
}

/* Typography — numbered type roles (ADR 138, Carbon-inspired specimen).
   Every binding is a semantic token; no raw sizes/weights/leading. label-02
   is the Barlow GX role: weight rides the variation axis (BRAND-TYPE-001). */
.nxt-typography {
  margin: 0;
  color: var(--fg-primary);
}

.nxt-typography[data-fit-width] {
  display: inline-block;
  max-inline-size: 100%;
  text-wrap: initial;
}

.nxt-typography[data-fit-width-lines="1"] {
  white-space: nowrap;
}

.nxt-typography[data-fit-width-lines="2"] {
  display: inline-grid;
  row-gap: var(--space-1);
}

.nxt-typography [data-fit-width-line] {
  display: inline-block;
  white-space: nowrap;
}

.nxt-typography[data-variant="display-01"],
.nxt-typography[data-variant="display-02"] {
  font-family: var(--font-display);
  font-weight: var(--weight-light);
  line-height: var(--lh-tight);
  letter-spacing: var(--track-tight);
  text-wrap: balance;
}
.nxt-typography[data-variant="display-01"] { font-size: var(--text-display-1); }
.nxt-typography[data-variant="display-02"] { font-size: var(--text-display-2); }

.nxt-typography[data-variant="heading-01"],
.nxt-typography[data-variant="heading-02"],
.nxt-typography[data-variant="heading-03"],
.nxt-typography[data-variant="heading-04"] {
  font-family: var(--font-sans);
  line-height: var(--lh-snug);
  letter-spacing: var(--track-snug);
  text-wrap: balance;
}
.nxt-typography[data-variant="heading-01"] { font-size: var(--text-3xl); font-weight: var(--weight-medium); }
.nxt-typography[data-variant="heading-02"] { font-size: var(--text-2xl); font-weight: var(--weight-medium); }
.nxt-typography[data-variant="heading-03"] { font-size: var(--text-xl); font-weight: var(--weight-medium); }
.nxt-typography[data-variant="heading-04"] { font-size: var(--text-lg); font-weight: var(--weight-medium); letter-spacing: var(--track-normal); }

/* text-box-trim (ADR 144): trim the half-leading above cap-height and below the
   alphabetic baseline so a display/heading box equals its glyph box. Spacing then
   produces the gap that was authored, not gap-plus-leading. The trimmed box is the
   CANONICAL box for these roles; engines without support (Firefox at implementation
   time) keep the un-trimmed box as graceful, slightly-looser degradation. Only the
   tight-leading display/heading roles trim — body/label/code/quote keep their
   leading box for readability. */
/* Headings (--font-sans = Silka) are excluded from the trim: Silka's webfont
   metrics yield a degenerate cap box under `text-box-edge: cap alphabetic`
   (a 36px heading collapses to a ~12px box), so the glyphs overflow and clip
   against the consuming surface. The trim stays on the display roles, which use
   --font-display and trim correctly. See ADR 144 for the metric-bound caveat. */
@supports (text-box: trim-both cap alphabetic) {
  .nxt-typography[data-variant="display-01"],
  .nxt-typography[data-variant="display-02"] {
    text-box: trim-both cap alphabetic;
  }
}

.nxt-typography[data-variant="body-01"],
.nxt-typography[data-variant="body-02"] {
  color: var(--fg-secondary);
  font-family: var(--font-sans);
  font-weight: var(--weight-regular);
  text-wrap: pretty;
}
.nxt-typography[data-variant="body-01"] { font-size: var(--text-base); line-height: var(--lh-normal); }
.nxt-typography[data-variant="body-02"] { font-size: var(--text-md); line-height: var(--lh-relaxed); }

/* label-01: mono-caps eyebrow register (matches statistic/date-tile chrome). */
.nxt-typography[data-variant="label-01"] {
  color: var(--fg-tertiary);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
  line-height: var(--lh-snug);
  letter-spacing: var(--track-caps);
  text-transform: uppercase;
}

/* label-02: Barlow GX UI label — weight via variation axis, never font-weight
   (BRAND-TYPE-001, ADR 137). */
.nxt-typography[data-variant="label-02"] {
  color: var(--fg-secondary);
  font-family: var(--font-ui);
  font-size: var(--text-sm);
  font-variation-settings: var(--font-wght-barlow-medium);
  font-synthesis: none;
  line-height: var(--lh-snug);
  letter-spacing: var(--track-wide);
}

.nxt-typography[data-variant="helper-01"] {
  color: var(--fg-tertiary);
  font-family: var(--font-sans);
  font-size: var(--text-xs);
  font-weight: var(--weight-regular);
  line-height: var(--lh-normal);
}

.nxt-typography[data-variant="code-01"],
.nxt-typography[data-variant="code-02"] {
  font-family: var(--font-mono);
  font-weight: var(--weight-regular);
  line-height: var(--lh-normal);
}
.nxt-typography[data-variant="code-01"] {
  display: inline-flex;
  padding: var(--typography-code-01-padding);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-sm);
  background: var(--bg-sunken);
  font-size: var(--text-sm);
}
.nxt-typography[data-variant="code-02"] {
  display: block;
  font-size: var(--text-base);
}

.nxt-typography[data-variant="quote-01"] {
  padding-left: var(--space-4);
  border-left: 2px solid var(--border-strong);
  color: var(--fg-secondary);
  font-family: var(--font-serif);
  font-size: var(--text-lg);
  font-weight: var(--weight-regular);
  line-height: var(--lh-relaxed);
}

/* ────────────────────────────────────────────────────────────────────────
 * DateTile — Tier 2 data-display tile, sibling of WeatherTile.
 *
 * Reference: audits/references/date-tile/project/preview/components-date.html
 * (claude.ai/design handoff bundle ingested 2026-05-27).
 *
 * Layout: three text slots stacked centered — month, day, year. The
 * `weekly` variant reorders to weekday / day / month via CSS `order:`.
 *
 * Typography is BarlowGX (already declared in the WeatherTile @font-face
 * block above — same font, same /fonts/BarlowGX.woff2). Axis settings —
 * day: 'wght' 100, 'wdth' 426; labels (month / year / weekday): 'wght' 50,
 * 'wdth' 426. Day:label size ratio ≈ 2.33:1 across the size ladder.
 *
 * Eight colorways translate the bundle's clay-/lime-/peri- raw scale to
 * this project's OKLCH neutral + accent + secondary aliases — same
 * mapping as WeatherTile. Default colorway is `lime` (bundle's hero).
 * ──────────────────────────────────────────────────────────────────────── */

.nxt-date-tile {
  --tile-w: 240px;
  --tile-h: 320px;
  --ink: var(--neutral-12);
  --surface: var(--accent);
  --pad-x: var(--space-5);
  --pad-y: var(--space-4);
  --label-size: 60px;
  --day-size: 140px;
  --gap-label-day: 8px;
  --gap-day-label: 8px;
  --label-var: var(--font-var-datetile-label);
  --day-var: var(--font-var-datetile-day);
  --tile-radius: var(--radius-md);

  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0;
  width: var(--tile-w);
  height: var(--tile-h);
  padding: var(--pad-y) var(--pad-x);
  background: var(--surface);
  color: var(--ink);
  border-radius: var(--tile-radius);
  font-family: 'BarlowGX', 'Barlow', system-ui, sans-serif;
  font-optical-sizing: auto;
  user-select: none;
  box-sizing: border-box;
}
.nxt-date-tile .m,
.nxt-date-tile .y {
  font-size: var(--label-size);
  line-height: var(--lh-display);
  font-variation-settings: var(--label-var);
  margin: 0;
  color: inherit;
}
.nxt-date-tile .m { margin-bottom: var(--gap-label-day); }
.nxt-date-tile .d {
  font-size: var(--day-size);
  line-height: var(--lh-display);
  font-variation-settings: var(--day-var);
  margin: 0 0 var(--gap-day-label) 0;
  font-variant-numeric: tabular-nums;
  color: inherit;
}

/* ── Colorways (same OKLCH mapping as WeatherTile) ────────────────────── */
.nxt-date-tile.ink {
  --ink: var(--neutral-1);
  --surface: var(--neutral-12);
}
.nxt-date-tile.ink-lime {
  --ink: var(--neutral-1);
  --surface: var(--neutral-12);
}
.nxt-date-tile.ink-lime .d { color: var(--accent); }
.nxt-date-tile.lime {
  --ink: var(--neutral-12);
  --surface: var(--accent);
}
.nxt-date-tile.peri {
  --ink: var(--neutral-1);
  --surface: var(--secondary);
}
.nxt-date-tile.sand {
  --ink: var(--neutral-1);
  --surface: var(--neutral-11);
}
.nxt-date-tile.earthy {
  /* Same WCAG AA fix as WeatherTile.earthy — ink on light to clear 4.5:1. */
  --ink: var(--neutral-12);
  --surface: var(--neutral-7);
}
.dark .nxt-date-tile.earthy {
  --ink: var(--neutral-1);
}
.nxt-date-tile.outline {
  --ink: var(--neutral-12);
  --surface: var(--bg-canvas);
  border: 1px solid var(--border-default);
}
.nxt-date-tile.basic {
  --ink: var(--neutral-12);
  --surface: transparent;
  border: none;
  --pad-y: var(--space-2);
  padding: var(--pad-y) var(--pad-x);
}

/* ── Weekly variant — weekday on top, then day, then month ─────────────── */
.nxt-date-tile.weekly .m { order: 3; margin-top: var(--gap-day-label); margin-bottom: 0; }
.nxt-date-tile.weekly .d { order: 2; }
.nxt-date-tile.weekly .y { order: 1; margin-bottom: var(--gap-label-day); }

/* ── Size ladder (matches WeatherTile dimensions exactly) ─────────────── */
.nxt-date-tile.md {
  --tile-w: 176px;
  --tile-h: 232px;
  --pad-x: var(--space-4);
  --pad-y: var(--space-3);
  --label-size: 42px;
  --day-size: 98px;
  --gap-label-day: 6px;
  --gap-day-label: 6px;
  --tile-radius: 3px;
}
.nxt-date-tile.sm {
  --tile-w: 120px;
  --tile-h: 160px;
  --pad-x: var(--space-3);
  --pad-y: var(--space-3);
  --label-size: 28px;
  --day-size: 66px;
  --gap-label-day: 4px;
  --gap-day-label: 4px;
  --tile-radius: var(--radius-sm);
}
.nxt-date-tile.xs {
  --tile-w: 80px;
  --tile-h: 108px;
  --pad-x: var(--space-2);
  --pad-y: var(--space-2);
  --label-size: 18px;
  --day-size: 42px;
  --gap-label-day: 2px;
  --gap-day-label: 2px;
  --tile-radius: var(--radius-sm);
}

/* ============================================================
 * MARQUEE
 *
 * Seamless horizontal scrolling brand-mark strip. Translated 1:1 from
 * audits/references/marquee/project/preview/components-marquee.html.
 * Class names are prefixed `nxt-marquee*` to avoid colliding with
 * pre-existing `.marquee*` selectors elsewhere in the runtime.
 *
 * Two `.nxt-marquee__group` copies inside each `.nxt-marquee` row produce
 * the seamless loop; the second copy is aria-hidden in the runtime so AT
 * users hear the items exactly once.
 * ============================================================ */
.nxt-marquee-wrap {
  --tile-w: 200px;
  --tile-h: 72px;
  --gap: var(--space-3);
  --duration: 48s;
  --scroll-end: calc(-100% - var(--gap));
  --marquee-ink-surface: oklch(0.12 0.013 85);
  --marquee-ink-fg: oklch(0.98 0.013 85);

  display: flex;
  flex-direction: column;
  gap: var(--gap);
  padding: var(--space-5) 0;
  background: var(--bg-canvas);
  border: 1px solid var(--border-default);
  border-radius: 3px;
  overflow: hidden;
}

.nxt-marquee {
  display: flex;
  overflow: hidden;
  user-select: none;
  gap: var(--gap);
  -webkit-mask-image: linear-gradient(
    to right,
    transparent 0,
    #000 12%,
    #000 88%,
    transparent 100%
  );
          mask-image: linear-gradient(
    to right,
    transparent 0,
    #000 12%,
    #000 88%,
    transparent 100%
  );
}

.nxt-marquee__group {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  gap: var(--gap);
  min-width: 100%;
  animation: nxt-marquee-scroll-x var(--duration) linear infinite;
}

.nxt-marquee:hover .nxt-marquee__group {
  animation-play-state: paused;
}

.nxt-marquee.reverse .nxt-marquee__group {
  animation-direction: reverse;
  animation-delay: calc(var(--duration) / -2);
}

@keyframes nxt-marquee-scroll-x {
  from {
    transform: translateX(0);
  }
  to {
    transform: translateX(var(--scroll-end));
  }
}

@media (prefers-reduced-motion: reduce) {
  .nxt-marquee__group {
    animation-play-state: paused;
  }
}

/* ---------- Tile ---------- */
.nxt-marquee-wrap .tile {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--marquee-wrap-gap);
  width: var(--tile-w);
  height: var(--tile-h);
  background: var(--neutral-3);
  border: 1px solid transparent;
  border-radius: 3px;
  color: var(--fg-tertiary);
  transition:
    color 240ms var(--ease-smooth),
    background-color 240ms var(--ease-smooth),
    border-color 240ms var(--ease-smooth);
}
.nxt-marquee-wrap .tile:hover {
  color: var(--neutral-12);
  background: var(--bg-canvas);
  border-color: var(--neutral-4);
}
.nxt-marquee-wrap .tile .ico {
  flex: 0 0 auto;
  width: var(--marquee-tile-icon-size);
  height: var(--marquee-tile-icon-size);
  color: currentColor;
}
.nxt-marquee-wrap .tile .ico svg {
  width: 100%;
  height: 100%;
  display: block;
  fill: currentColor;
}
.nxt-marquee-wrap .tile .wm {
  font-family: var(--font-sans);
  font-weight: var(--weight-medium);
  font-size: var(--text-md);
  letter-spacing: var(--track-tight);
  line-height: var(--lh-none);
  color: currentColor;
  white-space: nowrap;
}

/* ---------- Variant: compact ---------- */
.nxt-marquee-wrap.compact {
  --tile-w: 160px;
  --tile-h: 56px;
  --gap: var(--space-2);
  --duration: 36s;
}
.nxt-marquee-wrap.compact .tile { gap: var(--marquee-tile-compact-gap); }
.nxt-marquee-wrap.compact .tile .ico { width: 16px; height: 16px; }
.nxt-marquee-wrap.compact .tile .wm { font-size: var(--text-sm); }

/* ---------- Surface: ink ---------- */
.nxt-marquee-wrap.ink,
.nxt-marquee-wrap[data-surface="ink"] {
  background: var(--marquee-ink-surface);
  border-color: var(--marquee-ink-surface);
}
.nxt-marquee-wrap.ink .tile,
.nxt-marquee-wrap[data-surface="ink"] .tile {
  background: rgba(255, 255, 255, 0.06);
  color: rgba(255, 255, 255, 0.55);
}
.nxt-marquee-wrap.ink .tile:hover,
.nxt-marquee-wrap[data-surface="ink"] .tile:hover {
  color: var(--marquee-ink-fg);
  background: rgba(255, 255, 255, 0.1);
  border-color: rgba(255, 255, 255, 0.2);
}

/* ---------- Surface: plain ---------- */
.nxt-marquee-wrap.plain {
  background: transparent;
  border-color: transparent;
}
.nxt-marquee-wrap.plain .tile { background: transparent; }
.nxt-marquee-wrap.plain .tile:hover {
  background: var(--neutral-3);
  border-color: transparent;
}

/* ============================================================
 * MENU
 *
 * Vertical navigation list with a sliding pill that follows the
 * active item. Translated from
 * audits/references/menu-tabs/project/preview/components-menu-tabs.html.
 * Class names are prefixed `nxt-menu*` to avoid colliding with the
 * native `<menu>` element selector and any pre-existing `.menu` rules.
 *
 * The pill is positioned absolutely inside `.nxt-menu-list`, behind
 * the items. The runtime measures the active button's offsetTop and
 * offsetHeight in a layout effect and writes them onto the pill via
 * inline `transform: translateY(<n>px)` + `height`. Under
 * `prefers-reduced-motion: reduce` the transition is removed — the
 * pill still jumps to position, but without animation.
 * ============================================================ */
.nxt-menu {
  --nxt-menu-item-h: var(--nav-item-block-size);
  --nxt-menu-pill-bg: var(--selection-indicator-muted-bg);
  --nxt-menu-pill-radius: var(--selection-indicator-radius);
  --nxt-menu-surface: transparent;
  --nxt-menu-ink-idle: var(--nav-item-fg);
  --nxt-menu-ink-hover: var(--nav-item-fg-hover);
  --nxt-menu-ink-active: var(--fg-primary);
  --nxt-menu-ink-danger: var(--danger);
  --nxt-menu-ease: var(--selection-indicator-ease);
  --nxt-menu-duration: var(--selection-indicator-duration);

  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  min-width: 200px;
  padding: var(--space-2);
  background: var(--nxt-menu-surface);
  border-radius: var(--radius-md);
  font-family: var(--font-sans);
}

.nxt-menu-heading {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
  letter-spacing: var(--track-wide);
  text-transform: uppercase;
  color: var(--fg-tertiary);
  padding: var(--space-2) var(--space-3) var(--space-1);
}

.nxt-menu-list {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--menu-list-gap);
}

.nxt-menu-pill {
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  height: var(--nxt-menu-item-h);
  background: var(--nxt-menu-pill-bg);
  border-radius: var(--nxt-menu-pill-radius);
  transform: translateY(0);
  transition:
    transform var(--nxt-menu-duration) var(--nxt-menu-ease),
    height var(--nxt-menu-duration) var(--nxt-menu-ease),
    opacity var(--nxt-menu-duration) var(--nxt-menu-ease);
  pointer-events: none;
  z-index: 0;
  will-change: transform, height;
}

.nxt-menu-item {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: center;
  gap: var(--nav-item-gap);
  width: 100%;
  min-block-size: var(--nxt-menu-item-h);
  padding: 0 var(--nav-item-padding-inline);
  background: transparent;
  border: 0;
  border-radius: var(--nxt-menu-pill-radius);
  color: var(--nxt-menu-ink-idle);
  font: inherit;
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  line-height: var(--lh-none);
  text-align: left;
  cursor: pointer;
  appearance: none;
  -webkit-appearance: none;
  transition:
    color var(--nxt-menu-duration) var(--nxt-menu-ease);
}

.nxt-menu-item .ico {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--menu-item-icon-size);
  height: var(--menu-item-icon-size);
  color: currentColor;
}

.nxt-menu-item .ico svg {
  width: 100%;
  height: 100%;
  display: block;
}

.nxt-menu-item .lbl {
  flex: 1 1 auto;
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.nxt-menu-item .sc {
  flex: 0 0 auto;
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: var(--weight-regular);
  color: var(--fg-tertiary);
  letter-spacing: var(--track-normal);
}

.nxt-menu-item:hover {
  color: var(--nxt-menu-ink-hover);
}

.nxt-menu-item:focus-visible {
  outline: none;
  box-shadow: var(--nav-item-focus-shadow);
}

.nxt-menu-item.active {
  color: var(--nxt-menu-ink-active);
}

.nxt-menu-sep {
  height: var(--hairline-size);
  margin: var(--space-2) var(--space-3);
  background: var(--border-subtle);
}

.nxt-menu-item.danger {
  color: var(--nxt-menu-ink-danger);
}

.nxt-menu-item.danger:hover {
  color: var(--nxt-menu-ink-danger);
  background: var(--danger-soft-bg);
}

/* ---------- Treatment: ink ----------
 * An inverse surface: dark panel with light ink in the light theme, light
 * panel with dark ink in dark. The surface has always inverted (--neutral-12
 * flips with the ladder); the ink is expressed against --fg-inverse so it
 * inverts with it. Literal whites here rendered white-on-white in dark and
 * made every ink menu unreadable — the P0 the dark captures caught.
 *
 * Percentages chosen to meet WCAG 2.2 AA (≥ 4.5:1 on small text) against the
 * inverse surface. Full --fg-inverse is ~21:1; 70% ≈ 11.6:1; 62% ≈ 8.4:1;
 * 58% ≈ 7.0:1. Below 55% the 12px shortcut hint falls under 4.5:1 and axe
 * flags it. The ratios hold in both themes: the pair inverts together.
 */
.nxt-menu.ink {
  --nxt-menu-surface: var(--neutral-12);
  --nxt-menu-pill-bg: color-mix(in oklch, var(--fg-inverse) 12%, transparent);
  --nxt-menu-ink-idle: color-mix(in oklch, var(--fg-inverse) 70%, transparent);
  --nxt-menu-ink-hover: var(--neutral-1);
  --nxt-menu-ink-active: var(--neutral-1);
  --nav-item-focus-shadow: 0 0 0 2px var(--neutral-12), 0 0 0 4px var(--focus-ring);
  padding: var(--space-3);
  border-radius: var(--radius-md);
}

.nxt-menu.ink .nxt-menu-heading {
  color: color-mix(in oklch, var(--fg-inverse) 62%, transparent);
}

.nxt-menu.ink .nxt-menu-item .sc {
  color: color-mix(in oklch, var(--fg-inverse) 62%, transparent);
}

.nxt-menu.ink .nxt-menu-sep {
  background: color-mix(in oklch, var(--fg-inverse) 10%, transparent);
}

.nxt-menu.ink .nxt-menu-item.danger {
  /* On the dark ink surface, the OKLCH --danger step (semantic-error-9)
   * resolves to a deep brick that doesn't pass 4.5:1 against neutral-12.
   * Use --semantic-error-4 (a much lighter brick) for ink-treatment danger
   * ink — same family, same hue, light enough to meet contrast. The light
   * treatment retains the deeper --danger from the parent rule.
   */
  color: var(--semantic-error-4);
}
.nxt-menu.ink .nxt-menu-item.danger:hover {
  color: var(--semantic-error-4);
  background: rgba(138, 53, 32, 0.18);
}

/* ── Drilldown — hierarchical navigation up to 3 levels. Mobile renders
 * inside the existing drawer shell; desktop renders as an inline two-pane
 * navigation surface. The visual language stays inside the shared overlay/
 * nav tokens so this component reads like a first-party sibling of Menu,
 * Drawer, and Sidebar rather than a bespoke feature surface. */
.nxt-drilldown {
  color: var(--fg-primary);
}

.nxt-drilldown-shell {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-md);
  background: var(--bg-surface);
  box-shadow: var(--overlay-panel-shadow);
  overflow: hidden;
}

.nxt-drilldown-shell.has-detail {
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
}

.nxt-drilldown-pane + .nxt-drilldown-pane {
  border-left: 1px solid var(--border-strong);
}

.nxt-drilldown.mobile {
  min-block-size: 100%;
}

.nxt-drilldown-drawer {
  padding: 0;
}

.nxt-drilldown-drawer[data-presentation="overlay"] {
  right: 0;
  inline-size: 100%;
  max-inline-size: 100%;
  border-radius: 0;
}

.nxt-drilldown-drawer[data-presentation="overlay"] .nxt-drilldown-title {
  font-size: var(--text-2xl);
  font-weight: var(--weight-medium);
  line-height: var(--lh-tight);
  letter-spacing: var(--track-tight);
}

.nxt-drilldown-drawer[data-presentation="overlay"] .nxt-drilldown-row {
  min-block-size: var(--space-8);
  padding: var(--space-5) var(--space-4);
}

.nxt-drilldown-drawer[data-presentation="overlay"] .nxt-drilldown-row-label {
  font-size: var(--text-xl);
  font-weight: var(--weight-medium);
  line-height: var(--lh-snug);
  letter-spacing: var(--track-tight);
}

.nxt-drilldown-drawer[data-presentation="overlay"] .nxt-drilldown-row-description {
  font-size: var(--text-base);
}

.nxt-drilldown-level {
  display: grid;
  align-content: start;
  min-block-size: 100%;
}

.nxt-drilldown-header {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  justify-content: space-between;
  padding: var(--space-4);
  border-bottom: 1px solid var(--border-strong);
}

.nxt-drilldown-title {
  margin: 0;
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  line-height: var(--lh-snug);
  text-wrap: balance;
}

.nxt-drilldown-back {
  display: inline-flex;
  inline-size: var(--ctrl-block-h-md);
  min-block-size: var(--ctrl-block-h-md);
  align-items: center;
  justify-content: center;
  padding: 0;
  border: 0;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--fg-secondary);
  cursor: pointer;
  font: inherit;
  transition:
    background-color var(--dur-snap) var(--ease-snap),
    color var(--dur-snap) var(--ease-snap);
}

.nxt-drilldown-close {
  display: inline-flex;
  inline-size: var(--ctrl-block-h-md);
  min-block-size: var(--ctrl-block-h-md);
  align-items: center;
  justify-content: center;
  padding: 0;
  border: 0;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--fg-secondary);
  cursor: pointer;
  font: inherit;
  transition:
    background-color var(--dur-snap) var(--ease-snap),
    color var(--dur-snap) var(--ease-snap);
}

.nxt-drilldown-list {
  list-style: none;
  margin: 0;
  padding: var(--space-2);
  display: grid;
  gap: var(--space-1);
}

.nxt-drilldown-cascade {
  list-style: none;
  margin: 0;
  padding: var(--space-2);
  display: grid;
  gap: var(--space-1);
  border-bottom: 1px solid var(--border-strong);
}

.nxt-drilldown-cascade-button {
  display: inline-flex;
  width: 100%;
  min-block-size: var(--ctrl-block-h-2xl);
  align-items: center;
  justify-content: space-between;
  padding: var(--space-5) var(--space-4);
  border: 0;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--fg-primary);
  cursor: pointer;
  font: inherit;
  text-align: left;
  transition:
    background-color var(--dur-snap) var(--ease-snap),
    color var(--dur-snap) var(--ease-snap);
}

.nxt-drilldown-cascade-button[aria-current="step"] {
  background: var(--neutral-soft-bg);
}

.nxt-drilldown-cascade-label {
  font-size: var(--text-2xl);
  font-weight: var(--weight-medium);
  line-height: var(--lh-tight);
  letter-spacing: var(--track-tight);
}

.nxt-drilldown-row {
  display: inline-flex;
  align-items: center;
  width: 100%;
  min-block-size: var(--ctrl-block-h-md);
  gap: var(--space-3);
  padding: var(--space-3);
  border: 0;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--fg-primary);
  cursor: pointer;
  font: inherit;
  text-align: left;
  text-decoration: none;
  transition:
    background-color var(--dur-snap) var(--ease-snap),
    color var(--dur-snap) var(--ease-snap),
    transform var(--dur-instant) var(--ease-smooth);
}

.nxt-drilldown-row-main {
  display: grid;
  gap: var(--space-1);
  min-width: 0;
  flex: 1 1 auto;
}

.nxt-drilldown-row-label {
  color: inherit;
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  line-height: var(--lh-snug);
}

.nxt-drilldown-row-description {
  color: var(--fg-secondary);
  font-size: var(--text-xs);
  line-height: var(--lh-normal);
  text-wrap: pretty;
}

.nxt-drilldown-row-icon,
.nxt-drilldown-row-trailing {
  color: var(--fg-tertiary);
  flex: 0 0 auto;
}

.nxt-drilldown-row.active {
  background: var(--neutral-soft-bg);
  color: var(--fg-primary);
}

@media (hover: hover) {
  .nxt-drilldown-back:hover,
  .nxt-drilldown-close:hover,
  .nxt-drilldown-cascade-button:hover,
  .nxt-drilldown-row:hover {
    background: var(--neutral-soft-bg);
    color: var(--fg-primary);
  }
}

.nxt-drilldown-back:focus-visible,
.nxt-drilldown-close:focus-visible,
.nxt-drilldown-cascade-button:focus-visible,
.nxt-drilldown-row:focus-visible {
  outline: none;
  /* Literal on purpose: custom properties substitute where the token is
     defined (:root), so a local --focus-ring-gap-color can never reach
     --focus-ring-shadow-gap. See docs/plans/focus-ring-inventory.md. */
  box-shadow: 0 0 0 2px var(--bg-surface), 0 0 0 4px var(--focus-ring);
}

.nxt-drilldown-row:active {
  transform: scale(0.97);
}

/* ---------- Reduced motion ---------- */
@media (prefers-reduced-motion: reduce) {
  .nxt-menu-pill {
    transition: none;
  }
  .nxt-menu-item {
    transition: none;
  }
  .nxt-drilldown-back,
  .nxt-drilldown-close,
  .nxt-drilldown-cascade-button,
  .nxt-drilldown-row {
    transition: none;
  }
}
/* ============================================================
 * TABS
 *
 * Underline + pill tab strips with a sliding active-tab indicator.
 * Translated from audits/references/menu-tabs/project/preview/
 * components-menu-tabs.html. The bundle's bare `.tabs` / `.tab` /
 * `.tabs-pill` selectors are prefixed `nxt-*` to isolate from any
 * pre-existing rules.
 *
 * The sliding indicator position + width are driven by the runtime
 * (useLayoutEffect reads the active tab's offsetLeft + offsetWidth) and
 * expressed as CSS variables so movement stays on transform.
 * ============================================================ */

/* ---------- Underline variant ---------- */
.nxt-tabs {
  --nxt-tabs-motion-duration: var(--selection-indicator-duration);
  --nxt-tabs-motion-ease: var(--selection-indicator-ease);
  --nxt-tabs-indicator-x: 0px;
  --nxt-tabs-indicator-w: 0px;

  position: relative;
  display: inline-flex;
  align-items: stretch;
  gap: 0;
  max-inline-size: 100%;
  overflow-x: auto;
  border-bottom: 1px solid var(--border-subtle);
  font-family: var(--font-sans);
  scrollbar-gutter: stable;
}

.nxt-tabs-indicator {
  position: absolute;
  bottom: var(--tabs-indicator-bottom);
  left: 0;
  width: var(--nxt-tabs-indicator-w, 0px);
  height: var(--tabs-indicator-thickness);
  background: var(--selection-indicator-bg);
  border-radius: var(--selection-indicator-radius);
  opacity: 0;
  transform: translate3d(var(--nxt-tabs-indicator-x, 0px), 0, 0);
  transform-origin: left center;
  transition:
    opacity var(--dur-snap) var(--ease-snap),
    transform var(--nxt-tabs-motion-duration) var(--nxt-tabs-motion-ease),
    width var(--nxt-tabs-motion-duration) var(--nxt-tabs-motion-ease);
  pointer-events: none;
  will-change: transform, width;
}

.nxt-tab {
  flex: 0 0 auto;
  appearance: none;
  background: transparent;
  border: 0;
  min-block-size: var(--ctrl-block-h-sm);
  padding: var(--tab-padding);
  font: inherit;
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  letter-spacing: 0;
  line-height: var(--lh-none);
  color: var(--fg-tertiary);
  cursor: pointer;
  transition:
    color var(--dur-fast) var(--ease-smooth),
    transform var(--dur-snap) var(--ease-snap);
  white-space: nowrap;
}

.nxt-tab:hover {
  color: var(--fg-primary);
}

.nxt-tab.active,
.nxt-tab[aria-selected="true"] {
  color: var(--neutral-12);
}

.nxt-tab:active {
  transform: scale(0.96);
}

.nxt-tab:focus-visible {
  outline: 2px solid var(--focus-ring);
  outline-offset: 2px;
  border-radius: 2px;
}

/* ---------- Pill variant ---------- */
.nxt-tabs-pill {
  --nxt-tabs-motion-duration: var(--selection-indicator-duration);
  --nxt-tabs-motion-ease: var(--selection-indicator-ease);
  --nxt-tabs-indicator-x: 0px;
  --nxt-tabs-indicator-w: 0px;

  position: relative;
  display: inline-flex;
  align-items: stretch;
  gap: var(--pattern-controls-copy-gap);
  max-inline-size: 100%;
  overflow-x: auto;
  padding: var(--tabs-pill-padding);
  background: var(--bg-sunken);
  border: 1px solid var(--border-subtle);
  border-radius: 8px;
  font-family: var(--font-sans);
  scrollbar-gutter: stable;
}

.nxt-tabs-pill-bg {
  position: absolute;
  top: var(--tabs-pill-bg-top);
  bottom: var(--tabs-pill-bg-bottom);
  left: 0;
  width: var(--nxt-tabs-indicator-w, 0px);
  background: var(--selection-indicator-surface);
  border: 1px solid var(--selection-indicator-border);
  border-radius: var(--selection-indicator-radius);
  box-shadow: var(--selection-indicator-shadow);
  opacity: 0;
  transform: translate3d(var(--nxt-tabs-indicator-x, 0px), 0, 0);
  transform-origin: left center;
  transition:
    opacity var(--dur-snap) var(--ease-snap),
    transform var(--nxt-tabs-motion-duration) var(--nxt-tabs-motion-ease),
    width var(--nxt-tabs-motion-duration) var(--nxt-tabs-motion-ease);
  pointer-events: none;
  z-index: 0;
  will-change: transform, width;
}

.nxt-tab-pill {
  position: relative;
  z-index: 1;
  flex: 0 0 auto;
  appearance: none;
  background: transparent;
  border: 0;
  padding: var(--tab-pill-padding);
  height: var(--tabs-pill-block-size-md);
  font: inherit;
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  line-height: var(--lh-none);
  letter-spacing: 0;
  color: var(--fg-tertiary);
  cursor: pointer;
  transition:
    color var(--dur-fast) var(--ease-smooth),
    transform var(--dur-snap) var(--ease-snap);
  white-space: nowrap;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--nav-item-gap);
  border-radius: var(--nav-item-radius);
}

.nxt-tab-pill:hover {
  color: var(--fg-primary);
}

.nxt-tab-pill.active,
.nxt-tab-pill[aria-selected="true"] {
  color: var(--neutral-12);
}

.nxt-tab-pill:active {
  transform: scale(0.96);
}

.nxt-tab-pill:focus-visible {
  outline: 2px solid var(--focus-ring);
  outline-offset: 2px;
}

.nxt-tab-pill .ico {
  flex: 0 0 auto;
  width: var(--tabs-pill-icon-size-md);
  height: var(--tabs-pill-icon-size-md);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: currentColor;
}
.nxt-tab-pill .ico svg {
  width: 100%;
  height: 100%;
  display: block;
}

.nxt-tab-pill.icon-only {
  padding: 0;
  width: 28px;
  justify-content: center;
}

/* ---------- Pill size: sm ---------- */
.nxt-tabs-pill.sm {
  padding: var(--tabs-pill-sm-padding);
  border-radius: 7px;
  gap: var(--tabs-pill-gap);
}
.nxt-tabs-pill.sm .nxt-tabs-pill-bg {
  top: var(--tabs-pill-sm-bg-top);
  bottom: var(--tabs-pill-sm-bg-bottom);
  border-radius: var(--selection-indicator-radius);
}
.nxt-tabs-pill.sm .nxt-tab-pill {
  height: var(--tabs-pill-block-size-sm);
  padding: var(--tabs-pill-sm-tab-padding);
  font-size: var(--text-xs);
  border-radius: var(--nav-item-radius);
}
.nxt-tabs-pill.sm .nxt-tab-pill.icon-only {
  width: 24px;
  padding: 0;
}
.nxt-tabs-pill.sm .nxt-tab-pill .ico {
  width: var(--tabs-pill-icon-size-sm);
  height: var(--tabs-pill-icon-size-sm);
}

/* ---------- Pill size: lg ---------- */
.nxt-tabs-pill.lg {
  padding: var(--tabs-pill-lg-padding);
  border-radius: 10px;
  gap: var(--tabs-pill-lg-gap);
}
.nxt-tabs-pill.lg .nxt-tabs-pill-bg {
  top: var(--tabs-pill-lg-bg-top);
  bottom: var(--tabs-pill-bottom);
  border-radius: var(--selection-indicator-radius);
}
.nxt-tabs-pill.lg .nxt-tab-pill {
  height: var(--ctrl-block-h-sm);
  padding: var(--tabs-pill-lg-tab-padding);
  font-size: var(--text-base);
  border-radius: var(--nav-item-radius);
}
.nxt-tabs-pill.lg .nxt-tab-pill.icon-only {
  width: 36px;
  padding: 0;
}
.nxt-tabs-pill.lg .nxt-tab-pill .ico {
  width: var(--tabs-pill-icon-size-lg);
  height: var(--tabs-pill-icon-size-lg);
}

/* ---------- Pill treatment: dark ---------- */
/* Fixed-dark surface (does NOT follow page color-scheme inversion). Idle and
   hover label inks are solid mid-light neutrals on the dark surface — chosen
   over the bundle's translucent-white overlays because axe-core analyses the
   .lbl text colour against the page bg rather than the ancestor pill surface,
   which would fire color-contrast on the alpha-blended values. The dark
   surface remains identical to the bundle's visual intent; only the idle/hover
   label colours are solid instead of translucent. See ADR-079. */
.nxt-tabs-pill.nxt-tabs-pill--ink {
  background: var(--neutral-12);
  border-color: var(--neutral-12);
}
.nxt-tabs-pill.nxt-tabs-pill--ink .nxt-tabs-pill-bg {
  background: rgba(255, 255, 255, 0.10);
  border-color: rgba(255, 255, 255, 0.16);
  box-shadow: none;
}
.nxt-tabs-pill.nxt-tabs-pill--ink .nxt-tab-pill {
  background: var(--neutral-12);
  color: var(--neutral-4);
}
.nxt-tabs-pill.nxt-tabs-pill--ink .nxt-tab-pill:hover {
  color: var(--neutral-1);
}
.nxt-tabs-pill.nxt-tabs-pill--ink .nxt-tab-pill.active,
.nxt-tabs-pill.nxt-tabs-pill--ink .nxt-tab-pill[aria-selected="true"] {
  background: transparent;
  color: var(--neutral-1);
}

/* ---------- Reduced motion ---------- */
@media (prefers-reduced-motion: reduce) {
  .nxt-tabs-indicator,
  .nxt-tabs-pill-bg,
  .nxt-tab,
  .nxt-tab-pill {
    transition: none;
  }
  .nxt-tab:active,
  .nxt-tab-pill:active {
    transform: none;
  }
}

/* ============================================================
 * SEPARATOR
 *
 * Thin visual divider between content sections. Wraps Radix
 * react-separator. Horizontal = 1px tall, 100% wide. Vertical =
 * 1px wide, 100% tall (parent must establish height).
 * ============================================================ */
.nxt-separator {
  background-color: var(--border-default);
  flex-shrink: 0;
}
.nxt-separator[data-orientation="horizontal"] {
  height: var(--hairline-size);
  width: 100%;
}
.nxt-separator[data-orientation="vertical"] {
  width: 1px;
  height: 100%;
}

/* ============================================================
 * SKELETON
 *
 * Pulse-animated placeholder for loading content. Tier-2 hand-
 * rolled (no primitive fits). aria-hidden="true" — consumers
 * compose to match the shape of the actual content.
 * ============================================================ */
.nxt-skeleton {
  background-color: var(--neutral-3);
  animation: nxt-skeleton-pulse calc(var(--dur-deliberate) * 2) var(--ease-in-out) infinite;
  display: block;
}
.nxt-skeleton[data-shape="rectangular"] {
  border-radius: var(--radius-md);
  width: 100%;
  height: 1rem;
}
.nxt-skeleton[data-shape="circle"] {
  border-radius: 9999px;
  width: 2.5rem;
  height: 2.5rem;
}
.nxt-skeleton[data-shape="text"] {
  border-radius: var(--radius-sm);
  width: 100%;
  height: 1em;
  line-height: var(--lh-none);
}
.nxt-skeleton-row {
  display: grid;
  gap: var(--surface-frame-gap);
  padding: var(--surface-frame-padding);
}
.nxt-skeleton-line {
  display: block;
  inline-size: 100%;
  border-radius: var(--radius-sm);
  background-color: var(--neutral-3);
  animation: nxt-skeleton-pulse calc(var(--dur-deliberate) * 2) var(--ease-in-out) infinite;
}
.nxt-skeleton-line[data-role="title"] {
  block-size: calc(var(--text-base) * var(--lh-snug));
}
.nxt-skeleton-line[data-role="description"] {
  block-size: calc(var(--text-sm) * var(--lh-normal));
}
.nxt-skeleton-line[data-role="meta"] {
  block-size: calc(var(--text-xs) * var(--lh-tight));
}

@keyframes nxt-skeleton-pulse {
  0%, 100% {
    background-color: var(--neutral-3);
  }
  50% {
    background-color: var(--neutral-4);
  }
}

@media (prefers-reduced-motion: reduce) {
  .nxt-skeleton,
  .nxt-skeleton-line {
    animation: none;
  }
}

/* ============================================================
 * INPUT OTP
 *
 * Fixed-length one-time-passcode input. Tier-2 wrapper over the
 * input-otp library. Per-slot visible chrome; the library carries
 * paste / focus / keyboard behavior.
 *
 * Slot box matches text-input chrome (border, radius, focus ring)
 * for visual coherence across the form-control family.
 * ============================================================ */
.nxt-input-otp {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
}

.nxt-input-otp-group {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  pointer-events: none;
}

.nxt-input-otp-slot {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background-color: var(--field-frame-bg);
  border: var(--field-frame-border-width) solid var(--field-frame-border);
  border-radius: var(--field-frame-radius);
  color: var(--field-frame-fg);
  font-family: var(--font-mono);
  font-weight: var(--weight-medium);
  pointer-events: none;
  transition: border-color var(--dur-fast) var(--ease-smooth), background-color var(--dur-fast) var(--ease-smooth);
}

.nxt-input-otp-slot[data-size="sm"] {
  width: 32px;
  height: var(--input-otp-slot-block-size-sm);
  font-size: var(--text-sm);
}
.nxt-input-otp-slot[data-size="md"] {
  width: 40px;
  height: var(--input-otp-slot-block-size-md);
  font-size: var(--text-base);
}
.nxt-input-otp-slot[data-size="lg"] {
  width: 48px;
  height: var(--input-otp-slot-block-size-lg);
  font-size: var(--text-lg);
}

.nxt-input-otp-slot.active {
  border-color: var(--field-frame-border-focus);
  box-shadow: var(--field-frame-focus-shadow);
  outline-offset: 2px;
}

.nxt-input-otp-slot[data-state="filled"] {
  background-color: var(--field-frame-bg);
}

/* Disabled — the underlying single input carries `disabled`; the DS-rendered
   slots mirror the form-control family's disabled chrome so a disabled OTP is
   visually distinct from a filled/default one. */
.nxt-input-otp:has(input:disabled) .nxt-input-otp-slot {
  background-color: var(--input-bg-disabled);
  border-color: var(--input-border-disabled);
  color: var(--input-fg-disabled);
}

.nxt-input-otp-slot-char {
  line-height: var(--lh-none);
}

.nxt-input-otp-slot-caret {
  position: absolute;
  width: 1px;
  height: 1em;
  background-color: var(--accent);
  animation: nxt-input-otp-caret-blink 1.1s ease-in-out infinite;
}

.nxt-input-otp-separator {
  color: var(--fg-tertiary);
  font-family: var(--font-mono);
  font-size: var(--text-lg);
  user-select: none;
}

@keyframes nxt-input-otp-caret-blink {
  0%, 50% {
    opacity: 1;
  }
  51%, 100% {
    opacity: 0;
  }
}

@media (prefers-reduced-motion: reduce) {
  .nxt-input-otp-slot-caret {
    animation: none;
    opacity: 1;
  }
  .nxt-input-otp-slot {
    transition: none;
  }
}

/* ============================================================
 * AUTOCOMPLETE
 *
 * Text input + popover-positioned filtered option list. Tier-2
 * composition over Radix Popover; combobox behaviour is implemented
 * in the component (not cmdk).
 *
 * Input chrome reuses text-input visual language. Popover surface
 * reuses the popover/tooltip elevation pattern. Option highlight
 * reuses the select active-item pattern.
 * ============================================================ */
.nxt-autocomplete {
  display: inline-block;
  position: relative;
}

.nxt-autocomplete-input-wrap {
  position: relative;
  display: flex;
  align-items: center;
}

.nxt-autocomplete-input {
  width: 100%;
  background-color: var(--field-frame-bg);
  border: var(--field-frame-border-width) solid var(--field-frame-border);
  border-radius: var(--field-frame-radius);
  color: var(--field-frame-fg);
  font-family: var(--font-sans);
  font-size: var(--text-base);
  padding: 0 var(--space-3);
  outline: none;
  transition: border-color var(--dur-fast) var(--ease-smooth);
}

/* Heights consume the canonical control ladder (--ctrl-block-h-*) so an
 * autocomplete lines up with text-input/select in the same form row and
 * tracks density. Previously hard literals (32/40/48px) sat 4px short of
 * the md ladder. */
.nxt-autocomplete-input[data-size="sm"] { height: var(--ctrl-block-h-sm); font-size: var(--text-sm); }
.nxt-autocomplete-input[data-size="md"] { height: var(--ctrl-block-h-md); font-size: var(--text-base); }
.nxt-autocomplete-input[data-size="lg"] { height: var(--ctrl-block-h-lg); font-size: var(--text-lg); }

.nxt-autocomplete-input:focus {
  border-color: var(--field-frame-border-focus);
  box-shadow: var(--field-frame-focus-shadow);
  outline-offset: 2px;
}

.nxt-autocomplete-input:disabled {
  background-color: var(--field-frame-bg-disabled);
  color: var(--field-frame-fg-disabled);
  cursor: not-allowed;
}

.nxt-autocomplete-spinner {
  position: absolute;
  right: var(--space-3);
  width: var(--autocomplete-spinner-size);
  height: var(--autocomplete-spinner-size);
  border: 2px solid var(--neutral-4);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: nxt-autocomplete-spin 0.7s linear infinite;
}

.nxt-autocomplete-popover {
  min-width: var(--radix-popover-trigger-width, 200px);
  background-color: var(--overlay-panel-bg);
  color: var(--overlay-panel-fg);
  border: 1px solid var(--overlay-panel-border);
  border-radius: var(--overlay-panel-radius);
  box-shadow: var(--overlay-panel-shadow);
  z-index: var(--z-overlay);
  overflow: hidden;
  max-height: 320px;
}

.nxt-autocomplete-list {
  overflow-y: auto;
  padding: var(--space-1);
  max-height: 280px;
  list-style: none;
  margin: 0;
}

.nxt-autocomplete-empty {
  padding: var(--space-3);
  color: var(--fg-tertiary);
  font-size: var(--text-sm);
  text-align: center;
}

.nxt-autocomplete-group-label {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: var(--track-wide);
  text-transform: uppercase;
  color: var(--fg-tertiary);
  padding: var(--space-2) var(--space-2) var(--space-1);
}

.nxt-autocomplete-option {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-sm);
  cursor: pointer;
  font-size: var(--text-sm);
  color: var(--fg-primary);
  transition: background-color 120ms var(--ease-smooth);
}

/* Active = keyboard cursor (aria-activedescendant). Selected = current value. */
.nxt-autocomplete-option[data-active] {
  background-color: var(--accent-soft-bg);
}

.nxt-autocomplete-option[data-selected] {
  font-weight: var(--weight-medium);
}

.nxt-autocomplete-option[data-disabled] {
  color: var(--fg-tertiary);
  cursor: not-allowed;
  pointer-events: none;
}

.nxt-autocomplete-option-label {
  flex: 1;
}

.nxt-autocomplete-option-desc {
  color: var(--fg-secondary);
  font-size: var(--text-xs);
}

.nxt-autocomplete-check {
  color: var(--accent);
  flex-shrink: 0;
}

@keyframes nxt-autocomplete-spin {
  to { transform: rotate(360deg); }
}

@media (prefers-reduced-motion: reduce) {
  .nxt-autocomplete-spinner,
  .nxt-autocomplete-option,
  .nxt-autocomplete-input {
    animation: none;
    transition: none;
  }
}

/* ============================================================
 * SHEET
 *
 * Shares .nxt-drawer-content + .nxt-drawer-overlay rules (no
 * duplicate chrome). Sheet adds slot styling (header/footer/title/
 * description/close button) for the shadcn-aligned API.
 * ============================================================ */
.nxt-sheet-content {
  display: flex;
  flex-direction: column;
  padding: var(--space-5);
  gap: var(--space-3);
}

.nxt-sheet-header {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  padding-bottom: var(--space-2);
}

.nxt-sheet-title {
  font-family: var(--font-display, var(--font-sans));
  font-size: var(--text-lg);
  font-weight: var(--weight-medium);
  color: var(--fg-primary);
  margin: 0;
  line-height: var(--lh-snug);
}

.nxt-sheet-description {
  font-size: var(--text-sm);
  color: var(--fg-secondary);
  margin: 0;
  line-height: var(--lh-heading);
}

.nxt-sheet-footer {
  display: flex;
  justify-content: flex-end;
  gap: var(--space-2);
  margin-top: auto;
  padding-top: var(--space-3);
}

.nxt-sheet-close {
  position: absolute;
  top: var(--space-3);
  right: var(--space-3);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--ctrl-hit-min-compact);
  height: var(--ctrl-hit-min-compact);
  background: transparent;
  border: none;
  color: var(--fg-tertiary);
  cursor: pointer;
  border-radius: var(--radius-sm);
  transition: color var(--dur-fast) var(--ease-smooth), background-color var(--dur-fast) var(--ease-smooth);
}

.nxt-sheet-close[data-custom-content] {
  width: auto;
  min-width: 44px;
  min-height: var(--ctrl-block-h-xl);
  padding-inline: var(--space-2);
  font-family: var(--font-sans);
  font-size: var(--text-base);
  font-weight: var(--weight-medium);
  line-height: var(--lh-normal);
}

.nxt-drawer-content[data-fullscreen] .nxt-sheet-title {
  font-size: var(--text-xl);
  line-height: var(--lh-tight);
}

.nxt-sheet-close:hover {
  color: var(--fg-primary);
  background-color: var(--neutral-3);
}

.nxt-sheet-close:focus-visible {
  box-shadow: 0 0 0 2px var(--focus-ring);
}

@media (prefers-reduced-motion: reduce) {
  .nxt-sheet-close {
    transition: none;
  }
}

/* ──────────────────────────────────────────────────────────────────────────
 * PREVIEW EXAMPLE WRAPPER (P5 Phase 4)
 *
 * Each example on a generated /preview/<name>/ route is wrapped in a div
 * carrying data-preview-example="<example-name>". Runtime gates use that
 * attribute as a stable scoping selector (Phase 5 rendered-value runtime
 * check, future per-example assertions).
 *
 * display: contents — the wrapper exists in the DOM (for the selector) but
 * is transparent to layout, so each example renders as a direct child of
 * the preview flex row (preserves existing visual baselines).
 *
 * Safety: this rule applies only to dev-only preview routes that ship the
 * component catalog to engineers, not to user-facing surfaces. Modern Safari
 * (15.4+, 2022) correctly preserves the descendant accessibility tree for
 * display: contents. End-user a11y is unaffected — only preview-route DOM
 * inspection in older Safari would see the wrapper "vanish" from the
 * accessibility tree, which is fine for the catalog use case.
 * ────────────────────────────────────────────────────────────────────── */
.nxt-preview-example {
  display: contents;
}

/* ──────────────────────────────────────────────────────────────────────────
 * SYSTEM HOME + GENERATED DIAGRAMS
 * Root documentation surfaces use Page/Card/navigation recipes with a small
 * layout layer for the generated Mermaid map and route cards.
 * ────────────────────────────────────────────────────────────────────── */
.nxt-system-home {
  min-block-size: var(--viewport-block-full);
  max-inline-size: none;
  gap: var(--space-0);
  overflow-x: clip;
  background: var(--bg-canvas);
}

.nxt-system-hero,
.nxt-system-sections {
  inline-size: var(--docs-shell-inline-size);
  margin-inline: auto;
  padding-inline: var(--space-4);
}

.nxt-system-hero {
  display: grid;
  gap: var(--space-5);
  padding-block: var(--space-6);
  border-block-end: 1px solid var(--border-subtle);
}

.nxt-system-hero-copy {
  display: grid;
  gap: var(--space-2);
  max-inline-size: var(--system-hero-copy-measure);
  min-inline-size: 0;
}

.nxt-components-sort-control {
  display: grid;
  gap: var(--space-1);
  inline-size: min(100%, var(--field-w-medium));
  margin-block-start: var(--space-2);
}

.nxt-components-sort-label {
  color: var(--fg-secondary);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  line-height: var(--lh-normal);
}

.nxt-components-sort-select {
  min-block-size: var(--ctrl-block-h-md);
  padding-block: var(--ctrl-block-pad-md);
  padding-inline: var(--ctrl-inline-pad-md);
  color: var(--field-frame-fg);
  background: var(--field-frame-bg);
  border: var(--field-frame-border-width) solid var(--field-frame-border);
  border-radius: var(--field-frame-radius);
  font: inherit;
  font-size: var(--text-sm);
  line-height: var(--lh-normal);
  transition:
    border-color var(--dur-snap) var(--ease-snap),
    box-shadow var(--dur-fast) var(--ease-smooth);
}

@media (hover: hover) {
  .nxt-components-sort-select:hover {
    border-color: var(--field-frame-border-hover);
  }
}

.nxt-components-sort-select:focus-visible {
  outline: none;
  border-color: var(--field-frame-border-focus);
  box-shadow: var(--field-frame-focus-shadow);
}

.nxt-system-sections {
  display: grid;
  gap: var(--space-6);
  padding-block: var(--space-6);
}

.nxt-system-stat-grid {
  align-self: start;
}

.nxt-system-home .nxt-card,
.nxt-system-home code {
  min-inline-size: 0;
}

.nxt-system-home code {
  overflow-wrap: anywhere;
}


/* Global docs header — the single top bar across every docs surface. Holds the
 * brand wordmark and global search; cross-page navigation lives in the sidebar
 * rail below. Consumes only existing tokens + the eyebrow + nav-item classes. */
.nxt-docs-header {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3) var(--space-5);
  inline-size: 100%;
  padding-block: var(--space-4);
  padding-inline: var(--space-4);
  border-block-end: 1px solid var(--border-subtle);
  background: var(--bg-canvas);
}

.nxt-docs-header-search {
  margin-inline-start: auto;
  inline-size: 100%;
  max-inline-size: var(--docs-header-search-max-inline-size);
}

.nxt-docs-brand {
  display: inline-grid;
  gap: var(--docs-brand-gap);
  text-decoration: none;
  border-radius: var(--nav-item-radius);
}

.nxt-docs-brand:focus-visible {
  outline: none;
  box-shadow: var(--nav-item-focus-shadow);
}

.nxt-docs-brand-name {
  color: var(--fg-primary);
  font-size: var(--text-lg);
  font-weight: var(--weight-medium);
  line-height: var(--lh-tight);
  letter-spacing: var(--track-tight);
}

/* The docs brand suffix is an eyebrow-role label (it always carries
   .nxt-page-eyebrow). Its caps tracking existed only to space the uppercase the
   eyebrow role no longer applies; tracking now comes from --eyebrow-tracking. */
.nxt-docs-brand-suffix {
  letter-spacing: var(--eyebrow-tracking);
}

.nxt-system-work-grid {
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 17rem), 1fr));
}

.nxt-system-work-card .nxt-card-content {
  padding-block-start: 0;
}

.nxt-system-mermaid {
  display: grid;
  gap: var(--space-4);
  min-inline-size: 0;
  margin: 0;
}

.nxt-system-mermaid-caption {
  display: grid;
  gap: var(--space-2);
  max-inline-size: var(--preview-section-header-measure);
  min-inline-size: 0;
}

.nxt-system-mermaid-frame {
  contain: inline-size;
  display: grid;
  align-items: center;
  min-block-size: var(--system-mermaid-frame-min-block-size-expanded);
  max-inline-size: 100%;
  overflow: auto;
  padding: var(--space-4);
  border: 1px solid var(--border-subtle);
  border-radius: var(--surface-frame-radius);
  background: var(--bg-surface);
  scrollbar-gutter: stable both-edges;
}

.nxt-system-mermaid-svg {
  min-inline-size: var(--system-mermaid-svg-min-inline-size);
}

.nxt-system-mermaid-svg svg {
  display: block;
  max-inline-size: none;
}

.nxt-system-mermaid-status {
  margin: 0;
  color: var(--fg-secondary);
  font-size: var(--text-sm);
}

.nxt-system-summary-list {
  display: grid;
  gap: var(--space-2);
  margin: 0;
  padding-inline-start: var(--space-5);
  color: var(--fg-secondary);
  font-size: var(--text-sm);
  line-height: var(--lh-normal);
}

.nxt-system-summary-list li {
  min-inline-size: 0;
  overflow-wrap: anywhere;
}

.nxt-system-mermaid-source {
  min-inline-size: 0;
}

.nxt-system-mermaid-source summary {
  cursor: pointer;
  color: var(--fg-primary);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
}

.nxt-system-mermaid-source summary:focus-visible {
  outline: none;
  box-shadow: var(--surface-frame-focus-shadow);
}

.visual-drift-review {
  min-block-size: var(--viewport-block-full);
}

.visual-drift-review-header {
  padding-block-end: var(--space-6);
  border-block-end: 1px solid var(--border-subtle);
}

.visual-drift-review-header-grid {
  display: grid;
  gap: var(--space-5);
  min-inline-size: 0;
}

.visual-drift-review-copy {
  display: grid;
  gap: var(--space-3);
  min-inline-size: 0;
  max-inline-size: var(--system-mermaid-caption-caption-measure);
}

.visual-drift-summary-title {
  margin: 0;
  color: var(--fg-primary);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  line-height: var(--lh-snug);
}

.visual-drift-summary-content,
.visual-drift-review-list,
.visual-drift-proposal-stack,
.visual-drift-proposal-copy,
.visual-drift-screenshot-items {
  display: grid;
  min-inline-size: 0;
}

.visual-drift-summary-content {
  gap: var(--space-4);
}

.visual-drift-summary-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--space-3);
  margin: 0;
  font-size: var(--text-sm);
}

.visual-drift-summary-grid dt {
  color: var(--fg-secondary);
}

.visual-drift-summary-grid dd {
  margin: var(--space-1) 0 0;
  color: var(--fg-primary);
  font-weight: var(--weight-medium);
  font-variant-numeric: tabular-nums;
}

.visual-drift-save-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3);
}

.visual-drift-save-status {
  min-block-size: var(--time-picker-step-block-size);
  margin: 0;
  color: var(--fg-secondary);
  font-size: var(--text-sm);
}

.visual-drift-review-list {
  gap: var(--space-5);
}

.visual-drift-proposal-stack {
  gap: var(--space-5);
}

.visual-drift-proposal-grid {
  display: grid;
  gap: var(--space-5);
  min-inline-size: 0;
}

.visual-drift-proposal-copy {
  gap: var(--space-4);
}

.visual-drift-proposal-copy p {
  max-inline-size: var(--visual-drift-proposal-copy-p-measure);
  margin: 0;
  color: var(--fg-secondary);
  font-size: var(--text-sm);
  line-height: var(--lh-relaxed);
}

.visual-drift-affected-list {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin: 0;
  padding: 0;
  list-style: none;
}

.visual-drift-screenshot-grid {
  display: grid;
  gap: var(--space-4);
  min-inline-size: 0;
}

.visual-drift-screenshot-frame {
  min-inline-size: 0;
  margin: 0;
  padding: var(--space-3);
  border: 1px solid var(--border-subtle);
  border-radius: var(--surface-frame-radius);
  background: var(--bg-sunken);
}

.visual-drift-screenshot-frame figcaption {
  color: var(--fg-tertiary);
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
  line-height: var(--lh-snug);
  letter-spacing: var(--track-caps);
  text-transform: uppercase;
}

.visual-drift-screenshot-stage {
  margin-block-start: var(--space-3);
  padding: var(--space-3);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-sm);
  background: var(--bg-surface);
}

.visual-drift-screenshot-chrome {
  display: flex;
  align-items: center;
  gap: var(--visual-drift-screenshot-chrome-gap);
  padding-block-end: var(--space-2);
  border-block-end: 1px solid var(--border-subtle);
}

.visual-drift-screenshot-chrome span {
  inline-size: var(--visual-drift-screenshot-chrome-span-inline-size);
  block-size: var(--visual-drift-screenshot-bar-block-size);
  border-radius: var(--radius-full);
  background: var(--fg-tertiary);
  opacity: 0.5;
}

.visual-drift-screenshot-chrome span[data-level="medium"] {
  opacity: 0.35;
}

.visual-drift-screenshot-chrome span[data-level="weak"] {
  opacity: 0.25;
}

.visual-drift-screenshot-items {
  gap: var(--space-2);
  margin-block-start: var(--space-3);
}

.visual-drift-screenshot-row {
  display: flex;
  min-block-size: var(--visual-drift-screenshot-row-min-block-size);
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-sm);
  background: var(--bg-surface);
  color: var(--fg-secondary);
  font-size: var(--text-xs);
}

.visual-drift-screenshot-row[data-tone="after"] {
  color: var(--fg-primary);
}

.visual-drift-screenshot-row[data-emphasis="muted"] {
  border-style: dashed;
  background: var(--bg-sunken);
}

.visual-drift-screenshot-bar {
  flex: 0 0 auto;
  inline-size: var(--visual-drift-screenshot-bar-inline-size);
  block-size: var(--visual-drift-screenshot-chrome-span-block-size);
  border-radius: var(--radius-full);
  background: var(--border-default);
}

.visual-drift-screenshot-row[data-tone="after"] .visual-drift-screenshot-bar {
  inline-size: var(--visual-drift-screenshot-row-data-tone-after-visu-after-inline-size);
  background: var(--fg-primary);
}

@media (min-width: 960px) {
  .visual-drift-review-header-grid {
    grid-template-columns: minmax(0, 1fr) minmax(20rem, auto);
    align-items: end;
  }

  .visual-drift-proposal-grid {
    grid-template-columns: minmax(0, 1fr) minmax(21rem, 0.85fr);
  }
}

@media (min-width: 768px) {
  .visual-drift-screenshot-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (min-width: 960px) and (max-width: 1199px) {
  .visual-drift-screenshot-grid {
    grid-template-columns: minmax(0, 1fr);
  }
}

.nxt-motion-token-grid,
.nxt-motion-demo-grid {
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 18rem), 1fr));
}

.nxt-motion-demo-stack {
  display: grid;
  gap: var(--space-5);
  min-inline-size: 0;
}

.nxt-motion-demo-example {
  display: grid;
  gap: var(--space-3);
  min-inline-size: 0;
  max-inline-size: 100%;
  overflow-x: auto;
  padding-block-end: var(--space-1);
  scrollbar-gutter: stable;
}

.nxt-motion-table-scroll {
  contain: inline-size;
  max-inline-size: 100%;
  overflow-x: auto;
  border: 1px solid var(--border-subtle);
  border-radius: var(--surface-frame-radius);
  background: var(--bg-surface);
  scrollbar-gutter: stable both-edges;
}

.nxt-motion-table {
  inline-size: 100%;
  min-inline-size: var(--motion-table-min-inline-size);
  border-collapse: collapse;
  color: var(--fg-secondary);
  font-size: var(--text-sm);
  line-height: var(--lh-normal);
}

.nxt-motion-table caption {
  position: absolute;
  overflow: hidden;
  inline-size: var(--sr-only-size);
  block-size: var(--sr-only-size);
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

.nxt-motion-table th,
.nxt-motion-table td {
  padding: var(--space-3);
  border-block-end: 1px solid var(--border-subtle);
  text-align: start;
  vertical-align: top;
}

.nxt-motion-table thead th {
  color: var(--fg-secondary);
  font-weight: var(--weight-medium);
}

.nxt-motion-table tbody th {
  color: var(--fg-primary);
  font-weight: var(--weight-medium);
}

.nxt-motion-table tbody tr:last-child th,
.nxt-motion-table tbody tr:last-child td {
  border-block-end: 0;
}

.nxt-page-transition-demo-card .nxt-card-content {
  padding-block-start: 0;
}

.nxt-page-transition-demo-layout {
  display: grid;
  gap: var(--space-4);
  min-inline-size: 0;
}

.nxt-page-transition-demo-controls {
  display: grid;
  gap: var(--space-3);
  align-content: start;
  min-inline-size: 0;
}

.nxt-page-transition-demo-status {
  margin: 0;
  color: var(--fg-secondary);
  font-size: var(--text-sm);
  line-height: var(--lh-normal);
}

.nxt-page-transition-demo-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}

.nxt-page-transition-demo-stage {
  min-inline-size: 0;
  min-block-size: var(--page-transition-demo-min-block-size);
  overflow: clip;
  border: 1px solid var(--border-subtle);
  border-radius: var(--surface-frame-radius);
  background:
    radial-gradient(circle at 12% 14%, var(--accent-soft-bg), transparent 36%),
    radial-gradient(circle at 88% 90%, var(--secondary-soft-bg), transparent 34%),
    var(--bg-sunken);
}

.nxt-page-transition-demo-shell {
  --page-transition-duration: 380ms;
  --page-transition-enter-y: 13rem;
  --page-transition-exit-y: -4rem;
  --page-transition-mask-size: 8rem;
  --page-transition-blur-1: 0.0625em;
  --page-transition-blur-2: 0.125em;
  --page-transition-blur-3: 0.25em;
  --page-transition-blur-4: 0.5em;
  --page-transition-blur-5: 0.875em;

  min-block-size: var(--page-transition-demo-min-block-size);
  overflow: clip;
  border-radius: inherit;
}

.nxt-page-transition-demo-shell .nxt-page-transition__stack {
  min-block-size: inherit;
}

.nxt-page-transition-demo-page {
  display: grid;
  align-content: start;
  gap: var(--space-4);
  min-block-size: var(--page-transition-demo-min-block-size);
  padding: var(--space-4);
  color: var(--fg-primary);
  background: color-mix(in oklch, var(--bg-surface) 94%, transparent);
}

.nxt-page-transition-demo-page-header {
  display: grid;
  gap: var(--space-2);
  min-inline-size: 0;
}

.nxt-page-transition-demo-page-header h3 {
  margin: 0;
  color: var(--fg-primary);
  font-size: var(--text-xl);
  font-weight: var(--weight-medium);
  line-height: var(--lh-tight);
}

.nxt-page-transition-demo-page-header p:last-child {
  max-inline-size: var(--page-transition-demo-copy-measure);
  margin: 0;
  color: var(--fg-secondary);
  font-size: var(--text-sm);
  line-height: var(--lh-relaxed);
}

.nxt-page-transition-demo-metrics {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--space-2);
  margin: 0;
}

.nxt-page-transition-demo-metrics div {
  min-inline-size: 0;
  padding: var(--space-3);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-sm);
  background: var(--bg-surface);
}

.nxt-page-transition-demo-metrics dt {
  color: var(--fg-secondary);
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
  letter-spacing: var(--track-caps);
  line-height: var(--lh-tight);
  text-transform: uppercase;
}

.nxt-page-transition-demo-metrics dd {
  margin: var(--space-1) 0 0;
  color: var(--fg-primary);
  font-size: var(--text-xl);
  font-weight: var(--weight-medium);
  font-variant-numeric: tabular-nums;
  line-height: var(--lh-tight);
}

.nxt-page-transition-demo-list {
  display: grid;
  gap: var(--space-2);
  margin: 0;
  padding-inline-start: var(--space-5);
  color: var(--fg-secondary);
  font-size: var(--text-sm);
  line-height: var(--lh-normal);
}

.nxt-page-transition-demo-list li {
  min-inline-size: 0;
  overflow-wrap: anywhere;
}

@media (min-width: 960px) {
  .nxt-page-transition-demo-layout {
    grid-template-columns: minmax(16rem, 0.65fr) minmax(0, 1.35fr);
    align-items: start;
  }
}

@media (max-width: 389px) {
  .nxt-page-transition-demo-metrics {
    grid-template-columns: 1fr;
  }
}

@media (min-width: 960px) {
  .nxt-system-hero,
  .nxt-system-sections {
    padding-inline: var(--space-5);
  }

  .nxt-system-hero {
    grid-template-columns: minmax(0, 1.45fr) minmax(18rem, 0.8fr);
    align-items: start;
  }

  .nxt-system-hero-copy {
    grid-column: 1;
  }

  .nxt-system-stat-grid {
    grid-column: 2;
    grid-row: 1;
  }
}

@media (max-width: 767px) {
  .nxt-system-hero,
  .nxt-system-sections {
    padding-inline: var(--space-3);
  }

  .nxt-system-mermaid-frame {
    min-block-size: var(--pattern-grid-min-block-size);
    padding: var(--space-3);
  }
}

/* ──────────────────────────────────────────────────────────────────────────
 * PREVIEW HOME + CATALOG SHELL
 * /preview uses system Page/Card/Button/Field recipes plus these layout
 * recipes. They intentionally consume semantic aliases and spacing tokens
 * instead of local Tailwind utility styling.
 * ────────────────────────────────────────────────────────────────────── */
.nxt-preview-home {
  min-block-size: var(--viewport-block-full);
  max-inline-size: none;
  gap: var(--space-0);
  overflow-x: clip;
  background: var(--bg-canvas);
}

.nxt-preview-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  min-block-size: var(--viewport-block-full);
  inline-size: 100%;
}

.nxt-preview-rail {
  display: grid;
  order: 2;
  align-content: start;
  gap: var(--space-5);
  min-inline-size: 0;
  padding: var(--space-4);
  border-block-end: 1px solid var(--border-subtle);
  background: var(--bg-canvas);
}

.nxt-preview-brand {
  color: var(--fg-primary);
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
  letter-spacing: var(--track-caps);
  text-decoration: none;
  text-transform: uppercase;
}

.nxt-preview-brand:focus-visible,
.nxt-preview-inline-link:focus-visible,
.nxt-preview-chip-link:focus-visible {
  outline: none;
  box-shadow: var(--surface-frame-focus-shadow);
}

.nxt-preview-nav,
.nxt-preview-nav-group,
.nxt-preview-nav-list {
  display: grid;
  min-inline-size: 0;
}

.nxt-preview-nav {
  gap: var(--space-5);
}

.nxt-preview-nav-group {
  gap: var(--space-2);
}

.nxt-preview-nav-list,
.nxt-preview-chip-list,
.nxt-preview-path-list,
.nxt-preview-dependency-list {
  margin: 0;
  padding: 0;
  list-style: none;
}

.nxt-preview-nav-list {
  gap: var(--space-1);
}

.nxt-preview-nav-heading {
  margin: 0;
  color: var(--fg-tertiary);
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
  line-height: var(--lh-snug);
  text-transform: uppercase;
  letter-spacing: var(--track-caps);
}

.nxt-preview-nav-link {
  inline-size: 100%;
  justify-content: flex-start;
}

.nxt-preview-main {
  order: 1;
  min-inline-size: 0;
  overflow-x: clip;
}

.nxt-preview-hero,
.nxt-preview-sections {
  inline-size: var(--system-shell-inline-size);
  margin-inline: auto;
  padding-inline: var(--space-4);
}

.nxt-preview-hero {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-5);
  padding-block: var(--space-6);
  border-block-end: 1px solid var(--border-subtle);
}

.nxt-preview-hero-copy {
  display: grid;
  gap: var(--space-2);
  max-inline-size: var(--preview-hero-copy-measure);
}

.nxt-preview-hero-actions {
  justify-content: flex-start;
}

.nxt-preview-action-icon {
  flex: 0 0 auto;
}

.nxt-preview-stat-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
  gap: var(--space-3);
  margin: 0;
}

.nxt-preview-stat-grid div {
  min-inline-size: 0;
  padding: var(--space-3);
  border: 1px solid var(--border-subtle);
  border-radius: var(--surface-frame-radius);
  background: var(--bg-surface);
}

.nxt-preview-stat-grid dt {
  color: var(--fg-tertiary);
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
  text-transform: uppercase;
  letter-spacing: var(--track-caps);
}

.nxt-preview-stat-grid dd {
  margin: var(--space-1) 0 0;
  color: var(--fg-primary);
  font-size: var(--text-2xl);
  font-weight: var(--weight-medium);
  line-height: var(--lh-tight);
  font-variant-numeric: tabular-nums;
}

/* Rhythm QA surface (/preview/rhythm) — renders each --stack-gap-* role against a
   real specimen with its measured px, so a component off the ladder is visible at
   a glance rather than by grep. Dev/QA affordance, not a product component. */
.nxt-rhythm-lead {
  margin: var(--space-5) 0 0;
  max-width: 68ch;
  color: var(--fg-secondary);
  font-size: var(--text-sm);
  line-height: var(--lh-relaxed);
}

.nxt-rhythm-list {
  display: flex;
  flex-direction: column;
  gap: var(--stack-gap-section);
  margin-block-start: var(--stack-gap-section);
  padding: 0;
  list-style: none;
}

.nxt-rhythm-token {
  display: flex;
  align-items: baseline;
  gap: var(--space-2);
}

.nxt-rhythm-step {
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  color: var(--accent-soft-fg);
  background: var(--accent-soft-bg);
  border-radius: var(--radius-sm);
  padding: 0 var(--space-1);
  font-variant-numeric: tabular-nums;
}

.nxt-rhythm-row {
  display: grid;
  grid-template-columns: minmax(0, 16rem) minmax(0, 1fr);
  gap: var(--space-5);
  align-items: start;
  padding-block-start: var(--stack-gap-content);
  border-block-start: 1px solid var(--border-subtle);
}

.nxt-rhythm-meta {
  display: flex;
  flex-direction: column;
  gap: var(--stack-gap-heading);
}

.nxt-rhythm-role {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--fg-primary);
}

.nxt-rhythm-relationship {
  margin: 0;
  color: var(--fg-secondary);
  font-size: var(--text-sm);
  line-height: var(--lh-normal);
}

.nxt-rhythm-sample {
  margin: 0;
  color: var(--fg-tertiary);
  font-size: var(--text-xs);
  line-height: var(--lh-normal);
}

.nxt-rhythm-specimen {
  position: relative;
  padding: var(--space-4);
  padding-inline-end: var(--space-8);
  border: 1px solid var(--border-subtle);
  border-radius: var(--surface-frame-radius);
  background: var(--bg-surface);
}

.nxt-rhythm-stack {
  display: flex;
  flex-direction: column;
}

/* The readout measures the rendered box rather than echoing the token, so an
   overridden gap reports its real number here. */
.nxt-rhythm-readout {
  position: absolute;
  inset-block-start: var(--space-2);
  inset-inline-end: var(--space-2);
  color: var(--fg-tertiary);
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  font-variant-numeric: tabular-nums;
}

/* Enforcement sample — a realistic product surface + governance notes, rendered
   in the docs reading column. Tokens only. */
.nxt-enforcement-section {
  margin-block-start: var(--space-8);
}

.nxt-enforcement-section-head {
  /* Same head -> body boundary as .nxt-cv-block-head, and it bounds the same
     `related`-separated .nxt-cv-block-body. */
  margin-block-end: var(--stack-gap-section);
}

.nxt-enforcement-panel {
  display: grid;
  gap: var(--space-5);
}

.nxt-enforcement-panel-head {
  display: grid;
  gap: var(--stack-gap-content);
}

.nxt-enforcement-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 20rem);
  gap: var(--space-6);
  align-items: start;
}

.nxt-enforcement-grid-form {
  display: grid;
  gap: var(--space-5);
  min-inline-size: 0;
}

.nxt-enforcement-grid-aside {
  display: flex;
  flex-direction: column;
  gap: var(--stack-gap-heading);
  min-inline-size: 0;
}

@media (max-width: 767px) {
  .nxt-enforcement-grid {
    grid-template-columns: minmax(0, 1fr);
  }
}

.nxt-enforcement-rules {
  display: grid;
  gap: var(--space-4);
  margin: 0;
  padding: 0;
  list-style: none;
}

.nxt-enforcement-rules > li {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: var(--space-3);
  align-items: baseline;
  color: var(--fg-secondary);
  font-size: var(--text-sm);
  line-height: var(--lh-relaxed);
}

.nxt-enforcement-rule-recipe {
  display: inline-flex;
}

/* Linkable system statement — the whole stat card is a navigable link to the
 * canonical surface that shows the counted items. Card-link pattern: a
 * pseudo-element fills the cell so the entire card is clickable while the
 * focusable anchor stays on the value. Tokens only. */
.nxt-system-stat-cell {
  position: relative;
  transition-property: border-color;
  transition-duration: var(--dur-fast);
  transition-timing-function: var(--ease-snap);
}

.nxt-system-stat-link {
  color: inherit;
  text-decoration: none;
}

.nxt-system-stat-link::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: var(--surface-frame-radius);
}

.nxt-system-stat-link:focus-visible {
  outline: none;
}

.nxt-system-stat-link:focus-visible::after {
  box-shadow: var(--surface-frame-focus-shadow);
}

@media (hover: hover) {
  .nxt-system-stat-cell:hover {
    border-color: var(--border-strong);
  }

  .nxt-system-stat-cell:hover .nxt-system-stat-link {
    text-decoration: underline;
    text-underline-offset: 3px;
  }
}

.nxt-preview-mode-panel,
.nxt-preview-filter-bar {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 13rem), 1fr));
  gap: var(--space-3);
  min-inline-size: 0;
  padding: var(--space-3);
  border: 1px solid var(--border-subtle);
  border-radius: var(--surface-frame-radius);
  background: var(--bg-sunken);
}

.nxt-preview-stress-sample {
  display: grid;
  align-content: end;
  gap: var(--space-1);
  min-inline-size: 0;
  color: var(--fg-secondary);
  font-size: var(--text-xs);
  line-height: var(--lh-snug);
}

.nxt-preview-stress-sample strong {
  overflow-wrap: anywhere;
  color: var(--fg-primary);
  font-size: var(--text-sm);
  line-height: var(--lh-normal);
}

.nxt-preview-sections {
  display: grid;
  gap: var(--space-6);
  padding-block: var(--space-6);
}

.nxt-preview-section,
.nxt-preview-category,
.nxt-catalog-component {
  display: grid;
  gap: var(--space-4);
  min-inline-size: 0;
  scroll-margin-block-start: var(--space-5);
}

.nxt-preview-section {
  padding-block-end: var(--space-6);
  border-block-end: 1px solid var(--border-subtle);
  overflow-x: clip;
}

.nxt-preview-section:last-child {
  border-block-end: 0;
}

.nxt-preview-section-header,
.nxt-catalog-component-copy {
  display: grid;
  gap: var(--space-2);
  min-inline-size: 0;
  max-inline-size: var(--visual-drift-review-copy-measure);
}

/* Editorial text wrapping for the docs page/section template: balanced headings,
   orphan-free descriptions. Scoped to the hero/section-header containers so it
   never touches component-example copy in the frozen specimen grid. */
.nxt-system-hero-copy .nxt-page-title,
.nxt-preview-section-header .nxt-page-section-title {
  text-wrap: balance;
}

.nxt-system-hero-copy .nxt-page-description,
.nxt-preview-section-header .nxt-page-description {
  text-wrap: pretty;
}

.nxt-table-pattern-row-actions {
  display: grid;
  gap: var(--action-gap);
}

.nxt-table-pattern-example-stack {
  display: grid;
  gap: var(--stack-gap-related);
}

.nxt-table-pattern-action-status {
  min-block-size: var(--space-5);
  margin: 0;
  color: var(--fg-secondary);
  font-size: var(--text-sm);
  line-height: var(--lh-normal);
}

.nxt-preview-link-grid,
.nxt-preview-component-grid,
.nxt-catalog-example-grid,
.nxt-preview-dependency-grid,
.nxt-preview-mcp-grid {
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 19rem), 1fr));
}

.nxt-preview-link-card,
.nxt-preview-component-card,
.nxt-catalog-example-card,
.nxt-preview-empty-card,
.nxt-preview-command-card,
.nxt-preview-home .nxt-card {
  min-inline-size: 0;
}

.nxt-preview-link-card .nxt-card-description,
.nxt-preview-component-card .nxt-card-description {
  overflow-wrap: anywhere;
}

.nxt-preview-card-footer,
.nxt-preview-card-meta {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  align-items: center;
  justify-content: space-between;
  min-inline-size: 0;
}

.nxt-preview-card-meta {
  justify-content: flex-start;
  color: var(--fg-tertiary);
  font-size: var(--text-sm);
  font-variant-numeric: tabular-nums;
}

.nxt-preview-filter-field {
  min-inline-size: 0;
}

.nxt-preview-result-count {
  margin: 0;
  color: var(--fg-tertiary);
  font-size: var(--text-sm);
  font-variant-numeric: tabular-nums;
  line-height: var(--lh-normal);
}

.nxt-preview-demo-index {
  display: grid;
  gap: var(--space-3);
  min-inline-size: 0;
  inline-size: 100%;
  padding: var(--space-3);
  border: 1px solid var(--border-subtle);
  border-radius: var(--surface-frame-radius);
  background: var(--bg-surface);
}

.nxt-preview-demo-index-header {
  display: grid;
  gap: var(--space-1);
  min-inline-size: 0;
}

.nxt-preview-demo-index-title {
  margin: 0;
  color: var(--fg-primary);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  line-height: var(--lh-snug);
}

.nxt-preview-demo-index-nav {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  min-inline-size: 0;
}

.nxt-preview-matrix-shell {
  display: grid;
  gap: 0;
  inline-size: 100%;
  align-content: start;
  padding: 0;
  background: var(--bg-canvas);
}

.nxt-preview-matrix-subheader,
.nxt-preview-matrix-section {
  display: grid;
  gap: var(--space-3);
  min-inline-size: 0;
}

/* Full-bleed spec-sheet band: soft warm neutral with a hairline base.
   The band runs edge to edge; the inner grid caps content at 80rem. */
.nxt-preview-matrix-header {
  background: var(--bg-sunken);
  border-block-end: 1px solid var(--border-subtle);
  padding: var(--space-5) var(--space-6);
}

.nxt-preview-matrix-header-inner {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(16rem, 22rem);
  gap: var(--space-4);
  align-items: center;
  max-inline-size: var(--preview-matrix-header-inner-measure);
}

.nxt-preview-matrix-body {
  display: grid;
  gap: var(--space-7);
  align-content: start;
  padding: var(--space-6);
}

.nxt-preview-matrix-heading,
.nxt-preview-matrix-controls,
.nxt-preview-matrix-subheader {
  min-inline-size: 0;
}

.nxt-preview-matrix-heading {
  display: grid;
  gap: var(--space-2);
  justify-items: start;
}

.nxt-preview-matrix-controls {
  justify-self: end;
  align-self: center;
  min-inline-size: var(--preview-matrix-controls-min-inline-size);
}

.nxt-preview-matrix-eyebrow {
  color: var(--fg-tertiary);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
  letter-spacing: var(--track-caps);
  text-transform: uppercase;
}

.nxt-preview-matrix-subheader {
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: end;
  max-inline-size: var(--preview-matrix-subheader-measure);
  padding-block-end: var(--space-2);
  border-block-end: 1px solid var(--border-subtle);
}

.nxt-preview-matrix-subheading {
  display: grid;
  gap: var(--space-1);
  min-inline-size: 0;
}

.nxt-preview-matrix-title,
.nxt-preview-matrix-subtitle,
.nxt-preview-matrix-cell-title {
  margin: 0;
  color: var(--fg-primary);
  font-weight: var(--weight-medium);
}

.nxt-preview-matrix-title {
  font-size: var(--text-3xl);
  line-height: var(--lh-tight);
  letter-spacing: var(--track-snug);
  text-wrap: balance;
}

.nxt-preview-matrix-subtitle {
  font-size: var(--text-lg);
  line-height: var(--lh-tight);
}

/* Mono spec line — counts update when the view switches, so tabular
   numerals keep the line from shifting. */
.nxt-preview-matrix-spec {
  margin: 0;
  color: var(--fg-secondary);
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  line-height: var(--lh-normal);
  font-variant-numeric: tabular-nums;
}

.nxt-preview-matrix-count {
  color: var(--fg-tertiary);
  font-weight: var(--weight-medium);
}

.nxt-preview-matrix-axes {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin: var(--space-1) 0 0;
  padding: 0;
  list-style: none;
}

.nxt-preview-matrix-axis-chip {
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-sm);
  background: var(--bg-surface);
  padding: 2px var(--space-2);
  color: var(--fg-secondary);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  line-height: var(--lh-snug);
  font-variant-numeric: tabular-nums;
}

/* Theme Studio reuses the spec-sheet band register (eyebrow/title/spec/count
   classes above); this container adapts the band to the studio panel. */
.nxt-theme-band {
  background: var(--bg-sunken);
  border-block-end: 1px solid var(--border-subtle);
  padding: var(--space-5) var(--space-6);
}

.nxt-theme-band-inner {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: var(--space-4);
  align-items: center;
  margin-inline: auto;
  max-inline-size: var(--theme-band-inner-measure);
}

@media (max-width: 767px) {
  .nxt-theme-band {
    padding-inline: var(--space-4);
  }

  .nxt-theme-band-inner {
    grid-template-columns: minmax(0, 1fr);
  }

  .nxt-theme-band-actions {
    justify-content: flex-start;
  }
}

.nxt-preview-matrix-grid {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  gap: var(--space-4);
  align-items: start;
  margin: 0;
  padding: 0;
  list-style: none;
}

.nxt-preview-matrix-item,
.nxt-preview-matrix-cell {
  min-inline-size: 0;
}

.nxt-preview-matrix-item {
  position: relative;
  grid-column: span 4;
}

.nxt-preview-matrix-item:has(.nxt-split-button-menu) {
  z-index: var(--z-overlay);
}

.nxt-preview-matrix-item[data-preview-width="wide"] {
  grid-column: span 6;
}

.nxt-preview-matrix-item[data-preview-width="full"] {
  grid-column: 1 / -1;
}

.nxt-preview-matrix-cell {
  --preview-cell-pad: var(--space-4);
  display: grid;
  gap: var(--space-3);
  align-content: start;
  block-size: 100%;
  padding: var(--preview-cell-pad);
  border: 1px solid var(--border-subtle);
  border-radius: var(--surface-frame-radius);
  background: var(--bg-surface);
}

.nxt-preview-matrix-cell[data-copyable-source="true"] {
  gap: var(--stack-gap-related);
}

.nxt-preview-matrix-item[data-preview-frame="bleed"] .nxt-preview-matrix-cell-preview {
  inline-size: calc(100% + var(--preview-cell-pad) + var(--preview-cell-pad));
  margin-inline: calc(-1 * var(--preview-cell-pad));
}

.nxt-preview-matrix-cell-title {
  overflow-wrap: anywhere;
  font-size: var(--text-sm);
  line-height: var(--lh-snug);
}

.nxt-preview-matrix-axis-list {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin: 0;
  color: var(--fg-secondary);
  font-size: var(--text-xs);
  line-height: var(--lh-normal);
}

.nxt-preview-matrix-axis-pair {
  display: inline-flex;
  min-inline-size: 0;
  gap: var(--space-1);
}

.nxt-preview-matrix-axis-pair dt,
.nxt-preview-matrix-axis-pair dd {
  margin: 0;
}

.nxt-preview-matrix-axis-pair dt {
  color: var(--fg-tertiary);
}

.nxt-preview-matrix-axis-pair dd {
  color: var(--fg-primary);
}

.nxt-preview-matrix-cell-preview {
  display: flex;
  align-items: flex-start;
  justify-content: flex-start;
  min-block-size: var(--preview-matrix-cell-preview-min-block-size);
  min-inline-size: 0;
  overflow: visible;
  padding-block-start: var(--space-1);
}

.nxt-preview-matrix-item[data-preview-scroll="horizontal"] .nxt-preview-matrix-cell-preview {
  overflow-x: auto;
}

.nxt-preview-matrix-cell-preview:has(.nxt-split-button-menu) {
  overflow: visible;
}

/* SearchBox opens an absolutely-positioned suggestions panel. In preview cells
   reserve vertical room and stop clipping so every example's open dropdown
   (highlighted, many-results, loading, error) is fully visible. Scoped to cells
   that actually render a panel, so closed examples keep the default height. */
.nxt-preview-matrix-cell-preview:has(.nxt-search-box-panel) {
  overflow: visible;
  min-block-size: var(--search-box-panel-max-block-size);
}

.nxt-preview-matrix-cell-preview:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring-shadow-gap);
}

@media (max-width: 959px) {
  .nxt-preview-matrix-header-inner {
    grid-template-columns: 1fr;
    align-items: stretch;
  }

  .nxt-preview-matrix-controls {
    justify-self: stretch;
    min-inline-size: 0;
  }

  .nxt-preview-matrix-item {
    grid-column: span 6;
  }

  .nxt-preview-matrix-item[data-preview-width="full"] {
    grid-column: 1 / -1;
  }
}

@media (max-width: 767px) {
  /* Component docs otherwise nest desktop padding four levels deep, leaving
     only 146px for a specimen at the canonical 390px review width. Preserve
     outer breathing room, but let the matrix own its internal cell padding. */
  .nxt-cv-shell {
    padding-inline: var(--space-4);
  }

  .nxt-cv-block-body:has(> .nxt-preview-matrix-shell) {
    padding: 0;
  }

  .nxt-preview-matrix-header {
    padding-inline: var(--space-4);
  }

  .nxt-preview-matrix-body {
    padding-inline: 0;
  }

  .nxt-preview-matrix-grid {
    grid-template-columns: minmax(0, 1fr);
  }

  .nxt-preview-matrix-item,
  .nxt-preview-matrix-item[data-preview-width="wide"],
  .nxt-preview-matrix-item[data-preview-width="full"] {
    grid-column: 1;
  }
}

.nxt-preview-category-title {
  margin: 0;
  color: var(--fg-primary);
  font-size: var(--text-lg);
  font-weight: var(--weight-medium);
  line-height: var(--lh-tight);
  text-wrap: balance;
}

.nxt-preview-path-list,
.nxt-preview-dependency-list {
  display: grid;
  gap: var(--space-2);
  color: var(--fg-secondary);
  font-size: var(--text-sm);
  line-height: var(--lh-normal);
}

.nxt-preview-path-list code,
.nxt-preview-code code {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
}

.nxt-preview-path-list code {
  overflow-wrap: anywhere;
  color: var(--fg-primary);
}

.nxt-preview-chip-list {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  min-inline-size: 0;
}

.nxt-preview-chip-list .nxt-badge {
  max-inline-size: 100%;
}

.nxt-preview-chip-list .nxt-badge-label {
  white-space: normal;
  overflow-wrap: anywhere;
}

.nxt-catalog-spec-strip {
  display: grid;
  gap: var(--space-2);
  min-inline-size: 0;
  margin-block-start: var(--space-1);
  font-variant-numeric: tabular-nums;
}

.nxt-catalog-spec-strip-row {
  display: grid;
  grid-template-columns: max-content minmax(0, 1fr);
  gap: var(--space-2);
  align-items: start;
  min-inline-size: 0;
}

.nxt-catalog-spec-strip-label {
  color: var(--fg-tertiary);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--track-caps);
  line-height: var(--lh-snug);
  text-transform: uppercase;
}

/* Component facts — contract-driven facts card on the /preview catalog.
 * One hairline outer border; inner items stay flat (no card-in-card).
 * Absent contract data renders the muted Pending chip by design. */
.nxt-catalog-facts {
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  padding: var(--space-3) var(--space-4);
  display: grid;
  gap: var(--space-3);
}

.nxt-catalog-facts-title {
  margin: 0;
  color: var(--fg-tertiary);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--track-caps);
  line-height: var(--lh-snug);
  text-transform: uppercase;
}

.nxt-catalog-facts-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
  /* Row gap matches the column gap so the single-column stack stays clear of the
     item's own internal gap above. */
  gap: var(--space-4);
}

.nxt-catalog-facts-item {
  display: grid;
  /* Label -> value is a heading-block boundary over chips that themselves wrap
     at `--space-1`; at `--space-1` the label sat as close to the chips as the
     chips sit to each other. One rung up keeps the label reading as the label. */
  gap: var(--space-2);
  align-content: start;
  min-inline-size: 0;
}

.nxt-catalog-facts-label {
  color: var(--fg-tertiary);
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
  line-height: var(--lh-snug);
}

.nxt-catalog-facts-text {
  margin: 0;
  color: var(--fg-secondary);
  font-size: var(--text-sm);
  line-height: var(--lh-normal);
}

.nxt-catalog-facts-list {
  margin: 0;
  padding-inline-start: var(--space-4);
  color: var(--fg-secondary);
  font-size: var(--text-sm);
  line-height: var(--lh-normal);
}

/* New DataTable recipes should not consume more of the kitchen-sink's legacy
   flush-list allowance. Give this component's example list a real item rhythm. */
[data-kitchen-sink-component="data-table"] .nxt-catalog-facts-list {
  display: grid;
  gap: var(--stack-gap-heading);
}

.nxt-catalog-facts-chips {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1);
}

.nxt-catalog-facts-chip {
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-full);
  padding: 0 var(--space-2);
  color: var(--fg-secondary);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  line-height: var(--lh-relaxed);
  overflow-wrap: anywhere;
}

.nxt-catalog-facts-pending {
  display: inline-block;
  width: fit-content; /* grid items stretch by default — keep the chip compact */
  border-radius: var(--radius-full);
  padding: 0 var(--space-2);
  background: var(--bg-sunken);
  color: var(--fg-muted);
  font-size: var(--text-xs);
  line-height: var(--lh-relaxed);
}

.nxt-catalog-facts-link {
  color: var(--fg-secondary);
  font-size: var(--text-xs);
  text-decoration: underline;
  text-underline-offset: 2px;
  width: fit-content;
}

.nxt-preview-chip-link,
.nxt-preview-inline-link {
  border-radius: var(--control-frame-radius);
  color: var(--fg-primary);
  font-weight: var(--weight-medium);
  text-decoration: underline;
  text-decoration-color: var(--border-strong);
  text-underline-offset: 0.18em;
}

.nxt-preview-chip-link {
  display: inline-flex;
  align-items: center;
  min-block-size: var(--ctrl-block-h-sm);
  padding-inline: var(--space-3);
  border: 1px solid var(--border-subtle);
  text-decoration: none;
}

@media (hover: hover) {
  .nxt-preview-chip-link:hover,
  .nxt-preview-inline-link:hover {
    background: var(--bg-sunken);
    text-decoration-color: currentColor;
  }
}

.nxt-preview-dependency-list li {
  display: grid;
  gap: var(--space-1);
  min-inline-size: 0;
  padding-block: var(--space-2);
  border-block-end: 1px solid var(--border-subtle);
}

.nxt-preview-dependency-list li:last-child {
  border-block-end: 0;
}

.nxt-preview-dependency-list span {
  overflow-wrap: anywhere;
}

.nxt-preview-code {
  contain: inline-size;
  overflow-x: auto;
  max-inline-size: 100%;
  margin: 0;
  padding: var(--space-3);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  background: var(--bg-sunken);
  color: var(--fg-primary);
  line-height: var(--lh-relaxed);
  scrollbar-gutter: stable both-edges;
}

.nxt-preview-code code {
  white-space: pre;
}

.nxt-catalog-component {
  padding-block-end: var(--space-5);
  border-block-end: 1px solid var(--border-subtle);
  overflow-x: clip;
}

.nxt-catalog-component:last-child {
  border-block-end: 0;
}

.nxt-catalog-component-header {
  display: grid;
  gap: var(--space-3);
  min-inline-size: 0;
}

.nxt-catalog-component-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  align-items: center;
}

.nxt-catalog-example-grid {
  align-items: stretch;
}

.nxt-catalog-example-card {
  contain: inline-size;
  max-inline-size: none;
  overflow: clip;
}

.nxt-catalog-example-card .nxt-card-header,
.nxt-catalog-example-card .nxt-card-content {
  min-inline-size: 0;
}

.nxt-catalog-example-viewport {
  display: grid;
  align-items: center;
  contain: inline-size;
  min-block-size: var(--catalog-example-viewport-min-block-size);
  min-inline-size: 0;
  max-inline-size: 100%;
  overflow-x: auto;
  overflow-y: visible;
  padding-block: var(--space-2);
  scrollbar-gutter: stable;
}

.nxt-catalog-example-fit {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3);
  min-inline-size: 0;
  max-inline-size: 100%;
}

.nxt-catalog-example-fit > * {
  max-inline-size: 100%;
}

.nxt-pattern-page,
.nxt-pattern-gallery,
.nxt-pattern-family,
.nxt-pattern-frame-scroll,
.nxt-pattern-panel,
.nxt-pattern-fit,
.nxt-pattern-split,
.nxt-pattern-list {
  display: grid;
  min-inline-size: 0;
}

.nxt-pattern-gallery {
  gap: var(--space-6);
  inline-size: 100%;
  container-type: inline-size;
}

.nxt-pattern-gallery[data-constrained="true"] {
  inline-size: 100%;
  max-inline-size: 100%;
}

.nxt-pattern-family,
.nxt-pattern-panel,
.nxt-pattern-fit {
  gap: var(--space-4);
}

.nxt-pattern-frame {
  contain: inline-size;
  scroll-margin-block-start: calc(var(--space-10) + var(--space-8));
}

.nxt-pattern-gallery[data-constrained="true"] .nxt-pattern-grid {
  grid-template-columns: minmax(0, 1fr);
}

.nxt-pattern-gallery[data-constrained="true"] .nxt-pattern-frame-scroll {
  overflow-x: auto;
  overscroll-behavior-inline: contain;
}

.nxt-pattern-gallery[data-constrained="true"] .nxt-pattern-frame-scroll:focus-visible {
  outline: 2px solid var(--focus-ring);
  outline-offset: 2px;
}

.nxt-pattern-gallery[data-constrained="true"] .nxt-pattern-frame {
  inline-size:
    calc(
      var(--pattern-vw) +
      var(--card-padding) +
      var(--card-padding) +
      2px
    );
  min-inline-size:
    calc(
      var(--pattern-vw) +
      var(--card-padding) +
      var(--card-padding) +
      2px
    );
  max-inline-size: none;
}

.nxt-pattern-family-chip {
  justify-self: start;
  color: var(--fg-tertiary);
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
  letter-spacing: 0;
  line-height: var(--lh-tight);
  text-transform: uppercase;
}

.nxt-pattern-frame-intent {
  display: -webkit-box;
  overflow: hidden;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 1;
}

.nxt-pattern-stage {
  align-items: stretch;
  padding: var(--space-3);
  background: var(--bg-sunken);
}

.nxt-pattern-gallery[data-constrained="true"] .nxt-pattern-stage {
  container-name: nxt-pattern-stage;
  container-type: inline-size;
}

@container nxt-pattern-stage (max-width: 767px) {
  .nxt-pattern-gallery[data-constrained="true"] .nxt-form-layout[data-columns="2"] {
    grid-template-columns: minmax(0, 1fr);
  }
}

.nxt-pattern-empty {
  display: grid;
  gap: var(--space-2);
  min-inline-size: 0;
  padding: var(--space-6);
  border: 1px solid var(--border-subtle);
  border-radius: var(--surface-frame-radius);
  background: var(--bg-surface);
}

/* Responsive pattern gallery: sticky width control + 2-up grid + slider-driven
 * review-container constraint. Consumes only existing tokens. */
.nxt-pattern-shell {
  display: grid;
  gap: var(--space-5);
  min-inline-size: 0;
}

.nxt-pattern-index {
  display: grid;
  grid-template-columns: minmax(14rem, 1.5fr) minmax(13rem, 1fr) auto auto;
  gap: var(--space-3);
  align-items: end;
  min-inline-size: 0;
  padding: var(--space-4);
  border: 1px solid var(--border-subtle);
  border-radius: var(--surface-frame-radius);
  background: var(--bg-surface);
}

.nxt-pattern-index-field {
  display: grid;
  gap: var(--space-2);
  min-inline-size: 0;
}

.nxt-pattern-field-label {
  color: var(--field-label-fg);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  line-height: var(--lh-normal);
}

.nxt-pattern-search-input,
.nxt-pattern-select {
  inline-size: 100%;
  min-block-size: var(--pattern-family-rail-min-block-size);
  min-inline-size: 0;
  padding-inline: var(--space-3);
  border: var(--field-frame-border-width) solid var(--field-frame-border);
  border-radius: var(--field-frame-radius);
  background: var(--field-frame-bg);
  color: var(--field-frame-fg);
  font: inherit;
}

.nxt-pattern-search-input::placeholder {
  color: var(--input-placeholder);
}

.nxt-pattern-search-input:focus-visible,
.nxt-pattern-select:focus-visible {
  outline: none;
  border-color: var(--field-frame-border-focus);
  box-shadow: var(--field-frame-focus-shadow);
}

.nxt-pattern-index-status {
  min-block-size: var(--pattern-index-status-min-block-size);
  display: inline-flex;
  align-items: center;
  color: var(--fg-secondary);
  font-size: var(--text-sm);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.nxt-pattern-controls {
  position: sticky;
  inset-block-start: 0;
  z-index: 2;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: var(--space-3) var(--space-5);
  align-items: center;
  padding: var(--space-4);
  border: 1px solid var(--border-subtle);
  border-radius: var(--surface-frame-radius);
  background: var(--bg-surface);
}

.nxt-pattern-controls-copy {
  display: grid;
  gap: var(--pattern-controls-copy-gap);
  min-inline-size: 0;
}

.nxt-pattern-controls-ui {
  display: grid;
  gap: var(--space-3);
  min-inline-size: var(--pattern-controls-ui-min-inline-size);
}

.nxt-pattern-presets {
  display: inline-flex;
  flex-wrap: nowrap;
  justify-content: flex-end;
  min-inline-size: 0;
  padding: var(--pattern-presets-padding);
  border: 1px solid var(--border-subtle);
  border-radius: var(--surface-frame-radius);
  background: var(--bg-sunken);
}

.nxt-pattern-presets .nxt-button {
  min-inline-size: 0;
}

.nxt-pattern-controls-range {
  min-inline-size: 0;
}

.nxt-pattern-family-rail {
  display: none;
}

.nxt-pattern-mobile-jump {
  display: grid;
  gap: var(--space-2);
}

@media (max-width: 767px) {
  .nxt-pattern-index {
    grid-template-columns: minmax(0, 1fr);
  }

  .nxt-pattern-controls {
    grid-template-columns: minmax(0, 1fr);
  }

  .nxt-pattern-controls-ui {
    min-inline-size: 0;
  }

  .nxt-pattern-presets {
    justify-content: flex-start;
    overflow-x: auto;
  }
}

@media (min-width: 1200px) {
  .nxt-pattern-shell {
    grid-template-columns: 12rem minmax(0, 1fr);
    align-items: start;
  }

  .nxt-pattern-index,
  .nxt-pattern-controls,
  .nxt-pattern-mobile-jump,
  .nxt-pattern-gallery {
    grid-column: 2;
  }

  .nxt-pattern-family-rail {
    grid-column: 1;
    grid-row: 1 / span 4;
    position: sticky;
    inset-block-start: var(--space-4);
    display: grid;
    gap: var(--space-2);
    align-self: start;
    min-inline-size: 0;
  }

  /* When a width preset is active the responsive container review owns the full
     content width: collapse the family-rail column so the gallery is not boxed
     into the narrow content track (the docs sidebar already narrows the page).
     See interaction.spec "pattern gallery width presets". */
  .nxt-pattern-shell[data-preview-constrained="true"] {
    grid-template-columns: minmax(0, 1fr);
  }

  .nxt-pattern-shell[data-preview-constrained="true"] .nxt-pattern-index,
  .nxt-pattern-shell[data-preview-constrained="true"] .nxt-pattern-controls,
  .nxt-pattern-shell[data-preview-constrained="true"] .nxt-pattern-mobile-jump,
  .nxt-pattern-shell[data-preview-constrained="true"] .nxt-pattern-gallery,
  .nxt-pattern-shell[data-preview-constrained="true"] .nxt-pattern-family-rail {
    grid-column: 1;
  }

  .nxt-pattern-shell[data-preview-constrained="true"] .nxt-pattern-family-rail {
    grid-row: auto;
    position: static;
  }

  .nxt-pattern-family-rail a {
    display: flex;
    gap: var(--space-2);
    align-items: center;
    justify-content: space-between;
    min-block-size: var(--pattern-search-input-min-block-size);
    min-inline-size: 0;
    padding: var(--space-2) var(--space-3);
    border: 1px solid var(--border-subtle);
    border-radius: var(--surface-frame-radius);
    background: var(--bg-surface);
    color: var(--fg-secondary);
    font-size: var(--text-sm);
    line-height: var(--lh-normal);
    text-decoration: none;
  }

  .nxt-pattern-family-rail a[aria-current="true"] {
    border-color: var(--border-default);
    background: var(--bg-sunken);
    color: var(--fg-primary);
    font-weight: var(--weight-medium);
  }

  .nxt-pattern-family-rail a:focus-visible {
    outline: none;
    box-shadow: var(--focus-ring-shadow-gap);
  }

  .nxt-pattern-mobile-jump {
    display: none;
  }
}

/* One pattern container per row at every width: a pattern specimen is a page
   region, so halving the docs column made every specimen render at ~283px and
   read as a mobile view. Single column lets each specimen fill the real column
   width; the width presets (which set data-constrained) are how you review a
   pattern at an exact narrower or wider size. */
.nxt-pattern-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-4);
  align-items: stretch;
  min-inline-size: 0;
}

.nxt-pattern-grid .nxt-pattern-stage {
  min-block-size: var(--system-mermaid-frame-min-block-size);
  padding: var(--space-4);
}

.nxt-pattern-checklist {
  display: grid;
  gap: var(--space-2);
}

.nxt-pattern-fit {
  inline-size: 100%;
  align-items: stretch;
}

.nxt-pattern-fit > * {
  inline-size: 100%;
}

.nxt-pattern-split {
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-3);
  align-items: start;
}

.nxt-pattern-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  align-items: center;
  min-inline-size: 0;
}

.nxt-pattern-row[data-spread="true"] {
  justify-content: space-between;
}

.nxt-pattern-list {
  gap: var(--space-2);
  margin: 0;
  padding: 0;
  color: var(--fg-secondary);
  font-size: var(--text-sm);
  line-height: var(--lh-normal);
  list-style: none;
}

.nxt-pattern-list li {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  align-items: center;
  justify-content: space-between;
  min-inline-size: 0;
  padding-block: var(--space-2);
  border-block-end: 1px solid var(--border-subtle);
}

.nxt-pattern-list li:last-child {
  border-block-end: 0;
}

.nxt-pattern-list strong {
  color: var(--fg-primary);
  font-variant-numeric: tabular-nums;
}

.nxt-pattern-time-control,
.nxt-pattern-skeleton-stack {
  display: grid;
  gap: var(--space-2);
  min-inline-size: 0;
}

.nxt-pattern-time-control {
  margin-block-start: var(--space-3);
}

@media (min-width: 960px) {
  .nxt-preview-layout {
    grid-template-columns: 18rem minmax(0, 1fr);
  }

  .nxt-preview-rail {
    order: 1;
    position: sticky;
    inset-block-start: 0;
    block-size: var(--viewport-block-full);
    overflow-y: auto;
    border-block-end: 0;
    border-inline-end: 1px solid var(--border-subtle);
  }

  .nxt-preview-hero,
  .nxt-preview-sections {
    padding-inline: var(--space-5);
  }

  .nxt-preview-main {
    order: 2;
  }

  .nxt-preview-hero {
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: start;
  }

  .nxt-preview-stat-grid,
  .nxt-preview-mode-panel {
    grid-column: 1 / -1;
  }

  .nxt-catalog-component-header {
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: start;
  }
}

@media (max-width: 767px) {
  .nxt-preview-hero,
  .nxt-preview-sections,
  .nxt-preview-rail {
    padding-inline: var(--space-3);
  }

  .nxt-preview-mode-panel,
  .nxt-preview-filter-bar {
    padding: var(--space-2);
  }
}

/* ──────────────────────────────────────────────────────────────────────────
 * ACCORDION
 * Tier-2 wrapper over @radix-ui/react-accordion.
 * ────────────────────────────────────────────────────────────────────── */
.nxt-accordion {
  display: flex;
  flex-direction: column;
  width: 100%;
  max-width: 42rem;
  overflow: hidden;
  border: 1px solid var(--border-default);
  border-radius: var(--radius-md);
  background: var(--bg-surface);
  color: var(--fg-primary);
  font-family: var(--font-sans);
  font-size: var(--text-sm);
}

.nxt-accordion-item {
  border-bottom: 1px solid var(--border-subtle);
}

.nxt-accordion-item:last-child {
  border-bottom: 0;
}

.nxt-accordion-heading {
  display: flex;
  margin: 0;
}

.nxt-accordion-trigger {
  appearance: none;
  display: flex;
  min-height: var(--ctrl-block-h-md);
  width: 100%;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  border: 0;
  background: transparent;
  color: var(--fg-primary);
  cursor: pointer;
  font: inherit;
  font-weight: var(--weight-medium);
  padding: var(--space-3);
  text-align: left;
  transition:
    background-color var(--dur-snap) var(--ease-snap),
    color var(--dur-fast) var(--ease-smooth);
}

@media (hover: hover) {
  .nxt-accordion-trigger:hover {
    background: var(--neutral-soft-bg);
  }
  .nxt-accordion-trigger:hover .nxt-accordion-icon {
    color: var(--fg-primary);
  }
}

.nxt-accordion-trigger:active:not(:disabled) {
  background: var(--pressed-soft-bg);
}

.nxt-accordion-trigger:focus-visible {
  outline: none;
  box-shadow:
    inset 0 0 0 2px var(--bg-canvas),
    inset 0 0 0 4px var(--focus-ring);
}

.nxt-accordion-trigger:disabled,
.nxt-accordion-item[data-disabled] .nxt-accordion-trigger {
  color: var(--fg-tertiary);
  cursor: not-allowed;
}

.nxt-accordion-title {
  min-width: 0;
  flex: 1;
}

.nxt-accordion-icon {
  flex: 0 0 auto;
  color: var(--fg-tertiary);
  transition:
    color var(--dur-fast) var(--ease-smooth),
    transform var(--dur-fast) var(--ease-smooth);
}

.nxt-accordion-trigger[data-state="open"] .nxt-accordion-icon {
  color: var(--fg-primary);
  transform: rotate(180deg);
}

.nxt-accordion-panel {
  color: var(--fg-secondary);
}

.nxt-accordion-panel[data-state="closed"] {
  display: none;
}

.nxt-accordion-panel-inner {
  padding: 0 var(--space-3) var(--space-3);
  line-height: var(--lh-relaxed);
}

@media (prefers-reduced-motion: reduce) {
  .nxt-accordion-trigger,
  .nxt-accordion-icon {
    transition: none;
  }
}

/* ──────────────────────────────────────────────────────────────────────────
 * SIGNATURE
 * Special Candidate: capture, typed fallback, saved viewer, replay.
 * ────────────────────────────────────────────────────────────────────── */
.nxt-signature {
  --signature-inline-size: 480px;
  --signature-block-size: 200px;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  width: min(100%, var(--signature-inline-size));
  color: var(--fg-primary);
  font-family: var(--font-sans);
}

.nxt-signature[data-size="sm"],
.nxt-signature-viewer[data-size="sm"],
.nxt-signature-replay[data-size="sm"] {
  --signature-inline-size: 320px;
  --signature-block-size: 144px;
}

.nxt-signature[data-size="md"],
.nxt-signature-viewer[data-size="md"],
.nxt-signature-replay[data-size="md"] {
  --signature-inline-size: 480px;
  --signature-block-size: 200px;
}

.nxt-signature[data-size="lg"],
.nxt-signature-viewer[data-size="lg"],
.nxt-signature-replay[data-size="lg"] {
  --signature-inline-size: 640px;
  --signature-block-size: 240px;
}

.nxt-signature-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
}

.nxt-signature-label {
  min-width: 0;
}

.nxt-signature-mode,
.nxt-signature-toolbar {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-2);
}

.nxt-signature-mode {
  flex-shrink: 0;
}

.nxt-signature-description {
  margin: 0;
}

.nxt-signature-stage {
  position: relative;
  width: 100%;
  aspect-ratio: 480 / 200;
  min-height: var(--signature-stage-min-block-size);
  max-height: var(--signature-block-size);
  overflow: hidden;
  background: var(--bg-sunken);
  border: var(--field-frame-border-width) solid var(--field-frame-border);
  border-radius: var(--field-frame-radius);
  transition:
    background-color var(--dur-snap) var(--ease-snap),
    border-color var(--dur-fast) var(--ease-smooth),
    box-shadow var(--dur-fast) var(--ease-smooth);
}

.nxt-signature[data-size="sm"] .nxt-signature-stage { aspect-ratio: 320 / 144; }
.nxt-signature[data-size="lg"] .nxt-signature-stage { aspect-ratio: 640 / 240; }

.nxt-signature-stage[data-invalid] {
  border-color: var(--field-frame-border-invalid);
}

.nxt-signature-stage:focus-within {
  border-color: var(--field-frame-border-focus);
  box-shadow: var(--field-frame-focus-shadow);
}

.nxt-signature-canvas {
  display: block;
  width: 100%;
  height: 100%;
  cursor: crosshair;
  touch-action: none;
}

.nxt-signature-line {
  position: absolute;
  inset-inline: var(--space-5);
  inset-block-end: var(--signature-line-inset-block-end);
  height: var(--hairline-size);
  background: var(--border-default);
  pointer-events: none;
}

.nxt-signature-typed {
  font-family: var(--font-serif);
  font-size: var(--text-lg);
}

.nxt-signature-toolbar {
  padding-block-start: var(--space-1);
}

.nxt-signature-message {
  margin: 0;
}

.nxt-signature-status {
  min-height: 1.25em;
  margin: 0;
  color: var(--fg-tertiary);
  font-size: var(--text-xs);
  line-height: var(--lh-normal);
}

.nxt-signature[data-disabled] {
  opacity: 0.68;
}

/* Fill layout — signature + stage expand to fill their container instead of
   capping at the size block-height. Used by full-screen mobile signing. */
.nxt-signature[data-layout="fill"] {
  flex: 1 1 auto;
  width: 100%;
  max-width: none;
}
.nxt-signature[data-layout="fill"] .nxt-signature-stage {
  flex: 1 1 auto;
  max-height: none;
  aspect-ratio: auto;
  border-inline: 0;
  border-radius: 0;
}

.nxt-signature-viewer,
.nxt-signature-replay {
  width: min(100%, var(--signature-inline-size, 480px));
  color: var(--fg-primary);
  font-family: var(--font-sans);
}

.nxt-signature-viewer {
  display: flex;
  min-height: var(--signature-block-size, 200px);
  align-items: center;
  justify-content: center;
  overflow: hidden;
  background: var(--bg-sunken);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-sm);
}

.nxt-signature-viewer[data-empty] {
  color: var(--fg-tertiary);
  font-size: var(--text-sm);
}

.nxt-signature-viewer[data-kind="typed"] {
  font-family: var(--font-serif);
  font-size: var(--text-2xl);
  line-height: var(--lh-snug);
  padding: var(--space-4);
}

.nxt-signature-viewer-svg {
  display: block;
  width: 100%;
  height: var(--signature-block-size, 200px);
  color: var(--fg-primary);
}

.nxt-signature-viewer-svg path,
.nxt-signature-replay-path {
  /* intentional: captured signature stroke playback, not UI glyph */
  stroke-width: 3;
  vector-effect: non-scaling-stroke;
}

.nxt-signature-viewer-caption {
  position: absolute;
  width: var(--sr-only-size);
  height: var(--sr-only-size);
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

.nxt-signature-replay {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.nxt-signature-replay-stage {
  display: flex;
  min-height: var(--signature-block-size, 200px);
  align-items: center;
  justify-content: center;
  overflow: hidden;
  background: var(--bg-sunken);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-sm);
}

.nxt-signature-replay-stage svg {
  display: block;
  width: 100%;
  height: var(--signature-block-size, 200px);
}

.nxt-signature-replay-empty {
  color: var(--fg-tertiary);
  font-size: var(--text-sm);
}

.nxt-signature-replay[data-replay-state="playing"] .nxt-signature-replay-path {
  stroke-dasharray: 1000;
  stroke-dashoffset: 1000;
  animation: nxt-signature-replay var(--dur-deliberate) var(--ease-smooth) forwards;
}

@keyframes nxt-signature-replay {
  to {
    stroke-dashoffset: 0;
  }
}

@media (max-width: 767px) {
  .nxt-signature-header {
    align-items: flex-start;
    flex-direction: column;
  }

  .nxt-signature-mode {
    width: 100%;
  }
}

@media (prefers-reduced-motion: reduce) {
  .nxt-signature-stage,
  .nxt-signature-replay-path {
    transition: none;
    animation: none !important;
    stroke-dashoffset: 0;
  }
}

/* ──────────────────────────────────────────────────────────────────────────
 * ALERT MESSAGE (alert-message)
 * Tier-1 inline status panel. data-intent drives the colour palette.
 * ────────────────────────────────────────────────────────────────────── */
.nxt-alert {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  padding: var(--space-3);
  border-radius: var(--surface-frame-radius);
  border: 1px solid var(--surface-frame-border);
  background-color: var(--surface-frame-bg);
  color: var(--surface-frame-fg);
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  line-height: var(--lh-normal);
  transition: background-color var(--dur-fast) var(--ease-smooth), border-color var(--dur-fast) var(--ease-smooth);
}

.nxt-alert[data-intent="info"] {
  background-color: var(--info-soft-bg);
  border-color: var(--info);
  color: var(--info-soft-fg);
}

.nxt-alert[data-intent="success"] {
  background-color: var(--success-soft-bg);
  border-color: var(--success);
  color: var(--success-soft-fg);
}

.nxt-alert[data-intent="warning"] {
  background-color: var(--warning-soft-bg);
  border-color: var(--warning);
  color: var(--warning-soft-fg);
}

.nxt-alert[data-intent="danger"] {
  background-color: var(--danger-soft-bg);
  border-color: var(--danger);
  color: var(--danger-soft-fg);
}

.nxt-alert-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 20px;
  height: 20px;
  margin-top: 2px; /* intentional: optical — aligns the 20px icon to the first text line, not a stack gap */
  color: currentColor;
}

.nxt-alert-body {
  flex: 1;
  min-width: 0;
}

.nxt-alert-title {
  font-weight: var(--weight-medium);
  margin-bottom: var(--space-1);
  color: inherit;
  text-wrap: balance;
}

.nxt-alert-content,
.nxt-alert-message {
  color: inherit;
  text-wrap: pretty;
}

.nxt-alert-close {
  appearance: none;
  background: transparent;
  border: 0;
  padding: var(--space-1);
  margin: var(--alert-close-optical-margin);
  color: currentColor;
  cursor: pointer;
  border-radius: var(--radius-sm);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  opacity: 0.7;
  transition: opacity 120ms var(--ease-smooth), background-color 120ms var(--ease-smooth);
  min-width: var(--ctrl-hit-min-compact);
  min-height: var(--ctrl-hit-min-compact);
}

.nxt-alert-close:hover {
  opacity: 1;
  background-color: color-mix(in oklch, currentColor 10%, transparent);
}

.nxt-alert-close:focus-visible {
  outline: none;
  box-shadow: 0 0 0 2px var(--focus-ring);
}

/* ── Reveal — ground-up rework of the reveal-mask port ──────────────────
 * Media-reveal surface: poster/video beneath an animated halftone-dot
 * mask. The canvas ink resolves from `color` (bound to --fg-primary) so
 * the dot field follows light/dark + tenant themes. */
.nxt-reveal {
  --reveal-media-top: clamp(12.5rem, 27.5vh, 19rem);
  --reveal-ease: var(--ease-enter);

  display: block;
  position: relative;
  min-height: 100vh;
  overflow: hidden;
  isolation: isolate;
  background: var(--bg-canvas);
  color: var(--fg-primary);
  font-family: var(--font-mono);
  box-sizing: border-box;
}
.nxt-reveal *,
.nxt-reveal *::before,
.nxt-reveal *::after {
  box-sizing: border-box;
}
.nxt-reveal .media {
  position: absolute;
  z-index: 1;
  inset: var(--reveal-media-top) 0 0 0;
  overflow: hidden;
  pointer-events: none;
}
.nxt-reveal .media video,
.nxt-reveal .media img,
.nxt-reveal .media canvas,
.nxt-reveal .media .scrim {
  position: absolute;
  inset: 0;
  width: 100%;
  display: block;
}
.nxt-reveal .media video,
.nxt-reveal .media img {
  height: auto;
  opacity: 0;
  transition: opacity 460ms var(--reveal-ease);
}
.nxt-reveal .media canvas {
  height: 100%;
  z-index: 2;
  opacity: 0.78;
  /* The ink follows the theme, per the contract ("the dots follow the light or
   * dark theme") and docs.md ("resolves from computed --fg-primary … without
   * hardcoded canvas colors"), so the blend has to follow it too. `multiply`
   * only darkens: with near-white dark-theme ink it is the identity operation,
   * and the halftone silently vanished (the P1 the dark captures caught).
   * `screen` is its mirror — it only lightens — so light ink reads against the
   * media exactly as dark ink does in the light theme. */
  mix-blend-mode: multiply;
  color: var(--fg-primary); /* resolved by the engine as the dot ink */
  transition: opacity 460ms var(--reveal-ease);
}
.dark .nxt-reveal .media canvas {
  mix-blend-mode: screen;
}
.nxt-reveal .media .scrim {
  z-index: 3;
  height: 52%;
  opacity: 0;
  background: linear-gradient(
    to bottom,
    color-mix(in oklch, var(--fg-primary), transparent 22%) 0%,
    color-mix(in oklch, var(--fg-primary), transparent 28%) 9%,
    color-mix(in oklch, var(--fg-primary), transparent 38%) 18%,
    color-mix(in oklch, var(--fg-primary), transparent 51%) 28%,
    color-mix(in oklch, var(--fg-primary), transparent 65%) 39%,
    color-mix(in oklch, var(--fg-primary), transparent 77%) 50%,
    color-mix(in oklch, var(--fg-primary), transparent 87%) 62%,
    color-mix(in oklch, var(--fg-primary), transparent 94%) 74%,
    color-mix(in oklch, var(--fg-primary), transparent 98%) 88%,
    transparent 100%
  );
  transition: opacity 460ms var(--reveal-ease);
}
.nxt-reveal .foreground {
  position: relative;
  z-index: 4;
  display: block;
}
.nxt-reveal .foreground:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring-shadow-gap);
}
.nxt-reveal.is-trail-visible .media video,
.nxt-reveal.is-trail-visible .media img,
.nxt-reveal.is-static .media video,
.nxt-reveal.is-static .media img {
  opacity: 0.94;
}
.nxt-reveal.is-revealed .media canvas,
.nxt-reveal.is-static .media canvas {
  opacity: 0;
}
.nxt-reveal.is-trail-visible .media .scrim,
.nxt-reveal.is-static .media .scrim {
  opacity: 1;
}
.nxt-reveal.is-revealed .foreground {
  color: var(--fg-inverse);
}
@media (prefers-reduced-motion: reduce) {
  .nxt-reveal .media video,
  .nxt-reveal .media img,
  .nxt-reveal .media canvas,
  .nxt-reveal .media .scrim {
    transition: none;
  }
}

/* ── ErrorPage — DS-grade status surface composing Reveal ───────────────
 * Status code eyebrow, title, message, back/home actions, brand mark.
 * `is-plain` renders without media — the resilient incident path. */
.nxt-error-page {
  display: block;
}
.nxt-error-page.is-plain {
  min-height: 100vh;
  background: var(--bg-canvas);
  color: var(--fg-primary);
  font-family: var(--font-mono);
}
.nxt-error-page-content {
  position: relative;
  z-index: 4;
  display: grid;
  justify-items: center;
  gap: var(--space-4);
  width: min(28rem, calc(100% - var(--space-6, 2rem)));
  margin: 0 auto;
  padding: clamp(8rem, 18vh, 12rem) 0 var(--space-6, 2rem);
  text-align: center;
  font-family: var(--font-mono);
  color: var(--fg-primary);
  transition: color 320ms var(--ease-enter);
}
.nxt-error-page-content[data-inverted="true"] {
  color: var(--fg-inverse);
}
.nxt-error-page-mark {
  width: 2rem;
  height: 2rem;
  color: currentColor;
  opacity: 0.92;
}
.nxt-error-page-code {
  margin: 0;
  font-size: var(--text-xs, 12px);
  letter-spacing: var(--track-caps-x);
  text-transform: uppercase;
  /* de-emphasised but still AA at 12px against the canvas (was transparent 56%,
     which blended to ~3.1:1 and failed axe color-contrast). */
  color: color-mix(in oklch, currentColor, transparent 32%);
}
.nxt-error-page-title {
  margin: 0;
  font-family: var(--font-display);
  font-size: var(--text-2xl);
  font-weight: var(--weight-regular);
  line-height: var(--lh-snug);
  letter-spacing: var(--track-tight);
  text-wrap: balance;
  color: currentColor;
}
.nxt-error-page-message {
  margin: 0;
  max-width: 24rem;
  font-family: var(--font-sans);
  font-size: var(--text-base, 15px);
  line-height: var(--lh-normal);
  text-wrap: pretty;
  color: color-mix(in oklch, currentColor, transparent 30%);
}
.nxt-error-page-actions {
  display: inline-flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-3);
  margin-top: var(--space-2);
}
.nxt-error-page-actions svg {
  margin-right: var(--space-1, 4px);
}
@media (prefers-reduced-motion: reduce) {
  .nxt-error-page-content {
    transition: none;
  }
}

/* ── FileImporter — DS-styled wizard for the @green/file-import flow ─────
 * The composed shell (app/src/components/file-importer/) supplies all step
 * surfaces via DS primitives (Card, Alert, FormLayout, Field, Select, Switch,
 * EmptyState, Spinner, Progress, Statistic, Button).
 * The selectors below cover the wizard-specific chrome that doesn't
 * already exist as a primitive: the Stepper, the dropzone outline, the
 * map / review table layouts, and the stat row on the result screen. */
.nxt-file-importer {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  padding-block: var(--space-4);
}
.nxt-file-importer-body {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}
.nxt-file-importer-hint {
  font-size: var(--text-sm);
  color: var(--fg-tertiary);
  align-self: center;
}

/* Stepper — horizontal flex of [marker · label · connector] triples. */
.nxt-stepper {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  align-items: center;
  gap: 0;
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  overflow-x: auto;
  padding-block-end: var(--stepper-padding-block-end);
}
.nxt-stepper-step {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  color: var(--fg-tertiary);
  flex: 0 0 auto;
}
.nxt-stepper-step + .nxt-stepper-step {
  margin-inline-start: var(--space-3);
}
.nxt-stepper-marker {
  display: inline-flex;
  width: var(--stepper-marker-size);
  height: var(--stepper-marker-size);
  align-items: center;
  justify-content: center;
  background: var(--bg-sunken);
  border: 1px solid var(--border-default);
  border-radius: 9999px;
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-variant-numeric: tabular-nums;
  color: var(--fg-tertiary);
  transition: background var(--dur-fast) var(--ease-smooth, ease), border-color var(--dur-fast) var(--ease-smooth, ease), color var(--dur-fast) var(--ease-smooth, ease);
}
.nxt-stepper-label {
  font-weight: var(--weight-medium);
  letter-spacing: 0.02em;
}
.nxt-stepper-connector {
  display: inline-block;
  width: 32px;
  height: var(--hairline-size);
  margin-inline-start: var(--space-2);
  background: var(--border-default);
}
.nxt-stepper-step[data-state="complete"] {
  color: var(--fg-secondary);
}
.nxt-stepper-step[data-state="complete"] .nxt-stepper-marker {
  background: var(--neutral-fill);
  border-color: var(--neutral-fill);
  color: var(--neutral-fill-fg);
}
.nxt-stepper-step[data-state="complete"] .nxt-stepper-connector {
  background: var(--neutral-fill);
}
.nxt-stepper-step[data-state="current"] {
  color: var(--fg-primary);
}
.nxt-stepper-step[data-state="current"] .nxt-stepper-marker {
  background: var(--bg-canvas);
  border-color: var(--neutral-fill);
  color: var(--fg-primary);
  box-shadow: 0 0 0 3px color-mix(in oklch, var(--neutral-fill), transparent 88%);
}

/* Dropzone — large outlined affordance using a dashed border + EmptyState
 * inside. Drag-over feedback bumps the border color and tints the bg. */
.nxt-file-importer-dropzone {
  display: block;
  border: var(--border-width-strong) dashed var(--border-default);
  border-radius: var(--radius-md);
  background: var(--bg-canvas);
  padding: var(--space-5);
  transition: background var(--dur-fast) var(--ease-smooth, ease), border-color var(--dur-fast) var(--ease-smooth, ease);
}
.nxt-file-importer-dropzone[data-drag-over] {
  border-color: var(--border-strong);
  background: var(--bg-sunken);
}
.nxt-file-importer-upload-grid {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--space-4);
}
.nxt-file-importer-upload-icon,
.nxt-file-importer-column-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 2.5rem;
  min-height: 2.5rem;
  border: 1px solid var(--border-default);
  border-radius: var(--radius-sm);
  background: var(--bg-surface);
  color: var(--fg-primary);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  font-variant-numeric: tabular-nums;
}
.nxt-file-importer-upload-copy h3,
.nxt-file-importer-section-head h3,
.nxt-file-importer-map-source h4 {
  margin: 0;
  color: var(--fg-primary);
  font-size: var(--text-md);
  font-weight: var(--weight-medium);
  line-height: var(--lh-tight);
}
.nxt-file-importer-upload-copy p,
.nxt-file-importer-section-head p {
  margin: var(--space-1) 0 0;
  color: var(--fg-secondary);
  font-size: var(--text-sm);
  line-height: var(--lh-normal);
}
.nxt-file-importer-prepare-grid {
  display: grid;
  grid-template-columns: minmax(0, 1.4fr) minmax(18rem, 0.8fr);
  gap: var(--space-4);
  margin-block-end: var(--space-4);
}
.nxt-file-importer-panel {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-md);
  background: var(--bg-surface);
  padding: var(--space-4);
}
.nxt-file-importer-panel[data-tone="warning"] {
  border-color: var(--warning);
  background: color-mix(in oklch, var(--warning), var(--bg-surface) 95%);
}
.nxt-file-importer-section-head {
  display: flex;
  align-items: start;
  justify-content: space-between;
  gap: var(--space-3);
}
.nxt-file-importer-pill {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 1.75rem;
  border: 1px solid var(--border-default);
  border-radius: var(--radius-full);
  background: var(--bg-sunken);
  color: var(--fg-secondary);
  padding-inline: var(--space-2);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.nxt-file-importer-pill[data-tone="success"] {
  border-color: var(--success);
  color: var(--success);
}
.nxt-file-importer-pill[data-tone="warning"] {
  border-color: var(--warning);
  color: var(--warning);
}
.nxt-file-importer-required-list {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin: 0;
  padding: 0;
  list-style: none;
}
.nxt-file-importer-required-list li {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  min-height: 2rem;
  border: 1px solid var(--border-default);
  border-radius: var(--radius-full);
  background: var(--bg-surface);
  color: var(--fg-secondary);
  padding-inline: var(--space-2);
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
}
.nxt-file-importer-required-list li[data-state="missing"] {
  border-color: var(--warning);
  color: var(--warning);
}
.nxt-file-importer-map-section {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}
.nxt-file-importer-map-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}
.nxt-file-importer-map-card {
  display: grid;
  grid-template-columns: minmax(15rem, 1fr) minmax(13rem, 0.85fr) auto;
  align-items: center;
  gap: var(--space-3);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-md);
  background: var(--bg-surface);
  padding: var(--space-3);
}
.nxt-file-importer-map-source {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: start;
  gap: var(--space-3);
}

/* Map step table — three-column [source · samples · destination select] */
.nxt-file-importer-map-table {
  width: 100%;
  border-collapse: collapse;
  font-family: var(--font-sans);
  font-size: var(--text-sm);
}
.nxt-file-importer-map-table thead th {
  text-align: start;
  padding: var(--space-2) var(--space-3);
  font-size: var(--text-xs);
  letter-spacing: var(--track-caps);
  text-transform: uppercase;
  color: var(--fg-tertiary);
  font-weight: var(--weight-medium);
  border-bottom: 1px solid var(--border-default);
}
.nxt-file-importer-map-table tbody th {
  text-align: start;
  padding: var(--space-3);
  font-weight: var(--weight-medium);
  color: var(--fg-primary);
}
.nxt-file-importer-map-table tbody td {
  padding: var(--space-2) var(--space-3);
  color: var(--fg-secondary);
}
.nxt-file-importer-map-table tbody tr + tr {
  border-top: 1px solid var(--border-default);
}
.nxt-file-importer-samples {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--fg-tertiary);
}
.nxt-file-importer-confidence {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: var(--track-caps);
  text-transform: uppercase;
  color: var(--fg-tertiary);
}
.nxt-file-importer-confidence[data-confidence="high"] {
  color: var(--fg-primary);
}
.nxt-file-importer-confidence[data-confidence="review"] {
  color: var(--warning);
}
.nxt-file-importer-map-card > .nxt-file-importer-confidence {
  justify-self: end;
  border: 1px solid var(--border-default);
  border-radius: var(--radius-full);
  background: var(--bg-sunken);
  padding: 0.35rem var(--space-2);
  letter-spacing: 0;
}

/* Review step — toolbar above + scrollable table below. */
.nxt-file-importer-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding-block: var(--space-3);
}
.nxt-file-importer-toolbar-actions {
  display: inline-flex;
  gap: var(--space-2);
}
.nxt-file-importer-review-scroll {
  max-height: 480px;
  overflow: auto;
  border: 1px solid var(--border-default);
  border-radius: var(--radius-md);
}
.nxt-file-importer-review-table {
  width: 100%;
  border-collapse: collapse;
  font-family: var(--font-sans);
  font-size: var(--text-sm);
}
.nxt-file-importer-review-table thead th {
  position: sticky;
  top: 0;
  background: var(--bg-sunken);
  text-align: start;
  padding: var(--space-2) var(--space-3);
  font-size: var(--text-xs);
  letter-spacing: var(--track-caps);
  text-transform: uppercase;
  color: var(--fg-tertiary);
  font-weight: var(--weight-medium);
  border-bottom: 1px solid var(--border-default);
}
.nxt-file-importer-review-table tbody th,
.nxt-file-importer-review-table tbody td {
  padding: var(--space-1) var(--space-2);
  border-bottom: 1px solid var(--border-default);
  vertical-align: middle;
}
.nxt-file-importer-row-num {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--fg-tertiary);
  font-variant-numeric: tabular-nums;
  width: 4rem;
  text-align: end;
}
.nxt-file-importer-review-table tbody tr[data-row-error] {
  background: color-mix(in oklch, var(--danger), transparent 95%);
}

/* Progress phase — spinner alongside the labelled bar. */
.nxt-file-importer-progress-row {
  display: flex;
  align-items: center;
  gap: var(--space-4);
}
.nxt-file-importer-progress-row > .nxt-progress {
  flex: 1;
}

/* Result phase — KPI strip of Statistic primitives. */
.nxt-file-importer-stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: var(--space-4);
  margin-top: var(--space-4);
}

@media (max-width: 767px) {
  .nxt-file-importer {
    gap: var(--space-3);
    padding-block: var(--space-3);
  }
  .nxt-stepper {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: var(--space-2);
    overflow-x: visible;
  }
  .nxt-stepper-step {
    flex-direction: column;
    align-items: center;
    min-width: 0;
    gap: var(--space-1);
    text-align: center;
  }
  .nxt-stepper-step + .nxt-stepper-step {
    margin-inline-start: 0;
  }
  .nxt-stepper-marker {
    width: 24px;
    height: 24px;
    font-size: var(--text-2xs);
  }
  .nxt-stepper-label {
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: var(--text-xs);
  }
  .nxt-stepper-connector {
    display: none;
  }
  .nxt-file-importer-upload-grid,
  .nxt-file-importer-prepare-grid,
  .nxt-file-importer-map-card {
    grid-template-columns: 1fr;
  }
  .nxt-file-importer-section-head {
    flex-direction: column;
  }
  .nxt-file-importer-map-card > .nxt-file-importer-confidence {
    justify-self: start;
  }
  .nxt-file-importer-toolbar {
    flex-direction: column;
    align-items: stretch;
  }
  .nxt-file-importer-toolbar .nxt-switch {
    align-self: stretch;
  }
  .nxt-file-importer-toolbar .nxt-switch-content {
    min-width: 0;
  }
  .nxt-file-importer-toolbar-actions {
    display: grid;
    grid-template-columns: 1fr;
  }
  .nxt-file-importer-toolbar-actions .nxt-button {
    width: 100%;
  }
}

/* ============================================================================
   Calendar / DatePicker / TimePicker
   Logic: react-day-picker (calendar) + custom spin columns (time).
   Styling: semantic tokens only. Selection and range = neutral; periwinkle
   (--secondary) is reserved for today/weekend/time accents.
   ========================================================================== */

.nxt-calendar {
  --nxt-cal-cell: var(--calendar-cell-size-md);
  /* intentional: relative by design — the selected day scales with the cell's
     own font-size rather than a fixed step. */
  --nxt-calendar-selected-day-font-size: 1.5em;
  display: inline-block;
  /* Box chrome consolidated from the removed pre-ADR-125 block above —
     identical rendered result, single source. Geometry now resolves from
     component tokens in tokens.semantic.css. */
  width: var(--calendar-panel-inline-size);
  padding: var(--calendar-panel-padding-block) var(--calendar-panel-padding-inline);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-md);
  background: var(--bg-raised);
  color: var(--fg-primary);
  font-family: var(--font-ui);
  /* Barlow GX weight channel (BRAND-TYPE-001/002, ADR 137). */
  font-variation-settings: var(--font-wght-barlow-regular);
  font-synthesis: none;
}
.nxt-calendar[data-size="sm"] { --nxt-cal-cell: var(--calendar-cell-size-sm); }
.nxt-calendar[data-size="lg"] { --nxt-cal-cell: var(--calendar-cell-size-lg); }

.nxt-calendar-months {
  position: relative;
}

.nxt-calendar-month {
  display: grid;
  grid-template-areas:
    "caption"
    "grid";
  gap: var(--space-3);
}

.nxt-calendar-caption {
  grid-area: caption;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: var(--calendar-caption-control-size);
  padding-inline: calc(var(--calendar-caption-control-size) + var(--space-1));
}
.nxt-calendar-caption-label {
  font-size: var(--text-md);
  /* BRAND-TYPE-001 (ADR 137): Barlow weight via variation axis, not font-weight. */
  font-variation-settings: var(--font-wght-barlow-semibold);
  text-transform: capitalize;
}

.nxt-calendar-nav {
  grid-area: caption;
  position: absolute;
  inset-block-start: 0;
  inset-inline: 0;
  z-index: 1;
  display: flex;
  align-items: center;
  justify-content: space-between;
  pointer-events: none;
}
.nxt-calendar-nav-btn {
  pointer-events: auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  inline-size: var(--calendar-caption-control-size);
  block-size: var(--calendar-caption-control-size);
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--fg-primary);
  cursor: pointer;
  transition: background var(--dur-snap) var(--ease-snap);
}
.nxt-calendar-nav-btn:hover { background: var(--bg-sunken); }
.nxt-calendar-nav-btn:focus-visible { outline: none; box-shadow: var(--focus-ring-shadow-gap); }
.nxt-calendar-nav-btn:disabled { color: var(--fg-muted); cursor: not-allowed; }

.nxt-calendar-grid { grid-area: grid; display: flex; flex-direction: column; gap: var(--calendar-grid-gap); border-collapse: collapse; }
.nxt-calendar-grid thead,
.nxt-calendar-grid tbody { display: contents; }
.nxt-calendar-weekdays,
.nxt-calendar-week { display: grid; grid-template-columns: repeat(7, var(--nxt-cal-cell)); }
.nxt-calendar-weekday {
  display: flex;
  align-items: center;
  justify-content: center;
  block-size: var(--nxt-cal-cell);
  color: var(--fg-tertiary);
  font-size: var(--text-xs);
  font-variation-settings: var(--font-wght-barlow-medium);
  text-transform: uppercase;
  letter-spacing: var(--track-wide);
}
.nxt-calendar-day { inline-size: var(--nxt-cal-cell); block-size: var(--nxt-cal-cell); padding: 0; text-align: center; }

.nxt-calendar-day-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  inline-size: 100%;
  block-size: 100%;
  min-inline-size: 0;
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--fg-primary);
  font-size: var(--text-sm);
  font-variant-numeric: tabular-nums;
  cursor: pointer;
  transition: background var(--dur-snap) var(--ease-snap), color var(--dur-snap) var(--ease-snap);
}
.nxt-calendar-day-btn:hover { background: var(--bg-sunken); }
.nxt-calendar-day-btn:focus-visible { outline: none; box-shadow: var(--focus-ring-shadow-gap); position: relative; z-index: 1; }

/* Density-aware tap-target floor, carried over from the removed pre-ADR-125
   `.nxt-calendar-grid button` rule (which was NOT dead — it matched the rdp
   day buttons and, at (0,1,1) later in the file, outranked the frozen
   `.nxt-calendar button { min-height: var(--nav-item-block-size) }` rule;
   `--nav-item-block-size` substitutes at :root and freezes to the compact
   36px, so it must keep losing here). (0,2,0) preserves that outcome. */
.nxt-calendar-grid .nxt-calendar-day-btn { min-block-size: var(--ctrl-block-h-sm); }

/* Weekend: subtle periwinkle tint, except idle days are neutralized below. */
.nxt-calendar-day--weekend .nxt-calendar-day-btn { color: var(--secondary-soft-fg); }
/* Idle in-month days recede so selection, range, and today carry the visual weight. */
.nxt-calendar-day:not(.nxt-calendar-day--selected):not(.nxt-calendar-day--range-middle):not(.nxt-calendar-day--range-start):not(.nxt-calendar-day--range-end):not(.nxt-calendar-day--today):not(.nxt-calendar-day--outside):not(.nxt-calendar-day--disabled) .nxt-calendar-day-btn {
  color: var(--fg-tertiary);
}
/* Outside-month days recede through text only and inherit normal hover so
   range/hover states stay continuous across the grid. */
.nxt-calendar-day--outside .nxt-calendar-day-btn { color: var(--fg-tertiary); }
/* Today: periwinkle ring, bold (Barlow weight via variation axis, ADR 137). */
.nxt-calendar-day--today .nxt-calendar-day-btn { font-variation-settings: var(--font-wght-barlow-bold); box-shadow: inset 0 0 0 1px var(--secondary); }
/* Selected: neutral near-black fill (brand: lime reserved for hero only). */
.nxt-calendar-day--selected .nxt-calendar-day-btn,
.nxt-calendar-day--selected .nxt-calendar-day-btn:hover {
  background: var(--neutral-fill);
  color: var(--neutral-fill-fg);
  font-size: var(--nxt-calendar-selected-day-font-size);
  font-variation-settings: var(--font-wght-barlow-semibold);
}
.nxt-calendar-day--disabled .nxt-calendar-day-btn { color: var(--fg-muted); cursor: not-allowed; }

/* Range selection (mode="range") — neutral band with solid endpoints.
   Values mirror the date-picker range panel so the standalone range
   Calendar and the composed picker render the same selection language.
   These selectors never fire in single mode (rdp only emits range_*
   selection states under mode="range"). */
.nxt-calendar-day--range-middle .nxt-calendar-day-btn {
  border-radius: 0;
  border-block: 1px solid currentColor;
  border-inline: 0;
  background: transparent;
  color: var(--neutral-soft-fg);
}

.nxt-calendar-day--today.nxt-calendar-day--range-middle .nxt-calendar-day-btn {
  border-inline: 1px dotted var(--secondary);
  box-shadow: none;
}

.nxt-calendar-day--range-start .nxt-calendar-day-btn,
.nxt-calendar-day--range-end .nxt-calendar-day-btn {
  background: var(--neutral-fill);
  color: var(--neutral-fill-fg);
  font-size: var(--nxt-calendar-selected-day-font-size);
  font-variation-settings: var(--font-wght-barlow-semibold);
}

.nxt-calendar-day--range-start .nxt-calendar-day-btn {
  border-start-start-radius: var(--radius-md);
  border-end-start-radius: var(--radius-md);
  border-start-end-radius: 0;
  border-end-end-radius: 0;
}

.nxt-calendar-day--range-end .nxt-calendar-day-btn {
  border-start-start-radius: 0;
  border-end-start-radius: 0;
  border-start-end-radius: var(--radius-md);
  border-end-end-radius: var(--radius-md);
}

.nxt-calendar-day--range-start.nxt-calendar-day--range-end .nxt-calendar-day-btn {
  border-radius: var(--radius-md);
}

/* Twin-month layout for the standalone range calendar. rdp renders one Nav for
   the whole picker as the first child of UI.Months (a sibling of the two month
   grids). The single-month `grid-area: caption` nav placement does not apply
   here, so lay the months as a grid and let the shared nav occupy a full-width
   in-flow row spanning both months (prev far-left, next far-right). Each month
   track keeps a min-content floor so the 7-cell grid never overflows into its
   neighbour. */
.nxt-calendar--range {
  width: auto;
}

.nxt-calendar--range .nxt-calendar-months {
  display: grid;
  grid-template-columns: repeat(2, minmax(min-content, 1fr));
  gap: 0 var(--calendar-range-months-gap);
}

/* The shared nav is the first child; overlay it on the caption row so month
   labels and arrows share one line instead of consuming a separate row. */
.nxt-calendar--range .nxt-calendar-nav {
  grid-row: auto;
  grid-column: auto;
}
.nxt-calendar--range .nxt-calendar-month {
  grid-row: 1;
}

@media (max-width: 767px) {
  /* On mobile the popover is scroll-contained (overflow:auto, capped
     max-inline-size), so there is never page-level horizontal overflow. These
     single-column overrides stack the twin month grids and the paired time
     sections vertically. The time-grid override needs !important to win after
     the CSS optimizer reorders @media blocks relative to the base rule. */
  .nxt-calendar--range .nxt-calendar-months {
    grid-template-columns: minmax(min-content, 1fr);
  }

  .nxt-date-picker-time-grid {
    grid-template-columns: minmax(0, 1fr) !important;
  }
}

/* Invalid state — canonical form-control invalid border. */
.nxt-calendar[data-invalid] {
  border-color: var(--input-border-invalid);
}

/* ---- DatePicker popover ---- */
.nxt-date-picker-trigger {
  max-inline-size: 100%;
  min-inline-size: 0;
  white-space: normal;
  text-align: start;
}

.nxt-date-picker-popover {
  display: grid;
  gap: var(--date-picker-popover-gap);
  padding: 0;
  inline-size: max-content;
  max-inline-size: var(--date-picker-popover-max-inline-size);
  max-block-size: var(--date-picker-popover-max-block-size);
  overflow: auto;
}
.nxt-date-picker-time-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--date-picker-time-grid-gap);
  padding-block-start: var(--date-picker-time-padding-block-start);
  border-block-start: 1px solid var(--date-picker-time-border);
}
.nxt-date-picker-time {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: start;
  gap: var(--date-picker-time-label-gap);
  min-inline-size: 0;
}
.nxt-date-picker-time--single {
  padding-block-start: var(--date-picker-time-padding-block-start);
  border-block-start: 1px solid var(--date-picker-time-border);
}
.nxt-date-picker-time-label {
  color: var(--fg-secondary);
  font-family: var(--font-ui);
  font-size: var(--text-sm);
  font-variation-settings: var(--font-wght-barlow-medium);
  font-synthesis: none;
  line-height: var(--lh-snug);
  text-align: center;
}
.nxt-popover-arrow { fill: var(--overlay-bg); }


/* ---- TimePicker ---- */
.nxt-time-picker {
  --nxt-tp-num: var(--text-xl);
  display: inline-flex;
  align-items: stretch;
  gap: var(--space-2);
}
.nxt-time-picker[data-size="sm"] { --nxt-tp-num: var(--text-lg); }
.nxt-time-picker[data-size="lg"] { --nxt-tp-num: 1.75rem; }

.nxt-time-picker-segment {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  column-gap: var(--space-1);
  padding: var(--space-1) var(--space-2);
  border: 1px solid var(--field-frame-border);
  border-radius: var(--radius-sm);
  background: var(--field-frame-bg);
}
.nxt-time-picker-segment:focus-within { box-shadow: var(--focus-ring-shadow-gap); border-color: var(--neutral-fill); }

.nxt-time-picker-neighbor {
  grid-column: 1;
  text-align: center;
  color: var(--fg-tertiary);
  font-size: var(--text-xs);
  font-variant-numeric: tabular-nums;
  user-select: none;
}
.nxt-time-picker-segment > .nxt-time-picker-neighbor:nth-of-type(1) { grid-row: 1; }
.nxt-time-picker-segment > .nxt-time-picker-neighbor:nth-of-type(2) { grid-row: 3; }

.nxt-time-picker-value {
  grid-column: 1;
  grid-row: 2;
  inline-size: var(--time-picker-value-inline-size);
  border: 0;
  padding: 0;
  background: transparent;
  color: var(--fg-primary);
  font-family: var(--font-ui);
  font-size: var(--nxt-tp-num);
  /* BRAND-TYPE-001 (ADR 137): semibold via the Barlow variation axis —
     font-weight clamps Barlow GX to wght 188. */
  font-variation-settings: var(--font-wght-barlow-semibold);
  font-synthesis: none;
  font-variant-numeric: tabular-nums;
  text-align: center;
}
.nxt-time-picker-value:focus { outline: none; }

.nxt-time-picker-step {
  grid-column: 2;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  inline-size: var(--time-picker-step-inline-size);
  block-size: var(--time-picker-step-block-size);
  border: 0;
  background: transparent;
  color: var(--fg-secondary);
  cursor: pointer;
  border-radius: var(--radius-sm);
}
.nxt-time-picker-step:hover { background: var(--bg-sunken); color: var(--fg-primary); }
.nxt-time-picker-step--up { grid-row: 1; }
.nxt-time-picker-step--down { grid-row: 3; }

@media (hover: none) and (pointer: coarse) {
  .nxt-time-picker-segment {
    grid-template-rows: var(--ctrl-block-h-md) auto var(--ctrl-block-h-md);
  }

  .nxt-time-picker-step {
    min-inline-size: var(--ctrl-block-h-md);
    min-block-size: var(--ctrl-block-h-md);
  }
}

.nxt-time-picker-colon {
  align-self: center;
  color: var(--secondary);
  font-size: var(--nxt-tp-num);
  font-variation-settings: var(--font-wght-barlow-bold);
}

/* AM/PM segmented control — rendered only in 12-hour display (hourCycle h12).
   Vertical pill matching the segment field height; the pressed half fills with
   the periwinkle accent, mirroring the reference time band. */
.nxt-time-picker-meridiem {
  display: inline-grid;
  grid-template-rows: 1fr 1fr;
  align-self: stretch;
  margin-inline-start: var(--space-1);
  border: 1px solid var(--field-frame-border);
  border-radius: var(--radius-sm);
  overflow: hidden;
}
.nxt-time-picker-meridiem-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-inline-size: var(--time-picker-meridiem-min-inline-size);
  padding: 0 var(--space-2);
  border: 0;
  background: var(--field-frame-bg);
  color: var(--fg-secondary);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: var(--track-caps);
  text-transform: uppercase;
  cursor: pointer;
  transition: background var(--dur-snap) var(--ease-snap), color var(--dur-snap) var(--ease-snap);
}
.nxt-time-picker-meridiem-btn:hover { background: var(--neutral-soft-bg); color: var(--fg-primary); }
.nxt-time-picker-meridiem-btn[aria-pressed="true"] {
  background: var(--secondary);
  color: var(--secondary-fg);
}
.nxt-time-picker-meridiem-btn:focus-visible { outline: none; box-shadow: var(--focus-ring-shadow-gap); position: relative; z-index: 1; }

/* Invalid state — canonical form-control invalid border on each segment frame. */
.nxt-time-picker[data-invalid] .nxt-time-picker-segment,
.nxt-time-picker[data-invalid] .nxt-time-picker-meridiem {
  border-color: var(--input-border-invalid);
}

/* ---- TimePicker: combobox variant (default) — masked field + slot list ----
   The default pattern: a masked hh:mm field that opens a slot list, with
   optional − / + nudge flanks. The outer element carries the .nxt-input field
   frame (border, hover, focus ring, radius-sm); the whole control frame takes
   the system focus ring on focus-within. 24-hour only — no AM/PM. */
.nxt-time-picker[data-variant="combobox"] {
  position: relative;
  display: inline-flex;
  align-items: stretch;
  block-size: var(--ctrl-block-h-md);
  border: var(--field-frame-border-width) solid var(--field-frame-border);
  border-radius: var(--field-frame-radius);
  background: var(--field-frame-bg);
  color: var(--field-frame-fg);
  transition:
    border-color var(--dur-fast) var(--ease-smooth),
    box-shadow   var(--dur-fast) var(--ease-smooth);
}
@media (hover: hover) {
  .nxt-time-picker[data-variant="combobox"]:not([data-disabled]):hover {
    border-color: var(--field-frame-border-hover);
  }
}
.nxt-time-picker[data-variant="combobox"]:focus-within {
  border-color: var(--field-frame-border-focus);
  box-shadow: var(--field-frame-focus-shadow);
}
.nxt-time-picker[data-variant="combobox"][data-invalid] {
  /* Canonical form-control invalid border (matches text-input and the spinner
     variant) — family uniformity per check-cross-contract-tokens. */
  border-color: var(--input-border-invalid);
}
.nxt-time-picker[data-variant="combobox"][data-disabled] {
  /* Canonical form-control disabled family, not an ad-hoc opacity. */
  background: var(--input-bg-disabled);
  border-color: var(--input-border-disabled);
  color: var(--input-fg-disabled);
  pointer-events: none;
}
.nxt-time-picker[data-variant="combobox"][data-disabled] .nxt-time-picker-field,
.nxt-time-picker[data-variant="combobox"][data-disabled] .nxt-time-picker-nudge {
  color: var(--input-fg-disabled);
}

.nxt-time-picker-combobox {
  position: relative;
  display: flex;
  align-items: center;
  flex: 1 1 auto;
  min-inline-size: 0;
}
/* Masked hh:mm field — borderless inside the frame, Barlow numerals, the caret
   hidden so the segment selection range reads as the cursor. */
.nxt-time-picker-field {
  min-inline-size: 0;
  border: 0;
  padding-inline: var(--field-inline-pad-md);
  background: transparent;
  color: var(--fg-primary);
  font-family: var(--font-ui);
  font-size: var(--text-base);
  /* Display weight via the Barlow variation axis (ADR 137), like the calendar
     day and the spinner value. */
  font-variation-settings: var(--font-wght-barlow-semibold);
  font-synthesis: none;
  font-variant-numeric: tabular-nums;
  text-align: center;
  caret-color: transparent;
  cursor: default;
  outline: none;
}
.nxt-time-picker-field::selection {
  background: var(--secondary-soft-bg);
  color: var(--fg-primary);
}

/* Nudge flanks — 44px wide, stretched to the control's 44px row (42px inside the
   shared frame border), attached to the field with a 1px divider (the
   split-button attached-separator pattern: --control-frame-border-width + the
   field frame border colour; there is no dedicated separator token). Press
   feedback follows the system :active scale recipe. */
.nxt-time-picker-nudge {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  inline-size: var(--ctrl-block-h-md);
  border: 0;
  background: transparent;
  color: var(--fg-secondary);
  cursor: pointer;
  transition:
    background var(--dur-snap) var(--ease-snap),
    color      var(--dur-snap) var(--ease-snap),
    transform  var(--dur-instant) var(--ease-snap);
}
.nxt-time-picker-nudge[data-nudge-dir="earlier"] {
  border-inline-end: var(--control-frame-border-width) solid var(--field-frame-border);
}
.nxt-time-picker-nudge[data-nudge-dir="later"] {
  border-inline-start: var(--control-frame-border-width) solid var(--field-frame-border);
}
@media (hover: hover) {
  .nxt-time-picker-nudge:not(:disabled):hover { background: var(--bg-sunken); color: var(--fg-primary); }
}
.nxt-time-picker-nudge:not(:disabled):active { transform: scale(0.97); }
.nxt-time-picker-nudge:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring-shadow-gap);
  border-radius: var(--radius-sm);
  position: relative;
  z-index: 1;
}
.nxt-time-picker-nudge:disabled { cursor: not-allowed; }

/* Slot list — portaled to <body> (position set inline) so no ancestor overflow
   can clip it, exactly like the select menu. Reuses the select-menu surface
   (.nxt-select-menu) and option recipe (.nxt-select-option: neutral is-focused
   hover, ink-solid is-selected). Internal scroll with the thin scrollbar; opens
   centred on the selection. */
.nxt-time-picker-list {
  z-index: var(--z-tooltip);
  max-block-size: calc(var(--ctrl-block-h-sm) * 6);
  margin: 0;
  padding: var(--select-menu-list-padding);
  list-style: none;
  overflow-y: auto;
  scrollbar-width: thin;
  scrollbar-color: var(--border-strong) transparent;
}
.nxt-time-picker-option {
  display: flex;
  align-items: center;
  justify-content: center;
  min-block-size: var(--ctrl-block-h-sm);
  font-family: var(--font-ui);
  font-variation-settings: var(--font-wght-barlow-medium);
  font-variant-numeric: tabular-nums;
}
@media (hover: hover) {
  .nxt-time-picker-option:not(.is-selected):hover { background: var(--selection-indicator-muted-bg); }
}

@media (prefers-reduced-motion: reduce) {
  .nxt-calendar-day-btn,
  .nxt-calendar-nav-btn,
  .nxt-time-picker-meridiem-btn,
  .nxt-time-picker[data-variant="combobox"],
  .nxt-time-picker-nudge { transition: none; }
}

/* ============================================================================
 * DangerZone (danger-zone) + ConfirmationActions (confirmation-actions)
 * Confirmed destructive-action recipes (UI-ACTION-006/007, decision 132).
 * DangerZone is a bordered region tinted with the semantic-error surface so it
 * reads as separated from the commit cluster. ConfirmationActions is the
 * cancel → destructive row that lives in a dialog footer; gap is the action
 * token only.
 * ============================================================================ */

.nxt-danger-zone {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding: var(--space-4);
  border: 1px solid var(--danger);
  border-radius: var(--radius-md);
  background: var(--danger-soft-bg);
  color: var(--danger-soft-fg);
}

.nxt-danger-zone-title {
  font-family: var(--font-sans);
  font-size: var(--text-md);
  font-weight: var(--weight-medium);
  color: inherit;
  margin: 0;
}

.nxt-danger-zone-description {
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  line-height: var(--lh-normal);
  color: inherit;
  margin: 0;
  text-wrap: pretty;
}

.nxt-danger-zone-body {
  margin-top: var(--space-2);
}

.nxt-danger-zone-actions {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--action-gap);
}

.nxt-confirmation-actions {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  justify-content: flex-end;
  align-items: center;
  gap: var(--action-gap);
}

/* ============================================================================
 * Link, CodeSnippet, DescriptionList
 * Low-risk Tier 1 foundations added for program consistency coverage.
 * ============================================================================ */

.nxt-link {
  color: var(--secondary);
  font-family: var(--font-sans);
  line-height: var(--lh-normal);
  text-decoration-thickness: from-font;
  outline: none;
  transition:
    color var(--dur-snap) var(--ease-snap),
    text-decoration-color var(--dur-snap) var(--ease-snap);
}

.nxt-link[data-size="sm"] { font-size: var(--text-sm); }
.nxt-link[data-size="md"] { font-size: var(--text-md); }
.nxt-link[data-size="lg"] { font-size: var(--text-lg); }

.nxt-link[data-variant="default"] { text-decoration-line: underline; }

.nxt-link[data-variant="subtle"] {
  color: var(--fg-secondary);
  text-decoration-line: underline;
  text-decoration-color: transparent;
}

.nxt-link[data-variant="subtle"]:hover {
  color: var(--secondary-hover);
  text-decoration-color: currentColor;
}

.nxt-link[data-variant="inline"] {
  color: inherit;
  text-decoration-line: underline;
}

.nxt-link:hover { color: var(--secondary-hover); }

.nxt-link:focus-visible {
  border-radius: var(--radius-sm);
  box-shadow: var(--focus-ring-shadow-gap);
}

.nxt-link[data-disabled="true"] {
  color: var(--fg-tertiary);
  cursor: not-allowed;
  pointer-events: none;
  text-decoration-color: transparent;
}

/* ============================================================================
 * BrandWordmark
 * Canonical brand geometry comes from the public SVG symbol; the component
 * only owns spacing-backed presentation and accessible semantics.
 * ============================================================================ */

.nxt-brand-wordmark {
  display: block;
  flex: 0 0 auto;
  inline-size: calc(var(--space-6) * 5);
  max-inline-size: 100%;
  block-size: auto;
  aspect-ratio: var(--ratio-wordmark);
  color: currentColor;
  fill: currentColor;
}

.nxt-brand-wordmark[data-size="sm"] {
  inline-size: calc(var(--space-5) * 5);
}

.nxt-brand-wordmark[data-size="md"] {
  inline-size: calc(var(--space-6) * 5);
}

.nxt-brand-wordmark[data-size="lg"] {
  inline-size: calc(var(--space-10) * 5);
}

/* Tumble motion — three superimposed whole-wordmark copies roll in with
 * coloured glints and land as one aligned mark (inspired by, not parity with,
 * the preloader's per-letter three-d scene). Attribute-gated: nothing animates
 * without [data-run], which the runtime only sets when motion is allowed, so
 * reduced motion / frozen-motion render the settled aligned mark. Copy inks
 * and glint hues live in the --wm-* seam. The defaults are a currentColor
 * alpha ladder: on the footer's ink band (currentColor = --fg-inverse) they
 * compute to exactly the handoff's --overlay-on-inverse (15%),
 * fg-on-inverse-muted⊕overlay mix (48.5%), and --fg-inverse (100%) — while
 * staying legible on light doc surfaces instead of painting white-on-white.
 * A surface can still remap the seam outright. */
.nxt-brand-wordmark[data-motion="tumble"] {
  /* Tuning knobs — the intended edit points. */
  --wm-spin-turns: 0.42; /* fraction of a full revolution */
  --wm-glint-band: 12%;  /* glint brushstroke half-width */
  --wm-copy-1: color-mix(in oklch, currentColor 15%, transparent);
  --wm-copy-2: color-mix(in oklch, currentColor 48.5%, transparent);
  --wm-copy-3: currentColor;
  /* Glint hues — golf domain namespace in scoring order (birdie → bogey → par). */
  --wm-glint-1: var(--golf-strokes-birdie-fg);
  --wm-glint-2: var(--golf-strokes-bogey-fg);
  --wm-glint-3: var(--golf-strokes-par-fg);

  position: relative;
  inline-size: var(--preloader-three-d-stage-inline-size);
  max-inline-size: 100%;
  aspect-ratio: var(--ratio-wordmark);
  perspective: 2400px;
}

.nxt-brand-wordmark__copy {
  position: absolute;
  inset: 0;
}

.nxt-brand-wordmark__copy:nth-of-type(1) {
  color: var(--wm-copy-1);
}

.nxt-brand-wordmark__copy:nth-of-type(2) {
  color: var(--wm-copy-2);
}

.nxt-brand-wordmark__copy:nth-of-type(3) {
  color: var(--wm-copy-3);
}

.nxt-brand-wordmark__copy > svg {
  display: block;
  inline-size: 100%;
  block-size: 100%;
  fill: currentColor;
}

/* Glint layer — a narrow coloured brushstroke clipped to the glyphs. */
.nxt-brand-wordmark__glint {
  position: absolute;
  inset: 0;
  opacity: 0;
  -webkit-mask: url("/brand/nextcaddy-wordmark.svg") center / 100% 100% no-repeat;
          mask: url("/brand/nextcaddy-wordmark.svg") center / 100% 100% no-repeat;
  background-image: linear-gradient(
    100deg,
    transparent calc(50% - var(--wm-glint-band)),
    var(--wm-glint) 50%,
    transparent calc(50% + var(--wm-glint-band))
  );
  background-size: 300% 100%;
  background-position: 100% 0;
  background-repeat: no-repeat;
}

.nxt-brand-wordmark__copy:nth-of-type(1) .nxt-brand-wordmark__glint {
  --wm-glint: var(--wm-glint-1);
}

.nxt-brand-wordmark__copy:nth-of-type(2) .nxt-brand-wordmark__glint {
  --wm-glint: var(--wm-glint-2);
}

.nxt-brand-wordmark__copy:nth-of-type(3) .nxt-brand-wordmark__glint {
  --wm-glint: var(--wm-glint-3);
}

@media (prefers-reduced-motion: no-preference) {
  .nxt-brand-wordmark[data-motion="tumble"][data-run] .nxt-brand-wordmark__copy {
    animation:
      nxt-wm-tumble calc(var(--dur-deliberate) * 2) var(--ease-smooth) both,
      nxt-wm-unveil calc(var(--dur-deliberate) * 2) var(--ease-smooth) both;
    transform-origin: 50% 50%;
    will-change: transform, opacity;
    -webkit-mask-image: linear-gradient(100deg, #000 35%, transparent 75%);
            mask-image: linear-gradient(100deg, #000 35%, transparent 75%);
    -webkit-mask-size: 300% 100%;
            mask-size: 300% 100%;
    -webkit-mask-repeat: no-repeat;
            mask-repeat: no-repeat;
  }

  /* Tight phase offset — one continuous sweep, not three separate entrances. */
  .nxt-brand-wordmark[data-motion="tumble"][data-run] .nxt-brand-wordmark__copy:nth-of-type(2),
  .nxt-brand-wordmark[data-motion="tumble"][data-run] .nxt-brand-wordmark__copy:nth-of-type(2) .nxt-brand-wordmark__glint {
    animation-delay: var(--dur-instant);
  }

  .nxt-brand-wordmark[data-motion="tumble"][data-run] .nxt-brand-wordmark__copy:nth-of-type(3),
  .nxt-brand-wordmark[data-motion="tumble"][data-run] .nxt-brand-wordmark__copy:nth-of-type(3) .nxt-brand-wordmark__glint {
    animation-delay: calc(var(--dur-instant) * 2);
  }

  .nxt-brand-wordmark[data-motion="tumble"][data-run] .nxt-brand-wordmark__glint {
    animation: nxt-wm-glint calc(var(--dur-deliberate) * 2) var(--ease-smooth) both;
  }
}

@keyframes nxt-wm-tumble {
  from {
    transform: translateY(4%) rotateX(calc(var(--wm-spin-turns) * -1turn));
    opacity: 0;
  }
  18% {
    opacity: 1;
  }
  to {
    transform: translateY(0) rotateX(0turn);
    opacity: 1;
  }
}

/* Soft veil wipes off left-to-right in lockstep with the roll; ends fully clear. */
@keyframes nxt-wm-unveil {
  from {
    -webkit-mask-position: 100% 0;
    mask-position: 100% 0;
  }
  to {
    -webkit-mask-position: 0% 0;
    mask-position: 0% 0;
  }
}

@keyframes nxt-wm-glint {
  from {
    background-position: 130% 0;
    opacity: 0;
  }
  35% {
    opacity: 1;
  }
  65% {
    opacity: 1;
  }
  to {
    background-position: -30% 0;
    opacity: 0;
  }
}

/* ============================================================================
 * Login
 * Full-screen authentication composition adapted from _incoming/Login.zip.
 * ============================================================================ */

.nxt-login {
  --login-form-measure: var(--field-w-long);
  --login-panel-pad-inline: var(--space-5);
  --login-panel-pad-block: var(--space-7);
  --login-screen-block: var(--viewport-block-full);

  position: relative;
  display: grid;
  inline-size: 100%;
  min-inline-size: 0;
  min-block-size: var(--login-screen-block);
  color: var(--fg-primary);
  background: var(--bg-canvas);
}

.nxt-login-wall {
  display: none;
}

.nxt-login-panel {
  display: flex;
  align-items: center;
  justify-content: center;
  min-block-size: var(--login-screen-block);
  padding-block:
    max(var(--login-panel-pad-block), env(safe-area-inset-top))
    max(var(--login-panel-pad-block), env(safe-area-inset-bottom));
  padding-inline:
    max(var(--login-panel-pad-inline), env(safe-area-inset-left))
    max(var(--login-panel-pad-inline), env(safe-area-inset-right));
}

.nxt-login-form.nxt-form-layout {
  inline-size: 100%;
  max-inline-size: var(--login-form-measure);
  gap: 0;
}

.nxt-login-form-brand {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  margin-block-end: var(--space-8);
  color: var(--fg-primary);
}

.nxt-login-brand-wordmark {
  color: inherit;
}

.nxt-login-fields {
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
}

.nxt-login-password-row {
  position: relative;
}

.nxt-login-password-control {
  position: relative;
}

.nxt-login-password-control .nxt-input {
  inline-size: 100%;
  padding-inline-end: calc(var(--ctrl-inline-pad-lg) + var(--ctrl-block-h-lg) + var(--space-4));
}

.nxt-login-password-toggle.nxt-button {
  position: absolute;
  inset-block: var(--space-1);
  inset-inline-end: var(--space-1);
  block-size: auto;
  min-block-size: 0;
  padding-inline: var(--space-2);
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: var(--track-caps);
}

/* Login's reveal action is intentionally quieter than the global neutral
   ghost treatment. Keep the selector aligned with Button's variant axes so
   the local composition wins without introducing a one-off Button API. */
.nxt-login-password-toggle.nxt-button[data-intent="neutral"][data-emphasis="ghost"] {
  color: var(--fg-tertiary);
}

@media (hover: hover) {
  .nxt-login-password-toggle.nxt-button[data-intent="neutral"][data-emphasis="ghost"]:hover:not([disabled]):not([data-loading="true"]) {
    color: var(--fg-secondary);
  }
}

.nxt-login-forgot-link {
  display: inline-flex;
  margin-block-start: var(--space-2);
  text-decoration-color: currentColor;
  text-decoration-line: underline;
}

.nxt-login-meta {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  margin-block: var(--space-4) var(--space-7);
}

.nxt-login-action.nxt-button {
  inline-size: 100%;
}

.nxt-login-separator {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  margin-block: var(--space-6);
  color: var(--fg-tertiary);
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  line-height: var(--lh-normal);
  text-align: center;
}

.nxt-login-separator::before,
.nxt-login-separator::after {
  content: "";
  flex: 1 1 0;
  border-block-start: 1px solid var(--border-subtle);
}

.nxt-login-foot {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-1);
  margin: var(--space-7) 0 0;
  color: var(--fg-secondary);
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  line-height: var(--lh-normal);
  text-align: center;
}

.nxt-login-foot .nxt-link {
  text-decoration-color: currentColor;
  text-decoration-line: underline;
}

@media (min-width: 768px) {
  .nxt-login-password-row .nxt-field-header {
    padding-inline-end: min(48%, var(--field-w-medium));
  }

  .nxt-login-forgot-link {
    position: absolute;
    inset-block-start: 0;
    inset-inline-end: 0;
    max-inline-size: 48%;
    margin-block-start: 0;
    text-align: end;
  }
}

@media (min-width: 960px) {
  .nxt-login {
    grid-template-columns: minmax(0, 1.08fr) minmax(0, 1fr);
  }

  .nxt-login-wall {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: minmax(0, 1fr) auto minmax(0, 1fr);
    min-block-size: var(--login-screen-block);
    gap: var(--space-8);
    overflow: hidden;
    padding: var(--space-8);
    color: var(--fg-inverse);
    background: var(--bg-inverse);
  }

  .nxt-login-wall-screen,
  .nxt-login-wall-scrim {
    grid-area: 1 / 1 / -1 / -1;
    align-self: stretch;
    justify-self: stretch;
    min-inline-size: 0;
    min-block-size: 0;
  }

  .nxt-login-wall-screen {
    display: grid;
    overflow: hidden;
  }

  .nxt-login-screen-wall.nxt-screen-wall {
    inline-size: 100%;
    block-size: 100%;
    min-block-size: 0;
    border-radius: var(--radius-none);
  }

  .nxt-login-screen-wall .nxt-screen-wall__runtime {
    block-size: 100%;
    min-block-size: 0;
  }

  .nxt-login-screen-wall .nxt-screen-wall__runtime--static::before {
    display: none;
  }

  .nxt-login-wall-scrim {
    position: relative;
    /* Two coats of the canonical scrim keep inverse text above 4.5:1 even
       when the animated mask places its brightest pixel under a glyph. */
    background:
      linear-gradient(var(--overlay-scrim), var(--overlay-scrim)),
      linear-gradient(var(--overlay-scrim), var(--overlay-scrim));
    pointer-events: none;
  }

  .nxt-login-wall-headline {
    position: relative;
    grid-column: 1;
    grid-row: 2;
    max-inline-size: var(--field-w-long);
    margin: 0;
    color: var(--fg-inverse);
    font-family: var(--font-display);
    font-size: var(--text-6xl);
    font-weight: var(--weight-regular);
    line-height: var(--lh-tight);
    letter-spacing: 0;
    text-wrap: balance;
  }

  .nxt-login-logo-wall.nxt-logo-wall[data-surface="ink"] {
    --lw-cell-aspect: 5 / 2;
    --lw-logo-width: 72%;
    --lw-logo-height: 52%;
    grid-column: 1;
    grid-row: 3;
    align-self: end;
    padding: 0;
    background: transparent;
  }

  .nxt-login-panel {
    padding-inline: var(--space-8);
  }

  .nxt-login[data-brand-placement="wall"] .nxt-login-form-brand {
    position: absolute;
    inset-block-start: var(--space-8);
    inset-inline-start: var(--space-8);
    margin: 0;
    color: var(--fg-inverse);
  }

  .nxt-login[data-brand-placement="wall"] .nxt-login-brand-wordmark {
    inline-size: calc(var(--space-5) * 5);
  }
}

@media (forced-colors: active) {
  .nxt-login-wall-scrim {
    display: none;
  }
}

.nxt-code-snippet {
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  line-height: var(--lh-normal);
  color: var(--fg-primary);
  border-radius: var(--radius-sm);
}

.nxt-code-snippet[data-variant="inline"] {
  display: inline;
  padding-inline: var(--space-1);
  background: var(--bg-sunken);
}

.nxt-code-snippet-wrap {
  display: grid;
  gap: var(--space-2);
  /* allow the block <pre>'s own overflow-x:auto to engage instead of the grid
     item growing past a narrow container and clipping. */
  min-width: 0;
}

.nxt-code-snippet-scroll {
  --scroll-affordance-radius: var(--radius-sm);
}

.nxt-code-snippet[data-variant="block"] {
  display: block;
  margin: 0;
  padding: var(--space-3);
  overflow-x: auto;
  background: var(--bg-sunken);
  border: 1px solid var(--border-subtle);
}

.nxt-code-snippet-copy {
  justify-self: start;
  min-block-size: var(--ctrl-block-h-sm);
  padding-inline: var(--ctrl-inline-pad-sm);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-sm);
  background: var(--bg-surface);
  color: var(--fg-secondary);
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  cursor: pointer;
  transition:
    background-color var(--dur-snap) var(--ease-snap),
    color var(--dur-snap) var(--ease-snap),
    border-color var(--dur-snap) var(--ease-snap);
}

.nxt-code-snippet-copy:hover {
  background: var(--bg-sunken);
  color: var(--fg-primary);
  border-color: var(--border-default);
}

.nxt-code-snippet-copy:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring-shadow-gap);
}

.nxt-list {
  --nxt-list-row-block: var(--space-4);
  --nxt-list-row-inline: var(--space-4);
  --nxt-list-gap: var(--space-3);
  --nxt-list-title-size: var(--text-md);
  --nxt-list-description-size: var(--text-sm);

  display: grid;
  gap: 0;
  margin: 0;
  padding: 0;
  color: var(--fg-primary);
  font-family: var(--font-sans);
  line-height: var(--lh-normal);
  list-style: none;
}

.nxt-list[data-density="compact"] {
  --nxt-list-row-block: var(--space-3);
  --nxt-list-row-inline: var(--space-3);
  --nxt-list-gap: var(--space-2);
  --nxt-list-title-size: var(--text-sm);
  --nxt-list-description-size: var(--text-xs);
}

.nxt-list[data-density="comfortable"] {
  --nxt-list-row-block: var(--space-5);
  --nxt-list-row-inline: var(--space-5);
  --nxt-list-gap: var(--space-4);
  --nxt-list-title-size: var(--text-lg);
  --nxt-list-description-size: var(--text-md);
}

.nxt-list-item {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto auto;
  gap: var(--nxt-list-gap);
  align-items: center;
  min-inline-size: 0;
  padding: var(--nxt-list-row-block) var(--nxt-list-row-inline);
  border-radius: var(--radius-sm);
  color: var(--fg-primary);
}

.nxt-list[data-variant="separated"] > .nxt-list-item + .nxt-list-item {
  border-block-start: 1px solid var(--border-subtle);
  border-start-start-radius: 0;
  border-start-end-radius: 0;
}

.nxt-list[data-variant="zebra"] > .nxt-list-item:nth-child(even) {
  background: var(--bg-sunken);
}

.nxt-list-leading,
.nxt-list-trailing {
  display: inline-flex;
  align-items: center;
  min-inline-size: 0;
}

.nxt-list-leading {
  justify-content: center;
  color: var(--fg-tertiary);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0;
}

.nxt-list-content {
  display: grid;
  gap: var(--space-1);
  min-inline-size: 0;
}

.nxt-list-title,
.nxt-list-description {
  min-inline-size: 0;
  overflow-wrap: anywhere;
  text-wrap: pretty;
}

.nxt-list-title {
  color: var(--fg-primary);
  font-size: var(--nxt-list-title-size);
  font-weight: var(--weight-medium);
  line-height: var(--lh-snug);
}

.nxt-list-description {
  color: var(--fg-secondary);
  font-size: var(--nxt-list-description-size);
  line-height: var(--lh-normal);
}

.nxt-list-meta {
  min-inline-size: 0;
  color: var(--fg-tertiary);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-variant-numeric: tabular-nums;
  line-height: var(--lh-tight);
  letter-spacing: 0;
  text-align: end;
  white-space: nowrap;
}

@media (max-width: 767px) {
  .nxt-list-item {
    grid-template-columns: auto minmax(0, 1fr);
    align-items: start;
  }

  .nxt-list-meta,
  .nxt-list-trailing {
    grid-column: 2;
    justify-self: start;
    text-align: start;
  }
}

.nxt-description-list {
  display: grid;
  gap: var(--space-3);
  /* Inline axis only. The UA `dl` margin is block-axis; Preflight already zeroes it,
     so a full `margin: 0` here bought nothing and cost the block axis: unlayered and
     later in the file, it beat every `> * + *` region fallback of equal specificity
     (`.nxt-form-layout`, and now `.nxt-page-body`), pinning a DescriptionList flush
     against whatever preceded it. Measured signature: `nxt-form-layout | h1 ->
     nxt-description-list @0`. Resets must name the axis they mean. */
  margin-inline: 0;
  color: var(--fg-primary);
  font-family: var(--font-sans);
  line-height: var(--lh-normal);
}

.nxt-description-list[data-size="sm"] { font-size: var(--text-sm); }
.nxt-description-list[data-size="md"] { font-size: var(--text-md); }
.nxt-description-list[data-size="lg"] { font-size: var(--text-lg); }

.nxt-description-list-row {
  display: grid;
  gap: var(--space-2);
  padding-block-end: var(--space-2);
  border-block-end: 1px solid var(--border-subtle);
}

.nxt-description-list[data-orientation="horizontal"] .nxt-description-list-row {
  grid-template-columns: minmax(8rem, 1fr) minmax(0, 2fr);
  align-items: baseline;
}

.nxt-description-list[data-orientation="vertical"] .nxt-description-list-row {
  grid-template-columns: 1fr;
}

.nxt-description-list dt {
  color: var(--fg-secondary);
  font-weight: var(--weight-medium);
  overflow-wrap: anywhere;
}

.nxt-description-list dd {
  margin: 0;
  color: var(--fg-primary);
  overflow-wrap: anywhere;
}

/* ============================================================================
 * EventCalendar (event-calendar) — editorial month view (v4, ADR 149).
 * Enclosed card: a month grid of rounded day cells with monochrome marker dots,
 * and a tinted side panel whose day-reader is a compact schedule list with an
 * optional pinned "add event" action. Fully monochrome — category is text only;
 * the selected day uses the shared sliding selection indicator.
 * ============================================================================ */
.nxt-event-calendar {
  inline-size: min(var(--event-calendar-measure), 100%);
  color: var(--fg-primary);
  font-family: var(--font-sans);
  background: var(--bg-surface);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-md);
  overflow: hidden;
  container-type: inline-size;
  container-name: nxt-event-calendar;
}
/* Density variants (ADR 154). Overriding the geometry tokens reflows the whole
   component: compact's narrow measure drops below the 768px split so the reader
   stacks; full widens the measure and grows the type + cell scale. */
.nxt-event-calendar[data-variant="compact"] {
  --event-calendar-measure: var(--event-calendar-measure-compact);
  --event-calendar-day-min-block-size: var(--event-calendar-day-block-compact);
  --event-calendar-month-size: var(--text-2xl);
  --event-calendar-numeral-size: var(--text-4xl);
}
.nxt-event-calendar[data-variant="full"] {
  --event-calendar-measure: var(--event-calendar-measure-full);
  --event-calendar-day-min-block-size: var(--event-calendar-day-block-full);
  --event-calendar-panel-inline-size: var(--event-calendar-panel-inline-full);
  --event-calendar-month-size: var(--text-5xl);
  --event-calendar-numeral-size: var(--text-6xl);
}
.nxt-event-calendar[data-invalid] {
  border-color: var(--input-border-invalid);
}

.nxt-event-calendar-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
}

/* ---- Calendar pane ---- */
.nxt-event-calendar-cal {
  min-inline-size: 0;
  padding: var(--space-6);
}
.nxt-event-calendar-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  min-block-size: var(--event-calendar-masthead-block-size);
}
.nxt-event-calendar-display {
  display: flex;
  align-items: baseline;
  gap: var(--space-3);
  margin: 0;
}
.nxt-event-calendar-month-name {
  margin: 0;
  font-family: var(--font-sans);
  font-size: var(--event-calendar-month-size);
  font-weight: var(--weight-regular);
  line-height: var(--lh-tight);
  letter-spacing: var(--track-tight);
  text-transform: capitalize;
}
.nxt-event-calendar-year {
  color: var(--fg-tertiary);
  font-family: var(--font-sans);
  font-size: var(--text-lg);
  font-weight: var(--weight-regular);
  font-variant-numeric: tabular-nums;
}
.nxt-event-calendar-nav {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
}
.nxt-event-calendar-nav-btn {
  display: inline-grid;
  place-items: center;
  inline-size: var(--event-calendar-control-size);
  block-size: var(--event-calendar-control-size);
  border: 0;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--fg-tertiary);
  cursor: pointer;
  transition: background var(--dur-snap) var(--ease-snap), color var(--dur-snap) var(--ease-snap);
}
.nxt-event-calendar-nav-btn:hover { background: var(--neutral-soft-bg); color: var(--fg-primary); }
.nxt-event-calendar-today-btn {
  min-block-size: var(--event-calendar-control-size);
  padding-inline: var(--space-3);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--fg-secondary);
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  letter-spacing: var(--track-normal);
  cursor: pointer;
  transition: background var(--dur-snap) var(--ease-snap), color var(--dur-snap) var(--ease-snap);
}
.nxt-event-calendar-today-btn:hover { background: var(--neutral-soft-bg); color: var(--fg-primary); }
.nxt-event-calendar-nav-btn:focus-visible,
.nxt-event-calendar-today-btn:focus-visible,
.nxt-event-calendar-day:focus-visible,
.nxt-event-calendar-tl-item:focus-visible,
.nxt-event-calendar-add:focus-visible { outline: none; box-shadow: var(--focus-ring-shadow-gap); position: relative; z-index: 1; }

/* ---- Month grid ---- */
.nxt-event-calendar-dow-row {
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr));
  gap: var(--space-1);
  margin-block-start: var(--space-5);
  padding-block-end: var(--space-2);
  border-block-end: 1px solid var(--border-subtle);
}
.nxt-event-calendar-dow {
  color: var(--fg-tertiary);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  line-height: var(--lh-normal);
  letter-spacing: var(--track-caps);
  text-transform: uppercase;
  text-align: center;
}
.nxt-event-calendar-days {
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr));
  grid-auto-rows: minmax(var(--event-calendar-day-min-block-size), auto);
  gap: var(--space-1);
  margin-block-start: var(--space-2);
  position: relative;
  isolation: isolate;
  --indicator-x: 0px;
  --indicator-y: 0px;
  --indicator-w: 0px;
  --indicator-h: 0px;
}
.nxt-event-calendar-day-indicator {
  position: absolute;
  left: 0;
  top: 0;
  width: var(--indicator-w);
  height: var(--indicator-h);
  transform: translate3d(var(--indicator-x), var(--indicator-y), 0);
  background: var(--selection-indicator-bg);
  border-radius: var(--selection-indicator-radius);
  pointer-events: none;
  z-index: 0;
  transition:
    transform var(--motion-indicator-duration) var(--motion-indicator-ease),
    width var(--motion-indicator-duration) var(--motion-indicator-ease),
    height var(--motion-indicator-duration) var(--motion-indicator-ease);
}
.nxt-event-calendar-day {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  min-block-size: var(--event-calendar-day-min-block-size);
  padding: var(--space-3) var(--space-2);
  border: 0;
  border-radius: var(--radius-sm);
  background: transparent;
  color: inherit;
  text-align: center;
  cursor: pointer;
  position: relative;
  z-index: 1;
  transition: background var(--dur-snap) var(--ease-snap);
}
.nxt-event-calendar-day:hover { background: var(--neutral-soft-bg); }
.nxt-event-calendar-num {
  font-size: var(--text-lg);
  font-variant-numeric: tabular-nums;
  line-height: var(--lh-tight);
  letter-spacing: var(--track-tight);
  color: var(--fg-secondary);
  transition: font-size var(--dur-snap) var(--ease-snap), color var(--dur-snap) var(--ease-snap);
}
.nxt-event-calendar-day--muted { cursor: pointer; }
/* Out-of-month days are selectable buttons, so their number is interactive text
   and must clear WCAG AA 4.5:1. --fg-muted (the v5 handoff value) resolves to
   3.68:1 on the card surface; --fg-tertiary keeps them visibly muted vs the
   in-month --fg-secondary while staying AA-compliant (see ADR 153). */
.nxt-event-calendar-day--muted .nxt-event-calendar-num { color: var(--fg-tertiary); }
.nxt-event-calendar-day--today .nxt-event-calendar-num {
  color: var(--fg-primary);
  font-weight: var(--weight-medium);
  text-decoration: underline;
  text-decoration-thickness: 1.5px;
  text-underline-offset: 0.2em;
}
.nxt-event-calendar-day--disabled { cursor: not-allowed; }
.nxt-event-calendar-day--disabled .nxt-event-calendar-num { color: var(--fg-tertiary); opacity: 0.45; }
.nxt-event-calendar-day--disabled:hover { background: transparent; }
.nxt-event-calendar-day--selected {
  --focus-ring-gap-color: var(--bg-inverse);
  background: transparent;
}
.nxt-event-calendar-day--selected:hover { background: transparent; }
.nxt-event-calendar-day--selected .nxt-event-calendar-num {
  color: var(--fg-inverse);
  font-size: var(--text-xl);
  font-weight: var(--weight-medium);
  text-decoration: none;
  opacity: 1;
}

.nxt-event-calendar-markers {
  display: flex;
  align-items: center;
  gap: var(--space-1);
  min-block-size: var(--event-calendar-marker-size);
}
.nxt-event-calendar-marker {
  inline-size: var(--event-calendar-marker-size);
  block-size: var(--event-calendar-marker-size);
  border-radius: var(--radius-full);
  background: var(--fg-tertiary);
}
.nxt-event-calendar-day--today .nxt-event-calendar-marker { background: var(--fg-secondary); }
.nxt-event-calendar-day--selected .nxt-event-calendar-marker { background: var(--fg-inverse); }

/* ---- Day panel ---- */
.nxt-event-calendar-panel {
  display: flex;
  flex-direction: column;
  min-inline-size: 0;
  border-block-start: 1px solid var(--border-default);
  background: var(--bg-sunken);
}
.nxt-event-calendar-panel-scroll {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-block-size: 0;
  padding: var(--space-6) var(--space-6) var(--space-4);
}
.nxt-event-calendar-dateline {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-4);
  margin-block-start: 0;
  position: relative; /* anchor for the out-of-flow weather tile */
  min-block-size: var(--event-calendar-masthead-block-size);
}
/* Number + meta share a band-height row so the dateline matches the month
   header; the weather tile is positioned out of flow (below) and must not
   inflate this band, else the reader separator drops off the dow-row line. */
.nxt-event-calendar-dateline-main {
  flex: 1;
  min-inline-size: 0;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: var(--space-4);
  align-items: center;
  min-block-size: var(--event-calendar-masthead-block-size);
}
.nxt-event-calendar-big {
  color: var(--fg-primary);
  font-family: var(--font-sans);
  font-size: var(--event-calendar-numeral-size);
  font-weight: var(--weight-regular);
  line-height: var(--lh-tight);
  letter-spacing: var(--track-tight);
  font-variant-numeric: tabular-nums;
}
.nxt-event-calendar-dateline-meta {
  display: grid;
  gap: var(--stack-gap-heading);
  padding-block-start: 0;
}
.nxt-event-calendar-dateline .nxt-weather-tile {
  position: absolute;
  inset-block-start: 0;
  inset-inline-end: 0;
}
.nxt-event-calendar-dow-name {
  color: var(--fg-primary);
  font-size: var(--text-lg);
  font-weight: var(--weight-medium);
  text-transform: capitalize;
}
.nxt-event-calendar-my {
  color: var(--fg-tertiary);
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  text-transform: capitalize;
}

/* ---- Day reader: timeline ---- */
.nxt-event-calendar-timeline {
  display: flex;
  flex-direction: column;
  flex: 1;
  margin-block: var(--space-4) 0;
  /* Bleed the list to the panel edge so item hover breathes laterally; the
     item reclaims the inset as padding (below), keeping text on the grid. */
  margin-inline: calc(-1 * var(--space-3));
  padding: var(--space-2) 0;
  border-block-start: 1px solid var(--border-subtle);
  list-style: none;
  overflow-y: auto;
}
.nxt-event-calendar-tl-item {
  display: grid;
  grid-template-columns: var(--event-calendar-tl-time-size) minmax(0, 1fr);
  gap: var(--space-3);
  inline-size: 100%;
  padding: var(--space-4) var(--space-3);
  border: 0;
  border-radius: var(--radius-sm);
  background: transparent;
  color: inherit;
  text-align: start;
  cursor: pointer;
  transition: background var(--dur-snap) var(--ease-snap);
}
.nxt-event-calendar-tl-item:hover { background: var(--neutral-soft-bg); }
.nxt-event-calendar-tl-time {
  display: grid;
  gap: var(--stack-gap-micro);
  align-content: start;
}
.nxt-event-calendar-tl-start {
  color: var(--fg-primary);
  font-family: var(--font-sans);
  font-size: var(--text-md);
  font-weight: var(--weight-medium);
  font-variant-numeric: tabular-nums;
}
.nxt-event-calendar-tl-end {
  color: var(--fg-tertiary);
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  font-variant-numeric: tabular-nums;
}
.nxt-event-calendar-tl-body {
  display: grid;
  gap: var(--stack-gap-heading);
  min-inline-size: 0;
  align-content: start;
}
.nxt-event-calendar-tl-cat {
  color: var(--eyebrow-fg);
  font-family: var(--eyebrow-font);
  font-size: var(--eyebrow-size);
  font-weight: var(--eyebrow-weight);
  letter-spacing: var(--eyebrow-tracking);
}
.nxt-event-calendar-tl-title {
  color: var(--fg-primary);
  font-size: var(--text-md);
  font-weight: var(--weight-medium);
  text-wrap: pretty;
}
.nxt-event-calendar-tl-meta {
  color: var(--fg-tertiary);
  font-family: var(--font-sans);
  font-size: var(--text-sm);
}

/* ---- Empty state ---- */
.nxt-event-calendar-empty {
  display: flex;
  flex: 1;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  /* Replicate the dow-row spacing chain (space-5 + dow line height + space-2)
     so the empty-state separator lands on the same Y as the weekday line. */
  margin-block-start: calc(var(--space-5) + var(--text-xs) * var(--lh-normal) + var(--space-2));
  margin-inline: calc(-1 * var(--space-3));
  padding-block: var(--space-6);
  border-block-start: 1px solid var(--border-subtle);
  text-align: center;
}
.nxt-event-calendar-empty-glyph { color: var(--border-default); }

/* Club crest slot — placeholder marking event-free days. Isolated behind the
   nxt-event-calendar namespace, ready to graft a future ClubLogo component. */
.nxt-event-calendar-club {
  display: grid;
  justify-items: center;
  gap: var(--space-4);
  margin-block: auto;
  padding-block: var(--space-6);
  text-align: center;
}
.nxt-event-calendar-emblem {
  display: grid;
  place-items: center;
  inline-size: calc(var(--ctrl-block-h-xl) * 2);
  block-size: calc(var(--ctrl-block-h-xl) * 2);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-full);
  font-family: var(--font-mono);
  font-size: var(--text-3xl);
  letter-spacing: var(--track-tight);
  color: var(--fg-tertiary);
}
.nxt-event-calendar-club-name {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: var(--track-caps);
  text-transform: uppercase;
  /* 12px label on the sunken panel: --fg-muted is only 3.28:1 (fails AA);
     --fg-secondary clears 4.5:1 with margin (see ADR 153). */
  color: var(--fg-secondary);
}
.nxt-event-calendar-empty-title {
  color: var(--fg-secondary);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
}
.nxt-event-calendar-empty-lede {
  margin: 0;
  color: var(--fg-tertiary);
  font-size: var(--text-sm);
}

/* ---- Footer add-event action ---- */
.nxt-event-calendar-footer {
  padding: var(--space-3);
  border-block-start: 1px solid var(--border-subtle);
}
.nxt-event-calendar-add {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  inline-size: 100%;
  min-block-size: var(--event-calendar-add-size);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--fg-secondary);
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  letter-spacing: var(--track-tight);
  cursor: pointer;
  transition:
    background var(--dur-fast) var(--ease-smooth),
    color var(--dur-fast) var(--ease-smooth),
    border-color var(--dur-fast) var(--ease-smooth),
    min-block-size var(--dur-fast) var(--ease-smooth),
    font-size var(--dur-fast) var(--ease-smooth);
}
.nxt-event-calendar-add:hover { background: var(--neutral-soft-bg); color: var(--fg-primary); }
/* Empty day → the add action is the primary next step: filled + taller. */
.nxt-event-calendar-add[data-empty] {
  min-block-size: var(--event-calendar-add-size-lg);
  border-color: transparent;
  background: var(--neutral-fill);
  color: var(--neutral-fill-fg);
  font-size: var(--text-md);
}
.nxt-event-calendar-add[data-empty]:hover { background: var(--neutral-fill-hover); color: var(--neutral-fill-fg); }

/* Scroll affordance around the reader timeline. Scoped to the event calendar.
   The wrapper carries the dow-row-aligned offset; the list scrolls inside it.
   The edge fades must read against the sunken panel, not the card surface — so
   rather than remap the global --bg-surface token locally (which would make the
   token-boundary scanner treat event-calendar as its owner), override only the
   fade gradients to --bg-sunken here. */
.nxt-event-calendar .nxt-scroll-affordance {
  --scroll-affordance-border-inset: var(--space-0);
  flex: 1;
  min-block-size: 0;
  display: flex;
  flex-direction: column;
  margin-block-start: calc(var(--space-5) + var(--text-xs) * var(--lh-normal) + var(--space-2));
}
/* Fades match the panel tint: --bg-sunken normally and in the peek sheet, but
   the open sheet flips the panel to --bg-surface, so let the recipe default
   (also --bg-surface) apply there instead of a mismatched sunken band. */
.nxt-event-calendar:not([data-sheet-state="open"]) .nxt-scroll-affordance[data-axis="y"]::before {
  background: linear-gradient(to bottom, var(--bg-sunken), transparent);
}
.nxt-event-calendar:not([data-sheet-state="open"]) .nxt-scroll-affordance[data-axis="y"]::after {
  background: linear-gradient(to top, var(--bg-sunken), transparent);
}
.nxt-event-calendar .nxt-scroll-affordance .nxt-event-calendar-timeline {
  margin-block-start: 0;
  min-block-size: 0;
}

/* At a wide-enough container, split into calendar + tinted side panel. */
@container nxt-event-calendar (min-width: 768px) {
  .nxt-event-calendar-grid {
    grid-template-columns: minmax(0, 1fr) var(--event-calendar-panel-inline-size);
  }
  .nxt-event-calendar-cal { border-inline-end: 1px solid var(--border-default); }
  .nxt-event-calendar-panel {
    border-block-start: 0;
    /* Cap the panel to the pane height so a dense day genuinely overflows and
       the scroll affordance can fire, instead of stretching the whole card. */
    block-size: 0;
    min-block-size: 100%;
  }
}

@container nxt-event-calendar (max-width: 767px) {
  .nxt-event-calendar-cal {
    padding: var(--space-5) var(--space-4);
    --event-calendar-day-min-block-size: var(--space-8);
  }
  .nxt-event-calendar-panel-scroll { padding: var(--space-5) var(--space-4) var(--space-4); }
  .nxt-event-calendar-dow-row { margin-block-start: var(--space-4); }
}

/* ---- Mobile bottom sheet (ADR 155) ----
   When the reader reflows to a sheet (compact always, or a narrow container via
   the runtime ResizeObserver), the panel becomes a bottom sheet inside a
   fixed-height card: peek shows a lip (grabber + dateline), open slides it up
   over a scrim. Geometry is token-driven; motion drives transform/opacity only. */
.nxt-event-calendar[data-sheet-mode="true"] {
  --event-calendar-sheet-height: calc(var(--event-calendar-sheet-root) - var(--event-calendar-sheet-open-top));
  --event-calendar-sheet-closed-offset: calc(var(--event-calendar-sheet-root) - var(--event-calendar-sheet-peek) - var(--event-calendar-sheet-open-top));
  position: relative;
  display: block;
  block-size: var(--event-calendar-sheet-root);
}
/* Complete the height chain so the calendar pane can fill the fixed card: the
   root is display:block here, so the grid needs an explicit 100% height for the
   pane's block-size:100% (and the flex grid inside it) to resolve. */
.nxt-event-calendar[data-sheet-mode="true"] .nxt-event-calendar-grid {
  display: block;
  block-size: 100%;
}
.nxt-event-calendar[data-variant="compact"][data-sheet-mode="true"] {
  --event-calendar-sheet-root: var(--event-calendar-sheet-root-compact);
}
.nxt-event-calendar[data-sheet-mode="true"] .nxt-event-calendar-cal {
  block-size: 100%;
  border-inline-end: 0;
  /* keep the month grid clear of the peek lip */
  padding-block-end: calc(var(--event-calendar-sheet-peek) + var(--space-2));
  /* Fill the fixed card as a column so the grid can flex to fit every week row
     above the peek lip — otherwise a 5–6 week month clips into the hidden
     overflow and its bottom rows become unselectable. */
  display: flex;
  flex-direction: column;
  min-block-size: 0;
}
.nxt-event-calendar[data-sheet-mode="true"] .nxt-event-calendar-days {
  flex: 1;
  min-block-size: 0;
  grid-auto-rows: minmax(var(--event-calendar-day-min-block-size), 1fr);
}
.nxt-event-calendar[data-sheet-mode="true"] .nxt-event-calendar-day {
  min-block-size: 0;
}
.nxt-event-calendar[data-sheet-mode="true"] .nxt-event-calendar-panel {
  position: absolute;
  inset-inline: 0;
  inset-block-start: var(--event-calendar-sheet-open-top);
  block-size: var(--event-calendar-sheet-height);
  z-index: var(--z-overlay-panel);
  border-block-start: 0;
  border-start-start-radius: var(--radius-md);
  border-start-end-radius: var(--radius-md);
  box-shadow: var(--elevation-floating);
  background: var(--bg-sunken);
  transform: translateY(var(--event-calendar-sheet-closed-offset));
  transition: transform var(--dur-base) var(--ease-spring);
}
.nxt-event-calendar[data-sheet-mode="true"][data-sheet-state="open"] .nxt-event-calendar-panel {
  background: var(--bg-surface);
  transform: translateY(0);
}
.nxt-event-calendar-scrim {
  position: absolute;
  inset: 0;
  z-index: var(--z-overlay);
  border: 0;
  padding: 0;
  background: var(--dialog-scrim);
  opacity: 0;
  pointer-events: none;
  cursor: pointer;
  transition: opacity var(--dur-fast) var(--ease-smooth);
}
.nxt-event-calendar[data-sheet-state="open"] .nxt-event-calendar-scrim {
  opacity: 1;
  pointer-events: auto;
}
.nxt-event-calendar-grabber {
  display: flex;
  align-items: center;
  justify-content: center;
  inline-size: 100%;
  min-block-size: var(--space-6);
  border: 0;
  background: transparent;
  cursor: pointer;
}
.nxt-event-calendar-grabber span {
  inline-size: var(--space-7);
  block-size: var(--space-1);
  border-radius: var(--radius-full);
  background: var(--border-default);
}
.nxt-event-calendar-scrim:focus-visible,
.nxt-event-calendar-grabber:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring-shadow-gap);
  position: relative;
  z-index: 1;
}

@media (prefers-reduced-motion: reduce) {
  .nxt-event-calendar-nav-btn,
  .nxt-event-calendar-today-btn,
  .nxt-event-calendar-day-indicator,
  .nxt-event-calendar-day,
  .nxt-event-calendar-num,
  .nxt-event-calendar-tl-item,
  .nxt-event-calendar-add,
  .nxt-event-calendar[data-sheet-mode="true"] .nxt-event-calendar-panel,
  .nxt-event-calendar-scrim { transition: none; }
}

/* ---- Event Calendar variants preview (hand-authored /preview/event-calendar-variants) ----
   A full-bleed harness that escapes the docs shell so each variant renders at
   its intrinsic width on a neutral backdrop, with horizontal scroll to pan the
   wider frames. Flips with data-color-scheme on the root. */
.nxt-event-calendar-preview {
  display: flex;
  flex-direction: column;
  gap: var(--space-6);
  min-block-size: var(--viewport-block-full-dynamic);
  padding: var(--space-7) var(--space-8);
  background: var(--bg-sunken);
  color: var(--fg-primary);
  font-family: var(--font-sans);
}
.nxt-event-calendar-preview-toolbar {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-4);
  flex-wrap: wrap;
}
.nxt-event-calendar-preview-title {
  margin: 0;
  font-size: var(--text-2xl);
  font-weight: var(--weight-medium);
  letter-spacing: var(--track-tight);
}
.nxt-event-calendar-preview-lede {
  margin: var(--space-1) 0 0;
  color: var(--fg-tertiary);
  font-size: var(--text-sm);
}
.nxt-event-calendar-preview-canvas {
  display: flex;
  align-items: flex-start;
  gap: var(--space-8);
  overflow-x: auto;
  padding-block-end: var(--space-6);
}
.nxt-event-calendar-preview-frame {
  flex: 0 0 auto;
  display: grid;
  gap: var(--space-4);
  align-content: start;
}
.nxt-event-calendar-preview-frame-head h2 {
  margin: 0;
  font-size: var(--text-md);
  font-weight: var(--weight-medium);
}
.nxt-event-calendar-preview-frame-head p {
  margin: var(--space-1) 0 0;
  color: var(--fg-tertiary);
  font-size: var(--text-xs);
}

/* ============================================================================
 * GolfMarker — compact golf-course measurement marker.
 * Static data-display family for distances, tee measurements, and fairway width.
 * Source values are meters; yards are display-only conversion in the runtime.
 * ============================================================================ */

.nxt-golf-marker {
  --golf-marker-bg: var(--bg-surface);
  --golf-marker-fg: var(--fg-primary);
  --golf-marker-border: var(--border-default);
  --golf-marker-pad-block: var(--space-2);
  --golf-marker-pad-inline: var(--space-3);
  --golf-marker-gap: var(--space-2);
  --golf-marker-value-size: var(--text-2xl);
  --golf-marker-icon-size: 0.82em;

  position: relative;
  display: inline-flex;
  width: fit-content;
  align-items: center;
  justify-content: center;
  gap: var(--golf-marker-gap);
  min-inline-size: var(--golf-marker-min-inline-size);
  padding: var(--golf-marker-pad-block) var(--golf-marker-pad-inline);
  border: 1px solid var(--golf-marker-border);
  border-radius: var(--radius-md);
  background: var(--golf-marker-bg);
  color: var(--golf-marker-fg);
  font-family: var(--font-sans);
  font-variant-numeric: tabular-nums;
  line-height: var(--lh-tight);
  white-space: nowrap;
  vertical-align: middle;
  box-sizing: border-box;
}

.nxt-golf-marker-value {
  font-size: var(--golf-marker-value-size);
  font-weight: var(--weight-semibold);
  line-height: var(--lh-tight);
}

.nxt-golf-marker-unit {
  align-self: flex-end;
  padding-block-end: var(--golf-marker-unit-offset-block-end);
  color: currentColor;
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
  line-height: var(--lh-tight);
  opacity: 0.74;
}

.nxt-golf-marker-icon {
  display: block;
  flex: 0 0 auto;
  inline-size: var(--golf-marker-icon-size);
  block-size: var(--golf-marker-icon-size);
  color: currentColor;
}

.nxt-golf-marker[data-size="sm"] {
  --golf-marker-pad-block: var(--space-1);
  --golf-marker-pad-inline: var(--space-2);
  --golf-marker-gap: var(--space-1);
  --golf-marker-value-size: var(--text-lg);
  min-inline-size: var(--golf-marker-min-inline-size-sm);
  border-radius: var(--radius-sm);
}

.nxt-golf-marker[data-size="lg"] {
  --golf-marker-pad-block: var(--space-3);
  --golf-marker-pad-inline: var(--space-4);
  --golf-marker-value-size: var(--text-3xl);
  min-inline-size: var(--golf-marker-min-inline-size-lg);
  border-radius: var(--radius-lg);
}

.nxt-golf-marker[data-kind="green"] {
  --golf-marker-bg: var(--neutral-fill);
  --golf-marker-fg: var(--neutral-fill-fg);
  --golf-marker-border: var(--neutral-fill);
}

.nxt-golf-marker[data-kind="target"],
.nxt-golf-marker[data-kind="position"],
.nxt-golf-marker[data-kind="distance"] {
  --golf-marker-bg: var(--bg-surface);
  --golf-marker-fg: var(--fg-primary);
  --golf-marker-border: var(--border-default);
}

.nxt-golf-marker[data-kind="fairway-width"] {
  --golf-marker-bg: var(--bg-surface);
  --golf-marker-fg: var(--fg-primary);
  --golf-marker-border: var(--border-strong);
  min-inline-size: var(--golf-marker-fairway-min-inline-size);
  overflow: visible;
}

.nxt-golf-marker-rule {
  position: absolute;
  z-index: -1;
  inset-block-start: 50%;
  inset-inline-start: 50%;
  inline-size: var(--golf-marker-rule-inline-size);
  border-block-start: 1px dashed currentColor;
  opacity: 0.7;
  transform: translateX(-50%);
  pointer-events: none;
}

.nxt-golf-marker[data-kind="color-tee"] {
  --golf-marker-bg: var(--accent);
  --golf-marker-fg: var(--neutral-12);
  --golf-marker-border: color-mix(in oklch, var(--golf-marker-bg) 86%, var(--neutral-12));
}

.nxt-golf-marker[data-kind="color-tee"][data-tee-color="BL"] {
  --golf-marker-bg: var(--bg-surface);
  --golf-marker-fg: var(--fg-primary);
  --golf-marker-border: var(--border-strong);
}

.nxt-golf-marker[data-kind="color-tee"][data-tee-color="AM"] {
  --golf-marker-bg: var(--accent);
  --golf-marker-fg: var(--neutral-12);
}

.nxt-golf-marker[data-kind="color-tee"][data-tee-color="DO"],
.nxt-golf-marker[data-kind="color-tee"][data-tee-color="NA"] {
  --golf-marker-bg: var(--warning);
  --golf-marker-fg: var(--neutral-12);
}

.nxt-golf-marker[data-kind="color-tee"][data-tee-color="RO"],
.nxt-golf-marker[data-kind="color-tee"][data-tee-color="RS"] {
  --golf-marker-bg: var(--danger-soft-bg);
  --golf-marker-fg: var(--neutral-12);
}

.nxt-golf-marker[data-kind="color-tee"][data-tee-color="AZ"] {
  --golf-marker-bg: var(--info-soft-bg);
  --golf-marker-fg: var(--neutral-12);
}

.nxt-golf-marker[data-kind="color-tee"][data-tee-color="VE"] {
  --golf-marker-bg: var(--success-soft-bg);
  --golf-marker-fg: var(--neutral-12);
}

.nxt-golf-marker[data-kind="color-tee"][data-tee-color="NE"] {
  --golf-marker-bg: var(--neutral-fill);
  --golf-marker-fg: var(--neutral-fill-fg);
  --golf-marker-border: var(--neutral-fill);
}

/* ============================================================================
 * GolfHoleSign — compact hole-summary sign in the golf marker family.
 * Source length is meters; yards are display-only conversion in the runtime.
 * ============================================================================ */

.nxt-golf-hole-sign {
  --golf-hole-sign-fg: var(--fg-primary);
  --golf-hole-sign-border: var(--border-strong);
  --golf-hole-sign-dot-bg: var(--golf-tee-am-bg);
  --golf-hole-sign-unit-size: var(--text-xs);

  display: inline-flex;
  flex-direction: column;
  width: fit-content;
  color: var(--golf-hole-sign-fg);
  font-family: var(--font-ui);
  font-size: var(--golf-hole-sign-font-size);
  font-synthesis: none;
  font-variation-settings: var(--golf-hole-sign-font-var);
  font-variant-numeric: tabular-nums;
  line-height: var(--golf-hole-sign-line-height);
  text-rendering: geometricPrecision;
  box-sizing: border-box;
}

.nxt-golf-hole-sign-badge {
  display: flex;
  align-items: center;
  justify-content: center;
  color: currentColor;
  font-size: var(--golf-hole-sign-badge-font-size);
  text-align: center;
}

.nxt-golf-hole-sign-number {
  padding-inline: var(--golf-hole-sign-value-padding-inline);
  font-size: inherit;
  line-height: var(--golf-hole-sign-line-height);
  letter-spacing: var(--track-normal);
  text-align: end;
}

.nxt-golf-hole-sign-data {
  display: flex;
  flex-direction: column;
  flex-wrap: nowrap;
  gap: var(--golf-hole-sign-data-gap);
  font-size: var(--golf-hole-sign-data-font-size);
  line-height: var(--golf-hole-sign-line-height);
}

.nxt-golf-hole-sign-par {
  font-size: var(--golf-hole-sign-par-font-size);
}

.nxt-golf-hole-sign-hcp {
  display: contents;
}

.nxt-golf-hole-sign-length {
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: var(--golf-hole-sign-length-font-size);
}

.nxt-golf-hole-sign-tee {
  display: flex;
  align-items: center;
  border-block-start: 1px solid var(--golf-hole-sign-border);
  color: currentColor;
}

.nxt-golf-hole-sign-distance {
  font-size: inherit;
  line-height: var(--golf-hole-sign-line-height);
}

.nxt-golf-hole-sign-unit {
  margin-inline-start: var(--golf-hole-sign-tee-dot-gap);
  font-size: var(--golf-hole-sign-unit-size);
  line-height: var(--golf-hole-sign-line-height);
}

.nxt-golf-hole-sign-dot {
  display: inline-block;
  flex: 0 0 auto;
  inline-size: var(--golf-hole-sign-tee-dot-size);
  block-size: var(--golf-hole-sign-tee-dot-size);
  min-inline-size: var(--golf-hole-sign-tee-dot-size);
  margin-inline-start: var(--golf-hole-sign-tee-dot-gap);
  /* Hairline ring so the dot keeps a visible outline even when its tee color
     matches the surface (e.g. the white BL tee on a light card). */
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-full);
  background: var(--golf-hole-sign-dot-bg);
  font-size: var(--golf-hole-sign-tee-dot-font-size);
}

.nxt-golf-hole-sign[data-size="sm"] {
  --golf-hole-sign-font-size: var(--golf-hole-sign-font-size-sm);
}

.nxt-golf-hole-sign[data-size="lg"] {
  --golf-hole-sign-font-size: var(--golf-hole-sign-font-size-lg);
}

.nxt-golf-hole-sign[data-tee-color="BL"] {
  --golf-hole-sign-dot-bg: var(--golf-tee-bl-bg);
}

.nxt-golf-hole-sign[data-tee-color="AM"] {
  --golf-hole-sign-dot-bg: var(--golf-tee-am-bg);
}

.nxt-golf-hole-sign[data-tee-color="DO"],
.nxt-golf-hole-sign[data-tee-color="NA"] {
  --golf-hole-sign-dot-bg: var(--golf-tee-do-bg);
}

.nxt-golf-hole-sign[data-tee-color="NA"] {
  --golf-hole-sign-dot-bg: var(--golf-tee-na-bg);
}

.nxt-golf-hole-sign[data-tee-color="RO"],
.nxt-golf-hole-sign[data-tee-color="RS"] {
  --golf-hole-sign-dot-bg: var(--golf-tee-ro-bg);
}

.nxt-golf-hole-sign[data-tee-color="RS"] {
  --golf-hole-sign-dot-bg: var(--golf-tee-rs-bg);
}

.nxt-golf-hole-sign[data-tee-color="AZ"] {
  --golf-hole-sign-dot-bg: var(--golf-tee-az-bg);
}

.nxt-golf-hole-sign[data-tee-color="VE"] {
  --golf-hole-sign-dot-bg: var(--golf-tee-ve-bg);
}

.nxt-golf-hole-sign[data-tee-color="NE"] {
  --golf-hole-sign-dot-bg: var(--golf-tee-ne-bg);
}

.nxt-golf-hole-sign[data-animate="true"] .nxt-golf-hole-sign-number,
.nxt-golf-hole-sign[data-animate="true"] .nxt-golf-hole-sign-data,
.nxt-golf-hole-sign[data-animate="true"] .nxt-golf-hole-sign-length {
  overflow: hidden;
  opacity: 0;
  transform: translateY(var(--golf-hole-sign-enter-translate));
  animation: nxt-golf-hole-sign-enter var(--golf-hole-sign-enter-duration) var(--golf-hole-sign-enter-ease) forwards;
}

.nxt-golf-hole-sign[data-animate="true"] .nxt-golf-hole-sign-number {
  animation-delay: var(--golf-hole-sign-enter-delay-number);
}

.nxt-golf-hole-sign[data-animate="true"] .nxt-golf-hole-sign-data {
  animation-delay: var(--golf-hole-sign-enter-delay-data);
}

.nxt-golf-hole-sign[data-animate="true"] .nxt-golf-hole-sign-length {
  animation-delay: var(--golf-hole-sign-enter-delay-length);
}

@keyframes nxt-golf-hole-sign-enter {
  from {
    opacity: 0;
    transform: translateY(var(--golf-hole-sign-enter-translate));
  }
  to {
    opacity: 1;
    transform: translateY(var(--space-0));
  }
}

@media (prefers-reduced-motion: reduce) {
  .nxt-golf-hole-sign[data-animate="true"] .nxt-golf-hole-sign-number,
  .nxt-golf-hole-sign[data-animate="true"] .nxt-golf-hole-sign-data,
  .nxt-golf-hole-sign[data-animate="true"] .nxt-golf-hole-sign-length {
    opacity: 1;
    transform: none;
    animation: none;
  }
}

/* ──────────────────────────────────────────────────────────────────────────
 * DOCS SHELL
 * Sticky sidebar layout for documentation pages (/components, /patterns,
 * /foundations). Mirrors the nxt-preview-layout / nxt-preview-rail pattern
 * but under a docs-scoped namespace. All values reference semantic tokens.
 * ────────────────────────────────────────────────────────────────────── */
.nxt-docs-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  min-block-size: var(--viewport-block-full);
  inline-size: 100%;
}

.nxt-docs-rail {
  display: grid;
  order: 2;
  align-content: start;
  gap: var(--space-5);
  min-inline-size: 0;
  padding: var(--space-4);
  border-block-end: 1px solid var(--border-subtle);
  background: var(--bg-canvas);
}

.nxt-docs-main {
  order: 1;
  min-inline-size: 0;
  overflow-x: clip;
}

.nxt-docs-rail-section {
  display: grid;
  gap: var(--space-2);
  min-inline-size: 0;
}

.nxt-docs-rail-heading {
  margin: 0;
  color: var(--fg-tertiary);
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
  line-height: var(--lh-snug);
  text-transform: uppercase;
  letter-spacing: var(--track-caps);
}

/* Sidebar navigation — collapsible section groups */
.nxt-docs-sidebar-nav {
  min-inline-size: 0;
}

.nxt-docs-nav-list {
  display: grid;
  /* Three nesting levels, one rung each: group -> group 16, row -> items 8,
     item -> item 4. All three were --space-1, so the sidebar had no hierarchy. */
  gap: var(--space-4);
  margin: 0;
  padding: 0;
  list-style: none;
}

.nxt-docs-nav-group {
  display: grid;
  gap: var(--space-2);
}

.nxt-docs-nav-group-row {
  display: flex;
  align-items: center;
  gap: var(--space-1);
}

.nxt-docs-nav-section-link {
  flex: 1 1 auto;
  min-inline-size: 0;
  justify-content: flex-start;
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
}

.nxt-docs-nav-group-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  min-block-size: var(--ctrl-block-h-sm);
  min-inline-size: var(--ctrl-block-h-sm);
  padding: 0;
  border: 0;
  border-radius: var(--nav-item-radius);
  background: transparent;
  color: var(--fg-tertiary);
  cursor: pointer;
}

@media (hover: hover) {
  .nxt-docs-nav-group-toggle:hover {
    color: var(--fg-primary);
    background: var(--nav-item-bg-hover);
  }
}

.nxt-docs-nav-group-toggle:focus-visible {
  outline: none;
  box-shadow: var(--nav-item-focus-shadow);
}

.nxt-docs-nav-group-toggle svg {
  transition: transform var(--dur-fast) var(--ease-snap);
}

.nxt-docs-nav-group-toggle[aria-expanded="true"] svg {
  transform: rotate(90deg);
}

.nxt-docs-nav-group-items {
  display: grid;
  gap: var(--space-1);
  margin: 0;
  margin-inline-start: var(--space-3);
  padding: 0;
  padding-inline-start: var(--space-3);
  border-inline-start: 1px solid var(--border-subtle);
  list-style: none;
}

.nxt-docs-nav-group-items[hidden] {
  display: none;
}

.nxt-docs-nav-link {
  justify-content: flex-start;
  min-block-size: var(--ctrl-block-h-sm);
  font-size: var(--text-sm);
}

/* Breadcrumb bar — sits above page content in the main column */
.nxt-docs-breadcrumb-bar {
  padding-block: var(--space-3);
  padding-inline: var(--space-4);
  border-block-end: 1px solid var(--border-subtle);
}

/* In-page TOC */
.nxt-docs-toc-list {
  display: grid;
  gap: var(--space-1);
  margin: 0;
  padding: 0;
  list-style: none;
}

.nxt-docs-toc-link {
  display: block;
  padding-block: var(--space-1);
  padding-inline: var(--space-3);
  border-inline-start: 2px solid transparent;
  color: var(--fg-secondary);
  font-size: var(--text-sm);
  text-decoration: none;
  transition:
    color var(--dur-fast) var(--ease-snap),
    border-inline-start-color var(--dur-fast) var(--ease-snap);
}

.nxt-docs-toc-link[data-active] {
  color: var(--accent-outline);
  border-inline-start-color: var(--accent-outline);
  font-weight: var(--weight-medium);
}

@media (hover: hover) {
  .nxt-docs-toc-link:not([data-active]):hover {
    color: var(--fg-primary);
    border-inline-start-color: var(--border-strong);
  }
}

.nxt-docs-toc-link:focus-visible {
  outline: none;
  box-shadow: var(--nav-item-focus-shadow);
}

/* Global search */
.nxt-docs-search-wrap {
  position: relative;
  min-inline-size: 0;
}

.nxt-docs-search-dropdown {
  position: absolute;
  inset-block-start: calc(100% + var(--space-1));
  inset-inline: 0;
  z-index: var(--z-overlay-panel);
  max-block-size: var(--docs-search-dropdown-max-block-size);
  overflow-y: auto;
  border: 1px solid var(--border-default);
  border-radius: var(--radius-md);
  background: var(--bg-surface);
  box-shadow: var(--overlay-panel-shadow);
}

.nxt-docs-search-group-heading {
  padding-block: var(--space-2);
  padding-inline: var(--space-3);
  background: var(--bg-sunken);
  color: var(--fg-tertiary);
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
  text-transform: uppercase;
  letter-spacing: var(--track-caps);
}

.nxt-docs-search-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding-block: var(--space-2);
  padding-inline: var(--space-3);
  color: var(--fg-primary);
  font-size: var(--text-sm);
  text-decoration: none;
  cursor: pointer;
}

.nxt-docs-search-item[aria-selected="true"],
.nxt-docs-search-item:focus-visible {
  background: var(--bg-sunken);
  outline: none;
}

.nxt-docs-search-item-meta {
  color: var(--fg-tertiary);
  font-size: var(--text-xs);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.nxt-docs-search-empty {
  padding: var(--space-4) var(--space-3);
  color: var(--fg-secondary);
  font-size: var(--text-sm);
  text-align: center;
}

/* Mobile cross-section chip nav (< 960px) */
.nxt-docs-chip-nav {
  display: flex;
  gap: var(--space-1);
  overflow-x: auto;
  padding-block: var(--space-2);
  padding-inline: var(--space-4);
  border-block-end: 1px solid var(--border-subtle);
  scrollbar-width: none;
}

.nxt-docs-chip-nav::-webkit-scrollbar {
  display: none;
}

.nxt-docs-chip-link {
  white-space: nowrap;
  padding-block: var(--space-1);
  padding-inline: var(--space-3);
  border-radius: var(--radius-full);
  border: 1px solid var(--border-subtle);
  color: var(--fg-secondary);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  text-decoration: none;
  transition: background var(--dur-fast) var(--ease-snap);
  flex-shrink: 0;
}

.nxt-docs-chip-link[aria-current="page"] {
  background: var(--bg-sunken);
  border-color: var(--border-strong);
  color: var(--fg-primary);
}

/* Desktop: two-column sticky rail */
@media (min-width: 960px) {
  .nxt-docs-layout {
    grid-template-columns: 18rem minmax(0, 1fr);
  }

  .nxt-docs-rail {
    order: 1;
    position: sticky;
    inset-block-start: 0;
    block-size: var(--viewport-block-full);
    overflow-y: auto;
    border-block-end: 0;
    border-inline-end: 1px solid var(--border-subtle);
  }

  .nxt-docs-main {
    order: 2;
  }

  .nxt-docs-chip-nav {
    display: none;
  }
}

@media (max-width: 959px) {
  .nxt-docs-rail {
    display: none;
  }
}

/* ============================================================
 * FOOTER  (components/footer — Tier 3)
 *
 * Reusable site footer in three structured zones: a columns row (brand cell
 * plus eyebrow-headed link columns), a wordmark row (display or brand
 * wordmark, optionally with the tumble motion), and a meta bar (copyright +
 * back-to-top). A DS-native adaptation of the Osmo "Footer Parallax": when
 * `data-reveal` is present, the content rises and a dark veil fades out as
 * the band scrolls into view, driven entirely by a CSS scroll-driven
 * `view-timeline` — no GSAP. The reveal is gated by `@supports` +
 * `prefers-reduced-motion`; the settled / unsupported / reduced / reveal-off
 * state is a clean static footer (content at rest, veil fully transparent).
 *
 * Two surfaces via `data-surface`: default (warm canvas) and ink (dark band).
 * Structural geometry (reveal travel, cell flex bases) lives in the
 * component-local custom-property seam below; every colour / type / motion
 * value resolves to a semantic token.
 * ============================================================ */
.nxt-footer {
  --ft-reveal-travel: var(--space-7);
  /* Structural geometry (handoff-exact cell minima and note measure). */
  --ft-brand-min: 18rem;
  --ft-col-min: 9rem;
  --ft-note-measure: 36ch;
  /* Surface seam — overridden by [data-surface="ink"]. */
  --ft-bg: var(--bg-canvas);
  --ft-fg: var(--fg-primary);
  --ft-eyebrow: var(--eyebrow-fg);
  --ft-note: var(--fg-secondary);
  --ft-border: var(--border-subtle);
  --ft-meta: var(--fg-tertiary);
  /* Deliberate ghost tint: near-neutral with a whisper of the lime hue
     (computes to oklch(0.9415 0.02 142.4)). The base must stay the chroma-0
     --bg-sunken; --accent-soft-bg is high-chroma lime in this repo's ladder
     and the mix would stay vivid. */
  --ft-wordmark: color-mix(in oklch, var(--bg-sunken) 90%, var(--accent));
  --ft-link: var(--fg-secondary);
  --ft-link-hover: var(--secondary-hover);

  position: relative;
  isolation: isolate;
  overflow: clip;
  border-block-start: 1px solid var(--ft-border);
  background: var(--ft-bg);
  color: var(--ft-fg);
}

.nxt-footer[data-surface="ink"] {
  --ft-bg: var(--bg-inverse);
  --ft-fg: var(--fg-inverse);
  --ft-eyebrow: var(--fg-on-inverse-muted);
  --ft-note: var(--fg-on-inverse-muted);
  --ft-border: var(--overlay-on-inverse);
  --ft-meta: var(--fg-on-inverse-muted);
  --ft-wordmark: var(--fg-inverse);
  --ft-link: var(--fg-inverse);
  --ft-link-hover: var(--fg-inverse);
}

/* The shared focus ring gaps against --bg-canvas (light); on the ink band match
   the gap to the dark surface so the focus halo reads correctly. */
.nxt-footer[data-surface="ink"] .nxt-link:focus-visible {
  /* Literal on purpose: a local --focus-ring-gap-color never reaches the
     :root-resolved --focus-ring-shadow-gap (see focus-ring-inventory.md). */
  box-shadow: 0 0 0 2px var(--ft-bg), 0 0 0 4px var(--focus-ring);
}

.nxt-footer__content {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  gap: var(--space-9);
  padding-block: var(--space-9) var(--space-5);
  padding-inline: max(var(--space-6), calc((100% - var(--container-xl)) / 2));
}

/* Dark veil sits ABOVE the content (like the Osmo source's fading overlay): the
   whole band emerges from shadow uniformly as it scrolls in, so text never sits
   on a half-darkened background. pointer-events:none keeps links clickable. */
/* On the ink surface (band already --bg-inverse) the veil is dark-over-dark, so
   the reveal reduces to the content rise — an accepted degradation; there is no
   darker-than-inverse token to contrast against. */
.nxt-footer__veil {
  position: absolute;
  inset: 0;
  z-index: 2;
  background: var(--bg-inverse);
  opacity: 0;
  pointer-events: none;
}

/* Zone 1 — columns row: brand cell first, then the link columns. */
.nxt-footer__columns {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: var(--space-7) var(--space-8);
}

/* Brand cell: monogram + colophon note. No eyebrow — it is the brand
   statement, not a labelled column. */
.nxt-footer__brand {
  display: grid;
  flex: 2 1 20rem;
  align-content: start;
  justify-items: start;
  gap: var(--stack-gap-related);
  min-inline-size: min(100%, var(--ft-brand-min));
}

.nxt-footer__mark {
  display: block;
  inline-size: var(--space-6);
  block-size: auto;
  color: var(--ft-fg);
}

.nxt-footer__col {
  display: grid;
  flex: 1 1 10rem;
  align-content: start;
  gap: var(--space-3);
  min-inline-size: var(--ft-col-min);
}

/* Column eyebrow — the DS eyebrow role verbatim (quiet sentence case). */
.nxt-footer__eyebrow {
  margin: 0;
  color: var(--ft-eyebrow);
  font-family: var(--eyebrow-font);
  font-size: var(--eyebrow-size);
  font-weight: var(--eyebrow-weight);
  letter-spacing: var(--eyebrow-tracking);
  line-height: var(--lh-snug);
}

.nxt-footer__links {
  display: grid;
  gap: var(--space-2);
  margin: 0;
  padding: 0;
  list-style: none;
}

/* Footer links inherit the subtle link recipe but resolve to the surface seam,
   so they stay legible on the ink surface where --fg-secondary would vanish. */
.nxt-footer .nxt-link,
.nxt-footer .nxt-link[data-variant="subtle"] {
  color: var(--ft-link);
}

.nxt-footer .nxt-link:hover,
.nxt-footer .nxt-link[data-variant="subtle"]:hover {
  color: var(--ft-link-hover);
  text-decoration-color: currentColor;
}

.nxt-footer__note {
  margin: 0;
  max-inline-size: var(--ft-note-measure);
  color: var(--ft-note);
  font-size: var(--text-md);
  line-height: var(--lh-normal);
  text-wrap: pretty;
}

/* Zone 2 — wordmark row (also hosts the Zone 3 meta bar when present). */
.nxt-footer__wordmark-row {
  display: grid;
  /* minmax(0, 1fr): pin the implicit track to the container so the tumble
     stage's viewport-derived width caps at 100% instead of growing the track
     to max-content and overflowing narrow cells. */
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-5);
  /* size the wordmark to its own width, not the viewport, so it does not
     overflow when the footer is rendered in a narrow container. */
  container-type: inline-size;
}

.nxt-footer__wordmark {
  margin: 0;
  color: var(--ft-fg);
  font-family: var(--font-display);
  font-size: clamp(var(--text-4xl), 16cqi, var(--text-6xl));
  max-inline-size: 100%;
  font-weight: var(--weight-bold);
  line-height: var(--lh-tight);
  letter-spacing: var(--track-tight);
}

.nxt-footer__brand-wordmark {
  display: block;
  inline-size: 100%;
  block-size: auto;
  color: var(--ft-wordmark);
}

/* The tumble stage keeps its own stage width (it is a brand moment, not a
   full-bleed banner); the wordmark seam still inks the settled mark. */
.nxt-footer__brand-wordmark[data-motion="tumble"] {
  inline-size: var(--preloader-three-d-stage-inline-size);
  max-inline-size: 100%;
}

/* Zone 3 — meta bar: copyright + back-to-top on a hairline. The back-to-top
   link keeps the shared recipe; remapping --ft-link scopes its resting ink to
   the meta role without restyling .nxt-link here. */
.nxt-footer__meta {
  --ft-link: var(--ft-meta);

  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  row-gap: var(--stack-gap-content);
  column-gap: var(--space-5);
  border-block-start: 1px solid var(--ft-border);
  padding-block-start: var(--space-4);
}

.nxt-footer__copyright {
  margin: 0;
  color: var(--ft-meta);
  font-size: var(--text-sm);
  line-height: var(--lh-snug);
}

/* Scroll-driven reveal — opt-in (`data-reveal`) and motion-safe. The settled
   state (and every no-support / reduced-motion / reveal-off fallback) leaves
   content at rest with the veil fully transparent: a clean static band. */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .nxt-footer[data-reveal] {
      view-timeline-name: --nxt-footer-reveal;
      view-timeline-axis: block;
    }

    .nxt-footer[data-reveal] .nxt-footer__content {
      animation-name: nxt-footer-rise;
      animation-fill-mode: both;
      animation-timing-function: linear;
      animation-timeline: --nxt-footer-reveal;
      animation-range: entry 0% entry 60%;
    }

    .nxt-footer[data-reveal] .nxt-footer__veil {
      animation-name: nxt-footer-veil;
      animation-fill-mode: both;
      animation-timing-function: linear;
      animation-timeline: --nxt-footer-reveal;
      animation-range: entry 0% entry 60%;
    }
  }
}

@keyframes nxt-footer-rise {
  from {
    transform: translateY(var(--ft-reveal-travel));
  }
  to {
    transform: translateY(0);
  }
}

@keyframes nxt-footer-veil {
  from {
    opacity: 0.5;
  }
  to {
    opacity: 0;
  }
}

/* ============================================================
 * CASCADING SLIDER
 *
 * Clip-path carousel. The active slide is wide and centred; siblings
 * narrow; far slides clipped to a sliver. Each slide is full active-width
 * in the DOM — the runtime (cascading-slider.tsx) sets per-slide
 * transform / clip-path / z-index inline from computed slot geometry, and
 * toggles the transition on/off per slide to reproduce the source's
 * gsap.set (instant park) vs gsap.to (animated) split. CSS owns only the
 * static chrome and the tokenised transition timing.
 *
 * Ported from the Osmo "Cascading Slider" (GSAP → DS-native CSS transitions).
 * Geometry values (track height, gap, ratios) live in the component-local
 * custom-property seam below; every colour / radius / type / motion value
 * resolves to a semantic token.
 * ============================================================ */
.nxt-cascading-slider {
  --cs-gap: var(--space-2);
  /* Track height. Fixed by default (matches the source); consumers needing a
     shorter carousel on small viewports override --cs-track-h via media query. */
  --cs-track-h: 35rem;
  --cs-content-pad-block: var(--space-5);
  --cs-content-pad-inline: var(--space-6);

  width: 100%;
  max-width: 90rem;
  margin-inline: auto;
  position: relative;
}
.nxt-cascading-slider:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring-shadow);
  border-radius: var(--radius-lg);
}

.nxt-cascading-slider__collection {
  width: 100%;
}

.nxt-cascading-slider__viewport {
  width: 100%;
  height: var(--cs-track-h);
  position: relative;
  overflow: hidden;
  opacity: 0;
  transition: opacity var(--dur-base) var(--ease-smooth);
}
.nxt-cascading-slider__viewport[data-ready] {
  opacity: 1;
}

.nxt-cascading-slider__item {
  position: absolute;
  inset: 0 auto auto 0;
  height: 100%;
  cursor: pointer;
  user-select: none;
  will-change: transform, clip-path;
  clip-path: inset(0px round var(--radius-lg));
}
.nxt-cascading-slider__item[data-status="active"] {
  cursor: default;
}

.nxt-cascading-slider__item-inner {
  width: 100%;
  height: 100%;
  position: relative;
  overflow: hidden;
}
.nxt-cascading-slider__item-bg {
  position: absolute;
  inset: 0;
  z-index: 0;
}
.nxt-cascading-slider__img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.nxt-cascading-slider__item-content {
  position: absolute;
  inset: auto 0 0 0;
  z-index: 2;
  padding: calc(var(--cs-content-pad-block) * 1.5) var(--cs-content-pad-inline) var(--cs-content-pad-block);
  /* Editorial scrim — tokenised veil (reveal pattern). Inverts cleanly across
     color-scheme: dark veil + light heading in light UI, and vice-versa. */
  background-image: linear-gradient(
    to top,
    color-mix(in oklch, var(--fg-primary), transparent 10%) 0%,
    color-mix(in oklch, var(--fg-primary), transparent 22%) 38%,
    color-mix(in oklch, var(--fg-primary), transparent 64%) 72%,
    color-mix(in oklch, var(--fg-primary), transparent 100%) 100%
  );
}

.nxt-cascading-slider__heading {
  margin: 0;
  font-family: var(--font-display);
  font-size: var(--text-4xl);
  font-weight: var(--weight-regular);
  line-height: var(--lh-tight);
  letter-spacing: var(--track-tight);
  color: var(--fg-inverse);
  opacity: 0;
  transform: translateY(var(--space-1));
  transition:
    opacity var(--dur-base) var(--ease-enter),
    transform var(--dur-base) var(--ease-enter);
}
.nxt-cascading-slider__item[data-status="active"] .nxt-cascading-slider__heading {
  opacity: 1;
  transform: translateY(0);
  transition-delay: var(--dur-moderate);
}

/* ---------- Nav ---------- */
.nxt-cascading-slider__nav {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: var(--space-4);
  margin-top: var(--space-8);
}
.nxt-cascading-slider__button {
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--space-7);
  height: var(--space-7);
  padding: var(--space-3);
  border: none;
  border-radius: var(--radius-md);
  background: var(--accent-soft-bg);
  color: var(--accent-soft-fg);
  cursor: pointer;
  transition:
    background var(--dur-snap) var(--ease-snap),
    color var(--dur-snap) var(--ease-snap);
}
.nxt-cascading-slider__button:hover {
  background: var(--accent-soft-fg);
  color: var(--accent-soft-bg);
}
.nxt-cascading-slider__button:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring-shadow);
}
.nxt-cascading-slider__arrow {
  width: 100%;
  height: auto;
}
.nxt-cascading-slider__arrow[data-direction="prev"] {
  transform: rotate(180deg);
}

/* ---------- Surface: ink (clear chrome over a dark panel) ---------- */
.nxt-cascading-slider[data-surface="ink"] {
  background: var(--neutral-12);
  padding: var(--space-5);
  border-radius: var(--radius-lg);
}

@media (prefers-reduced-motion: reduce) {
  .nxt-cascading-slider__item,
  .nxt-cascading-slider__heading,
  .nxt-cascading-slider__viewport {
    transition: none !important;
  }
}

/* SectionedList — grouped scrollable list with optional sticky section headers.
   Sticky headers use native position: sticky against the nearest scroll ancestor
   (the root when [data-scroll="true"], otherwise a height-constrained parent).
   Header background is always opaque (--bg-canvas) so rows do not bleed through. */
.nxt-sectioned-list {
  --nxt-sectioned-list-sticky-top: 0px;
  --nxt-sectioned-list-max-block: none;
  display: flex;
  flex-direction: column;
  color: var(--fg-primary);
}

.nxt-sectioned-list[data-scroll="true"] {
  overflow: auto;
  max-block-size: var(--nxt-sectioned-list-max-block);
}

.nxt-sectioned-list-section {
  display: flex;
  flex-direction: column;
}

.nxt-sectioned-list-header {
  margin: 0;
  padding: var(--space-2) var(--space-3);
  background: var(--bg-canvas);
  color: var(--fg-tertiary);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
  letter-spacing: var(--track-caps);
  text-transform: uppercase;
  border-block-end: 1px solid var(--border-subtle);
}

.nxt-sectioned-list[data-sticky="true"] .nxt-sectioned-list-header {
  position: sticky;
  top: var(--nxt-sectioned-list-sticky-top, 0);
  z-index: 1;
}

.nxt-sectioned-list-items {
  list-style: none;
  margin: 0;
  padding: 0;
}

.nxt-sectioned-list-item {
  border-block-end: 1px solid var(--border-subtle);
}

.nxt-sectioned-list-item:last-child {
  border-block-end: none;
}

.nxt-sectioned-list-item-row {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  justify-content: center;
  min-block-size: var(--nav-item-block-size);
  padding: var(--space-2) var(--space-3);
}

a.nxt-sectioned-list-item-row,
button.nxt-sectioned-list-item-row {
  min-block-size: var(--ctrl-block-h-sm);
  color: inherit;
  text-decoration: none;
  border-radius: var(--radius-md);
}

button.nxt-sectioned-list-item-row {
  inline-size: 100%;
  appearance: none;
  border: 0;
  background: transparent;
  font: inherit;
  text-align: start;
  cursor: pointer;
}

a.nxt-sectioned-list-item-row:hover,
button.nxt-sectioned-list-item-row:hover {
  background: var(--nav-item-bg-hover);
}

a.nxt-sectioned-list-item-row:focus-visible,
button.nxt-sectioned-list-item-row:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring-shadow-gap);
}

.nxt-sectioned-list-item[data-disabled="true"] .nxt-sectioned-list-item-row {
  opacity: 0.5;
  pointer-events: none;
}

.nxt-sectioned-list-item-label {
  color: var(--fg-primary);
  font-size: var(--text-base);
  font-weight: var(--weight-medium);
}

.nxt-sectioned-list-item-meta {
  color: var(--fg-tertiary);
  font-size: var(--text-sm);
  font-variant-numeric: tabular-nums;
}

.nxt-sectioned-list[data-size="sm"] .nxt-sectioned-list-item-row {
  padding: var(--space-1) var(--space-3);
}

.nxt-sectioned-list[data-size="sm"] .nxt-sectioned-list-item-label {
  font-size: var(--text-sm);
}

.nxt-sectioned-list[data-size="lg"] .nxt-sectioned-list-item-row {
  padding: var(--space-3);
}

.nxt-sectioned-list[data-size="lg"] .nxt-sectioned-list-item-label {
  font-size: var(--text-md);
}

/* ============================================================
 * SEARCH BOX
 * Free-text search input with inline suggestion panel.
 * ============================================================ */
.nxt-search-box {
  position: relative;
  display: grid;
  gap: var(--space-1);
  inline-size: min(100%, var(--search-box-inline-size));
}

.nxt-search-box .nxt-input[data-kind="search"]::-webkit-search-cancel-button,
.nxt-search-box .nxt-input[data-kind="search"]::-webkit-search-decoration,
.nxt-search-box .nxt-input[data-kind="search"]::-webkit-search-results-button,
.nxt-search-box .nxt-input[data-kind="search"]::-webkit-search-results-decoration {
  appearance: none;
  -webkit-appearance: none;
  display: none;
}

.nxt-search-box .nxt-input-affix {
  padding-inline: var(--space-2);
}

.nxt-search-box .nxt-input-affix--prefix {
  padding-inline-end: 0;
}

.nxt-search-box .nxt-input-affix--suffix {
  padding-inline-start: var(--space-1);
}

.nxt-search-box .nxt-input-slot > .nxt-input {
  padding-inline-start: var(--space-2);
  padding-inline-end: var(--space-2);
}

.nxt-search-box-clear.nxt-button {
  inline-size: var(--space-6);
  block-size: var(--space-6);
  min-inline-size: var(--space-6);
  min-block-size: var(--space-6);
}

.nxt-search-box-clear.nxt-button:focus-visible {
  outline: 2px solid var(--input-border-focus);
  outline-offset: 2px;
  box-shadow: none;
}

.nxt-search-box-panel {
  position: absolute;
  z-index: var(--z-overlay-panel);
  inset-block-start: calc(100% + var(--space-1));
  inset-inline: 0;
  overflow: hidden;
  max-block-size: var(--search-box-panel-max-block-size);
  border: 1px solid var(--overlay-panel-border);
  border-radius: var(--overlay-panel-radius);
  background: var(--overlay-panel-bg);
  color: var(--overlay-panel-fg);
  box-shadow: var(--overlay-panel-shadow);
}

.nxt-search-box-listbox {
  display: grid;
  gap: var(--space-1);
  max-block-size: var(--search-box-panel-max-block-size);
  overflow-y: auto;
  padding: var(--space-1);
}

.nxt-search-box-group {
  display: grid;
  gap: var(--space-1);
}

.nxt-search-box-group-label {
  padding-block: var(--space-2) var(--space-1);
  padding-inline: var(--space-2);
  color: var(--eyebrow-fg);
  font-family: var(--eyebrow-font);
  font-size: var(--eyebrow-size);
  font-weight: var(--eyebrow-weight);
  letter-spacing: var(--eyebrow-tracking);
}

.nxt-search-box-option {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  inline-size: 100%;
  min-block-size: var(--ctrl-block-h-sm);
  padding-block: var(--space-2);
  padding-inline: var(--space-3);
  border-radius: var(--radius-sm);
  color: var(--fg-primary);
  text-align: start;
  cursor: pointer;
}

.nxt-search-box-option[data-active] {
  /* Neutral selection language — shared --selection-indicator recipe (Select,
     Menu, Tabs). Accent (lime) is reserved for the single hero CTA per view. */
  background: var(--selection-indicator-muted-bg);
}

.nxt-search-box-option[data-disabled] {
  color: var(--fg-tertiary);
  cursor: not-allowed;
}

.nxt-search-box-option-main {
  display: grid;
  min-inline-size: 0;
}

.nxt-search-box-option-label {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
}

.nxt-search-box-option-main [data-match] {
  /* Subtle neutral emphasis on matched text — a light neutral chip + heavier
     weight, never the reserved accent. */
  border-radius: var(--radius-sm);
  background: var(--selection-indicator-muted-bg);
  color: var(--fg-primary);
  font-weight: var(--weight-medium);
}

/* On the (single) active row the chip background equals the row background, so
   step up to the stronger neutral fill to keep the match visible by colour as
   well as weight (WCAG 1.4.1 — not weight alone). */
.nxt-search-box-option[data-active] .nxt-search-box-option-main [data-match] {
  background: var(--selection-indicator-bg);
  color: var(--neutral-fill-fg);
}

.nxt-search-box-option-breadcrumb {
  overflow: hidden;
  color: var(--fg-tertiary);
  font-size: var(--text-xs);
  text-overflow: ellipsis;
  white-space: nowrap;
}

.nxt-search-box-option-description {
  color: var(--fg-secondary);
  font-size: var(--text-xs);
}

.nxt-search-box-option-meta {
  color: var(--fg-tertiary);
  font-size: var(--text-xs);
  font-variant-numeric: tabular-nums;
}

.nxt-search-box-option-meta {
  flex: none;
  max-inline-size: 35%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.nxt-search-box-status {
  display: grid;
  gap: var(--space-1);
  padding: var(--space-3);
  color: var(--fg-tertiary);
  font-size: var(--text-sm);
}

.nxt-search-box-empty-hint {
  color: var(--fg-secondary);
  font-size: var(--text-xs);
}

.nxt-search-box-footer {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  padding: var(--space-2) var(--space-3);
  border-block-start: 1px solid var(--border-subtle);
  color: var(--fg-tertiary);
  font-size: var(--text-xs);
}

.nxt-search-box-footer-hint {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
}

/* DocSearch ⌘K modal: a SearchBox composed inside a Dialog. Reuses field-frame
   tokens for the trigger and lets the SearchBox panel show inside the modal. */
.nxt-doc-search-trigger {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  inline-size: 100%;
  padding: var(--space-2) var(--space-3);
  border: var(--field-frame-border-width) solid var(--field-frame-border);
  border-radius: var(--field-frame-radius);
  background: var(--field-frame-bg);
  color: var(--fg-tertiary);
  font-size: var(--text-sm);
  text-align: start;
  cursor: pointer;
}

.nxt-doc-search-trigger-label {
  flex: 1;
}

.nxt-doc-search-trigger-kbd {
  flex: none;
}

.nxt-doc-search-trigger:hover {
  border-color: var(--field-frame-border-focus);
}

.nxt-doc-search-trigger:focus-visible {
  outline: none;
  box-shadow: var(--field-frame-focus-shadow);
}

.nxt-doc-search-modal {
  overflow: visible;
}

.nxt-doc-search-modal-box {
  inline-size: 100%;
  max-inline-size: none;
}
/* ============================================================================
 * Video-reel — DS-native port of the Osmo "Mini Showreel Player". A compact
 * "Play Showreel" card whose poster morphs into a centred, dimmed lightbox
 * playing a native <video>, and morphs back on close. Modal a11y is composed
 * from Radix Dialog; the open/close morph is a measured-rect FLIP reproduced
 * as a tokenised CSS transition (no animation library — the runtime parks the
 * frame at the trigger rect via the --reel-from-* vars, then transitions to
 * the centred identity transform). Geometry lives in a component-local
 * --reel-* seam (mirrors cascading-slider's --cs-* / Marquee's --tile-*).
 * ============================================================================ */

.nxt-video-reel {
  --reel-aspect: 16 / 10; /* the source's 62.5% padding box */
  --reel-card-max: 22rem;
  /* definite width (capped to the container) so the media's aspect-ratio
     resolves to a real height instead of collapsing in a shrink-wrap box. */
  display: block;
  inline-size: var(--reel-card-max);
  max-inline-size: 100%;
}

/* Gallery — the canonical multi-reel layout: a centred, padded container that
   gives each card room to breathe and stacks 1 → 2 → 3 across as width allows
   (auto-fit, so it collapses to a single stacked column on narrow viewports). */
.nxt-video-reel-gallery {
  /* component-local geometry seam (same convention as --reel-* / --cs-*) */
  --reel-gallery-max: 72rem;
  --reel-gallery-col-min: 16rem;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(var(--reel-gallery-col-min), 1fr));
  gap: var(--space-6);
  inline-size: 100%;
  max-inline-size: var(--reel-gallery-max);
  margin-inline: auto;
  padding: var(--space-6) var(--space-4);
}
.nxt-video-reel-gallery .nxt-video-reel {
  display: block;
  max-inline-size: none;
}

/* ---------- Trigger card ---------- */
.nxt-video-reel__card {
  display: flex;
  flex-direction: column;
  gap: var(--surface-frame-gap);
  inline-size: 100%;
  padding: var(--surface-frame-padding);
  background: var(--surface-frame-bg);
  color: var(--surface-frame-fg);
  border: 1px solid var(--surface-frame-border);
  border-radius: var(--surface-frame-radius);
  box-shadow: var(--surface-frame-shadow);
  font-family: var(--font-sans);
  text-align: start;
  cursor: pointer;
  transition:
    border-color var(--dur-base) var(--ease-enter),
    box-shadow var(--dur-base) var(--ease-enter);
}
.nxt-video-reel__card:hover {
  border-color: var(--surface-frame-border-hover);
}
.nxt-video-reel__card:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring-shadow);
}
/* While the lightbox is open the in-page card is hidden so only the morphing
 * overlay is visible — the source's single-element "lift". */
.nxt-video-reel__card[data-reel-open] {
  visibility: hidden;
}

.nxt-video-reel[data-surface="ink"] .nxt-video-reel__card {
  background: var(--neutral-12);
  border-color: color-mix(in oklch, var(--neutral-12), white 12%);
  color: var(--fg-inverse);
}

.nxt-video-reel__media {
  position: relative;
  display: block;
  aspect-ratio: var(--reel-aspect);
  border-radius: var(--surface-frame-media-radius);
  overflow: hidden;
  /* Solid token surface shown when no poster is supplied (the poster <img>,
     when present, covers it). */
  background: var(--neutral-12);
}
.nxt-video-reel__poster {
  position: absolute;
  inset: 0;
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
  display: block;
}
.nxt-video-reel__badge {
  position: absolute;
  inset: 0;
  margin: auto;
  inline-size: var(--space-8);
  block-size: var(--space-8);
  display: grid;
  place-items: center;
  border-radius: var(--radius-full);
  background: var(--accent);
  color: var(--accent-fg);
  transition: transform var(--dur-base) var(--ease-enter);
}
.nxt-video-reel__card:hover .nxt-video-reel__badge {
  transform: scale(1.06);
}
.nxt-video-reel__label {
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  line-height: var(--lh-snug);
}

/* ---------- Lightbox ---------- */
.nxt-video-reel__scrim {
  position: fixed;
  inset: 0;
  z-index: var(--z-overlay);
  background: var(--overlay-scrim);
  opacity: 0;
  transition: opacity var(--dur-base) var(--ease-enter);
}
.nxt-video-reel__scrim[data-reel-phase="open"] {
  opacity: 1;
}

.nxt-video-reel__positioner {
  position: fixed;
  inset: 0;
  z-index: var(--z-overlay-panel);
  display: grid;
  place-items: center;
  padding: var(--space-4);
  pointer-events: none;
}

.nxt-video-reel__frame {
  /* Geometry seam. The frame is portaled outside .nxt-video-reel, so the
     --reel-* vars are declared here (not on the wrapper) — including
     --reel-aspect, which the portaled media (native <video> and the YouTube
     stage) needs; without it the stage's aspect-ratio is invalid and its
     absolutely-positioned children collapse to 0 height. */
  --reel-aspect: 16 / 10;
  --reel-frame-max: min(64rem, calc(100vw - var(--space-8)));
  --reel-from-x: 0px;
  --reel-from-y: 0px;
  --reel-from-scale: 1;
  pointer-events: auto;
  inline-size: var(--reel-frame-max);
  max-inline-size: 100%;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding: var(--space-3);
  background: var(--overlay-panel-bg);
  color: var(--overlay-panel-fg);
  border-radius: var(--overlay-panel-radius);
  box-shadow: var(--overlay-panel-shadow);
  outline: none;
  /* init: parked at the measured trigger rect, hidden — no transition. The
     opacity start hides the one-frame measure/park before the morph runs. */
  opacity: 0;
  transform-origin: top left;
  transform: translate(var(--reel-from-x), var(--reel-from-y))
    scale(var(--reel-from-scale));
}
/* opacity is the canonical enter/exit signal (it always changes 0<->1, so the
   runtime's onTransitionEnd fires reliably even if the measured morph degrades
   to a plain fade). transform adds the FLIP morph on top. */
.nxt-video-reel__frame[data-reel-phase="open"] {
  opacity: 1;
  transform: none;
  transition:
    opacity var(--dur-slow) var(--ease-smooth),
    transform var(--dur-slow) var(--ease-smooth);
}
.nxt-video-reel__frame[data-reel-phase="closing"] {
  opacity: 0;
  transform: translate(var(--reel-from-x), var(--reel-from-y))
    scale(var(--reel-from-scale));
  transition:
    opacity var(--dur-slow) var(--ease-smooth),
    transform var(--dur-slow) var(--ease-smooth);
}

.nxt-video-reel__bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
}
.nxt-video-reel__title {
  margin: 0;
  font-family: var(--font-sans);
  font-size: var(--text-lg);
  font-weight: var(--weight-medium);
  line-height: var(--lh-snug);
  color: var(--overlay-panel-fg);
}
.nxt-video-reel__close {
  flex: none;
  display: grid;
  place-items: center;
  inline-size: var(--space-7);
  block-size: var(--space-7);
  border: none;
  border-radius: var(--radius-md);
  background: transparent;
  color: var(--overlay-panel-fg);
  cursor: pointer;
  transition: background var(--dur-base) var(--ease-enter);
}
.nxt-video-reel__close:hover {
  background: color-mix(in oklch, var(--overlay-panel-fg), transparent 88%);
}
.nxt-video-reel__close:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring-shadow);
}
.nxt-video-reel__video {
  inline-size: 100%;
  aspect-ratio: var(--reel-aspect);
  display: block;
  border-radius: var(--surface-frame-media-radius);
  background: var(--neutral-12);
}

/* YouTube (or other iframe-embed) path: a 16:10 stage with the poster behind
   and the autoplay embed layered on top once playback starts. */
.nxt-video-reel__stage {
  position: relative;
  inline-size: 100%;
  aspect-ratio: var(--reel-aspect);
  border-radius: var(--surface-frame-media-radius);
  overflow: hidden;
  background: var(--neutral-12);
}
.nxt-video-reel__embed {
  position: absolute;
  inset: 0;
  inline-size: 100%;
  block-size: 100%;
  border: 0;
  display: block;
}

/* Reduced motion: no scale/translate — the lightbox cross-fades in place. The
 * runtime sets its reducedRef so the exit "done" signal is the opacity
 * transition rather than transform. */
@media (prefers-reduced-motion: reduce) {
  .nxt-video-reel__frame,
  .nxt-video-reel__frame[data-reel-phase="open"],
  .nxt-video-reel__frame[data-reel-phase="closing"] {
    transform: none;
    transition: opacity var(--dur-base) var(--ease-enter);
  }
  .nxt-video-reel__frame {
    opacity: 0;
  }
  .nxt-video-reel__frame[data-reel-phase="open"] {
    opacity: 1;
  }
  .nxt-video-reel__card,
  .nxt-video-reel__badge {
    transition: none;
  }
  .nxt-video-reel__card:hover .nxt-video-reel__badge {
    transform: none;
  }
}

/* ============================================================
 * LogoWall — responsive grid of brand logos that swap one cell
 * at a time with a slide-and-fade, cycling through a larger pool.
 *
 * Each logo is a CSS mask-image silhouette recoloured to a single
 * token (--lw-logo-color), so heterogeneous source SVGs read as a
 * uniform monochrome wall and invert per surface. The visible cell
 * count and dwell interval live in this stylesheet (--lw-visible,
 * --lw-cycle-interval) and are read back by the runtime, mirroring
 * Marquee's --tile-* / cascading-slider's --cs-* seam convention.
 * No new global tokens; the swap motion is a keyframe (no library).
 *
 * Ported from the Osmo "Logo Wall Cycle" (GSAP -> DS-native).
 * ============================================================ */
.nxt-logo-wall {
  /* Component-local geometry seam — consumes globals, introduces none.
     --lw-columns/--lw-visible here are the SSR / no-container fallback; the
     live values are declared on __list under the container queries below. */
  --lw-columns: 4;
  --lw-visible: 8;
  --lw-gap: var(--space-2);
  --lw-cell-aspect: 3 / 2;
  /* Logo box base. Each mark's optical `fit` scale composes onto these
     (calc(base * fit), set inline by the runtime), so per-mark scaling never
     hardcodes the percentage. */
  --lw-logo-base-w: 72%;
  --lw-logo-base-h: 52%;
  --lw-logo-width: var(--lw-logo-base-w);
  --lw-logo-height: var(--lw-logo-base-h);
  --lw-logo-color: var(--fg-muted);
  --lw-cycle-interval: 1500ms;

  container-type: inline-size;
  width: 100%;
}

/* Container-first column ladder (4 → 3 → 2 → 1), keyed off the wall's own
   inline size so a wall inside a login panel or narrow side region degrades
   on ITS width, not the viewport's. The seam moves to the list: a container
   query styles descendants of the container, never the container itself.
   Edges are the canonical --bp-* band edges (--bp-lg 960 / --bp-md 768 /
   --bp-sm 390). */
.nxt-logo-wall__list {
  --lw-columns: 4;
  --lw-visible: 8;

  display: grid;
  grid-template-columns: repeat(var(--lw-columns), 1fr);
  gap: var(--lw-gap);
  margin: 0;
  padding: 0;
  list-style: none;
}

@container (max-width: 959px) {
  .nxt-logo-wall__list {
    --lw-columns: 3;
    --lw-visible: 6;
  }
}
@container (max-width: 767px) {
  .nxt-logo-wall__list {
    --lw-columns: 2;
    --lw-visible: 6;
    --lw-cell-aspect: 5 / 2;
  }
}
@container (max-width: 389px) {
  .nxt-logo-wall__list {
    --lw-columns: 1;
    --lw-visible: 4;
    --lw-cell-aspect: 5 / 2;
  }
}

.nxt-logo-wall__item {
  position: relative;
  aspect-ratio: var(--lw-cell-aspect);
  /* The two swap layers stack centred; overflow clips the slide motion. */
  display: grid;
  place-items: center;
  overflow: hidden;
}

.nxt-logo-wall__logo {
  /* --lw-mask (the SVG url) and --lw-fit (per-mark optical scale, 1 = the
     wall's own box) are set per-logo inline by the runtime; declared here so
     they are known seams rather than undeclared tokens. */
  --lw-mask: none;
  --lw-fit: 1;
  grid-area: 1 / 1;
  width: calc(var(--lw-logo-width) * var(--lw-fit));
  height: calc(var(--lw-logo-height) * var(--lw-fit));
  background-color: var(--lw-logo-color);
  -webkit-mask: var(--lw-mask) center / contain no-repeat;
  mask: var(--lw-mask) center / contain no-repeat;
}

.nxt-logo-wall__logo[data-enter] {
  animation: nxt-logo-wall-enter var(--dur-deliberate) var(--ease-smooth) both;
}
.nxt-logo-wall__logo[data-exit] {
  animation: nxt-logo-wall-exit var(--dur-deliberate) var(--ease-smooth) both;
}

@keyframes nxt-logo-wall-enter {
  from { opacity: 0; transform: translateY(50%); }
  to { opacity: 1; transform: translateY(0); }
}
@keyframes nxt-logo-wall-exit {
  from { opacity: 1; transform: translateY(0); }
  to { opacity: 0; transform: translateY(-50%); }
}

/* Surface: ink — light logos on a dark panel for dark sections. */
.nxt-logo-wall[data-surface="ink"] {
  --lw-logo-color: var(--fg-inverse);
  background: var(--neutral-12);
  padding: var(--space-5);
  border-radius: var(--radius-lg);
}

/* ============================================================================
   SCREEN WALL
   ========================================================================== */

.nxt-screen-wall {
  --screen-wall-min-height: 22.5rem;

  display: block;
  position: relative;
  width: 100%;
  min-height: var(--screen-wall-min-height);
  overflow: hidden;
  border-radius: var(--radius-md);
  color: var(--fg-inverse);
  background: var(--bg-inverse);
}

.nxt-screen-wall__runtime {
  display: block;
  width: 100%;
  min-height: inherit;
}

.nxt-screen-wall__runtime--static {
  display: grid;
  place-items: center;
  background: var(--bg-inverse);
}

.nxt-screen-wall__runtime--static::before {
  content: "";
  inline-size: min(calc(var(--space-10) * 5), calc(100% - var(--space-8)));
  block-size: var(--space-10);
  background: currentColor;
  -webkit-mask: url("/brand/nextcaddy-wordmark.svg") center / contain no-repeat;
  mask: url("/brand/nextcaddy-wordmark.svg") center / contain no-repeat;
}

@media (prefers-reduced-motion: reduce) {
  .nxt-logo-wall__logo[data-enter],
  .nxt-logo-wall__logo[data-exit] {
    animation: none;
  }
}

/* ==========================================================================
   Component-view doc blocks (.nxt-cv-*) — presentational chrome for the
   data-driven /preview/<component> page (blocks 01–14). Tokens only.
   ========================================================================== */

/* Page container — centered reading column (reference `.wrap`). The width is a
   scoped seam token so the focused doc column stays narrower than the full docs
   shell. */
.nxt-cv-shell {
  --cv-shell-inline-size: min(100%, 1080px);
  inline-size: var(--cv-shell-inline-size);
  margin-inline: auto;
  padding-inline: var(--space-7);
  padding-block: var(--space-7);
  min-inline-size: 0;
}

/* Page hero — large component title at the top of the doc column. */
/* The hero stacks three layers -- identity (eyebrow + title), status badges, and
   the description -- which previously all sat at one uniform 12px gap, so four
   different relationships read at the same distance and the eyebrow detached from
   its own title. The layers now separate at `related`; the eyebrow and title fuse
   at `heading` inside .nxt-cv-hero-heading. */
.nxt-cv-hero {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--stack-gap-related);
  padding-block: var(--space-8) var(--space-7);
  border-bottom: 1px solid var(--border-subtle);
  margin-block-end: var(--space-6);
  scroll-margin-block-start: var(--space-5);
}

.nxt-cv-hero-heading {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--stack-gap-heading);
  min-inline-size: 0;
}

.nxt-cv-title {
  font-size: var(--text-4xl);
  font-weight: var(--weight-medium);
  line-height: var(--lh-tight);
  color: var(--fg-primary);
  margin: 0;
}

.nxt-cv-hero-description {
  font-size: var(--text-lg);
  color: var(--fg-secondary);
  line-height: var(--lh-relaxed);
  margin: 0;
  max-width: 70ch;
}

/* Opt-in discovery panel for components with a richer interactive workbench.
   The Component View renders this only when component-view/workbench-registry
   declares a first-party workbench route for the current component. */
.nxt-cv-workbench {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-5);
  margin-block-end: var(--space-6);
  padding: var(--space-5);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  background: var(--accent-soft-bg);
}

.nxt-cv-workbench-copy {
  min-inline-size: 0;
  max-inline-size: var(--component-view-workbench-copy-measure);
}

.nxt-cv-workbench-eyebrow {
  margin: 0 0 var(--space-1);
  color: var(--accent-soft-fg);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
  letter-spacing: var(--track-caps);
  text-transform: uppercase;
}

.nxt-cv-workbench-title {
  margin: 0;
  color: var(--fg-primary);
  font-size: var(--text-xl);
  font-weight: var(--weight-medium);
  line-height: var(--lh-snug);
}

.nxt-cv-workbench-description {
  margin: var(--space-2) 0 0;
  color: var(--fg-secondary);
  font-size: var(--text-sm);
  line-height: var(--lh-relaxed);
}

.nxt-cv-workbench-link {
  display: inline-flex;
  flex: 0 0 auto;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  min-block-size: var(--component-view-workbench-link-min-block-size);
  padding-inline: var(--space-4);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-md);
  background: var(--bg-surface);
  color: var(--fg-primary);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  line-height: var(--lh-snug);
  text-decoration: none;
}

.nxt-cv-workbench-link:active {
  background: var(--bg-canvas);
}

.nxt-cv-workbench-link:focus-visible {
  outline: 2px solid var(--focus-ring);
  outline-offset: 2px;
}

@media (hover: hover) {
  .nxt-cv-workbench-link:hover {
    background: var(--bg-sunken);
  }
}

/* Anatomy / table-of-contents map (reference `.anat`). */
.nxt-cv-anat {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-2) var(--space-5);
  margin: 0;
  padding-block-end: var(--space-5);
}

.nxt-cv-anat-item {
  display: grid;
  grid-template-columns: auto 1fr auto;
  gap: var(--space-3);
  align-items: baseline;
  padding: var(--space-2);
  border-bottom: 1px solid var(--border-subtle);
  border-radius: var(--radius-sm);
  text-decoration: none;
  color: inherit;
  transition: background var(--dur-fast) var(--ease-smooth);
}

.nxt-cv-anat-item:hover {
  background: var(--bg-sunken);
}

.nxt-cv-anat-item:hover .nxt-cv-anat-name {
  color: var(--secondary-soft-fg);
}

.nxt-cv-anat-item:hover .nxt-cv-anat-num {
  background: var(--accent);
  color: var(--accent-fg);
}

.nxt-cv-anat-num {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--fg-tertiary);
  background: var(--bg-sunken);
  border-radius: var(--radius-sm);
  padding: var(--space-1) var(--space-2);
  transition: background var(--dur-fast) var(--ease-smooth);
}

.nxt-cv-anat-name {
  font-size: var(--text-sm);
}

.nxt-cv-anat-src {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--fg-tertiary);
  text-align: end;
}

/* A documentation section (reference `.spec`): numbered head + surface-card
   body, separated by a top rule. */
.nxt-cv-block {
  padding-block: var(--space-7);
  border-top: 1px solid var(--border-subtle);
  scroll-margin-block-start: var(--space-5);
  min-inline-size: 0;
}

.nxt-cv-block-head {
  display: grid;
  grid-template-columns: auto 1fr auto;
  gap: var(--space-3);
  align-items: start;
  /* Head -> body is a group boundary, and the body's own children sit at
     `related` (16px, below). At `--space-4` the boundary was exactly the gap it
     bounds, so the head read as one more row of the body rather than its
     heading -- ADR 155 amendment 3's ratio, one rung up from what it bounds. */
  margin-block-end: var(--stack-gap-section);
}

.nxt-cv-block-num {
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  color: var(--accent-soft-fg);
  background: var(--accent-soft-bg);
  border-radius: var(--radius-sm);
  padding: var(--space-1) var(--space-2);
  line-height: var(--lh-snug);
  block-size: fit-content;
}

.nxt-cv-block-headings {
  min-inline-size: 0;
}

.nxt-cv-block-name {
  font-size: var(--text-xl);
  font-weight: var(--weight-medium);
  margin: 0;
}

.nxt-cv-block-purpose {
  font-size: var(--text-sm);
  color: var(--fg-secondary);
  line-height: var(--lh-relaxed);
  margin: var(--space-1) 0 0;
  max-width: 62ch;
}

.nxt-cv-block-src {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1);
  justify-content: flex-end;
  align-content: start;
  max-width: 280px;
}

/* The body owns the separation between its own children. Without this, a block
   rendering more than one child (ActionsBlock: resource bar then import `pre`)
   stacked them flush, since neither child declares a block-axis margin --
   reported as "nxt-cv-resourcebar is attached to the pre, no vertical spacing
   whatsoever". Declaring it once on the parent keeps the seam single-owned
   rather than adding a margin to each child that could then double up. */
.nxt-cv-block-body {
  display: grid;
  /* Grid items default to min-width:auto and so refuse to shrink below their
     min-content width -- measured as /preview/chart overflowing its body by 63px
     once this became a grid. minmax(0, 1fr) restores the block-flow behaviour. */
  grid-template-columns: minmax(0, 1fr);
  row-gap: var(--stack-gap-related);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  background: var(--bg-surface);
  padding: var(--space-5);
  min-inline-size: 0;
}

/* Layout-primitive specimens own full-width composition — let their body card
   sit flush so the component lays out edge to edge. */
.nxt-cv-block-body:has(> .nxt-cv-specimen--bleed) {
  padding: 0;
  overflow: clip;
}

@media (max-width: 767px) {
  .nxt-cv-workbench {
    align-items: stretch;
  }
  .nxt-cv-workbench-link {
    inline-size: 100%;
  }
  .nxt-cv-anat {
    grid-template-columns: minmax(0, 1fr);
  }
  .nxt-cv-block-head {
    grid-template-columns: auto 1fr;
  }
  .nxt-cv-block-src {
    grid-column: 1 / -1;
    justify-content: flex-start;
    max-width: none;
  }
}

.nxt-cv-eyebrow {
  margin: 0;
  color: var(--fg-tertiary);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
  letter-spacing: var(--track-caps);
  text-transform: uppercase;
}

.nxt-cv-header-heading {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3);
  min-inline-size: 0;
}

.nxt-cv-badge-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  align-items: center;
  min-inline-size: 0;
}

.nxt-cv-resourcebar {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  align-items: center;
  min-inline-size: 0;
}

.nxt-cv-import {
  margin: 0;
  overflow-x: auto;
  padding: var(--space-3);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  background: var(--bg-sunken);
  color: var(--fg-secondary);
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  line-height: var(--lh-normal);
}

.nxt-cv-specimen {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  align-items: center;
  padding: var(--space-5);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg);
  background: var(--bg-surface);
  /* Intrinsically wide specimens (pagination rails, slide-to-confirm tracks)
     can exceed the narrow doc column; scroll within the card instead of
     overflowing the page. Mirrors .nxt-cv-import / .nxt-cv-specimen--bleed. */
  min-inline-size: 0;
  overflow-x: auto;
}

/* Layout primitives (page, grid, stack, …) own their own composition and may
   include a sticky completion region. Top-align and establish a scroll
   container (overflow: auto) so a `position: sticky` footer scopes to this box
   and sits after the content — instead of pinning to the viewport and
   overlapping the body. Mirrors the proven `.nxt-preview-matrix-cell-preview`
   recipe block 06 already renders cleanly with. */
.nxt-cv-specimen--bleed {
  align-items: flex-start;
  overflow: auto;
}

.nxt-cv-code {
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  color: var(--fg-primary);
}

.nxt-cv-code-muted {
  color: var(--fg-secondary);
}

.nxt-cv-muted {
  color: var(--fg-tertiary);
  font-size: var(--text-sm);
}

.nxt-cv-table-wrap {
  overflow-x: auto;
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
}

.nxt-cv-table {
  inline-size: 100%;
  border-collapse: collapse;
  font-size: var(--text-sm);
}

.nxt-cv-table th,
.nxt-cv-table td {
  padding: var(--space-2) var(--space-3);
  text-align: start;
  vertical-align: top;
  border-block-end: 1px solid var(--border-subtle);
}

.nxt-cv-table thead th {
  color: var(--fg-secondary);
  font-weight: var(--weight-medium);
  background: var(--bg-sunken);
}

.nxt-cv-table tbody tr:last-child td {
  border-block-end: 0;
}

.nxt-cv-axis-list,
.nxt-cv-def-list {
  display: grid;
  gap: var(--space-3);
  margin: 0;
}

.nxt-cv-axis,
.nxt-cv-def {
  display: grid;
  gap: var(--space-2);
  padding-block-end: var(--space-3);
  border-block-end: 1px solid var(--border-subtle);
}

.nxt-cv-axis:last-child,
.nxt-cv-def:last-child {
  padding-block-end: 0;
  border-block-end: 0;
}

.nxt-cv-axis-name,
.nxt-cv-def-term {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  margin: 0;
}

.nxt-cv-axis-options {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin: 0;
}

.nxt-cv-def-detail {
  display: grid;
  gap: var(--space-1);
  margin: 0;
  color: var(--fg-secondary);
}

.nxt-cv-def-detail p {
  margin: 0;
}

.nxt-cv-list {
  display: grid;
  gap: var(--space-1);
  margin: 0;
  padding-inline-start: var(--space-4);
  color: var(--fg-secondary);
  font-size: var(--text-sm);
  line-height: var(--lh-normal);
}

.nxt-cv-link-list {
  display: grid;
  gap: var(--space-2);
  margin: 0;
  padding: 0;
  list-style: none;
}

.nxt-cv-link {
  color: var(--accent-soft-fg);
  text-decoration: underline;
  text-underline-offset: 2px;
}

.nxt-cv-link:hover {
  color: var(--fg-primary);
}

.nxt-cv-link:focus-visible {
  outline: 2px solid var(--focus-ring);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

.nxt-cv-subsection {
  display: grid;
  gap: var(--space-2);
  min-inline-size: 0;
}

.nxt-cv-subheading {
  margin: 0;
  color: var(--fg-primary);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  line-height: var(--lh-snug);
}

.nxt-cv-token-groups {
  display: grid;
  gap: var(--space-4);
}

.nxt-cv-token-group {
  display: grid;
  gap: var(--space-2);
  min-inline-size: 0;
}

.nxt-cv-token-group-label {
  margin: 0;
  color: var(--fg-tertiary);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: var(--track-caps);
  text-transform: uppercase;
}

.nxt-cv-chip-list {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin: 0;
  padding: 0;
  list-style: none;
}

.nxt-cv-chip {
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-sm);
  background: var(--bg-surface);
  padding: 2px var(--space-2);
  color: var(--fg-secondary);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  line-height: var(--lh-snug);
}

.nxt-cv-columns {
  display: grid;
  gap: var(--space-5);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 16rem), 1fr));
}

.nxt-cv-column {
  display: grid;
  gap: var(--space-2);
  align-content: start;
  min-inline-size: 0;
}

.nxt-cv-dodont-list {
  display: grid;
  gap: var(--space-4);
  margin: 0;
  padding: 0;
  list-style: none;
}

.nxt-cv-dodont {
  display: grid;
  gap: var(--space-3);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 18rem), 1fr));
}

.nxt-cv-dodont-rationale {
  grid-column: 1 / -1;
  margin: 0;
  color: var(--fg-tertiary);
  font-size: var(--text-sm);
  line-height: var(--lh-normal);
}

.nxt-cv-dodont-cell {
  display: grid;
  gap: var(--space-1);
  align-content: start;
  padding: var(--space-3);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  background: var(--bg-surface);
  min-inline-size: 0;
  overflow-wrap: anywhere;
}

.nxt-cv-dodont-cell[data-kind="do"] {
  border-color: var(--success);
}

.nxt-cv-dodont-cell[data-kind="dont"] {
  border-color: var(--danger-outline);
}

.nxt-cv-dodont-cell p {
  margin: 0;
  color: var(--fg-secondary);
  font-size: var(--text-sm);
  line-height: var(--lh-normal);
}

.nxt-cv-dodont-label {
  color: var(--fg-primary);
  font-weight: var(--weight-medium);
  text-transform: uppercase;
  letter-spacing: var(--track-caps);
  font-size: var(--text-xs) !important;
}

.nxt-cv-prevnext {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  justify-content: space-between;
  padding-block-start: var(--space-4);
  border-block-start: 1px solid var(--border-subtle);
}

.nxt-cv-prevnext-link {
  display: grid;
  gap: var(--space-1);
  padding: var(--space-3);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  background: var(--bg-surface);
  color: var(--fg-primary);
  text-decoration: none;
  min-inline-size: 0;
}

.nxt-cv-prevnext-link[data-dir="next"] {
  text-align: end;
}

.nxt-cv-prevnext-link:hover {
  border-color: var(--border-default);
  background: var(--bg-sunken);
}

.nxt-cv-prevnext-link:focus-visible {
  outline: 2px solid var(--focus-ring);
  outline-offset: 2px;
}

.nxt-cv-prevnext-dir {
  color: var(--fg-tertiary);
  font-size: var(--text-xs);
  letter-spacing: var(--track-caps);
  text-transform: uppercase;
}

.nxt-cv-prevnext-label {
  font-weight: var(--weight-medium);
}

/* ── media-carousel ────────────────────────────────────────────────────────
 * DS-native port of the media-carousel-ds-preview-v3 prototype. A fixed-dark
 * media stage: the root carries `dark` (which flips the raw OKLCH neutral
 * ladder) so the colour seam — keyed to raw --neutral-* steps — resolves dark
 * regardless of page theme. NOTE: semantic aliases (--bg-canvas/--fg-primary)
 * are substituted at :root and do NOT re-resolve in a subtree, so a fixed-dark
 * surface must consume the raw ladder steps directly (the cascading-slider /
 * logo-wall ink precedent; steps are allowlisted in check-tokens-semantic).
 * No drop shadows (dark-mode brand rule) — depth via the darker media slot +
 * a tokenised hairline border. Transition choreography (cover panels + circle
 * reveal + staggered logo) is driven by the native Web Animations API;
 * timing/easing live in the --mc-* seam so they stay overridable. */
.nxt-media-carousel {
  /* One radius rung across the component: the surface/control frame default.
     The media slot, link card and QR share --radius-sm; no bespoke calc(). */
  --mc-radius: var(--surface-frame-radius);
  --mc-media-radius: var(--radius-sm);
  --mc-qr-radius: var(--radius-sm);
  --mc-bg: var(--neutral-1);
  --mc-media-bg: var(--neutral-2);
  --mc-media-padding: var(--surface-frame-padding);
  --mc-gap: var(--surface-frame-gap);
  --mc-link-padding: var(--space-5);
  /* Controls on the DS control ladder: box, icon, gap and radius. */
  --mc-control-size: var(--ctrl-block-h-md);
  --mc-control-icon: var(--ctrl-icon-md);
  --mc-control-gap: var(--ctrl-gap-md);
  --mc-control-radius: var(--control-frame-radius);
  /* Container-relative geometry: the stage is embedded, so it scales with its
     own width (cqi/cqw against the viewport container), never the page's. */
  --mc-qr-panel-width: clamp(11rem, 22cqi, 15rem);
  --mc-qr-size: clamp(6.5rem, 14cqi, 9rem);
  --mc-qr-size-stacked: var(--space-8);
  --mc-qr-bg: var(--neutral-3);
  --mc-qr-fg: var(--neutral-12);
  --mc-fg-muted: var(--neutral-11);
  --mc-border: var(--neutral-4);
  --mc-border-strong: var(--neutral-7);
  --mc-transition-bg: var(--neutral-2);
  --mc-transition-fg: var(--neutral-12);
  --mc-logo-height: clamp(2.5rem, 12cqi, 5rem);
  --mc-panel-top-h: 15cqw;
  --mc-panel-bottom-h: 20cqw;
  --mc-control-bg: color-mix(in oklch, var(--neutral-1) 82%, transparent);
  --mc-control-fg: var(--neutral-12);
  --mc-control-border: var(--neutral-4);
  /* Carousel-specific timing (read back by the runtime); bespoke choreography
     curves kept as overridable seam tokens. */
  --mc-transition-duration: 900ms;
  --mc-transition-hold: 220ms;
  --mc-ease-cover: cubic-bezier(0.625, 0.05, 0, 1);
  --mc-ease-in: cubic-bezier(0.16, 1, 0.3, 1);
  --mc-ease-out: cubic-bezier(0.87, 0, 0.13, 1);
  --mc-height: clamp(20rem, 52vh, 40rem);

  width: 100%;
  height: var(--mc-height);
  display: grid;
  align-items: stretch;
  font-family: var(--font-sans);
  color: var(--neutral-12);
}

.nxt-media-carousel__viewport {
  position: relative;
  width: 100%;
  height: 100%;
  border-radius: var(--mc-radius);
  background: var(--mc-bg);
  border: 1px solid var(--mc-border);
  overflow: hidden;
  isolation: isolate;
  /* The query container for every cqi/cqw length and @container branch below. */
  container-type: inline-size;
  container-name: nxt-media-carousel;
}

.nxt-media-carousel__stage { position: absolute; inset: 0; display: grid; place-items: stretch; overflow: hidden; }
.nxt-media-carousel__slide { position: absolute; inset: 0; display: grid; min-width: 0; min-height: 0; padding: var(--mc-media-padding); will-change: transform, opacity; }
/* Definite rows on the shell and the slot: without them the media's height:100%
   resolves against an auto row sized by the image's own intrinsic height, so
   tall artwork overflows the slot and gets clipped by its overflow:hidden. */
.nxt-media-carousel__slide-shell { display: grid; grid-template-columns: minmax(0, 1fr); grid-template-rows: minmax(0, 1fr); gap: var(--mc-gap); min-width: 0; min-height: 0; width: 100%; height: 100%; }
.nxt-media-carousel__slide--has-link .nxt-media-carousel__slide-shell { grid-template-columns: minmax(0, 1fr) minmax(150px, var(--mc-qr-panel-width)); align-items: stretch; }
.nxt-media-carousel__media-slot { min-width: 0; min-height: 0; display: grid; grid-template-rows: minmax(0, 1fr); place-items: center; border-radius: var(--mc-media-radius); background: var(--mc-media-bg); overflow: hidden; }
.nxt-media-carousel__media { display: block; width: 100%; height: 100%; max-width: 100%; max-height: 100%; border: 0; background: transparent; object-fit: contain; object-position: center; user-select: none; }

.nxt-media-carousel__link-card {
  min-width: 0; min-height: 0; display: grid; align-content: center; justify-items: center; gap: var(--stack-gap-heading);
  border: 1px solid var(--mc-border); border-radius: var(--mc-media-radius);
  background: var(--mc-qr-bg); color: var(--mc-qr-fg); padding: var(--mc-link-padding); text-align: center; overflow: hidden;
}
/* QR is a placeholder in this slice — generation is deferred to tournament-card
   (qrcode.react). The box reserves the scannable footprint. */
.nxt-media-carousel__qr { display: grid; place-items: center; width: var(--mc-qr-size); height: var(--mc-qr-size); border-radius: var(--mc-qr-radius); border: 1px dashed var(--mc-border-strong); background: color-mix(in oklch, var(--neutral-12) 6%, transparent); }
/* --lh-snug, not --lh-tight: 1.05 clipped descenders on two-line names. */
.nxt-media-carousel__link-name { margin: 0; max-width: 16ch; font-size: var(--text-md); font-weight: var(--weight-medium); letter-spacing: var(--track-tight); line-height: var(--lh-snug); }
.nxt-media-carousel__link-url { margin: 0; max-width: 22ch; color: var(--mc-fg-muted); font-size: var(--text-xs); line-height: var(--lh-heading); overflow-wrap: anywhere; }
.nxt-media-carousel__link-anchor { display: block; margin-block-end: var(--stack-gap-content); color: inherit; text-decoration: none; }
.nxt-media-carousel__link-anchor:focus-visible { outline: var(--focus-ring-width) solid var(--neutral-12); outline-offset: var(--focus-ring-gap); border-radius: var(--mc-qr-radius); }

.nxt-media-carousel__transition { z-index: 10; pointer-events: none; position: absolute; inset: 0; overflow: clip; opacity: 0; visibility: hidden; }
.nxt-media-carousel__transition-panel { color: var(--mc-transition-bg); background-color: currentColor; justify-content: center; align-items: center; width: 100%; height: 100%; display: flex; position: absolute; top: 100%; left: 0; will-change: transform; }
.nxt-media-carousel__transition-panel-top { transform-origin: bottom; flex-flow: column; align-items: center; width: 100%; height: 0%; display: flex; position: absolute; bottom: calc(100% - 1px); left: 0; overflow: hidden; will-change: transform; }
.nxt-media-carousel__transition-panel-bottom { transform-origin: top; flex-flow: column; justify-content: flex-end; align-items: center; width: 100%; height: 0%; display: flex; position: absolute; top: calc(100% - 1px); left: 0; overflow: hidden; will-change: transform; }
.nxt-media-carousel__transition-panel-circle { aspect-ratio: auto; background-color: currentColor; border-radius: 50%; width: 125%; height: 500%; position: absolute; }
.nxt-media-carousel__transition-logo {
  color: var(--mc-transition-fg); opacity: 0; height: var(--mc-logo-height); width: auto; max-width: min(78vw, 52rem);
  display: flex; position: absolute; top: 50%; left: 50%; overflow: hidden; transform: translate(-50%, -50%);
  align-items: center; justify-content: center;
}
.nxt-media-carousel__transition-logo svg { display: block; height: 100%; width: auto; max-width: 100%; }
.nxt-media-carousel__transition-logo svg, .nxt-media-carousel__transition-logo svg * { fill: currentColor !important; stroke: none !important; }
.nxt-media-carousel__transition-logo path { transform-box: fill-box; transform-origin: center bottom; }

/* Built-in overlay controls (prev / counter / next), bottom-centre of the
   viewport, on the DS control language: --ctrl-* ladder sizing, lucide glyphs
   sized by --mc-control-icon, nav-item hover + scale(0.97) press, tokenised
   focus ring. The opacity/visibility transition carries the idle fade (below). */
.nxt-media-carousel__controls { position: absolute; z-index: 5; left: 50%; bottom: var(--space-4); transform: translateX(-50%); display: flex; gap: var(--mc-control-gap); align-items: center; transition: opacity var(--dur-base) var(--ease-smooth), visibility var(--dur-base) var(--ease-smooth); }
.nxt-media-carousel__button, .nxt-media-carousel__counter { border: 1px solid var(--mc-control-border); background: var(--mc-control-bg); color: var(--mc-control-fg); backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px); }
.nxt-media-carousel__button { display: grid; place-items: center; inline-size: var(--mc-control-size); block-size: var(--mc-control-size); border-radius: var(--mc-control-radius); cursor: pointer; font: inherit; transition: background-color var(--dur-snap) var(--ease-snap), color var(--dur-snap) var(--ease-snap), transform var(--dur-instant) var(--ease-smooth); }
.nxt-media-carousel__button > svg { inline-size: var(--mc-control-icon); block-size: var(--mc-control-icon); flex-shrink: 0; }
.nxt-media-carousel__button:hover { background: color-mix(in oklch, var(--neutral-1) 92%, transparent); }
.nxt-media-carousel__button:active:not(:disabled) { transform: scale(0.97); }
.nxt-media-carousel__button:focus-visible { outline: var(--focus-ring-width) solid var(--neutral-12); outline-offset: var(--focus-ring-gap); }
.nxt-media-carousel__button:disabled { opacity: var(--control-frame-disabled-opacity); cursor: default; }
.nxt-media-carousel__counter { block-size: var(--mc-control-size); display: inline-flex; align-items: center; justify-content: center; min-inline-size: 0; white-space: nowrap; border-radius: var(--mc-control-radius); padding-inline: var(--ctrl-inline-pad-sm); padding-block: 0; font-size: var(--text-sm); font-weight: var(--weight-medium); letter-spacing: var(--track-normal); font-variant-numeric: tabular-nums; }

/* Idle fade: 10s without input dims the overlay controls to half, 10s more
   hides them; any interaction restores them (the runtime flips data-controls
   on the root). visibility:hidden is deliberate — hidden controls must also
   leave the tab order. */
.nxt-media-carousel[data-controls="dim"] .nxt-media-carousel__controls { opacity: 0.5; }
.nxt-media-carousel[data-controls="hidden"] .nxt-media-carousel__controls { opacity: 0; visibility: hidden; }

/* Narrow stage (keyed on the component's own width, not the viewport): the
   link panel drops under the media and turns horizontal — QR at the left,
   name + URL stacked beside it. The controls move to the TOP of the stage so
   they never sit on the panel (so the old bottom-clearance padding is gone). */
@container nxt-media-carousel (max-width: 767px) {
  .nxt-media-carousel__controls { top: var(--space-4); bottom: auto; }
  .nxt-media-carousel__slide--has-link .nxt-media-carousel__slide-shell { grid-template-columns: minmax(0, 1fr); grid-template-rows: minmax(0, 1fr) auto; }
  .nxt-media-carousel__link-card { grid-template-columns: auto minmax(0, 1fr); align-items: center; justify-items: start; text-align: start; gap: var(--stack-gap-heading) var(--space-4); padding: var(--space-4); }
  .nxt-media-carousel__link-anchor { grid-row: span 2; margin-block-end: 0; }
  .nxt-media-carousel__qr { inline-size: var(--mc-qr-size-stacked); block-size: var(--mc-qr-size-stacked); }
  .nxt-media-carousel__link-name, .nxt-media-carousel__link-url { max-width: none; }
}

/* Very narrow stage: the QR keeps its place at the left, one rung smaller, so
   the link text keeps a readable measure. (The handoff drew this rung at
   419px; 389px is the canonical band edge below --bp-sm — see the ADR.) */
@container nxt-media-carousel (max-width: 389px) {
  .nxt-media-carousel__link-card { --mc-qr-size-stacked: var(--space-7); padding: var(--space-3) var(--space-4); }
}

@media (prefers-reduced-motion: reduce) {
  .nxt-media-carousel__slide,
  .nxt-media-carousel__transition-panel,
  .nxt-media-carousel__transition-panel-top,
  .nxt-media-carousel__transition-panel-bottom,
  .nxt-media-carousel__transition-logo { transition: none !important; animation: none !important; }
}

/* ============================================================ *
 * tournament-card v2 — composition of date-tile typography,
 * Badge and Progress primitives. Component-scoped --tc-* values
 * carry fixed design dimensions; rule bodies consume tokens only.
 * ============================================================ */
.tournament-card {
  --tc-radius: 16px;
  --tc-inner-radius: calc(var(--tc-radius) - 8px);
  --tc-pad: var(--space-3);
  --tc-gap: var(--space-3);
  --tc-stat-gap: var(--space-6);
  --tc-shell-bg: var(--clay-12);
  --tc-shell-border: transparent;
  --tc-shell-shadow: var(--elevation-floating);
  --tc-inner-bg: var(--bg-surface);
  --tc-inner-border: transparent;
  --tc-date-num: var(--neutral-1);
  --tc-date-label: var(--clay-3);
  --tc-eyebrow: var(--secondary);
  --tc-stat-icon: var(--clay-8);
  --tc-stat-text: var(--clay-8);
  --tc-title: var(--clay-9);
  --tc-divider: var(--border-subtle);
  --tc-track: var(--border-default);
  --tc-fill: var(--secondary);
  --tc-inner-pad: var(--space-4);
  --tc-band-w: 96px;
  --tc-date-num-size: 64px;
  --tc-date-label-size: 24px;
  --tc-title-size: 22px;
  --tc-qr-size: 72px;
  --tc-eyebrow-size: 11px;
  --tc-stat-count-size: 14px;
  --tc-stat-countdown-size: 13px;
  --tc-icon-size: var(--space-4);
  --tc-border-w: 1px;
  --tc-focus-w: 2px;
  --tc-divider-w: 1px;
  --tc-progress-h: 6px;
  --tc-badge-pad-block: 6px;
  --tc-badge-pad-inline: 10px;
  --tc-date-label-offset: 2px;
  --tc-full: 100%;
  --tc-min-w: 480px;
  --tc-date-font: 'BarlowGX', 'Barlow', system-ui, sans-serif;
  --label-var: var(--font-var-datetile-label);
  --day-var: var(--font-var-datetile-day);

  inline-size: var(--tc-full);
  padding: var(--tc-pad);
  border: var(--tc-border-w) solid var(--tc-shell-border);
  border-radius: var(--tc-radius);
  background: var(--tc-shell-bg);
  box-shadow: var(--tc-shell-shadow);
  color: var(--tc-title);
  font-family: var(--font-sans);
}

.tournament-card.size-lg {
  --tc-pad: var(--space-4);
  --tc-inner-pad: var(--space-5);
  --tc-stat-gap: var(--space-7);
  --tc-band-w: 120px;
  --tc-date-num-size: 80px;
  --tc-date-label-size: 28px;
  --tc-title-size: 28px;
  --tc-qr-size: 88px;
  --tc-icon-size: 18px;
  --tc-min-w: 560px;
}

.tournament-card.mobile {
  --tc-radius: 20px;
  --tc-inner-radius: 12px;
  --tc-pad: var(--space-4);
  --tc-date-num-size: 36px;
  --tc-date-label-size: 18px;
  --tc-title-size: 20px;
  --tc-qr-size: 64px;
  --tc-track: var(--border-default);

  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

.tournament-card.mobile.size-lg {
  --tc-pad: var(--space-5);
  --tc-date-num-size: 44px;
  --tc-date-label-size: 22px;
  --tc-title-size: 24px;
  --tc-qr-size: 80px;
}

.tournament-card.desktop {
  display: flex;
  align-items: stretch;
  gap: var(--space-0);
}

.tournament-card.desktop[data-qr="true"] {
  min-inline-size: var(--tc-min-w);
}

.tournament-card.tone-muted {
  --tc-shell-bg: var(--clay-2);
  --tc-shell-border: var(--border-subtle);
  --tc-shell-shadow: var(--elevation-raised);
  --tc-date-num: var(--clay-9);
  --tc-date-label: var(--clay-7);
  --tc-eyebrow: var(--clay-8);
  --tc-stat-icon: var(--clay-6);
  --tc-stat-text: var(--clay-8);
  --tc-fill: var(--clay-8);
  --tc-inner-border: var(--border-subtle);
}

.tournament-card.desktop.tone-muted {
  --tc-radius: var(--radius-sm);
  --tc-inner-radius: var(--radius-sm);
  --tc-track: var(--border-default);
}

.tournament-card.mobile.tone-muted {
  --tc-track: var(--clay-4);
}

.tournament-card[data-interactive="true"] {
  cursor: pointer;
  text-decoration: none;
  transition: box-shadow var(--dur-fast) var(--ease-smooth);
}

@media (hover: hover) and (pointer: fine) {
  .tournament-card[data-interactive="true"]:hover {
    box-shadow: var(--elevation-modal);
  }
}

.tournament-card[data-interactive="true"]:focus-visible {
  outline: var(--tc-focus-w) solid var(--focus-ring);
  outline-offset: var(--space-1);
}

.tournament-card .tc-knockout-fill {
  fill: var(--tc-inner-bg);
}

.tournament-card .tc-knockout-stroke {
  stroke: var(--tc-inner-bg);
}

.tournament-card .tc-icon-svg {
  display: block;
  inline-size: var(--tc-full);
  block-size: var(--tc-full);
}

.tournament-card .tc-mobile-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
}

.tournament-card .tc-date {
  display: flex;
  align-items: baseline;
  gap: var(--space-2);
  color: var(--tc-date-num);
  font-family: var(--tc-date-font);
  font-optical-sizing: auto;
  font-synthesis: none;
  user-select: none;
}

.tournament-card.desktop .tc-date {
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  gap: var(--space-0);
}

.tournament-card .tc-date-num {
  color: var(--tc-date-num);
  font-size: var(--tc-date-num-size);
  font-variation-settings: var(--day-var);
  font-variant-numeric: tabular-nums;
  line-height: var(--lh-tight);
}

.tournament-card .tc-date-label {
  color: var(--tc-date-label);
  font-size: var(--tc-date-label-size);
  font-variation-settings: var(--label-var);
  line-height: var(--lh-tight);
}

.tournament-card.desktop .tc-date-label {
  margin-bottom: var(--tc-date-label-offset); /* intentional: optical */
}

.tournament-card .tc-band {
  flex: 0 0 auto;
  inline-size: var(--tc-band-w);
  display: flex;
  align-items: center;
  justify-content: flex-start;
}

.tournament-card .tc-inner {
  flex: 1 1 auto;
  min-inline-size: var(--space-0);
  display: flex;
  align-items: stretch;
  gap: var(--space-4);
  padding: var(--tc-inner-pad);
  border: var(--tc-border-w) solid var(--tc-inner-border);
  border-radius: var(--tc-inner-radius);
  background: var(--tc-inner-bg);
}

.tournament-card .tc-content {
  flex: 1 1 auto;
  min-inline-size: var(--space-0);
  display: flex;
  flex-direction: column;
  gap: var(--tc-gap);
}

.tournament-card .tc-content-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-4);
}

.tournament-card .tc-eyebrow {
  display: flex;
  align-items: center;
  min-inline-size: var(--space-0);
  gap: var(--space-2);
  color: var(--tc-eyebrow);
}

.tournament-card .tc-eyebrow-icon,
.tournament-card .tc-stat-icon {
  display: inline-flex;
  flex: 0 0 auto;
  inline-size: var(--tc-icon-size);
  block-size: var(--tc-icon-size);
}

.tournament-card .tc-eyebrow-label {
  overflow: hidden;
  color: var(--tc-eyebrow);
  font-size: var(--tc-eyebrow-size);
  font-weight: var(--weight-medium);
  letter-spacing: var(--track-wide);
  line-height: var(--lh-tight);
  text-overflow: ellipsis;
  text-transform: uppercase;
  white-space: nowrap;
}

.tournament-card .tc-title {
  color: var(--tc-title);
  font-size: var(--tc-title-size);
  font-weight: var(--weight-medium);
  line-height: var(--lh-tight);
  text-wrap: pretty;
}

.tournament-card .tc-stats {
  display: flex;
  align-items: center;
  gap: var(--tc-stat-gap);
}

.tournament-card .tc-stat {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  min-inline-size: var(--space-0);
}

.tournament-card .tc-stat-icon {
  color: var(--tc-stat-icon);
}

.tournament-card .tc-stat-num {
  color: var(--tc-stat-text);
  font-size: var(--tc-stat-count-size);
  font-variant-numeric: tabular-nums;
  font-weight: var(--weight-medium);
  line-height: var(--lh-tight);
}

.tournament-card .tc-stat-mono {
  color: var(--tc-stat-text);
  font-family: var(--font-mono);
  font-size: var(--tc-stat-countdown-size);
  font-variant-numeric: tabular-nums;
  font-weight: var(--weight-medium);
  line-height: var(--lh-tight);
}

.tournament-card .tc-badge {
  flex: 0 0 auto;
  padding: var(--tc-badge-pad-block) var(--tc-badge-pad-inline); /* intentional: tight-text scale */
}

.tournament-card .tc-qr-col {
  flex: 0 0 auto;
  display: flex;
  align-items: stretch;
  gap: var(--space-4);
}

.tournament-card .tc-divider {
  align-self: stretch;
  inline-size: var(--tc-divider-w);
  background: var(--tc-divider);
}

.tournament-card .tc-qr-box {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
}

.tournament-card .tc-qr {
  display: block;
  inline-size: var(--tc-qr-size);
  block-size: var(--tc-qr-size);
  color: var(--tc-title);
}

.tournament-card .tc-progress-wrap {
  inline-size: var(--tc-full);
}

.tournament-card.desktop .tc-progress-wrap {
  margin-top: auto;
  padding-top: var(--space-2);
}

.tournament-card .tc-progress {
  inline-size: var(--tc-full);
}

.tournament-card .tc-progress .nxt-progress-track {
  block-size: var(--tc-progress-h);
  background: var(--tc-track);
}

.tournament-card .tc-progress .nxt-progress-fill {
  background: var(--tc-fill);
  transition: inline-size var(--dur-slow) var(--ease-spring);
}

@media (prefers-reduced-motion: reduce) {
  .tournament-card[data-interactive="true"],
  .tournament-card .tc-progress .nxt-progress-fill {
    transition: none;
  }
}

/* ============================================================================
   FOCUS CURSOR (animated shared focus ring)
   Runtime-positioned floating ring driven by FocusRingCursor (app shell).
   The static token rings remain the source of truth: remove this section or
   its runtime and every component keeps its CSS focus ring unchanged.
   ========================================================================= */
.nxt-focus-cursor {
  position: fixed;
  inset-block-start: 0;
  inset-inline-start: 0;
  overflow: visible;
  pointer-events: none;
  z-index: var(--z-tooltip);
  opacity: 0;
  transition-property: opacity;
  transition-duration: var(--dur-instant);
  transition-timing-function: var(--ease-smooth);
}

.nxt-focus-cursor[data-active="true"] {
  opacity: 1;
}

.nxt-focus-cursor-geometry {
  transform-box: border-box;
  transform-origin: 0 0;
}

.nxt-focus-cursor-ring {
  fill: none;
  stroke: var(--focus-ring);
  stroke-width: var(--focus-ring-width);
}

/* Static-ring suppression while the cursor is anchored. Focus shadows resolve
   against :root (custom properties substitute where the token is defined, not
   where it is used), so a color-var override cannot mute them — suppress the
   painted indicator itself. !important keeps this deterministic against
   higher-specificity component rules; the lock attribute only exists while
   the runtime is anchored, so every static ring returns the moment the
   cursor lets go (or the feature is removed).

   The whole block is gated on the same conditions that keep the cursor
   rendered: if reduced-motion or forced-colors flips ON mid-session the
   cursor is display:none, and ungated suppression would leave keyboard focus
   with no indicator at all (WCAG 2.4.7). */
@media (prefers-reduced-motion: no-preference) and (forced-colors: none) {
  [data-nxt-focus-cursor-lock]:focus-visible {
    outline-color: transparent !important;
    box-shadow: none !important;
  }

  /* Composite fields carry the ring on a wrapper via :focus-within, and
     selection controls on a sibling/descendant mark — suppress those carriers
     too (list derived from docs/plans/focus-ring-inventory.md; keep in sync
     with RING_CARRIERS in FocusRingCursor.tsx). Non-ring cues (line-chrome
     underlines, background tints, focus border colors) stay on purpose — the
     cursor complements them. */
  :is(.nxt-input-slot, [data-slot="affix"], .nxt-control-frame, .nxt-field-frame, .nxt-signature-stage, .nxt-time-picker-segment, .nxt-file-input):has([data-nxt-focus-cursor-lock]) {
    outline-color: transparent !important;
    box-shadow: none !important;
  }
  .nxt-select:has([data-nxt-focus-cursor-lock]) .nxt-select-control {
    box-shadow: none !important;
  }
  .nxt-checkbox-input[data-nxt-focus-cursor-lock] ~ .nxt-checkbox-box {
    box-shadow: none !important;
  }
  .nxt-radio[data-nxt-focus-cursor-lock] .nxt-radio-circle {
    box-shadow: none !important;
  }
}

/* The runtime disables itself under these; CSS is belt and braces. */
@media (prefers-reduced-motion: reduce) {
  .nxt-focus-cursor {
    display: none;
  }
}
@media (forced-colors: active) {
  .nxt-focus-cursor {
    display: none;
  }
}

/* ── course-locator ──────────────────────────────────────────────────────── */

.nxt-course-locator {
  /* Component-local geometry seam (the mc/cs component-token precedent).
     --cl-pin-size is the brand 44px tap-target floor for golfer-facing controls. */
  --cl-panel-max-h: 48rem;
  --cl-side-max-w: 26rem;
  --cl-list-max-h: 32rem;
  --cl-map-min-h: 19rem;
  --cl-pin-size: 44px;
  display: grid;
  grid-template-columns: minmax(18rem, var(--cl-side-max-w)) minmax(0, 1fr);
  column-gap: var(--space-6);
  inline-size: 100%;
  block-size: min(100svh, var(--cl-panel-max-h));
}

.nxt-course-locator-side {
  display: flex;
  flex-flow: column;
  inline-size: 100%;
  max-inline-size: var(--cl-side-max-w);
  min-inline-size: 0;
}

.nxt-course-locator-header {
  padding-block-end: var(--space-4);
}

.nxt-course-locator-heading {
  margin: 0;
  font-size: var(--text-lg);
  font-weight: var(--weight-semibold);
  line-height: var(--lh-snug);
}

.nxt-course-locator-listwrap {
  min-block-size: 0;
  flex: 1;
}

.nxt-course-locator-list {
  display: flex;
  flex-flow: column;
  gap: 0;
  block-size: 100%;
  overflow: auto;
  padding-block-end: var(--space-4);
}

.nxt-course-locator-card {
  position: relative;
  --card-padding: var(--space-4);
  --card-gap: var(--space-3);
  --card-title-gap: var(--space-1);
  border-radius: var(--radius-sm);
  cursor: pointer;
}

.nxt-course-locator-item {
  padding-block-end: var(--space-2);
}

.nxt-course-locator-card[data-active="true"] {
  --card-bg: var(--neutral-fill);
  --card-border: var(--neutral-fill);
  --card-fg: var(--neutral-fill-fg);
  --card-fg-secondary: var(--neutral-fill-fg);
  --card-fg-tertiary: var(--neutral-fill-fg);
  box-shadow: var(--elevation-raised);
}

.nxt-course-locator-card-header {
  gap: var(--space-1);
}

.nxt-course-locator-select {
  all: unset;
  display: inline;
  cursor: pointer;
  font: inherit;
  color: inherit;
}

.nxt-course-locator-select:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring-shadow);
  border-radius: var(--radius-sm);
}

.nxt-course-locator-address {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  color: var(--card-fg-secondary);
}

.nxt-course-locator-address-icon svg {
  inline-size: var(--space-4);
  block-size: var(--space-4);
  display: block;
}

.nxt-course-locator-link {
  display: inline-flex;
  align-items: center;
  align-self: flex-start;
  min-block-size: var(--ctrl-block-h-md);
  padding-inline: var(--ctrl-inline-pad-sm);
  color: var(--card-fg);
  font-weight: var(--weight-medium);
  text-underline-offset: 0.18em;
  text-decoration-thickness: 1px;
  text-decoration-line: none;
}

.nxt-course-locator-link::after {
  display: inline-block;
  margin-inline-start: var(--space-2);
  content: "→";
  transition: transform var(--dur-fast) var(--ease-smooth);
}

@media (hover: hover) and (pointer: fine) {
  .nxt-course-locator-card:hover {
    border-color: var(--border-strong);
    box-shadow: var(--elevation-raised);
  }

  .nxt-course-locator-card:hover .nxt-course-locator-link {
    text-decoration: underline;
  }

  .nxt-course-locator-card:hover .nxt-course-locator-link::after {
    transform: translateX(2px);
  }
}

.nxt-course-locator-main {
  position: relative;
  isolation: isolate;
  flex: 1;
  min-inline-size: 0;
  border-radius: var(--radius-sm);
  overflow: clip;
}

.nxt-course-locator-map {
  position: absolute;
  isolation: isolate;
  inset: 0;
}

.nxt-course-locator-touch-toggle {
  position: absolute;
  z-index: var(--z-overlay);
  inset-block-start: var(--space-3);
  inset-inline-end: var(--space-3);
  box-shadow: var(--elevation-raised);
}

.nxt-course-locator-map-error {
  position: absolute;
  z-index: var(--z-overlay);
  inset-block-start: 50%;
  inset-inline-start: 50%;
  display: grid;
  gap: var(--space-3);
  justify-items: center;
  inline-size: min(calc(var(--space-10) * 3), calc(100% - var(--space-6)));
  padding: var(--space-4);
  transform: translate(-50%, -50%);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  background: var(--bg-surface);
  box-shadow: var(--elevation-raised);
  text-align: center;
}

.nxt-course-locator-map-error p {
  margin: 0;
}

.nxt-course-locator-empty {
  margin: 0;
  color: var(--fg-secondary);
}

/* Leaflet chrome on tokens (import order in globals.css lets these win). */
.nxt-course-locator .leaflet-container {
  background: var(--bg-surface);
  font: inherit;
}

.nxt-course-locator .leaflet-bar a {
  min-inline-size: var(--ctrl-block-h-md);
  min-block-size: var(--ctrl-block-h-md);
  background: var(--bg-surface);
  color: var(--fg-primary);
  border-color: var(--border);
}

.nxt-course-locator .leaflet-control-attribution {
  background: var(--bg-surface);
  color: var(--fg-secondary);
}

.nxt-course-locator .leaflet-control-attribution a {
  color: var(--fg-secondary);
}

/* Pins */
.nxt-course-locator-pin-anchor {
  background: none;
  border: none;
}

.nxt-course-locator-pin {
  all: unset;
  box-sizing: border-box;
  display: flex;
  align-items: center;
  justify-content: center;
  inline-size: var(--cl-pin-size);
  block-size: var(--cl-pin-size);
  padding: var(--space-2);
  border-radius: var(--radius-full);
  background: var(--neutral-fill);
  color: var(--neutral-fill-fg);
  cursor: pointer;
}

.nxt-course-locator-pin svg {
  inline-size: 100%;
  block-size: 100%;
}

.nxt-course-locator-pin-mark {
  display: block;
  inline-size: 72%;
  block-size: 72%;
  background: currentColor;
  mask: url("/brand/nextcaddy-mark.svg") center / contain no-repeat;
  -webkit-mask: url("/brand/nextcaddy-mark.svg") center / contain no-repeat;
  pointer-events: none;
}

.nxt-course-locator-pin[data-active="true"] {
  outline: 2px solid var(--neutral-fill);
  outline-offset: var(--space-2);
}

.nxt-course-locator-pin:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring-shadow);
}

@media (max-width: 959px) {
  .nxt-course-locator {
    display: flex;
    flex-flow: column;
    block-size: auto;
  }

  .nxt-course-locator-main {
    aspect-ratio: 3 / 2;
    flex: none;
  }

  .nxt-course-locator-side {
    max-inline-size: none;
  }

  .nxt-course-locator-list {
    block-size: auto;
    max-block-size: var(--cl-list-max-h);
  }
}

@media (hover: none) and (pointer: coarse) {
  :is(
    .nxt-input,
    .nxt-textarea,
    .nxt-select-input,
    .nxt-select-input input,
    .nxt-autocomplete-input,
    .nxt-time-picker-field,
    .nxt-time-picker-value
  ) {
    font-size: var(--editable-text-size-coarse);
  }

  :is(.nxt-input, .nxt-textarea, .nxt-autocomplete-input)[data-size] {
    font-size: var(--editable-text-size-coarse);
  }
}

@media (max-width: 767px) {
  .nxt-course-locator-main {
    aspect-ratio: 1;
    min-block-size: var(--cl-map-min-h);
  }
}

/* SVG stroke weight lives here, not in the markup string — the token-resolve
   scanner treats any quoted `stroke-*` text as a Tailwind utility. */
.nxt-course-locator-pin svg path,
.nxt-course-locator-address-icon svg path {
  stroke-width: 1.5;
}
/* ---------------------------------------------------------------------------
 * kanban-board
 * ------------------------------------------------------------------------- */

.nxt-kanban {
  display: grid;
  gap: var(--stack-gap-content);
  color: var(--fg-primary);
  font-family: var(--font-sans);
  --nxt-kanban-gap: var(--space-3);
  --nxt-kanban-column-width: 18rem;
  --nxt-kanban-card-padding: var(--space-3);
  --nxt-kanban-card-gap: var(--space-2);
  --nxt-kanban-indicator-color: var(--focus-ring);
}

.nxt-kanban--compact {
  --nxt-kanban-gap: var(--space-2);
  --nxt-kanban-column-width: 16rem;
  --nxt-kanban-card-padding: var(--space-2);
  --nxt-kanban-card-gap: var(--space-1);
}

.nxt-kanban--comfortable {
  --nxt-kanban-gap: var(--space-3);
  --nxt-kanban-column-width: 18rem;
  --nxt-kanban-card-padding: var(--space-3);
  --nxt-kanban-card-gap: var(--space-2);
}

.nxt-kanban--expanded {
  --nxt-kanban-gap: var(--space-4);
  --nxt-kanban-column-width: 20rem;
  --nxt-kanban-card-padding: var(--space-4);
  --nxt-kanban-card-gap: var(--space-3);
}

.nxt-kanban--gigantic {
  --nxt-kanban-gap: var(--space-5);
  --nxt-kanban-column-width: 24rem;
  --nxt-kanban-card-padding: var(--space-5);
  --nxt-kanban-card-gap: var(--space-3);
}

.nxt-kanban-label {
  color: var(--fg-primary);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  line-height: var(--lh-tight);
}

.nxt-kanban-columns {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: var(--nxt-kanban-column-width);
  gap: var(--nxt-kanban-gap);
  align-items: start;
  overflow-x: auto;
  padding-block-end: var(--space-2);
  min-inline-size: 0;
}

.nxt-kanban-column {
  display: grid;
  gap: var(--stack-gap-content);
  padding: var(--space-2);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-md);
  background: var(--bg-sunken);
  min-inline-size: 0;
}

/* Disabled communicates through surface and the (contrast-exempt) handle,
 * never by dimming text below WCAG contrast. */
.nxt-kanban-column[data-disabled="true"] {
  border-style: dashed;
  background: var(--bg-surface);
}

.nxt-kanban-column[data-disabled="true"] .nxt-kanban-column-count {
  color: var(--fg-secondary);
}

.nxt-kanban-column[data-drop-target="true"] {
  border-color: var(--border-strong);
  outline: 1px solid var(--nxt-kanban-indicator-color);
  outline-offset: -1px;
}

.nxt-kanban-column-title {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  column-gap: var(--space-2);
  margin: 0;
  padding-inline: var(--space-1);
  color: var(--fg-primary);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  line-height: var(--lh-tight);
}

.nxt-kanban-column-count {
  color: var(--fg-tertiary);
  font-size: var(--text-xs);
  font-variant-numeric: tabular-nums;
}

.nxt-kanban-column-items {
  display: grid;
  gap: var(--nxt-kanban-card-gap);
  margin: 0;
  padding: 0;
  list-style: none;
  min-block-size: var(--space-6);
}

.nxt-kanban-place-slot {
  display: block;
}

/* Placement target shown only while a card is held, so a pointer user can
 * finish a move without dragging (WCAG 2.2 SC 2.5.7). */
.nxt-kanban-place {
  inline-size: 100%;
  min-block-size: var(--space-6);
  padding: var(--space-2);
  border: 1px dashed var(--border-strong);
  border-radius: var(--radius-md);
  background: transparent;
  color: var(--fg-secondary);
  font: inherit;
  font-size: var(--text-xs);
  text-align: center;
  cursor: pointer;
}

@media (hover: hover) {
  .nxt-kanban-place:hover {
    border-color: var(--focus-ring);
    color: var(--fg-primary);
  }
}

.nxt-kanban-place:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring-shadow-gap);
}

.nxt-kanban-card {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  column-gap: var(--space-2);
  padding: var(--nxt-kanban-card-padding);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-md);
  background: var(--bg-surface);
  transition:
    background-color var(--dur-snap) var(--ease-snap),
    border-color var(--dur-fast) var(--ease-smooth),
    box-shadow var(--dur-fast) var(--ease-smooth),
    opacity var(--dur-fast) var(--ease-smooth);
}

@media (hover: hover) {
  .nxt-kanban-card:hover {
    border-color: var(--border-strong);
  }
}

.nxt-kanban-card[data-dragging="true"] {
  border-color: var(--border-strong);
  background: var(--accent-soft-bg);
  box-shadow: 0 0 0 1px var(--border-strong);
}

.nxt-kanban-card[data-keyboard-active="true"] {
  box-shadow: 0 0 0 1px var(--focus-ring);
}

.nxt-kanban-card[data-drop-target="true"]:not([data-dragging="true"]) {
  border-color: var(--border-strong);
}

.nxt-kanban-card[data-drop-position="before"] {
  box-shadow: inset 0 2px 0 0 var(--nxt-kanban-indicator-color);
}

.nxt-kanban-card[data-drop-position="after"] {
  box-shadow: inset 0 -2px 0 0 var(--nxt-kanban-indicator-color);
}

.nxt-kanban-card[data-disabled="true"] {
  background: var(--bg-sunken);
  border-style: dashed;
}

@media (prefers-reduced-motion: no-preference) {
  .nxt-kanban-card[data-dropped="true"] {
    animation: nxt-kanban-drop-flash var(--dur-base) var(--ease-smooth);
  }

  @keyframes nxt-kanban-drop-flash {
    0% {
      background: var(--accent-soft-bg);
      border-color: var(--border-strong);
    }
    100% {
      background: var(--bg-surface);
      border-color: var(--border-default);
    }
  }
}

@media (forced-colors: active) {
  /* Forced colors strips box-shadows; the drop indicator falls back to a
   * Highlight border on the target edge. */
  .nxt-kanban-card[data-drop-position="before"] {
    border-block-start-color: Highlight;
    border-block-start-width: 2px;
  }

  .nxt-kanban-card[data-drop-position="after"] {
    border-block-end-color: Highlight;
    border-block-end-width: 2px;
  }

  .nxt-kanban-column[data-drop-target="true"] {
    outline: 2px solid Highlight;
  }

  .nxt-kanban-card[data-dragging="true"] {
    border-color: Highlight;
  }
}

@media (forced-colors: active) and (prefers-reduced-motion: no-preference) {
  .nxt-kanban-card[data-dropped="true"] {
    border-color: Highlight;
  }
}

.nxt-kanban-card-body {
  display: grid;
  gap: var(--stack-gap-heading);
  min-inline-size: 0;
  flex: 1 1 auto;
}

.nxt-kanban-card-copy {
  display: grid;
  gap: var(--stack-gap-heading);
  min-inline-size: 0;
}

.nxt-kanban-card-label {
  color: var(--fg-primary);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  line-height: var(--lh-tight);
  overflow-wrap: anywhere;
}

.nxt-kanban-card-description {
  color: var(--fg-secondary);
  font-size: var(--text-xs);
  line-height: var(--lh-snug);
  overflow-wrap: anywhere;
}

.nxt-kanban-handle {
  position: relative;
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  inline-size: var(--space-6);
  block-size: var(--space-6);
  padding: 0;
  border: none;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--fg-tertiary);
  cursor: grab;
  touch-action: none;
}

@media (hover: hover) {
  .nxt-kanban-handle:hover:not(:disabled) {
    color: var(--fg-primary);
    background: var(--bg-sunken);
  }
}

.nxt-kanban-handle:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring-shadow-gap);
}

.nxt-kanban-handle:disabled {
  cursor: default;
  opacity: 0.5;
}

.nxt-kanban-card[data-dragging="true"] .nxt-kanban-handle {
  cursor: grabbing;
}
