/*
 * Sairik Labs UI system.
 *
 * Loaded last by both hosts and scoped to `@layer system`, which is declared
 * after `overrides` in tokens.css. That makes this file the single place where
 * shared component behaviour is decided, without having to unpick the legacy
 * per-page stylesheets first.
 *
 * Sections
 *   01 Element rhythm
 *   02 Layout shells and containers
 *   03 Typography
 *   04 Buttons and links
 *   05 Forms
 *   06 Surfaces: card, panel, section
 *   07 Status: badge, alert, toast, inline message
 *   08 Data: table, toolbar, pagination, stat, chart
 *   09 Navigation: tabs, segmented, breadcrumb, menu
 *   10 Overlays: dialog, drawer, popover, tooltip
 *   11 States: empty, loading, skeleton, error
 *   12 Marketing chrome
 *   13 Utilities
 */

@layer system {
  /* ==================================================================== *
   * 01 Element rhythm
   * ==================================================================== */

  html {
    -webkit-text-size-adjust: 100%;
    text-size-adjust: 100%;
  }

  html:has(dialog[open]),
  body:has(dialog[open]) {
    overflow: hidden;
    overscroll-behavior: contain;
  }

  body {
    background: var(--color-canvas);
    color: var(--color-text);
    font-family: var(--font-body);
    font-size: 1rem;
    line-height: var(--lh-body);
    letter-spacing: var(--tracking-body);
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    text-rendering: optimizeLegibility;
  }

  ::selection {
    background: var(--color-brand-soft);
    color: var(--color-brand-strong);
  }

  /* One focus treatment everywhere. Never remove it without replacing it. */
  :focus-visible {
    outline: var(--ring-width) solid var(--color-focus);
    outline-offset: var(--ring-offset);
    border-radius: var(--r-xs);
  }
  :focus:not(:focus-visible) {
    outline: none;
  }

  .ui-icon {
    width: 1em;
    height: 1em;
    flex: none;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.75;
    stroke-linecap: round;
    stroke-linejoin: round;
    font-size: 1rem;
  }

  hr {
    height: 1px;
    margin: var(--sp-6) 0;
    border: 0;
    background: var(--color-divider);
  }

  code,
  kbd,
  samp,
  pre {
    font-family: var(--font-mono);
    font-size: 0.9em;
  }

  /* ==================================================================== *
   * 02 Layout shells and containers
   * ==================================================================== */

  /* `.shell` is the horizontal container. It caps reading width on very
     wide displays instead of letting lines run to 2000px. */
  .shell {
    width: 100%;
    max-width: var(--shell-content-max);
    margin-inline: auto;
    padding-inline: var(--shell-gutter);
  }

  .shell-public {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: auto 1fr auto;
    min-height: 100dvh;
    background: var(--color-canvas);
  }
  .shell-public > main {
    min-width: 0;
  }

  .shell-focus {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: auto 1fr;
    justify-items: center;
    min-height: 100dvh;
    padding: var(--sp-6) var(--shell-gutter) var(--sp-16);
    background:
      radial-gradient(120% 70% at 50% -10%, var(--color-brand-faint), transparent 60%),
      var(--color-canvas);
  }
  .shell-focus > main {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    min-width: 0;
    align-content: center;
    width: min(100%, 26rem);
  }

  /* The standard page body inside the app shell. Content is capped so a
     34-inch display shows a readable column, not a stretched one. */

  /* Responsive column set. `--min` is the point at which a column may no
     longer hold its content, so the grid rewraps rather than squeezing. */

  /* ==================================================================== *
   * 03 Typography
   * ==================================================================== */

  .ui-small {
    font-size: var(--fs-sm);
    line-height: var(--lh-snug);
  }

  /* Section eyebrow. Small caps carry the label role without needing a
     heavier weight or a colour block. */
  .eyebrow {
    display: inline-block;
    margin: 0;
    color: var(--color-text-muted);
    font-family: var(--font-body);
    font-size: var(--fs-2xs);
    font-weight: var(--fw-semibold);
    line-height: var(--lh-control);
    letter-spacing: var(--tracking-caps);
    text-transform: uppercase;
  }

  /* Numeric data. Tabular figures keep columns aligned and make deltas
     scannable without extra rules or separators. */
  .ui-metric-value,
  [data-numeric] {
    font-family: var(--font-numeric);
    font-variant-numeric: tabular-nums lining-nums;
    font-feature-settings: var(--numeric-features);
    letter-spacing: -0.01em;
  }

  /* ==================================================================== *
   * 04 Buttons and links
   * ==================================================================== */

  /*
   * Three levels of emphasis, and only one primary per view:
   *   primary    the single action the page exists for
   *   secondary  bordered, for real but non-defining actions
   *   ghost      toolbar and row-level actions
   * `danger` is a modifier on any level, not a fourth level.
   */
  .button {
    --_bg: var(--color-action);
    --_fg: var(--color-action-text);
    --_bd: var(--color-action);
    --_h: var(--control-h-lg);
    --_px: var(--sp-4);
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--sp-2);
    min-height: var(--_h);
    padding: 0 var(--_px);
    border: 1px solid var(--_bd);
    border-radius: var(--r-control);
    background: var(--_bg);
    color: var(--_fg);
    font-family: inherit;
    font-size: var(--fs-base);
    font-weight: var(--fw-medium);
    line-height: var(--lh-control);
    letter-spacing: var(--tracking-label);
    text-align: center;
    text-decoration: none;
    white-space: nowrap;
    cursor: pointer;
    transition:
      background-color var(--dur-fast) var(--ease-out),
      border-color var(--dur-fast) var(--ease-out),
      color var(--dur-fast) var(--ease-out);
  }
  .button .ui-icon {
    font-size: 1.0625em;
    margin-inline: -0.1em;
  }
  .button:hover {
    --_bg: var(--color-action-hover);
    --_bd: var(--color-action-hover);
  }
  .button:active {
    transform: translateY(0.5px);
  }
  .button:disabled,
  .button[aria-disabled="true"] {
    opacity: 0.45;
    pointer-events: none;
  }

  .button.outline {
    --_bg: var(--color-surface);
    --_fg: var(--color-text);
    --_bd: var(--color-control-border);
  }
  .button.outline:hover {
    --_bg: var(--color-surface-hover);
    --_bd: var(--color-control-border-hover);
  }

  .button.ghost {
    --_bg: transparent;
    --_fg: var(--color-text-secondary);
    --_bd: transparent;
  }
  .button.ghost:hover {
    --_bg: var(--color-surface-hover);
    --_fg: var(--color-text);
    --_bd: transparent;
  }

  .button.brand {
    --_bg: var(--color-brand);
    --_fg: var(--color-text-inverse);
    --_bd: var(--color-brand);
  }
  .button.brand:hover {
    --_bg: var(--color-brand-strong);
    --_bd: var(--color-brand-strong);
  }

  .button.danger {
    --_bg: var(--color-danger-fg);
    --_fg: var(--color-text-inverse);
    --_bd: var(--color-danger-fg);
  }
  .button.danger:hover {
    --_bg: oklch(38% 0.16 26);
    --_bd: oklch(38% 0.16 26);
  }
  /* A destructive action offered as a secondary control still has to look
     destructive, or the confirm dialog is the first warning the user gets. */
  .button.danger.outline {
    --_bg: var(--color-surface);
    --_fg: var(--color-danger-fg);
    --_bd: var(--color-danger-line);
  }
  .button.danger.outline:hover {
    --_bg: var(--color-danger-bg);
    --_bd: var(--color-danger-fg);
  }

  .button.small {
    --_h: var(--control-h-sm);
    --_px: var(--sp-3);
    font-size: var(--fs-sm);
  }
  
  .button.large {
    --_h: var(--control-h-xl);
    --_px: var(--sp-6);
    font-size: var(--fs-md);
  }
  .button.full {
    width: 100%;
  }

  /* Square control for icon-only actions. Keeps the 24px hit target rule
     without inheriting the text button's horizontal padding. */

  /* Busy state for any action that starts server work. The label stays in
     place so the button does not resize mid-click. */
  .button[data-busy="true"] {
    color: transparent !important;
    pointer-events: none;
  }
  .button[data-busy="true"]::after {
    content: "";
    position: absolute;
    width: 1em;
    height: 1em;
    border: 2px solid color-mix(in oklab, var(--_fg) 35%, transparent);
    border-top-color: var(--_fg);
    border-radius: 50%;
    animation: ui-spin 0.6s linear infinite;
  }

  @keyframes ui-spin {
    to {
      transform: rotate(1turn);
    }
  }

  .ui-link {
    color: var(--color-link);
    text-decoration: none;
    text-underline-offset: 0.2em;
  }
  .ui-link:hover {
    color: var(--color-link-hover);
    text-decoration: underline;
  }

  .brand-imageai .text-link:has(> .ui-icon) {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    max-width: 100%;
    white-space: nowrap;
  }
  .brand-imageai .text-link > .ui-icon {
    flex: 0 0 auto;
  }

  /* Trailing arrow that leans out on hover. Used for "read more" style
     links where a full button would be too much weight. */

  /* ==================================================================== *
   * 05 Forms
   * ==================================================================== */

  /* Required is marked on the label, not by an asterisk floating in the
     placeholder where it disappears the moment someone types. */

  /* Readonly stays readable: the value still matters, only editing is off. */

  /* Search field: the icon sits inside so the control reads as search
     without needing a label above it in a toolbar. */

  /* Checkbox and radio: drawn from the control border so they sit in the
     same visual family as inputs rather than the browser default. */

  /* Switch is reserved for settings that apply immediately. Anything that
     needs a Save button uses a checkbox. */

  /* Choice cards: a radio group where each option needs a description.
     Used instead of a select whenever the choice has consequences. */

  /* Fieldsets group related inputs so a long form reads as a few decisions
     rather than thirty boxes. */

  /* File input / dropzone */

  /* ==================================================================== *
   * 06 Surfaces
   * ==================================================================== */

  /*
   * A card is for a repeated object in a collection. A panel is for a
   * region of one page. Neither is a way to add a border for its own sake,
   * and neither nests inside the other.
   */

  /* Page header. Title, one-line purpose, and the page's actions — nothing
     else competes at this level. */

  /* Section header inside a page. Uses a rule rather than another card
     boundary so nested containers do not pile up. */
  .ui-section-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--sp-4);
    padding-bottom: var(--sp-3);
    border-bottom: 1px solid var(--color-divider);
    margin-bottom: var(--sp-4);
  }
  .ui-section-head h2,
  .ui-section-head h3 {
    margin: 0;
    font-family: var(--font-body);
    font-size: var(--fs-md);
    font-weight: var(--fw-semibold);
    letter-spacing: var(--tracking-heading);
  }

  /* ==================================================================== *
   * 07 Status
   * ==================================================================== */

  /*
   * One badge component, four semantic tones plus neutral. Tone is chosen
   * by meaning, never to add colour: neutral is the default and most
   * statuses should stay neutral so the ones that matter stand out.
   */

  /* Status dot: for row-level state where a full badge would add too much
     ink to every line of a table. */

  /* A live process gets a pulse; a settled state does not. */
  
  @keyframes ui-pulse {
    0%,
    100% {
      opacity: 1;
      box-shadow: 0 0 0 0 color-mix(in oklab, var(--color-info-fg) 45%, transparent);
    }
    60% {
      opacity: 0.8;
      box-shadow: 0 0 0 4px transparent;
    }
  }

  /* Alert: a message about the page. Toast: a message about what just
     happened. They are not interchangeable. */

  .ui-inline-error {
    border-color: var(--color-danger-line);
    background: var(--color-danger-bg);
  }

  .ui-inline-error {
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    padding: var(--sp-3) var(--sp-4);
    border: 1px solid var(--color-danger-line);
    border-radius: var(--r-md);
    color: var(--color-danger-fg);
    font-size: var(--fs-base);
  }

  .ui-inline-error:empty,
  .ui-inline-error[hidden],
  .admin-async-error[hidden] {
    display: none;
  }

  /*
   * Toasts stack in a fixed region anchored to the bottom-right on desktop
   * and the top on mobile, where the bottom edge belongs to navigation.
   * A bare `.toast` rendered by the server before scripts run positions
   * itself, so the message is never lost.
   */
  .toast-region {
    position: fixed;
    z-index: var(--z-toast);
    right: var(--sp-5);
    bottom: var(--sp-5);
    display: flex;
    flex-direction: column;
    gap: var(--sp-2);
    width: min(24rem, calc(100vw - 2 * var(--sp-5)));
    pointer-events: none;
  }
  .toast {
    position: fixed;
    right: var(--sp-5);
    bottom: var(--sp-5);
    z-index: var(--z-toast);
    display: flex;
    align-items: flex-start;
    gap: var(--sp-3);
    max-width: min(24rem, calc(100vw - 2 * var(--sp-5)));
    padding: var(--sp-3) var(--sp-3) var(--sp-3) var(--sp-4);
    border: 1px solid var(--color-border);
    border-left: 3px solid var(--color-neutral-fg);
    border-radius: var(--r-md);
    background: var(--color-surface-raised);
    box-shadow: var(--elev-3);
    color: var(--color-text);
    font-size: var(--fs-base);
    line-height: var(--lh-snug);
    pointer-events: auto;
  }
  .toast-region > .toast {
    position: static;
    max-width: none;
    opacity: 0;
    transform: translateY(6px);
    transition:
      opacity var(--dur-normal) var(--ease-out),
      transform var(--dur-normal) var(--ease-out);
  }
  .toast-region > .toast.visible {
    opacity: 1;
    transform: none;
  }
  .toast-region > .toast.leaving {
    opacity: 0;
    transform: translateY(-4px);
  }
  .toast > .ui-icon {
    flex: none;
    margin-top: 0.1em;
    font-size: 1.0625rem;
    color: var(--color-neutral-fg);
  }
  .toast > span {
    flex: 1 1 auto;
    min-width: 0;
  }
  .toast > button {
    flex: none;
    display: grid;
    place-items: center;
    width: 1.5rem;
    height: 1.5rem;
    border: 0;
    border-radius: var(--r-xs);
    background: transparent;
    color: var(--color-text-faint);
    cursor: pointer;
  }
  .toast > button:hover {
    background: var(--color-surface-hover);
    color: var(--color-text);
  }
  .toast.success {
    border-left-color: var(--color-success-fg);
  }
  .toast.success > .ui-icon {
    color: var(--color-success-fg);
  }
  .toast.error {
    border-left-color: var(--color-danger-fg);
  }
  .toast.error > .ui-icon {
    color: var(--color-danger-fg);
  }
  .toast.warning {
    border-left-color: var(--color-warning-fg);
  }
  .toast.warning > .ui-icon {
    color: var(--color-warning-fg);
  }
  .toast.info > .ui-icon {
    color: var(--color-info-fg);
  }
  @media (max-width: 48rem) {
    .toast-region {
      right: var(--sp-3);
      left: var(--sp-3);
      bottom: auto;
      top: var(--sp-3);
      width: auto;
    }
    .toast {
      right: var(--sp-3);
      left: var(--sp-3);
      bottom: auto;
      top: var(--sp-3);
      max-width: none;
    }
  }

  /* Progress. `--progress` is set inline by whatever owns the value. */

  @keyframes ui-indeterminate {
    0% {
      transform: translateX(-100%);
    }
    100% {
      transform: translateX(320%);
    }
  }

  /* ==================================================================== *
   * 09 Navigation
   * ==================================================================== */

  /* Segmented control for mutually exclusive view modes. Not for
     navigation — that is what tabs are for. */
  .ui-segmented {
    display: inline-flex;
    padding: 2px;
    border: 1px solid var(--color-border);
    border-radius: var(--r-md);
    background: var(--color-surface-sunken);
  }
  .ui-segmented > :is(a, button, label) {
    display: inline-flex;
    align-items: center;
    gap: var(--sp-2);
    padding: 0 var(--sp-3);
    height: calc(var(--control-h-md) - 4px);
    border: 0;
    border-radius: calc(var(--r-md) - 2px);
    background: transparent;
    color: var(--color-text-muted);
    font-size: var(--fs-sm);
    font-weight: var(--fw-medium);
    text-decoration: none;
    white-space: nowrap;
    cursor: pointer;
  }
  .ui-segmented > :is(a, button, label):is(.active, [aria-pressed="true"], [aria-current="true"], :has(input:checked)) {
    background: var(--color-surface);
    box-shadow: var(--elev-1);
    color: var(--color-text);
  }

  /* Vertical nav used by both sidebars. */

  /* Menus built on <details> so they work without JavaScript. */
  .account-menu-panel {
    position: absolute;
    z-index: var(--z-popover);
    min-width: 12rem;
    padding: var(--sp-1);
    border: 1px solid var(--color-border);
    border-radius: var(--r-lg);
    background: var(--color-surface-raised);
    box-shadow: var(--elev-3);
    animation: ui-pop var(--dur-fast) var(--ease-out);
  }
  @keyframes ui-pop {
    from {
      opacity: 0;
      transform: translateY(-4px) scale(0.985);
    }
  }

  /* ==================================================================== *
   * 10 Overlays
   * ==================================================================== */

  dialog.confirm-dialog {
    width: min(30rem, calc(100vw - 2rem));
    max-height: min(80dvh, 44rem);
    padding: 0;
    border: 1px solid var(--color-border);
    border-radius: var(--r-dialog);
    background: var(--color-surface-raised);
    box-shadow: var(--elev-4);
    color: var(--color-text);
  }
  dialog.confirm-dialog::backdrop {
    background: var(--color-overlay);
    backdrop-filter: blur(2px);
  }
  dialog.confirm-dialog[open] {
    animation: ui-dialog-in var(--dur-normal) var(--ease-out);
  }
  @keyframes ui-dialog-in {
    from {
      opacity: 0;
      transform: translateY(8px) scale(0.98);
    }
  }

  dialog.confirm-dialog footer {
    display: flex;
    justify-content: flex-end;
    gap: var(--sp-2);
    padding: var(--sp-4) var(--sp-5);
    border-top: 1px solid var(--color-divider);
    background: var(--color-surface-sunken);
  }
  dialog.confirm-dialog .confirm-dialog-card {
    display: grid;
    gap: 0;
  }
  dialog.confirm-dialog .confirm-dialog-copy {
    display: grid;
    gap: var(--sp-2);
    padding: var(--sp-5);
  }
  dialog.confirm-dialog .confirm-dialog-copy h2 {
    margin: 0;
    font-family: var(--font-body);
    font-size: var(--fs-lg);
    font-weight: var(--fw-semibold);
  }
  dialog.confirm-dialog .confirm-dialog-copy p {
    margin: 0;
    color: var(--color-text-secondary);
    line-height: var(--lh-body);
  }
  dialog.confirm-dialog .confirm-dialog-icon {
    display: grid;
    place-items: center;
    width: 2.25rem;
    height: 2.25rem;
    margin: var(--sp-5) var(--sp-5) 0;
    border-radius: var(--r-md);
    background: var(--color-danger-bg);
    color: var(--color-danger-fg);
  }

  /* Drawer: an edge-anchored surface for filters and secondary detail. */

  /* Tooltip driven by `data-tooltip`. Delayed so it never fires during a
     casual pass across a toolbar. */
  [data-tooltip] {
    position: relative;
  }
  [data-tooltip]::after {
    content: attr(data-tooltip);
    position: absolute;
    z-index: var(--z-tooltip);
    top: calc(100% + 6px);
    left: 50%;
    max-width: 16rem;
    width: max-content;
    padding: var(--sp-1) var(--sp-2);
    border-radius: var(--r-sm);
    background: var(--color-surface-inverse);
    color: var(--color-text-inverse);
    font-size: var(--fs-2xs);
    font-weight: var(--fw-medium);
    line-height: 1.35;
    white-space: normal;
    opacity: 0;
    transform: translate(-50%, -2px);
    pointer-events: none;
    transition:
      opacity var(--dur-fast) var(--ease-out),
      transform var(--dur-fast) var(--ease-out);
    transition-delay: 0s;
  }
  [data-tooltip]:hover::after,
  [data-tooltip]:focus-visible::after {
    opacity: 1;
    transform: translate(-50%, 0);
    transition-delay: 400ms;
  }
  [data-tooltip=""]::after {
    display: none;
  }
  /* A tooltip is a hover affordance, so a touch device never gets to read it.
     Leaving it rendered is not free either: it is laid out at the trigger's
     width plus its own text, which pushed the page sideways whenever the
     trigger sat near a screen edge. */
  @media (hover: none),
  (max-width: 64rem) {
    [data-tooltip]::after {
      display: none;
    }
  }
  /* Header actions sit hard against the right edge, so a centred tooltip has
     nowhere to go. Anchor those to the same edge as their trigger. */
  .site-header .nav-actions [data-tooltip]::after {
    left: auto;
    right: 0;
    transform: translateY(-2px);
  }
  .site-header .nav-actions [data-tooltip]:hover::after,
  .site-header .nav-actions [data-tooltip]:focus-visible::after {
    transform: translateY(0);
  }

  /* ==================================================================== *
   * 11 States
   * ==================================================================== */

  /*
   * Every collection needs four states, and the empty state carries the
   * most weight: it is the first thing a new account sees.
   */
  .ui-empty-state {
    display: grid;
    justify-items: center;
    gap: var(--sp-2);
    /* Flat by default. An empty state almost always sits inside a panel or
       a table that already draws the container, and a dashed box inside a
       bordered card is the classic card-in-card. */
    padding: var(--sp-12) var(--sp-6);
    border: 0;
    border-radius: 0;
    background: none;
    text-align: center;
  }
  
  .ui-empty-icon {
    display: grid;
    place-items: center;
    width: 2.75rem;
    height: 2.75rem;
    margin-bottom: var(--sp-1);
    border: 1px solid var(--color-border);
    border-radius: var(--r-lg);
    background: var(--color-surface-sunken);
    color: var(--color-text-muted);
  }
  .ui-empty-icon .ui-icon {
    font-size: 1.25rem;
  }
  .ui-empty-state h2,
  .ui-empty-state h3 {
    margin: 0;
    font-family: var(--font-body);
    font-size: var(--fs-md);
    font-weight: var(--fw-semibold);
  }
  .ui-empty-state p {
    margin: 0;
    max-width: 40ch;
    color: var(--color-text-muted);
    font-size: var(--fs-base);
    line-height: var(--lh-snug);
  }
  .ui-empty-state .button {
    margin-top: var(--sp-3);
  }

  /* Skeletons mirror the shape of the content they replace, so the layout
     does not jump when data lands. */
  .ui-skeleton {
    display: grid;
    gap: var(--sp-3);
    padding: var(--sp-4);
  }
  .ui-skeleton-line {
    display: block;
    height: 0.75rem;
    border-radius: var(--r-xs);
    background: linear-gradient(
      90deg,
      var(--color-surface-active) 25%,
      var(--color-surface-hover) 37%,
      var(--color-surface-active) 63%
    );
    background-size: 400% 100%;
    animation: ui-shimmer 1.4s linear infinite;
  }
  .ui-skeleton-line.heading {
    width: 32%;
    height: 1rem;
  }
  .ui-skeleton-line.subheading {
    width: 52%;
  }
  .ui-skeleton-line.row {
    width: 100%;
    height: 1.25rem;
  }
  .ui-skeleton-line.row:nth-child(even) {
    width: 88%;
  }
  @keyframes ui-shimmer {
    to {
      background-position: -400% 0;
    }
  }
  @media (prefers-reduced-motion: reduce) {
    .ui-skeleton-line {
      animation: none;
    }
  }

  /* Generic regions pause input during refresh. Admin lists manage their own
     loading styles and keep filters and cached rows interactive. */
  [data-async-region]:not([data-admin-region])[aria-busy="true"] {
    position: relative;
    opacity: 0.55;
    pointer-events: none;
    transition: opacity var(--dur-fast) linear;
  }

  /* ==================================================================== *
   * 12 Marketing chrome
   * ==================================================================== */

  .shell-public-body {
    font-size: 1rem;
  }

  .site-header {
    position: sticky;
    top: 0;
    z-index: var(--z-header);
    border-bottom: 1px solid transparent;
    background: color-mix(in srgb, var(--color-canvas) 88%, transparent);
    backdrop-filter: saturate(140%) blur(10px);
    transition:
      border-color var(--dur-normal) var(--ease-out),
      background-color var(--dur-normal) var(--ease-out);
  }
  /* The header only grows a border once the page has moved, so the top of
     the page stays a single uninterrupted surface. */
  .site-header.scrolled {
    border-bottom-color: var(--color-border);
    background: color-mix(in srgb, var(--color-canvas) 96%, transparent);
  }
  .site-header .nav-wrap {
    display: flex;
    align-items: center;
    gap: var(--sp-6);
    min-height: 4rem;
  }
  .site-header .brand {
    display: inline-flex;
    align-items: center;
    gap: var(--sp-2);
    flex: none;
    color: var(--color-text);
    font-size: var(--fs-lg);
    font-weight: var(--fw-semibold);
    letter-spacing: -0.015em;
    text-decoration: none;
  }
  .site-header .brand img {
    width: 1.75rem;
    height: 1.75rem;
    border-radius: var(--r-sm);
  }
  .site-header .desktop-nav {
    display: flex;
    align-items: center;
    gap: var(--sp-1);
    margin-right: auto;
  }
  .site-header .desktop-nav > a {
    display: inline-flex;
    align-items: center;
    gap: var(--sp-1);
    padding: var(--sp-2) var(--sp-3);
    border: 0;
    border-radius: var(--r-control);
    background: transparent;
    color: var(--color-text-secondary);
    font-size: var(--fs-md);
    font-weight: var(--fw-medium);
    text-decoration: none;
    cursor: pointer;
  }
  .site-header .desktop-nav > a:hover {
    background: var(--color-surface-hover);
    color: var(--color-text);
  }
  .site-header .desktop-nav > a[aria-current="page"] {
    color: var(--color-text);
    font-weight: var(--fw-semibold);
  }
  .site-header .nav-actions {
    display: flex;
    align-items: center;
    gap: var(--sp-2);
    flex: none;
  }

  .account-popover,
  .nav-menu {
    position: relative;
  }
  .account-popover > summary {
    list-style: none;
  }
  .account-popover > summary::-webkit-details-marker {
    display: none;
  }
  .account-menu-panel {
    top: calc(100% + var(--sp-2));
    right: 0;
    /* A lower layer still sets `left` for a fixed-position phone variant that
       this rule takes away by restoring `absolute`. Left plus right plus a
       min-width over-constrains the box, so the browser drops `right` and the
       menu drifts off the side of the screen. */
    left: auto;
  }
  /* Anchored to a trigger that already sits at the right edge, so the panel
     only has the space to its left to work with. */
  @media (max-width: 30rem) {
    .site-header .account-menu-panel {
      width: min(18rem, calc(100vw - var(--sp-6)));
    }
  }

  .account-popover > summary .account-avatar {
    display: grid;
    place-items: center;
    width: var(--control-h-md);
    height: var(--control-h-md);
    overflow: hidden;
    border-radius: var(--r-pill);
    background: var(--color-brand-soft);
    color: var(--color-brand-strong);
    font-size: var(--fs-sm);
    font-weight: var(--fw-semibold);
  }
  .account-popover > summary .account-avatar img {
    width: 100%;
    height: 100%;
    object-fit: cover;
  }

  .nav-toggle {
    display: none;
    flex-direction: column;
    justify-content: center;
    gap: 4px;
    width: var(--control-h-md);
    height: var(--control-h-md);
    padding: 0 0.45rem;
    border: 1px solid var(--color-border);
    border-radius: var(--r-control);
    background: var(--color-surface);
    cursor: pointer;
  }
  .nav-toggle span {
    display: block;
    height: 1.5px;
    /* `gap` is the only spacer. A lower layer also puts a 5px block margin on
       these bars, which pushed them further apart than the close transform
       below travels, so the open state formed a chevron instead of a cross. */
    margin: 0;
    border-radius: 2px;
    background: var(--color-text);
    transition: transform var(--dur-fast) var(--ease-out), opacity var(--dur-fast) linear;
  }
  .nav-toggle[aria-expanded="true"] span:nth-child(1) {
    transform: translateY(5.5px) rotate(45deg);
  }
  .nav-toggle[aria-expanded="true"] span:nth-child(2) {
    opacity: 0;
  }
  .nav-toggle[aria-expanded="true"] span:nth-child(3) {
    transform: translateY(-5.5px) rotate(-45deg);
  }

  @media (max-width: 64rem) {
    .site-header .desktop-nav,
    .site-header .desktop-auth {
      display: none;
    }
    .nav-toggle {
      display: flex;
    }
    .site-header .nav-actions {
      margin-left: auto;
    }
  }

  .mobile-nav {
    display: none;
    border-top: 1px solid var(--color-border);
    background: var(--color-surface);
  }
  .mobile-nav.open {
    display: block;
    max-height: calc(100dvh - 4rem);
    overflow: auto;
  }
  body.mobile-nav-open {
    overflow: hidden;
  }
  .mobile-nav-inner {
    display: grid;
    gap: var(--sp-1);
    padding-block: var(--sp-3) var(--sp-6);
    /* The drawer is full height by design, but its rows are not: a lower layer
       gives this a `min-height` of the viewport, and a stretch-aligned grid
       spread five links over 780px. */
    align-content: start;
  }
  /* "Products" is a peer of the other destinations, so it reads as one. It was
     inheriting a muted secondary colour and lighter weight from a lower layer,
     which made the one item with a submenu look like the one disabled item. */
  .mobile-main-link {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: var(--sp-3) var(--sp-2);
    border-radius: var(--r-control);
    color: var(--color-text);
    font-size: var(--fs-lg);
    font-weight: var(--fw-medium);
    text-decoration: none;
    cursor: pointer;
  }
  .mobile-product-link {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto;
    align-items: center;
    gap: var(--sp-3);
    min-height: 3.75rem;
    padding: var(--sp-2);
    border-radius: var(--r-control);
    color: var(--color-text);
    text-decoration: none;
  }
  .mobile-product-link .nav-icon { display: grid; place-items: center; width: 2rem; height: 2rem; border-radius: .5rem; color: var(--color-brand-strong); background: var(--color-brand-faint); }
  .mobile-product-link b,
  .mobile-product-link small { display: block; }
  .mobile-product-link b { font-size: var(--fs-sm); }
  .mobile-product-link small { margin-top: .15rem; color: var(--color-text-muted); font-size: var(--fs-xs); line-height: 1.35; }
  .mobile-main-link:hover,
  .mobile-product-link:hover {
    background: var(--color-surface-hover);
  }

  .mobile-auth {
    display: grid;
    /* One per row. A lower layer still pairs these two-up from when the drawer
       carried sign in and sign up together, which left a lone action sitting at
       half width looking like it had lost its partner. */
    grid-template-columns: 1fr;
    gap: var(--sp-2);
    padding-block: var(--sp-3);
  }
  .mobile-auth .button {
    --_h: var(--control-h-xl);
    width: 100%;
  }

  /* Marketing section rhythm. Sections alternate surface rather than
     stacking cards, which is what gives a long page its pace. */

  .site-footer {
    border-top: 1px solid var(--color-border);
    background: var(--color-canvas-alt);
    color: var(--color-text-secondary);
    font-size: var(--fs-md);
  }
  /* Mobile first, because the desktop track list cannot collapse: its floors
     add up to 16rem + 9rem + gap, which is wider than a phone. Stated the
     other way round it forced the whole document to scroll sideways on every
     handset. The link lists are short, so two columns beats one — it halves
     the height without crowding. */
  .site-footer .footer-main {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--sp-8) var(--sp-6);
    padding-block: clamp(3rem, 5vw, 4.5rem) var(--sp-10);
  }
  @media (min-width: 40rem) {
    .site-footer .footer-main {
      grid-template-columns: repeat(4, minmax(0, 1fr));
    }
  }
  @media (min-width: 64rem) {
    .site-footer .footer-main {
      grid-template-columns: minmax(16rem, 1.6fr) repeat(auto-fit, minmax(9rem, 1fr));
      gap: clamp(2rem, 4vw, 4rem);
    }
  }
  .site-footer .footer-brand-block {
    display: grid;
    gap: var(--sp-3);
    align-content: start;
    max-width: 26rem;
    /* Full bleed until the brand column exists as its own track. */
    grid-column: 1 / -1;
  }
  @media (min-width: 64rem) {
    .site-footer .footer-brand-block {
      grid-column: auto;
    }
  }
  /* A lower layer hides the last two link groups below 64rem so its own
     narrower grid would fit. That grid is gone; the groups are not optional. */
  .site-footer .footer-main > div:not(.footer-brand-block) {
    display: flex;
    flex-direction: column;
  }
  .site-footer .footer-brand {
    display: inline-flex;
    align-items: center;
    gap: var(--sp-2);
    color: var(--color-text);
    font-size: var(--fs-lg);
    font-weight: var(--fw-semibold);
    text-decoration: none;
  }
  .site-footer .footer-brand img {
    width: 1.75rem;
    height: 1.75rem;
    border-radius: var(--r-sm);
  }
  .site-footer .footer-brand-block p {
    margin: 0;
    color: var(--color-text-muted);
    font-size: var(--fs-md);
    line-height: var(--lh-body);
  }
  .site-footer .footer-address {
    font-size: var(--fs-sm);
  }
  .site-footer .footer-address a {
    color: var(--color-text-muted);
  }
  .site-footer .footer-address a:hover {
    color: var(--color-text);
  }
  .site-footer .footer-heading {
    margin: 0 0 var(--sp-3);
    color: var(--color-text);
    font-family: var(--font-body);
    font-size: var(--fs-2xs);
    font-weight: var(--fw-semibold);
    letter-spacing: var(--tracking-caps);
    text-transform: uppercase;
  }
  .site-footer .footer-main > div > a {
    display: block;
    padding-block: var(--sp-1);
    color: var(--color-text-muted);
    font-size: var(--fs-md);
    text-decoration: none;
  }
  .site-footer .footer-main > div > a:hover {
    color: var(--color-text);
  }
  .site-footer .footer-cookie-settings {
    display: inline-flex;
    align-items: center;
    gap: var(--sp-2);
    padding: 0;
    border: 0;
    background: none;
    color: var(--color-text-muted);
    font: inherit;
    font-size: var(--fs-sm);
    text-decoration: underline;
    text-underline-offset: 0.2em;
    cursor: pointer;
  }
  .site-footer .footer-bottom {
    border-top: 1px solid var(--color-border-subtle);
    padding-block: var(--sp-5);
    color: var(--color-text-faint);
    font-size: var(--fs-sm);
  }

  /* ==================================================================== *
   * 13 Utilities
   * ==================================================================== */

  .navigation-progress {
    position: fixed;
    z-index: var(--z-skip);
    inset: 0 auto auto 0;
    width: 0;
    height: 2px;
    background: var(--color-brand);
    opacity: 0;
    transition:
      width var(--dur-slow) var(--ease-out),
      opacity var(--dur-fast) linear;
  }
  .navigation-progress.active {
    width: 68%;
    opacity: 1;
  }

  .skip-link {
    position: fixed;
    z-index: var(--z-skip);
    top: var(--sp-3);
    left: var(--sp-3);
    padding: var(--sp-2) var(--sp-4);
    border-radius: var(--r-control);
    background: var(--color-surface-inverse);
    color: var(--color-text-inverse);
    font-size: var(--fs-base);
    font-weight: var(--fw-medium);
    text-decoration: none;
    transform: translateY(-200%);
    transition: transform var(--dur-fast) var(--ease-out);
  }
  .skip-link:focus {
    transform: none;
  }

  /* Cookie consent and preference dialog (shared by marketing, auth, workspace). */
  .cookie-consent-banner {
    position: fixed;
    z-index: var(--z-skip);
    right: 22px;
    bottom: 22px;
    display: grid;
    width: min(760px, calc(100vw - 44px));
    gap: 17px;
    padding: 20px;
    border: 1px solid var(--border);
    border-radius: 20px;
    background: color-mix(in srgb, var(--background) 96%, transparent);
    box-shadow: 0 24px 70px color-mix(in srgb, var(--color-ink) 20%, transparent);
    backdrop-filter: blur(22px);
    pointer-events: auto;
  }

  body:has([data-cookie-banner]) {
    padding-bottom: max(28px, calc(env(safe-area-inset-bottom) + 12px));
  }

  .cookie-consent-copy {
    display: flex;
    min-width: 0;
    align-items: flex-start;
    gap: 14px;
  }

  .cookie-consent-icon {
    display: grid;
    width: 44px;
    height: 44px;
    flex: 0 0 auto;
    place-items: center;
    border-radius: 14px;
    background: color-mix(in srgb, var(--primary) 10%, var(--muted));
    color: var(--primary);
  }

  .cookie-consent-copy > div {
    min-width: 0;
  }

  .cookie-consent-copy .eyebrow {
    font-size: 0.54rem;
  }

  .cookie-consent-copy h2,
  .cookie-consent-heading {
    margin: 3px 0 6px;
    font-size: 1.04rem;
    font-weight: 700;
    line-height: 1.3;
    color: var(--foreground);
  }

  .cookie-consent-copy p:not(.cookie-consent-heading) {
    margin: 0;
    color: var(--muted-foreground);
    font-size: 0.75rem;
    line-height: 1.62;
  }

  .cookie-consent-copy a {
    display: inline-block;
    margin-top: 7px;
    color: var(--foreground);
    font-size: 0.64rem;
    font-weight: 700;
    text-decoration: underline;
    text-underline-offset: 3px;
  }

  .cookie-consent-actions {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    flex-wrap: wrap;
    gap: 8px;
  }

  .cookie-consent-actions .button {
    min-height: 39px;
  }

  .cookie-settings-dialog {
    width: min(720px, calc(100vw - 36px));
    max-width: 48rem;
    max-height: min(760px, calc(100vh - 36px));
    padding: 0;
    overflow: auto;
    border: 1px solid var(--border);
    border-radius: 22px;
    background: var(--background);
    box-shadow: 0 30px 90px color-mix(in srgb, var(--color-ink) 28%, transparent);
  }

  .cookie-settings-dialog::backdrop {
    background: color-mix(in srgb, var(--color-ink) 48%, transparent);
    backdrop-filter: blur(4px);
  }

  .cookie-settings-dialog > .dialog-close-row {
    position: absolute;
    z-index: var(--z-raised);
    top: 13px;
    right: 13px;
  }

  .cookie-settings-dialog > .dialog-close-row button {
    display: grid;
    width: 36px;
    height: 36px;
    place-items: center;
    border: 1px solid var(--border);
    border-radius: 11px;
    background: var(--surface);
  }

  .cookie-settings-dialog > header {
    display: flex;
    align-items: flex-start;
    gap: 13px;
    padding: 22px 58px 19px 22px;
    border-bottom: 1px solid var(--border);
    background: color-mix(in srgb, var(--muted) 34%, transparent);
  }

  .cookie-settings-heading-icon {
    display: grid;
    width: 44px;
    height: 44px;
    flex: 0 0 auto;
    place-items: center;
    border-radius: 14px;
    background: var(--surface);
    color: var(--primary);
    box-shadow: var(--shadow-sm);
  }

  .cookie-settings-dialog > header > div {
    display: grid;
    gap: 3px;
  }

  .cookie-settings-dialog h2 {
    margin: 0;
    font-size: 1.15rem;
  }

  .cookie-settings-dialog > header p {
    margin: 0;
    color: var(--muted-foreground);
    font-size: 0.68rem;
  }

  .cookie-category-list {
    display: grid;
    gap: 12px;
    padding: 18px 22px;
  }

  .cookie-category-card {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto;
    align-items: start;
    gap: 13px;
    padding: 15px;
    border: 1px solid var(--border);
    border-radius: 15px;
    background: var(--surface);
  }

  .cookie-category-card.essential {
    background: color-mix(in srgb, var(--muted) 34%, var(--surface));
  }

  .cookie-category-icon {
    display: grid;
    width: 38px;
    height: 38px;
    place-items: center;
    border-radius: 12px;
    background: var(--muted);
    color: var(--primary);
  }

  .cookie-category-card > div:nth-child(2) {
    min-width: 0;
  }

  .cookie-category-title {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px;
  }

  .cookie-category-title h3 {
    margin: 0;
    font-size: 0.8rem;
  }

  .cookie-category-title span {
    padding: 3px 7px;
    border-radius: 999px;
    background: var(--muted);
    color: var(--muted-foreground);
    font-size: 0.52rem;
    font-weight: 700;
  }

  .cookie-category-card p {
    margin: 6px 0 0;
    color: var(--muted-foreground);
    font-size: 0.66rem;
    line-height: 1.55;
  }

  .cookie-category-card .feature-switch {
    position: relative;
    display: inline-flex;
    width: 52px;
    height: 44px;
    align-items: center;
    justify-content: center;
    margin-top: -5px;
    cursor: pointer;
  }

  .cookie-category-card .feature-switch input {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    margin: 0;
    opacity: 0;
    cursor: inherit;
  }

  .cookie-category-card .feature-switch span {
    position: relative;
    display: block;
    width: 44px;
    height: 24px;
    border-radius: 999px;
    background: var(--color-text-muted);
    transition: background-color .18s ease;
  }

  .cookie-category-card .feature-switch span::after {
    position: absolute;
    top: 3px;
    left: 3px;
    width: 18px;
    height: 18px;
    border-radius: 50%;
    background: #fff;
    box-shadow: 0 1px 3px color-mix(in srgb, var(--color-ink) 20%, transparent);
    content: "";
    transition: transform .18s ease;
  }

  .cookie-category-card .feature-switch input:checked + span { background: var(--color-brand); }
  .cookie-category-card .feature-switch input:checked + span::after { transform: translateX(20px); }
  .cookie-category-card .feature-switch input:focus-visible + span { outline: 2px solid var(--color-focus); outline-offset: 3px; }
  .cookie-category-card .feature-switch:has(input:disabled) { cursor: default; opacity: .6; }
  .cookie-category-card .feature-switch:has(input:disabled) span { background: var(--color-text-muted); }

  .cookie-settings-dialog > footer {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 16px 22px;
    border-top: 1px solid var(--border);
    background: color-mix(in srgb, var(--muted) 28%, transparent);
  }

  .cookie-settings-dialog > footer > div {
    display: flex;
    align-items: center;
    gap: 8px;
  }

  .footer-cookie-settings {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    margin: 0;
    padding: 0;
    border: 0;
    background: transparent;
    color: inherit;
    font: inherit;
    text-align: left;
    cursor: pointer;
  }

  .footer-cookie-settings .ui-icon {
    width: 14px;
    height: 14px;
  }

  @media (max-width: 48rem) {
    .cookie-consent-banner {
      right: 12px;
      bottom: max(12px, env(safe-area-inset-bottom));
      left: 12px;
      width: auto;
      max-height: min(46vh, 340px);
      overflow: auto;
      overscroll-behavior: contain;
      padding: 14px;
    }
    .cookie-consent-actions {
      display: grid;
      grid-template-columns: 1fr 1fr;
    }
    .cookie-consent-actions .button {
      width: 100%;
    }
    .cookie-consent-actions .button:last-child {
      grid-column: 1/-1;
    }
    .cookie-settings-dialog {
      width: calc(100vw - 20px);
      max-height: calc(100vh - 20px);
    }
    .cookie-category-card {
      grid-template-columns: auto minmax(0, 1fr);
    }
    .cookie-category-card > .feature-switch {
      grid-column: 2;
      justify-self: end;
    }
    .cookie-settings-dialog > footer {
      align-items: stretch;
      flex-direction: column;
    }
    .cookie-settings-dialog > footer > div {
      display: grid;
      grid-template-columns: 1fr 1fr;
    }
    .cookie-settings-dialog > footer .button {
      width: 100%;
    }
  }

  @media (max-width: 30rem) {
    .cookie-consent-copy {
      gap: 10px;
    }
    .cookie-consent-icon {
      width: 38px;
      height: 38px;
    }
    .cookie-consent-actions {
      grid-template-columns: 1fr;
    }
    .cookie-consent-actions .button:last-child {
      grid-column: auto;
    }
    .cookie-category-list {
      padding: 14px;
    }
    .cookie-settings-dialog > header {
      padding-left: 16px;
    }
    .cookie-settings-dialog > footer {
      padding: 14px;
    }
    .cookie-settings-dialog > footer > div {
      grid-template-columns: 1fr;
    }
  }
}
