/* ==========================================================================
   ui.css - the component library's stylesheet (wave 35 lane R1).

   THE ARCHITECTURE - the cascade is explicit, five layers in a fixed
   order declared before anything else in this sheet:

       @layer reset, tokens, base, components, utilities;

   * reset     - UA neutralization, scoped to .ui-* chrome only (the
                 document reset belongs to app.css, untouched).
   * tokens    - the DEFAULTS for every component's theming knobs,
                 declared on :root and mapped onto the design tokens
                 (app.css). Design tokens are REFERENCED here, never
                 redefined.
   * base      - the cross-cutting doctrine for library chrome: the
                 one focus ring and the reduced-motion carve-out.
   * components- every component's styles live here, and only here.
   * utilities - RESERVED for the surface sheets (board.css, list.css,
                 ... become @layer utilities consumers): they set the
                 knobs and add surface classes, they never re-define
                 the primitives. Empty on purpose.

   THE KNOB CONTRACT (the library's law, tested in stylesheet_test):

   Components READ their custom properties (--btn-bg, --pop-shadow,
   ...), they never SET them - every declaration lives in
   @layer tokens on :root. Inheritance proximity therefore does the
   theming: any container that declares a knob beats :root, so
   "set them on a container to theme a region" always works, and the
   var() fallbacks below double as the defaults when the tokens
   layer is stripped.

   LOAD ORDER - link AFTER app.css (e.g. in the root layout, via
   SneckWeb.AssetVsn.url("/assets/ui.css")). app.css ships unlayered
   rules, and unlayered styles beat every layer, so legacy sheets
   keep winning until their surfaces migrate - the library is
   strictly opt-in (nothing legacy targets .ui-* classes).

   Tokens only, both themes. No surface-specific rules, ever.
   ========================================================================== */

@layer reset, tokens, base, components, utilities;

/* -- reset ------------------------------------------------------------------
   Scoped UA neutralization for the library's own controls. Never a
   global selector - app.css owns the document. */
@layer reset {
  .ui-btn,
  .ui-pop-trigger,
  .ui-dd-trigger,
  .ui-dd-opt,
  .ui-tab,
  .ui-modal-x {
    appearance: none;
    -webkit-appearance: none;
    margin: 0;
    padding: 0;
    background: none;
    border: none;
    border-radius: 0;
    font: inherit;
    letter-spacing: normal;
    color: inherit;
    cursor: pointer;
  }

  .ui-input,
  .ui-select,
  .ui-textarea {
    margin: 0;
    font: inherit;
    letter-spacing: normal;
  }

  .ui-modal-title {
    margin: 0;
  }
}

/* -- tokens -----------------------------------------------------------------
   The theming-knob defaults, mapped onto the design tokens. These are
   the ONLY custom-property declarations in the sheet - components
   consume, containers override, :root is the floor. Design tokens
   (app.css) are referenced, never redefined. */
