@tailwind base;
@tailwind components;
@tailwind utilities;

@layer base {
  body {
    @apply min-h-screen bg-surface text-[#0a2540] antialiased;
  }
  a {
    @apply transition-colors duration-150;
  }
  input[type="date"]::-webkit-calendar-picker-indicator,
  input[type="datetime-local"]::-webkit-calendar-picker-indicator {
    display: none;
    -webkit-appearance: none;
  }

  input[type="date"]::-webkit-inner-spin-button,
  input[type="datetime-local"]::-webkit-inner-spin-button {
    display: none;
    -webkit-appearance: none;
  }


  /* Visible keyboard focus, everywhere (WCAG 2.4.7).
     Tailwind's preflight removes the default outline, and the Summit classes only
     ever defined focus styles for inputs and two shell buttons — so links and most
     buttons had no indicator at all. An outline rather than a box-shadow, so it
     follows each control's own border-radius and costs no layout. :where() keeps it
     at zero specificity, so anything with its own focus treatment still wins. */
  [data-theme] :where(a, button, summary, [role="button"], [tabindex]:not([tabindex="-1"])):focus-visible {
    outline: 2px solid var(--brand);
    outline-offset: 2px;
  }

  /* Safety net for form controls inside a themed scope.
     @tailwindcss/forms gives every input a white background, so any control that
     did not opt into .reg-input renders as a white box on the dark canvas — the
     store quantity stepper is one, and it is not the sort of thing a class-by-class
     sweep reliably finds. :where() keeps this at zero specificity so .reg-input and
     any explicit utility still win; this only catches what nothing else styled. */
  [data-theme] :where(input:not([type="checkbox"]):not([type="radio"]):not([type="submit"]):not([type="button"]):not([type="range"]):not([type="file"])),
  [data-theme] :where(select),
  [data-theme] :where(textarea) {
    background-color: var(--field);
    color: var(--tx);
    border-color: var(--field-line);
  }
  [data-theme] :where(input)::placeholder,
  [data-theme] :where(textarea)::placeholder {
    color: var(--tx4);
  }
  [data-theme] :where(select) option {
    background-color: var(--panel-solid);
    color: var(--tx);
  }

  /* ══════════════════════════════════════════════════════════════
     APP SHELL TOKENS.

     Layout.jsx's header and footer are shared with /admin/*, which is out of
     scope for the reskin. So the shell reads its own token set whose *defaults*
     reproduce today's Stripe-docs palette exactly — an unthemed shell renders
     byte-identical to before. The [data-theme] block below remaps them onto the
     Summit tokens, and Layout only sets data-theme on participant routes.

     Order matters: [data-theme] must follow .app-shell to win the specificity tie
     when both land on the same element.
     ══════════════════════════════════════════════════════════════ */
  .app-shell {
    --shell-bg: #f6f9fc;
    --shell-panel: rgba(255, 255, 255, 0.95);
    --shell-panel-solid: #ffffff;
    --shell-line: #e6ebf1;
    --shell-line-soft: #f5f5f4;
    --shell-tx: #0a2540;
    --shell-tx2: #697386;
    --shell-hover: #f6f9fc;
    --shell-accent: #5851eb;
    --shell-cta: #635bff;
    --shell-cta-hover: #5851eb;
    --shell-cta-ink: #ffffff;
    --shell-footer-bg: #f5f5f4;
    --shell-footer-line: #e7e5e4;
    --shell-ring: rgba(10, 37, 64, 0.2);
  }

  .app-shell[data-theme],
  [data-theme] .app-shell {
    --shell-bg: var(--bg);
    --shell-panel: var(--panel);
    --shell-panel-solid: var(--panel-solid);
    --shell-line: var(--line);
    --shell-line-soft: var(--line);
    --shell-tx: var(--tx);
    --shell-tx2: var(--tx3);
    --shell-hover: var(--brand-tint);
    --shell-accent: var(--brand-tx);
    --shell-cta: var(--brand);
    --shell-cta-hover: var(--brand);
    --shell-cta-ink: var(--brand-ink);
    --shell-footer-bg: var(--panel-2);
    --shell-footer-line: var(--line);
    --shell-ring: var(--brand-glow);
  }

  /* ══════════════════════════════════════════════════════════════
     SUMMIT THEME TOKENS — participant side only.
     Values are verbatim from design/previews/trailreg-B-summit.html,
     which is the canonical colour source for this skin.

     The attribute selector (not :root) is deliberate: the theme is
     scoped to a participant-only wrapper so /admin/* and /community/*
     keep the moss/rust console palette. See Layout.jsx <main>.

     --brand-tx exists separately from --brand because the bright ember
     (#ff6b2c) only reaches ~2.6:1 on a light background. Fills use
     --brand; text uses --brand-tx. Do not collapse them.
     ══════════════════════════════════════════════════════════════ */
  [data-theme="dark"] {
    --bg: #080c0b;
    --grad-1: rgba(255, 107, 44, 0.13);
    --grad-2: rgba(47, 214, 139, 0.10);
    --panel: rgba(18, 27, 25, 0.72);
    --panel-2: rgba(24, 36, 34, 0.60);
    --panel-solid: #121b19;
    --panel-shadow: none;
    --line: rgba(185, 200, 195, 0.12);
    --line-2: rgba(185, 200, 195, 0.22);
    --tx: #f4f7f6;
    --tx2: #b9c8c3;
    --tx3: #8ba09a;
    /* Lifted from the prototype's #65807a: that measured 4.11:1 on --panel-solid,
       under the 4.5 AA floor for the hints and meta text this level carries. */
    --tx4: #6e8782;
    --brand: #ff6b2c;
    --brand-tx: #ff8d5e;
    --brand-ink: #0b0f0e;
    --brand-glow: rgba(255, 107, 44, 0.35);
    --brand-tint: rgba(255, 107, 44, 0.07);
    --ok: #5ce7a8;
    --ok-tx: #5ce7a8;
    --ok-line: rgba(92, 231, 168, 0.5);
    --ok-tint: rgba(92, 231, 168, 0.09);
    --danger: #ff5a52;
    --danger-tx: #ff8f88;
    /* White on the bright red is 3.07:1; the near-black ink is 6.28:1. */
    --danger-ink: #0b0f0e;
    --danger-line: rgba(255, 90, 82, 0.5);
    --danger-tint: rgba(255, 90, 82, 0.1);
    --field: rgba(8, 12, 11, 0.65);
    /* Control boundaries carry a heavier line than decorative hairlines. The field
       fill sits only ~1.05:1 from the panel, so the border is the only thing
       identifying an input, and WCAG 1.4.11 asks 3:1 of it. --line-2 gives 1.65:1. */
    --field-line: rgba(185, 200, 195, 0.45);
    --track: rgba(185, 200, 195, 0.14);
    --ridge-1: #0d1413;
    --ridge-2: #121b19;
    --ridge-op: 0.5;
    --hero-veil: 0.86;
  }

  [data-theme="light"] {
    --bg: #f2f5f4;
    --grad-1: rgba(207, 71, 17, 0.10);
    --grad-2: rgba(20, 108, 60, 0.09);
    --panel: rgba(255, 255, 255, 0.88);
    --panel-2: #eaefed;
    --panel-solid: #ffffff;
    --panel-shadow: 0 1px 2px rgba(11, 22, 20, 0.04), 0 12px 28px -18px rgba(11, 22, 20, 0.22);
    --line: rgba(13, 30, 26, 0.13);
    --line-2: rgba(13, 30, 26, 0.24);
    --tx: #0b1614;
    --tx2: #3b4f4a;
    /* Darkened alongside --tx4: lifting --tx4 to AA closed the gap between the two
       levels to 0.01:1, which inverted the ladder. --tx3 has to stay clearly
       stronger than the level below it. */
    --tx3: #51635e;
    /* Darkened from the prototype's #6b7d77, which measured 3.74:1 on --panel-2.
       This is the drift the plan predicted for --tx4 on light. */
    --tx4: #5f6f6a;
    --brand: #cf4711;
    --brand-tx: #a8380c;
    --brand-ink: #ffffff;
    --brand-glow: rgba(207, 71, 17, 0.26);
    --brand-tint: rgba(207, 71, 17, 0.07);
    --ok: #0f8a56;
    --ok-tx: #0b6e44;
    --ok-line: rgba(15, 138, 86, 0.45);
    --ok-tint: rgba(15, 138, 86, 0.08);
    --danger: #c02617;
    --danger-tx: #9c1409;
    --danger-ink: #ffffff;
    --danger-line: rgba(192, 38, 23, 0.45);
    --danger-tint: rgba(192, 38, 23, 0.07);
    --field: #ffffff;
    /* See the dark note: the field fill is ~1.01:1 from the panel here. */
    --field-line: rgba(13, 30, 26, 0.49);
    --track: rgba(13, 30, 26, 0.12);
    --ridge-1: #dee6e2;
    --ridge-2: #e9efec;
    --ridge-op: 0.85;
    --hero-veil: 0.72;
  }

}

@layer components {
  .link-primary {
    @apply font-medium text-primary-500 hover:text-primary-600 hover:underline;
  }
  .card-flat {
    @apply rounded-lg border border-[#e6ebf1] bg-white shadow-flat;
  }
  .card-flat-md {
    @apply rounded-lg border border-[#e6ebf1] bg-white shadow-flat-md;
  }

  /* TrailLoader.jsx — SVGator scene in public/trail-loader.svg (<object>) */
  .trail-loader {
    @apply items-center justify-center;
  }

  /* Grow with Layout <main flex-1> so we can center in the full column under the header. */
  .trail-loader--page {
    @apply flex w-full max-w-full min-h-0 min-w-0 flex-1 items-center justify-center py-10;
  }

  .trail-loader__frame {
    @apply inline-flex flex-col items-center gap-1;
  }

  .trail-loader__brand {
    @apply text-[0.65rem] font-bold tracking-[0.12em] text-gray-900;
    font-family: system-ui, sans-serif;
  }

  /* Summit: the label follows the theme. The SVG itself still needs recolouring — Phase 4. */
  [data-theme] .trail-loader__brand { color: var(--tx3); }

  .trail-loader__object {
    display: block;
    border: 0;
    aspect-ratio: 2740 / 1568;
    pointer-events: none;
    /* Hide top & bottom 10% of the SVG frame (viewBox) */
    clip-path: inset(15% 0 15% 0);
  }

  .trail-loader--page .trail-loader__object {
    width: 150px;
    max-width: 100%;
  }

  /* ── Organizer console ── */
  .font-display {
    font-family: 'Fraunces', Georgia, serif;
    font-optical-sizing: auto;
    letter-spacing: -0.01em;
  }

  /* Topographic line backgrounds */
  .topo {
    background-color: #faf7f2;
    background-image:
      radial-gradient(1200px 600px at 10% -10%, rgba(45,90,63,0.08), transparent 60%),
      radial-gradient(900px 500px at 110% 10%, rgba(179,83,31,0.06), transparent 55%),
      url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='600' height='600'><defs><pattern id='t' width='600' height='600' patternUnits='userSpaceOnUse'><g fill='none' stroke='%233a2e1f' stroke-opacity='0.05' stroke-width='1'><path d='M0 80 C 150 30, 300 130, 600 60'/><path d='M0 160 C 180 100, 320 210, 600 140'/><path d='M0 240 C 160 180, 340 300, 600 220'/><path d='M0 320 C 200 260, 360 380, 600 300'/><path d='M0 400 C 170 340, 380 460, 600 380'/><path d='M0 480 C 190 420, 360 540, 600 460'/><path d='M0 560 C 160 500, 340 600, 600 540'/></g></pattern></defs><rect width='100%' height='100%' fill='url(%23t)'/></svg>");
    background-repeat: no-repeat, no-repeat, repeat;
  }

  .topo-dark {
    background-color: #142a22;
    background-image:
      radial-gradient(800px 400px at 0% 0%, rgba(255,255,255,0.04), transparent 60%),
      url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='600' height='600'><defs><pattern id='t' width='600' height='600' patternUnits='userSpaceOnUse'><g fill='none' stroke='%23ffffff' stroke-opacity='0.04' stroke-width='1'><path d='M0 80 C 150 30, 300 130, 600 60'/><path d='M0 160 C 180 100, 320 210, 600 140'/><path d='M0 240 C 160 180, 340 300, 600 220'/><path d='M0 320 C 200 260, 360 380, 600 300'/><path d='M0 400 C 170 340, 380 460, 600 380'/><path d='M0 480 C 190 420, 360 540, 600 460'/></g></pattern></defs><rect width='100%' height='100%' fill='url(%23t)'/></svg>");
  }

  /* Hairline borders */
  .hairline { border-color: rgba(58,46,31,.09); }

  /* Nav item in dark sidebar */
  .org-nav-item { position: relative; transition: all .15s ease; }
  .org-nav-item.active { background: rgba(255,255,255,.08); color: #ffffff; }
  .org-nav-item.active::before {
    content: "";
    position: absolute;
    left: 0; top: 8px; bottom: 8px;
    width: 3px;
    background: #cb6e33;
    border-radius: 0 3px 3px 0;
  }

  /* KPI card left-border accents */
  .accent-moss { box-shadow: inset 3px 0 0 #2d5a3f, 0 1px 2px rgba(24,20,12,.04), 0 8px 24px -12px rgba(24,20,12,.08); }
  .accent-rust { box-shadow: inset 3px 0 0 #b3531f, 0 1px 2px rgba(24,20,12,.04), 0 8px 24px -12px rgba(24,20,12,.08); }
  .accent-tan  { box-shadow: inset 3px 0 0 #b6a891, 0 1px 2px rgba(24,20,12,.04), 0 8px 24px -12px rgba(24,20,12,.08); }

  /* Map/course hero gradient */
  .map-hero {
    background:
      linear-gradient(180deg, rgba(20,42,34,.1), rgba(20,42,34,.55)),
      radial-gradient(600px 280px at 20% 30%, rgba(95,153,89,.5), transparent 60%),
      radial-gradient(500px 280px at 80% 70%, rgba(203,110,51,.35), transparent 60%),
      url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 800 300'><defs><pattern id='c' width='800' height='300' patternUnits='userSpaceOnUse'><g fill='none' stroke='%23ffffff' stroke-opacity='0.22' stroke-width='1.2'><path d='M0 50 C 200 10, 400 90, 800 20'/><path d='M0 100 C 220 60, 440 140, 800 80'/><path d='M0 150 C 190 110, 420 200, 800 140'/><path d='M0 200 C 210 160, 460 250, 800 200'/><path d='M0 250 C 200 220, 430 280, 800 250'/></g><path d='M100 220 C 200 150, 320 260, 440 180 S 680 200, 760 120' fill='none' stroke='%23cb6e33' stroke-width='3' stroke-dasharray='6 6'/><circle cx='100' cy='220' r='6' fill='%23cb6e33'/><circle cx='760' cy='120' r='6' fill='%232d5a3f' stroke='%23ffffff' stroke-width='2'/></pattern></defs><rect width='100%' height='100%' fill='url(%23c)'/></svg>") center/cover;
    background-color: #1d3a2c;
  }

  /* Inline pill badge */
  .org-pill {
    display: inline-flex;
    align-items: center;
    gap: .375rem;
    padding: .125rem .5rem;
    border-radius: 9999px;
    font-size: .72rem;
    font-weight: 600;
    letter-spacing: .02em;
  }

  /* Segmented control */
  .org-seg button { transition: all .15s; }
  .org-seg button.active { background: #ffffff; box-shadow: 0 1px 2px rgba(24,20,12,.08); color: #142a22; }

  /* Logo mark */
  .org-mark { display: inline-flex; align-items: center; gap: .5rem; }
  .org-mark-ico {
    width: 30px; height: 30px;
    border-radius: 9px;
    background: linear-gradient(135deg, #2d5a3f, #5e9959 70%, #cb6e33);
    display: grid; place-items: center;
    box-shadow: inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(24,20,12,.15);
  }

  /* ══════════════════════════════════════════════════════════════
     SUMMIT COMPONENTS — participant side only.
     These are the classes the participant JSX uses in place of the
     stone-* utility strings. Ported from the prototype's bare-element
     rules; deliberately class-scoped so nothing leaks into /admin/*.
     ══════════════════════════════════════════════════════════════ */

  /* text levels */
  .t1 { color: var(--tx); }
  .t2 { color: var(--tx2); }
  .t3 { color: var(--tx3); }
  .t4 { color: var(--tx4); }
  .brandtx { color: var(--brand-tx); }
  .oktx { color: var(--ok-tx); }

  /* plain surfaces — for markup that is not a full .reg-card */
  .surf { background-color: var(--panel-solid); }
  .surf-2 { background-color: var(--panel-2); }
  .surf-bg { background-color: var(--bg); }
  .surf-field { background-color: var(--field); }

  /* hairlines */
  .hair { border-color: var(--line); }
  .hair-t { border-top: 1px solid var(--line); }

  /* page canvas */
  .reg-surface {
    background:
      radial-gradient(900px 500px at 12% -6%, var(--grad-1), transparent 62%),
      radial-gradient(760px 460px at 96% 4%, var(--grad-2), transparent 58%),
      var(--bg);
    color: var(--tx2);
    transition: background-color 0.3s ease;
  }

  /* surfaces */
  .reg-card {
    background: var(--panel);
    border: 1px solid var(--line);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    box-shadow: var(--panel-shadow);
  }
  .reg-card-2 {
    background: var(--panel-2);
    border: 1px solid var(--line);
  }

  .reg-link { color: var(--tx3); }
  .reg-link:hover { color: var(--brand-tx); }

  /* ── event hero ── */
  .reg-hero { background: var(--bg); }

  /* Scrim over an organizer's photo. Weighted to the bottom, where the headline sits,
     and sized for a bright busy image rather than a flattering one. */
  .reg-hero-veil {
    background:
      linear-gradient(180deg, rgba(4, 8, 7, 0.42) 0%, rgba(4, 8, 7, 0.62) 55%, rgba(4, 8, 7, var(--hero-veil)) 100%),
      radial-gradient(700px 320px at 18% 108%, var(--brand-glow), transparent 66%);
  }

  /* No banner — the common case. A generated plate, not an empty box. */
  .reg-hero-plain {
    background:
      radial-gradient(700px 320px at 20% 110%, var(--brand-glow), transparent 65%),
      linear-gradient(180deg, transparent, var(--bg) 96%);
  }

  /* Type sits on the photo in both themes, so it stays light there regardless. The
     shadow is what carries the small text over a bright, busy upload — the scrim
     alone is not enough for the kicker, which sits high where the scrim is weakest. */
  .on-photo .reg-hero-body { text-shadow: 0 1px 3px rgba(4, 8, 7, 0.85), 0 0 18px rgba(4, 8, 7, 0.55); }
  .on-photo .reg-hero-body .t1 { color: #f4f7f6; }
  .on-photo .reg-hero-body .t3 { color: rgba(244, 247, 246, 0.9); }
  .on-photo .reg-hero-body .brandtx { color: #ffc4a8; }

  /* sticky mobile action bar */
  .reg-sticky-bar {
    background: color-mix(in srgb, var(--bg) 92%, transparent);
    border-color: var(--line);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
  }

  /* elevation-profile progress line */
  .reg-climb { transition: stroke-dashoffset 0.5s cubic-bezier(0.2, 0.8, 0.3, 1); }
  @media (prefers-reduced-motion: reduce) {
    .reg-climb { transition: none; }
  }

  /* result-card header: a brand plate, so its type is always light on both themes */
  .reg-medal-plate {
    background: linear-gradient(135deg, var(--brand), color-mix(in srgb, var(--brand) 55%, #000));
    color: var(--brand-ink);
  }

  /* Organizer-uploaded imagery — event logos, header logos, sponsor logos. Most are
     PNGs drawn for a white page, either with a white box or a transparent
     background, so on dark they either halo or disappear. Rather than guess per
     image (invert wrecks colour logos; a filter wrecks photographs), sit them on a
     neutral chip in dark mode only. Light mode is untouched, which is also the
     safe default for the many events that never see the dark skin. */
  .reg-logo-chip { display: inline-flex; border-radius: 0.6rem; }
  [data-theme="dark"] .reg-logo-chip {
    background: #f4f7f6;
    padding: 0.5rem 0.75rem;
    box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.3);
  }

  /* Our own logo mark is flat black artwork, so inverting it is safe and is already
     the established approach here for white-label headers. */
  [data-theme="dark"] .shell-logo-mark { filter: invert(1); }

  /* Waiver PDFs. The pages are white paper with black type — that is the document,
     not our styling, and cannot be themed. So on dark we frame them deliberately:
     a lifted tray holding what read as sheets, rather than a bare white rectangle
     dropped on black. */
  .reg-paper-tray {
    background: var(--panel-2);
    border: 1px solid var(--line);
  }
  .reg-paper-page {
    background: #ffffff;
    border: 1px solid rgba(13, 30, 26, 0.18);
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.28), 0 12px 32px -14px rgba(0, 0, 0, 0.5);
  }

  /* modals */
  .reg-scrim { background: rgba(4, 8, 7, 0.62); backdrop-filter: blur(2px); -webkit-backdrop-filter: blur(2px); }
  .reg-modal {
    background: var(--panel-solid);
    border: 1px solid var(--line);
    box-shadow: 0 32px 80px -30px rgba(0, 0, 0, 0.6);
  }
  .reg-avatar { background: var(--brand); color: var(--brand-ink); }

  /* selectable category card */
  .reg-pick {
    transition:
      transform 0.18s cubic-bezier(0.2, 0.8, 0.3, 1),
      border-color 0.18s,
      box-shadow 0.18s,
      background 0.18s;
  }
  .reg-pick:hover:not(.is-disabled) {
    transform: translateY(-3px);
    border-color: var(--line-2);
  }
  .reg-pick.is-on {
    border-color: var(--brand);
    background: var(--brand-tint);
    box-shadow: 0 0 0 1px var(--brand), 0 18px 44px -22px var(--brand-glow);
  }
  .reg-pick.is-disabled { opacity: 0.42; }

  /* form controls */
  .reg-input {
    background: var(--field);
    border: 1px solid var(--field-line);
    border-radius: 0.7rem;
    color: var(--tx);
  }
  .reg-input::placeholder { color: var(--tx4); }
  .reg-input:focus {
    border-color: var(--brand);
    --tw-ring-color: transparent;
    box-shadow: 0 0 0 3px var(--brand-glow);
    outline: none;
  }
  .reg-input option {
    background: var(--panel-solid);
    color: var(--tx);
  }
  /* composite field (phone: country selector + number share one border) */
  .reg-field-group {
    background: var(--field);
    border: 1px solid var(--field-line);
    border-radius: 0.7rem;
    color: var(--tx);
  }
  .reg-field-group:focus-within {
    border-color: var(--brand);
    box-shadow: 0 0 0 3px var(--brand-glow);
  }
  .reg-field-group.is-invalid { border-color: var(--danger); }
  .reg-field-group.is-invalid:focus-within {
    border-color: var(--danger);
    box-shadow: 0 0 0 3px var(--danger-tint);
  }
  .reg-affix {
    border-right: 1px solid var(--line);
    background: var(--panel-2);
    color: var(--tx2);
  }

  .reg-input.is-locked {
    background: var(--panel-2);
    color: var(--tx3);
  }

  .reg-check {
    border-color: var(--field-line);
    background: var(--field);
    color: var(--brand);
  }
  .reg-check:focus {
    border-color: var(--brand);
    --tw-ring-color: transparent;
    box-shadow: 0 0 0 3px var(--brand-glow);
    outline: none;
  }

  /* buttons */
  .reg-btn {
    background: var(--brand);
    color: var(--brand-ink);
    transition: transform 0.14s, box-shadow 0.16s, filter 0.14s;
    box-shadow: 0 10px 30px -12px var(--brand-glow);
  }
  .reg-btn:hover:not(:disabled) {
    transform: translateY(-2px);
    box-shadow: 0 18px 40px -14px var(--brand-glow);
    filter: brightness(1.06);
  }
  .reg-btn:active:not(:disabled) { transform: translateY(0); }
  .reg-btn:disabled {
    opacity: 0.38;
    transform: none;
    box-shadow: none;
    cursor: not-allowed;
  }
  .reg-btn-ghost {
    border: 1px solid var(--field-line);
    color: var(--tx2);
    background: transparent;
    transition: 0.15s;
  }
  .reg-btn-ghost:hover:not(:disabled) {
    border-color: var(--brand);
    color: var(--tx);
    background: var(--brand-tint);
  }
  .reg-btn-ghost:disabled { opacity: 0.38; cursor: not-allowed; }

  .dangertx { color: var(--danger-tx); }

  /* validation + alert surfaces */
  .reg-input.is-invalid { border-color: var(--danger); }
  .reg-input.is-invalid:focus { box-shadow: 0 0 0 3px var(--danger-tint); border-color: var(--danger); }
  .reg-alert {
    border: 2px solid var(--danger-line);
    background: var(--danger-tint);
    color: var(--danger-tx);
  }
  .reg-note {
    border: 1px solid var(--line);
    background: var(--panel-2);
    color: var(--tx2);
  }
  .reg-ok {
    border: 1px solid var(--ok-line);
    background: var(--ok-tint);
    color: var(--ok-tx);
  }

  /* dropdown listbox (country / city-state comboboxes, profile picker) */
  .reg-listbox {
    background: var(--panel-solid);
    border: 1px solid var(--field-line);
    border-radius: 0.7rem;
    box-shadow: 0 18px 44px -22px rgba(0, 0, 0, 0.55);
  }
  .reg-option { color: var(--tx2); }
  .reg-option:hover { background: var(--brand-tint); color: var(--tx); }
  .reg-option.is-active { background: var(--brand-tint); color: var(--tx); }
  .reg-option.is-selected { background: var(--brand-tint); color: var(--brand-tx); font-weight: 600; }

  /* +/- stepper */
  .reg-qty {
    width: 34px;
    height: 34px;
    border-radius: 0.55rem;
    border: 1px solid var(--field-line);
    background: var(--field);
    color: var(--tx2);
    font-weight: 600;
  }
  .reg-qty:hover:not(:disabled) {
    border-color: var(--brand);
    color: var(--brand-tx);
  }
  .reg-qty:disabled { opacity: 0.38; cursor: not-allowed; }

  /* Sign in with Apple: Apple's guidelines allow a black or a white button, so
     invert with the theme rather than pinning one and losing it on the other. */
  .reg-btn-apple {
    background: var(--tx);
    color: var(--bg);
    border-color: var(--tx);
  }
  .reg-btn-apple:hover { filter: brightness(1.12); }

  /* destructive action (remove registrant, discard cart) */
  .reg-btn-danger {
    background: var(--danger);
    color: var(--danger-ink);
    transition: filter 0.14s;
  }
  .reg-btn-danger:hover:not(:disabled) { filter: brightness(1.08); }
  .reg-btn-danger:disabled { opacity: 0.38; cursor: not-allowed; }

  /* inline "x" that removes a row */
  .reg-remove { color: var(--tx4); transition: color 0.14s, background 0.14s; }
  .reg-remove:hover:not(:disabled) { color: var(--danger-tx); background: var(--danger-tint); }

  /* unselected radio/check ring */
  .reg-radio-off { border-color: var(--field-line); }

  /* quantity stepper shell */
  .reg-stepper { border: 1px solid var(--field-line); background: var(--field); }

  /* capacity bar */
  .reg-meter {
    height: 6px;
    border-radius: 999px;
    background: var(--track);
    overflow: hidden;
    display: flex;
  }

  /* condensed display type */
  .reg-display {
    font-family: 'Barlow Condensed', 'Inter var', Inter, sans-serif;
    letter-spacing: 0.01em;
  }
  .reg-headline {
    font-family: 'Barlow Condensed', 'Inter var', Inter, sans-serif;
    text-transform: uppercase;
    font-weight: 700;
    letter-spacing: 0.02em;
    line-height: 0.95;
  }
  .reg-kicker {
    font-family: 'JetBrains Mono', ui-monospace, monospace;
    font-size: 0.62rem;
    letter-spacing: 0.2em;
    text-transform: uppercase;
  }
  .reg-tick { font-variant-numeric: tabular-nums; }

  /* motion */
  .reg-fade-in { animation: reg-fade-in 0.38s cubic-bezier(0.2, 0.8, 0.3, 1) both; }
  @keyframes reg-fade-in {
    from { opacity: 0; transform: translateY(12px); }
    to { opacity: 1; transform: none; }
  }
  .reg-pulse { animation: reg-pulse 2.4s ease-in-out infinite; }
  @keyframes reg-pulse {
    0%, 100% { box-shadow: 0 0 0 0 var(--brand-glow); }
    50% { box-shadow: 0 0 0 7px transparent; }
  }

  @media (prefers-reduced-motion: reduce) {
    .reg-pick,
    .reg-pick:hover:not(.is-disabled),
    .reg-btn,
    .reg-btn:hover:not(:disabled),
    .reg-btn:active:not(:disabled) {
      transform: none;
      transition: none;
    }
    .reg-fade-in,
    .reg-pulse { animation: none; }
    /* Capacity meter fills animate their width, which is motion. The utility that
       drives it lives in the utilities layer, so this needs !important to win. */
    .reg-meter > * { transition: none !important; }
  }

  /* ── app shell (header/footer, shared with /admin/*) ── */
  .shell-surface { background-color: var(--shell-bg); color: var(--shell-tx); }
  .shell-header { background-color: var(--shell-panel); border-color: var(--shell-line); }
  .shell-hair { border-color: var(--shell-line); }
  .shell-hair-soft { border-color: var(--shell-line-soft); }
  .shell-tx { color: var(--shell-tx); }
  .shell-muted { color: var(--shell-tx2); }

  .shell-link { color: var(--shell-tx2); }
  .shell-link:hover { color: var(--shell-accent); }
  .shell-strong-link { color: var(--shell-tx); }
  .shell-strong-link:hover { color: var(--shell-accent); }

  .shell-menu {
    background-color: var(--shell-panel-solid);
    border-color: var(--shell-line);
  }
  .shell-menu-item { color: var(--shell-tx); }
  .shell-menu-item:hover { background-color: var(--shell-hover); }

  .shell-btn {
    border-color: var(--shell-line);
    background-color: var(--shell-panel-solid);
    color: var(--shell-tx);
  }
  .shell-btn:hover { background-color: var(--shell-hover); }
  .shell-btn:focus-visible { outline: none; box-shadow: 0 0 0 2px var(--shell-ring); }

  .shell-cta { background-color: var(--shell-cta); color: var(--shell-cta-ink); }
  .shell-cta:hover { background-color: var(--shell-cta-hover); filter: brightness(1.06); }

  .shell-footer-link { color: var(--shell-tx2); }
  .shell-footer-link:hover { color: var(--shell-tx); }

  .shell-footer {
    background-color: var(--shell-footer-bg);
    border-color: var(--shell-footer-line);
  }

  /* transparent bordered icon button (hamburger, theme toggle) */
  .shell-ghost-btn {
    border-color: var(--shell-line);
    color: var(--shell-tx2);
    background-color: transparent;
  }
  .shell-ghost-btn:hover { color: var(--shell-tx); background-color: var(--shell-hover); }
  .shell-ghost-btn:focus-visible { outline: none; box-shadow: 0 0 0 2px var(--shell-ring); }
}