@layer tokens {
  :root {
    /* button - the resting face IS the secondary variant */
    --btn-bg: var(--bg-3);
    --btn-fg: var(--text);
    --btn-border: var(--border);
    --btn-primary-bg: var(--accent);
    --btn-primary-fg: var(--accent-ink);
    --btn-primary-border: transparent;
    --btn-ghost-fg: var(--muted);
    --btn-danger-bg: var(--danger);
    --btn-danger-fg: var(--lift);
    --btn-danger-border: transparent;
    --btn-warning-bg: var(--warning-wash);
    --btn-warning-fg: var(--warning-text);
    --btn-warning-border: var(--warning-wash-border);

    /* input */
    --input-bg: var(--bg-2);
    --input-fg: var(--text);
    --input-border: var(--border-strong);
    --input-placeholder: var(--muted);
    --input-focus-ring: var(--focus-ring);
    --input-error-border: var(--danger);

    /* modal */
    --modal-bg: var(--bg-1);
    --modal-border: var(--border);
    --modal-shadow: var(--shadow-3);
    --modal-radius: var(--r-lg);
    --modal-scrim: var(--scrim);
    --modal-blur: 2px;

    /* popover (also the dropdown's panel chrome) */
    --pop-bg: var(--bg-3);
    --pop-border: var(--border);
    --pop-shadow: var(--shadow-2);
    --pop-radius: var(--r-md);
    --pop-offset: 6px;

    /* badge */
    --badge-bg: var(--wash-4);
    --badge-fg: var(--text-2);
    --badge-border: var(--border);
    --badge-count-bg: var(--accent-soft);
    --badge-count-fg: var(--accent);

    /* card */
    --card-bg: var(--bg-2);
    --card-fg: var(--text);
    --card-border: var(--border-strong);
    --card-shadow: var(--shadow-1);
    --card-radius: var(--r-md);
    --card-pad: var(--sp-3);

    /* skeleton */
    --skel-bg: var(--wash-4);
    --skel-shine: var(--wash-6);
    --skel-radius: var(--r-sm);

    /* empty state */
    --empty-title-fg: var(--text);
    --empty-fg: var(--muted);
    --empty-icon-fg: var(--faint);

    /* tooltip */
    --tip-bg: var(--bg-3);
    --tip-fg: var(--text);
    --tip-border: var(--border-strong);
    --tip-delay: 450ms;

    /* tabs */
    --tabs-track: var(--bg-3);
    --tabs-fg: var(--muted);
    --tabs-active-bg: var(--accent-soft);
    --tabs-active-fg: var(--accent);
    --tabs-h: var(--tab-h);
  }
}

/* -- base -------------------------------------------------------------------
   The cross-cutting doctrine baked once for every library control:
   one keyboard-only focus ring (language rule 2) and the
   reduced-motion carve-out (rule 3). Surfaces inherit; they never
   restate these. */
@layer base {
  .ui-btn:focus-visible,
  .ui-pop-trigger:focus-visible,
  .ui-dd-trigger:focus-visible,
  .ui-dd-opt:focus-visible,
  .ui-tab:focus-visible,
  .ui-modal-x:focus-visible {
    outline: none;
    box-shadow: var(--focus-ring);
  }

  .ui-input:focus-visible,
  .ui-select:focus-visible,
  .ui-textarea:focus-visible {
    outline: none;
    box-shadow: var(--input-focus-ring, var(--focus-ring));
  }

  @media (prefers-reduced-motion: reduce) {
    .ui-btn,
    .ui-pop-trigger,
    .ui-pop,
    .ui-pop-backdrop,
    .ui-modal-backdrop,
    .ui-modal-panel,
    .ui-dd-opt,
    .ui-tab,
    .ui-skel-line,
    .ui-skel-block,
    .ui-skel-circle,
    .ui-tip::after {
      transition-duration: 0.01ms !important;
      animation-duration: 0.01ms !important;
      animation-iteration-count: 1 !important;
    }
  }
}

/* -- components ------------------------------------------------------------- */

@layer components {
  /* == button ============================================================= */

  .ui-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--sp-1);
    height: 28px;
    padding: 0 var(--sp-3);
    font-family: var(--font-body);
    font-size: var(--size-sm);
    font-weight: 550;
    line-height: 1;
    white-space: nowrap;
    border-radius: var(--r-sm);
    background: var(--btn-bg, var(--bg-3));
    color: var(--btn-fg, var(--text));
    border: 1px solid var(--btn-border, var(--border));
    cursor: pointer;
    transition:
      background var(--dur-fast) var(--ease),
      color var(--dur-fast) var(--ease),
      border-color var(--dur-fast) var(--ease),
      box-shadow var(--dur-fast) var(--ease);
  }

  /* The one hover lift: a white-wash gradient over whatever face the
     button wears - token-based, theme-safe, variant-agnostic. */
  .ui-btn:not(:disabled):not([aria-disabled='true']):hover {
    background-image: linear-gradient(var(--wash-3), var(--wash-3));
  }

  .ui-btn:disabled,
  .ui-btn[aria-disabled='true'] {
    opacity: 0.55;
    cursor: default;
  }

  .ui-btn[aria-busy='true'] {
    pointer-events: none;
  }

  .ui-btn--sm {
    height: 24px;
    padding: 0 var(--sp-2);
    font-size: var(--size-xs);
  }

  .ui-btn--lg {
    height: 36px;
    padding: 0 var(--sp-4);
    font-size: var(--size-base);
  }

  .ui-btn--primary {
    background: var(--btn-primary-bg, var(--accent));
    color: var(--btn-primary-fg, var(--accent-ink));
    border-color: var(--btn-primary-border, transparent);
    font-weight: 600;
  }

  .ui-btn--primary:disabled,
  .ui-btn--primary[aria-disabled='true'] {
    background: var(--primary-disabled-bg);
    color: var(--primary-disabled-text);
  }

  .ui-btn--ghost {
    background: transparent;
    color: var(--btn-ghost-fg, var(--muted));
    border-color: transparent;
  }

  .ui-btn--ghost:not(:disabled):not([aria-disabled='true']):hover {
    color: var(--text);
  }

  .ui-btn--danger {
    background: var(--btn-danger-bg, var(--danger));
    color: var(--btn-danger-fg, var(--lift));
    border-color: var(--btn-danger-border, transparent);
    font-weight: 600;
  }

  /* Warning is the quiet variant: the v2.2-ratified washes carry it. */
  .ui-btn--warning {
    background: var(--btn-warning-bg, var(--warning-wash));
    color: var(--btn-warning-fg, var(--warning-text));
    border: 1px solid var(--btn-warning-border, var(--warning-wash-border));
  }

  .ui-btn-icon {
    display: inline-flex;
    flex: 0 0 auto;
  }

  .ui-btn-spinner {
    display: inline-block;
    width: 12px;
    height: 12px;
    flex: 0 0 auto;
    border-radius: var(--r-pill);
    border: 1.5px solid currentColor;
    border-right-color: transparent;
    animation: ui-spin 600ms linear infinite;
  }

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

  /* == input =============================================================== */

  .ui-field {
    display: flex;
    flex-direction: column;
    gap: var(--sp-1);
    min-width: 0;
  }

  .ui-field-label {
    font-size: var(--size-sm);
    font-weight: 550;
    color: var(--text-2);
  }

  .ui-field-help {
    margin: 0;
    font-size: var(--size-xs);
    color: var(--muted);
  }

  .ui-field-error {
    margin: 0;
    font-size: var(--size-xs);
    color: var(--danger);
  }

  .ui-control {
    box-sizing: border-box;
    width: 100%;
    height: 30px;
    padding: 0 var(--sp-2);
    font-family: var(--font-body);
    font-size: var(--size-base);
    line-height: var(--lh-base);
    color: var(--input-fg, var(--text));
    background: var(--input-bg, var(--bg-2));
    border: 1px solid var(--input-border, var(--border-strong));
    border-radius: var(--r-sm);
    transition:
      border-color var(--dur-fast) var(--ease),
      box-shadow var(--dur-fast) var(--ease);
  }

  .ui-control::placeholder {
    color: var(--input-placeholder, var(--muted));
  }

  .ui-control:focus-visible {
    border-color: var(--accent-dim);
  }

  .ui-control[aria-invalid='true'] {
    border-color: var(--input-error-border, var(--danger));
  }

  .ui-control:disabled,
  .ui-control[readonly] {
    opacity: 0.65;
  }

  .ui-textarea {
    height: auto;
    min-height: 64px;
    padding: var(--sp-2);
    resize: vertical;
  }

  /* == form controls: consistent height + vertical centering ============= */
  /* Every interactive control at the SAME height so side-by-side rows
     (filter groups, form rows, dropdowns) baseline-align. Buttons
     center via flex. Native fields (input/select) get NO flex:
     engines center their text via the content box + line-height, and
     display:flex on a <select> is engine-unreliable (the label can
     pin to the top). Same height + line-height on both. */
  .ui-btn {
    display: inline-flex;
    align-items: center;
    vertical-align: middle;
  }

  .ui-input,
  .ui-select,
  .ui-btn {
    height: var(--ui-ctl-h, 30px);
    line-height: var(--lh-sm);
    vertical-align: middle;
  }

  .ui-textarea {
    line-height: var(--lh-base);
  }

  .ui-select {
    padding-right: var(--sp-4);
  }

  /* == modal =============================================================== */

  .ui-modal-root {
    position: fixed;
    inset: 0;
    z-index: 300;
    display: grid;
    place-items: center;
    padding: var(--sp-4);
  }

  .ui-modal-backdrop {
    position: absolute;
    inset: 0;
    background: var(--modal-scrim, var(--scrim));
    backdrop-filter: blur(var(--modal-blur, 2px));
    -webkit-backdrop-filter: blur(var(--modal-blur, 2px));
    animation: ui-fade var(--dur-base) var(--ease);
  }

  .ui-modal-panel {
    position: relative;
    display: flex;
    flex-direction: column;
    width: 100%;
    max-width: 480px;
    max-height: calc(100vh - 2 * var(--sp-6));
    overflow-y: auto;
    overscroll-behavior: contain;
    background: var(--modal-bg, var(--bg-1));
    color: var(--text);
    border: 1px solid var(--modal-border, var(--border));
    border-radius: var(--modal-radius, var(--r-lg));
    box-shadow: var(--modal-shadow, var(--shadow-3));
    animation: ui-modal-in var(--dur-base) var(--ease);
  }

  .ui-modal--sm {
    max-width: 320px;
  }

  .ui-modal--lg {
    max-width: 640px;
  }

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

  .ui-modal-title {
    font-family: var(--font-body);
    font-size: var(--size-md);
    line-height: var(--lh-md);
    font-weight: 600;
    color: var(--text);
  }

  .ui-modal-x {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 24px;
    height: 24px;
    border-radius: var(--r-sm);
    color: var(--muted);
    font-size: var(--size-sm);
  }

  .ui-modal-x:hover {
    color: var(--text);
    background: var(--wash-3);
  }

  .ui-modal-body {
    padding: var(--sp-4);
    overflow-y: auto;
    overscroll-behavior: contain;
  }

  .ui-modal-footer {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: var(--sp-2);
    padding: var(--sp-3) var(--sp-4) var(--sp-4);
    border-top: 1px solid var(--border);
  }

  @keyframes ui-modal-in {
    from {
      opacity: 0;
      transform: translateY(4px) scale(0.98);
    }
  }

  @keyframes ui-fade {
    from {
      opacity: 0;
    }
  }

  /* == popover (and the dropdown's panel chrome) =========================== */

  .ui-pop-anchor {
    position: relative;
    display: inline-flex;
    min-width: 0;
  }

  /* The pill trigger - the extracted tool-btn recipe (list.css). */
  .ui-pop-trigger {
    display: inline-flex;
    align-items: center;
    gap: var(--sp-1);
    height: 28px;
    padding: 0 var(--sp-3);
    font-family: var(--font-body);
    font-size: var(--size-sm);
    font-weight: 550;
    white-space: nowrap;
    color: var(--muted);
    background: transparent;
    border: 1px solid var(--border);
    border-radius: var(--r-pill);
    transition:
      border-color var(--dur-fast) var(--ease),
      color var(--dur-fast) var(--ease),
      background var(--dur-fast) var(--ease);
  }

  .ui-pop-trigger:hover {
    border-color: var(--border-strong);
    color: var(--text);
  }

  .ui-pop-trigger[aria-expanded='true'] {
    border-color: var(--accent-dim);
    color: var(--text);
    background: var(--bg-1);
  }

  /* The transparent fixed click-away - the reliable LiveView pattern. */
  .ui-pop-backdrop {
    position: fixed;
    inset: 0;
    z-index: 75;
    background: transparent;
  }

  .ui-pop {
    position: absolute;
    top: calc(100% + var(--pop-offset, 6px));
    left: 0;
    z-index: 76;
    min-width: 220px;
    max-width: 340px;
    max-height: 360px;
    overflow-y: auto;
    overscroll-behavior: contain;
    padding: var(--sp-1);
    background: var(--pop-bg, var(--bg-3));
    border: 1px solid var(--pop-border, var(--border));
    border-radius: var(--pop-radius, var(--r-md));
    box-shadow: var(--pop-shadow, var(--shadow-2));
    scrollbar-width: thin;
    animation: ui-pop-in var(--dur-fast) var(--ease);
  }

  .ui-pop--bottom-end {
    left: auto;
    right: 0;
  }

  .ui-pop--top-start {
    top: auto;
    bottom: calc(100% + var(--pop-offset, 6px));
  }

  .ui-pop--top-end {
    top: auto;
    bottom: calc(100% + var(--pop-offset, 6px));
    left: auto;
    right: 0;
  }

  .ui-pop--right {
    top: 0;
    left: calc(100% + var(--pop-offset, 6px));
  }

  .ui-pop--left {
    top: 0;
    left: auto;
    right: calc(100% + var(--pop-offset, 6px));
  }

  @keyframes ui-pop-in {
    from {
      opacity: 0;
      transform: translateY(-2px);
    }
  }

  /* == badge =============================================================== */

  .ui-badge {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    border-radius: var(--r-pill);
    font-family: var(--font-body);
    font-weight: 550;
    line-height: 1;
    white-space: nowrap;
    box-sizing: border-box;
  }

  .ui-badge--sm {
    padding: 2px 6px;
    font-size: var(--size-2xs);
  }

  .ui-badge--md {
    padding: 3px 8px;
    font-size: var(--size-xs);
  }

  .ui-badge--chip {
    background: var(--badge-bg, var(--wash-4));
    color: var(--badge-fg, var(--text-2));
    border: 1px solid var(--badge-border, var(--border));
  }

  .ui-badge--tone-accent {
    background: var(--accent-soft);
    color: var(--accent);
    border-color: transparent;
  }

  .ui-badge--tone-success {
    background: var(--success-wash);
    color: var(--success-text);
    border-color: var(--success-wash-border);
  }

  .ui-badge--tone-warning {
    background: var(--warning-wash);
    color: var(--warning-text);
    border-color: var(--warning-wash-border);
  }

  .ui-badge--tone-danger {
    background: var(--danger-wash);
    color: var(--danger-text);
    border-color: var(--danger-border);
  }

  /* The info wash is not yet a ratified token (v2.2 ratified success
     and warning only); the local color-mix mirrors the recipe and is
     flagged for ratification in the lane report. */
  .ui-badge--tone-info {
    background: color-mix(in srgb, var(--info) 10%, transparent);
    color: var(--info);
    border-color: color-mix(in srgb, var(--info) 32%, transparent);
  }

  .ui-badge--count {
    justify-content: center;
    min-width: 16px;
    padding: 0 5px;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    background: var(--badge-count-bg, var(--accent-soft));
    color: var(--badge-count-fg, var(--accent));
  }

  .ui-badge--status {
    background: transparent;
    color: var(--text-2);
    border: none;
  }

  .ui-badge-dot {
    width: 7px;
    height: 7px;
    flex: 0 0 auto;
    border-radius: var(--r-pill);
  }

  .ui-badge--status-backlog .ui-badge-dot {
    background: var(--status-backlog);
  }

  .ui-badge--status-todo .ui-badge-dot {
    background: var(--status-todo);
  }

  .ui-badge--status-in_progress .ui-badge-dot {
    background: var(--status-in_progress);
  }

  .ui-badge--status-done .ui-badge-dot {
    background: var(--status-done);
  }

  .ui-badge--status-canceled .ui-badge-dot {
    background: var(--status-canceled);
  }

  /* == card ================================================================= */

  .ui-card {
    display: flex;
    flex-direction: column;
    min-width: 0;
    background: var(--card-bg, var(--bg-2));
    color: var(--card-fg, var(--text));
    border: 1px solid var(--card-border, var(--border-strong));
    border-radius: var(--card-radius, var(--r-md));
    box-shadow: var(--card-shadow, var(--shadow-1));
  }

  .ui-card-header {
    display: flex;
    align-items: center;
    gap: var(--sp-2);
    padding: var(--sp-3) var(--sp-3) var(--sp-2);
    border-bottom: 1px solid var(--border);
    font-size: var(--size-base);
    font-weight: 600;
  }

  .ui-card-body {
    padding: var(--card-pad, var(--sp-3));
  }

  .ui-card-footer {
    display: flex;
    align-items: center;
    gap: var(--sp-2);
    padding: var(--sp-2) var(--sp-3) var(--sp-3);
    border-top: 1px solid var(--border);
  }

  /* == dropdown ============================================================== */

  .ui-dd-anchor {
    position: relative;
    display: inline-flex;
    min-width: 0;
  }

  .ui-dd-caret {
    font-size: var(--size-2xs);
    transition: transform var(--dur-fast) var(--ease);
  }

  .ui-dd-trigger[aria-expanded='true'] .ui-dd-caret {
    transform: rotate(180deg);
  }

  .ui-dd-list {
    display: flex;
    flex-direction: column;
    min-width: 180px;
    max-height: 300px;
    padding: var(--sp-1);
    gap: 1px;
  }

  .ui-dd-opt {
    display: flex;
    align-items: center;
    gap: var(--sp-2);
    width: 100%;
    height: 30px;
    padding: 0 var(--sp-2);
    line-height: var(--lh-sm);
    text-align: left;
    font-family: var(--font-body);
    font-size: var(--size-sm);
    color: var(--text-2);
    border-radius: var(--r-sm);
    transition:
      background var(--dur-fast) var(--ease),
      color var(--dur-fast) var(--ease);
  }

  .ui-dd-opt:hover:not(:disabled),
  .ui-dd-opt--active {
    background: var(--wash-4);
    color: var(--text);
  }

  .ui-dd-opt--selected {
    color: var(--text);
    font-weight: 550;
  }

  .ui-dd-opt:disabled {
    opacity: 0.5;
    cursor: default;
  }

  .ui-dd-check {
    display: inline-flex;
    justify-content: center;
    width: 14px;
    flex: 0 0 auto;
    color: var(--accent);
    font-size: var(--size-sm);
  }

  .ui-dd-check::before {
    content: '✓';
    visibility: hidden;
  }

  .ui-dd-opt--selected .ui-dd-check::before {
    visibility: visible;
  }

  .ui-dd-label {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  /* == skeleton ============================================================== */

  .ui-skel {
    display: flex;
    flex-direction: column;
    gap: var(--sp-2);
    min-width: 0;
  }

  .ui-skel-line,
  .ui-skel-block,
  .ui-skel-circle {
    background-color: var(--skel-bg, var(--wash-4));
    background-image: linear-gradient(
      100deg,
      transparent 20%,
      var(--skel-shine, var(--wash-6)) 50%,
      transparent 80%
    );
    background-size: 200% 100%;
    border-radius: var(--skel-radius, var(--r-sm));
    animation: ui-shimmer 1.4s linear infinite;
  }

  .ui-skel-line {
    height: 10px;
  }

  .ui-skel-line--title {
    width: 60%;
    height: var(--size-md);
    margin-bottom: var(--sp-1);
  }

  .ui-skel-line--last {
    width: 70%;
  }

  .ui-skel-block {
    height: 80px;
  }

  .ui-skel-circle {
    width: 32px;
    height: 32px;
    border-radius: var(--r-pill);
  }

  @keyframes ui-shimmer {
    from {
      background-position: 180% 0;
    }

    to {
      background-position: -80% 0;
    }
  }

  /* == empty state ============================================================ */

  .ui-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--sp-2);
    max-width: 420px;
    margin-inline: auto;
    padding: var(--sp-7) var(--sp-6);
    text-align: center;
  }

  .ui-empty-icon {
    display: inline-flex;
    color: var(--empty-icon-fg, var(--faint));
  }

  .ui-empty-title {
    margin: 0;
    font-family: var(--font-body);
    font-size: var(--size-md);
    line-height: var(--lh-md);
    font-weight: 600;
    color: var(--empty-title-fg, var(--text));
  }

  .ui-empty-explain {
    margin: 0;
    font-size: var(--size-sm);
    color: var(--empty-fg, var(--muted));
  }

  .ui-empty-action {
    margin-top: var(--sp-2);
  }

  /* == tooltip ================================================================ */

  .ui-tip {
    position: relative;
    display: inline-flex;
  }

  .ui-tip::after {
    content: attr(data-tip);
    position: absolute;
    z-index: 76;
    max-width: 260px;
    padding: 3px var(--sp-2);
    font-family: var(--font-body);
    font-size: var(--size-xs);
    line-height: var(--lh-xs);
    white-space: nowrap;
    background: var(--tip-bg, var(--bg-3));
    color: var(--tip-fg, var(--text));
    border: 1px solid var(--tip-border, var(--border-strong));
    border-radius: var(--r-sm);
    box-shadow: var(--shadow-2);
    pointer-events: none;
    opacity: 0;
    transition: opacity var(--dur-fast) var(--ease);
  }

  .ui-tip--top::after {
    bottom: calc(100% + 6px);
    left: 50%;
    transform: translateX(-50%);
  }

  .ui-tip--bottom::after {
    top: calc(100% + 6px);
    left: 50%;
    transform: translateX(-50%);
  }

  .ui-tip--right::after {
    left: calc(100% + 6px);
    top: 50%;
    transform: translateY(-50%);
  }

  .ui-tip--left::after {
    right: calc(100% + 6px);
    top: 50%;
    transform: translateY(-50%);
  }

  /* Entry is delayed (the knob), exit is instant - the delay rides
     only the reveal transitions. Keyboard users get the same hint
     through :focus-within; the hover half stays behind a hover-capable
     pointer so touch never sticks a tip open. */
  .ui-tip:focus-within::after {
    opacity: 1;
    transition-delay: var(--tip-delay, 450ms);
  }

  @media (hover: hover) {
    .ui-tip:hover::after {
      opacity: 1;
      transition-delay: var(--tip-delay, 450ms);
    }
  }

  /* == tabs =================================================================== */

  .ui-tabs {
    display: inline-flex;
    align-items: center;
    gap: 2px;
    padding: 2px;
    background: var(--tabs-track, var(--bg-3));
    border-radius: var(--r-sm);
  }

  .ui-tab {
    display: inline-flex;
    align-items: center;
    gap: var(--sp-1);
    height: var(--tabs-h, var(--tab-h, 30px));
    padding: 0 var(--sp-3);
    font-family: var(--font-body);
    font-size: var(--size-sm);
    font-weight: 550;
    white-space: nowrap;
    color: var(--tabs-fg, var(--muted));
    background: transparent;
    border: none;
    border-radius: var(--r-sm);
    transition:
      color var(--dur-fast) var(--ease),
      background var(--dur-fast) var(--ease);
  }

  .ui-tab:hover {
    color: var(--text);
  }

  /* The accent marks the ACTIVE state - language rule 4. */
  .ui-tab--active {
    background: var(--tabs-active-bg, var(--accent-soft));
    color: var(--tabs-active-fg, var(--accent));
  }

  .ui-tab-count {
    min-width: 16px;
    padding: 0 4px;
    border-radius: var(--r-pill);
    background: var(--wash-5);
    font-size: var(--size-2xs);
    font-weight: 700;
    line-height: 14px;
    font-variant-numeric: tabular-nums;
    text-align: center;
  }

  .ui-tab--active .ui-tab-count {
    background: var(--wash-6);
  }
}

/* -- utilities ----------------------------------------------------------------
   RESERVED for the surface sheets: consumers set the knobs from
   @layer tokens and add surface-specific classes here - they never
   re-define the primitives (that is the migration contract R3/R4
   follow; see notes/w35_r1_components.md). Intentionally empty. */
@layer utilities {
}
