* { margin: 0; padding: 0; box-sizing: border-box; }

html {
  scroll-behavior: smooth;
}

body {
  background-color: #0a0806;
  /* Plain black. The suede lives only behind the feature text blocks
     (.page.feature, below) — Red, 2026-09-05. */
  color: #f2ede6;
  font-family: "Archivo Narrow", "Arial Narrow", "Helvetica Neue", Arial, sans-serif;
  overflow-x: hidden;
}
html { overflow-x: hidden; }

/* ---- chrome wordmark (Red, 2026-09-05: live-text liquid chrome) ----
   Replaces the baked giro-wordmark-chrome.png (BLUE's render read as flat
   grey in a different face - Red: "does not look good"). The wordmark is
   real text again in the site's own heavy condensed face (Archivo Narrow,
   now actually loaded in index.html) and scales with the viewport.
   The chrome is a steep multi-band gradient clipped to the glyphs; its
   angle AND position are driven by two unitless custom properties
   --chrome-x / --chrome-y (0-100) that main.js feeds from the pointer on
   desktop and from scroll progress on touch devices, so the reflection
   moves with you; a slow wander keeps it alive when nothing moves.
   Base CSS from Red's Copilot snippet; adapted to the h1 sizing here. */
:root {
  --chrome-x: 50; --chrome-y: 50;
  --g1x: 30; --g1y: 40; --g2x: 70; --g2y: 60; --d1x: 50; --d1y: 80;
}
.chrome-text {
  /* Four layers, all clipped to the glyphs. Top→bottom: two soft white
     glints and one dark pool that each wander their own squiggly path
     (positions from main.js), then the base metal band gradient whose
     angle + position also move. The glints are what make the reflection
     read as "a little bit here, a little bit there" (Red) rather than one
     band sweeping through. */
  background-image:
    radial-gradient(ellipse 26% 70% at calc(var(--g1x) * 1%) calc(var(--g1y) * 1%),
      rgba(255,255,255,0.95) 0%, rgba(255,255,255,0.35) 35%, rgba(255,255,255,0) 70%),
    radial-gradient(ellipse 16% 45% at calc(var(--g2x) * 1%) calc(var(--g2y) * 1%),
      rgba(255,255,255,0.85) 0%, rgba(255,255,255,0) 70%),
    radial-gradient(ellipse 34% 55% at calc(var(--d1x) * 1%) calc(var(--d1y) * 1%),
      rgba(18,20,24,0.85) 0%, rgba(18,20,24,0) 70%),
    linear-gradient(
      calc(96deg + (var(--chrome-x) - 50) * 0.9deg),
      #4a4c52 0%,
      #e6e7ea 14%,
      #ffffff 24%,
      #a4a6ac 38%,
      #23252a 50%,
      #a4a6ac 60%,
      #ffffff 74%,
      #e6e7ea 84%,
      #4a4c52 100%
    );
  background-size: 100% 100%, 100% 100%, 100% 100%, 260% 260%;
  background-position: 0 0, 0 0, 0 0, calc(var(--chrome-x) * 1%) calc(var(--chrome-y) * 1%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  text-shadow: none;
  /* No CSS animation or transition here: main.js eases the two steering
     values every frame (mouse on desktop, scroll distance on touch, plus a
     slow wander), so CSS smoothing would only add lag on top. */
  /* Own compositing layer: the per-frame repaint of the clipped text must
     not drag the video/suede behind it into the repaint. */
  transform: translateZ(0);
  filter:
    drop-shadow(0 1px 0 rgba(255,255,255,0.45))
    drop-shadow(0 -1px 0 rgba(20,20,24,0.7))
    drop-shadow(0 8px 26px rgba(230,231,234,0.22));
}
/* Touch devices: no blurred shadows. Blurring a re-rasterised clipped text
   every frame is what made iOS Safari run out of memory at the closer
   ("a problem repeatedly occurred", Red 2026-09-05). The chrome layers
   carry the look on their own. */
@media (hover: none) {
  .chrome-text { filter: none; }
}
/* Section titles wear the same chrome; hover-slide transforms on
   .tease-text still apply since the h2 sits inside it. */
.tease h2.chrome-text { color: transparent; }
/* Reduced motion: main.js leaves the values at 50/50 — a static gradient. */

/* Reused by .num / .tease-desc below. */
@keyframes chromeShine {
  0%   { background-position: 130% 0; }
  60%  { background-position: -60% 0; }
  100% { background-position: -60% 0; }
}

/* ---- top bar (BLUE, 2026-09-05) ----
   Thin fixed strip, always on top of the page stack. Grid keeps the G
   logo TRULY centered regardless of how wide "About Us" / "Contact Us"
   end up being on either side. Both links are inert on purpose — BLUE:
   "neither will do anything yet." */
.topbar {
  position: fixed;
  top: 0; left: 0; right: 0;
  height: 32px;
  z-index: 150;
  background: #000;
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  padding: 0 14px;
}
.topbar-mark-link { grid-column: 2; justify-self: center; display: block; line-height: 0; }
.topbar-mark { height: 20px; width: auto; display: block; }

/* ---- hamburger + drawer (Red, 2026-09-05) ----
   Two lines, right end of the bar. Click: lines fold into an X and the
   drawer slides in from the right over a dimmed page. */
.menu-btn {
  grid-column: 3; justify-self: end;
  width: 34px; height: 32px;
  background: none; border: 0; padding: 0; cursor: pointer;
  display: flex; flex-direction: column; justify-content: center; align-items: flex-end; gap: 6px;
}
.menu-btn span {
  display: block; width: 22px; height: 2px;
  background: rgba(242, 237, 230, 0.85);
  transition: transform 260ms cubic-bezier(.2,.7,.2,1), width 200ms, opacity 200ms;
}
.menu-btn span:nth-child(2) { width: 16px; }
.menu-btn:hover span { background: #fff; }
html.menu-open .menu-btn span:nth-child(1) { transform: translateY(4px) rotate(45deg); }
html.menu-open .menu-btn span:nth-child(2) { width: 22px; transform: translateY(-4px) rotate(-45deg); }

.scrim {
  position: fixed; inset: 0; z-index: 200;
  background: rgba(6, 5, 4, 0.62);
  backdrop-filter: blur(2px); -webkit-backdrop-filter: blur(2px);
  /* The dim FADES with the drawer, both ways (Red, 2026-09-15: the menu was
     "choppier" on the phone). It used to be shown and set to full in the
     same instant, so a phone had to draw a full-screen blur from nothing on
     the slide's first frame - a hitch right where the motion starts - and
     on close it blinked off while the drawer was still sliding out. Now it
     is never display:none: visibility waits for the fade, like the drawer. */
  opacity: 0; visibility: hidden;
  transition: opacity 340ms, visibility 0s linear 340ms;
}
html.menu-open .scrim, html.panel-open .scrim {
  opacity: 1; visibility: visible;
  transition: opacity 340ms, visibility 0s;
}

.drawer {
  position: fixed; top: 0; right: 0; bottom: 0; z-index: 210;
  width: min(84vw, 360px);
  background: #0a0806;
  border-left: 1px solid rgba(242, 237, 230, 0.08);
  display: flex; flex-direction: column;
  padding: 72px 32px 28px;
  transform: translateX(100%);
  /* closing: keep the panel visible until the slide-out has finished (the
     old rule hid it on the first frame, so the drawer only ever vanished) */
  transition: transform 340ms cubic-bezier(.2,.7,.2,1), visibility 0s linear 340ms;
  visibility: hidden;
  will-change: transform;
}
html.menu-open .drawer { transform: translateX(0); visibility: visible; transition: transform 340ms cubic-bezier(.2,.7,.2,1), visibility 0s; }
.drawer-nav { display: flex; flex-direction: column; gap: 22px; }
.drawer-link {
  font-size: clamp(1.4rem, 5vw, 1.8rem);
  font-weight: 800; font-stretch: condensed;
  letter-spacing: 0.12em; text-transform: uppercase;
  color: #f2ede6; text-decoration: none;
  /* opacity is IN the transition list now (Red, 2026-09-15): it was left out
     since 09-05, so each link jumped from invisible to full in one frame at
     its delay and only the last 24px slid - the "boom boom boom" he heard
     on the phone. Now each link fades while it slides. */
  transition: color 160ms, transform 260ms cubic-bezier(.2,.7,.2,1), opacity 260ms cubic-bezier(.2,.7,.2,1);
  transform: translateX(24px); opacity: 0;
  /* Layers up front (Red, 2026-09-15: EVENTS SAVED MESSAGES BUILDS SETTINGS
     HOME went "boom boom boom" on the phone). Without this, each link was
     drawn onto its own layer the moment ITS delayed slide began - six
     rasterisations of big condensed text, 55 ms apart, in the middle of the
     drawer's slide - one hitch per link. With it, the layers exist before the
     menu opens and the slide only moves cheap layers. Six small text layers +
     one row: cheap. (The icons inside .drawer-socials stay unpromoted on touch,
     see .chrome-icon - the row fades as one layer above them.) */
  will-change: transform, opacity;
}
html.menu-open .drawer-link { transform: none; opacity: 1; }
/* The links ride in AFTER the panel (Red, 2026-09-14: "slide in with it, a little
   delayed"). The panel takes 340ms; the old delays (60/110/160ms) put the first
   two links in place before the panel had even arrived, so only the third —
   ABOUT US — was ever caught moving. Now every link starts once the panel is
   most of the way in and lands after it, one after the other. Six steps: the
   account page's menu has six links. */
html.menu-open .drawer-link:nth-child(1) { transition-delay: 200ms; }
html.menu-open .drawer-link:nth-child(2) { transition-delay: 255ms; }
html.menu-open .drawer-link:nth-child(3) { transition-delay: 310ms; }
html.menu-open .drawer-link:nth-child(4) { transition-delay: 365ms; }
html.menu-open .drawer-link:nth-child(5) { transition-delay: 420ms; }
html.menu-open .drawer-link:nth-child(6) { transition-delay: 475ms; }
html.menu-open .drawer-link:nth-child(7) { transition-delay: 530ms; }
html.menu-open .drawer-link:nth-child(8) { transition-delay: 585ms; }
html.menu-open .drawer-link:nth-child(9) { transition-delay: 640ms; }
html.menu-open .drawer-link:nth-child(10) { transition-delay: 695ms; }
html.menu-open .drawer-link:nth-child(11) { transition-delay: 750ms; }
html.menu-open .drawer-link:nth-child(12) { transition-delay: 805ms; }
/* the stagger ran out at six (Red, 2026-09-22 ~04:10: 'some of the things in the hamburger
   menu don't have that sliding animation') — the account page's drawer had more links than
   that, and the seventh onward popped in with no delay. Twelve covers every drawer we have. */
.drawer-link:hover { color: #fff; }
.drawer-socials { display: flex; gap: 22px; margin-top: 40px; opacity: 0; transition: opacity 320ms; will-change: opacity; }
html.menu-open .drawer-socials { opacity: 1; transition-delay: 420ms; }
@media (prefers-reduced-motion: reduce) {
  .drawer-link, .drawer-socials { transition: none; transform: none; opacity: 1; }
}
.drawer-foot { margin-top: auto; }
.signin-btn {
  display: block; box-sizing: border-box; text-align: center; text-decoration: none;
  width: 100%;
  padding: 14px 18px;
  background: #f2ede6; color: #0a0806;
  border: 0; cursor: pointer;
  font: inherit; font-size: 0.82rem; font-weight: 800;
  letter-spacing: 0.28em; text-transform: uppercase;
  transition: background 160ms;
}
.signin-btn:hover { background: #fff; }
.drawer-note { margin: 12px 0 0; font-size: 0.68rem; letter-spacing: 0.18em; text-transform: uppercase; color: rgba(242, 237, 230, 0.5); text-align: center; }
/* signed-in menu bottom (Red, 2026-09-07): face + name + @handle above the
   button, a quiet sign-out under it. Painted by session.js. */
.drawer-user { display: flex; align-items: center; gap: 12px; margin: 0 0 16px; }
.drawer-avatar { width: 40px; height: 40px; border-radius: 50%; object-fit: cover; background: #1a1512; flex: 0 0 auto; }
.drawer-user-text { min-width: 0; }
.drawer-user-name { font-size: 0.95rem; font-weight: 800; letter-spacing: 0.04em; color: #f2ede6; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.drawer-user-handle { margin-top: 2px; font-size: 0.68rem; letter-spacing: 0.18em; text-transform: uppercase; color: rgba(242, 237, 230, 0.5); }
.drawer-signout {
  display: block; width: 100%; margin: 12px 0 0; padding: 4px 0;
  background: none; border: 0; cursor: pointer;
  font: inherit; font-size: 0.68rem; letter-spacing: 0.18em; text-transform: uppercase;
  color: rgba(242, 237, 230, 0.5); text-align: center;
  transition: color 160ms;
}
.drawer-signout:hover { color: #fff; }
.drawer-signout:disabled { opacity: 0.5; cursor: default; }
/* `hidden` has to WIN over the two display rules above (found 2026-09-22 while
   giving /shop/ the same drawer): both elements ship with the attribute and are
   un-hidden by session.js when a session exists, but `display: flex` / `display:
   block` beat the UA's `[hidden]`, so a signed-OUT menu has been showing an
   empty face and a dead SIGN OUT under the SIGN IN button. This is the home
   page's live behaviour too, not something the shop introduced. */
.drawer-user[hidden], .drawer-signout[hidden] { display: none; }

/* ---- social icons in chrome ----
   Same chrome layers as the text (they carry .chrome-text so main.js steers
   them), but the glyph is a mask instead of clipped text. Glyphs: Simple
   Icons (CC0), public/icons/. */
.chrome-icon {
  display: inline-block;
  width: 26px; height: 26px;
  -webkit-background-clip: border-box; background-clip: border-box;
  -webkit-mask-image: var(--icon); mask-image: var(--icon);
  -webkit-mask-size: contain; mask-size: contain;
  -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
  -webkit-mask-position: center; mask-position: center;
  transition: transform 200ms cubic-bezier(.2,.7,.2,1);
}
.chrome-icon:hover { transform: translateZ(0) scale(1.12); }
/* Touch: icons are static chrome (shared.js skips them) and get no layer
   promotion — mask + promoted layer + repaint is the iOS flicker recipe. */
@media (hover: none) {
  .chrome-icon, .chrome-icon:hover { transform: none; will-change: auto; }
}
.icon-instagram { --icon: url("/icons/instagram.svg"); }
.icon-youtube   { --icon: url("/icons/youtube.svg"); }
.icon-tiktok    { --icon: url("/icons/tiktok.svg"); }
.icon-reddit    { --icon: url("/icons/reddit.svg"); }
.icon-x         { --icon: url("/icons/x.svg"); }
.socials { display: flex; gap: 26px; justify-content: center; margin-top: 2.2rem; }
.socials .chrome-icon { width: 30px; height: 30px; }

/* ---- panels (waitlist / about / account) — design shells ---- */
.panel { position: fixed; inset: 0; z-index: 220; display: grid; place-items: center; padding: 24px; }
.panel[hidden] { display: none; }
.panel-card {
  position: relative;
  width: min(92vw, 420px);
  background: #0a0806;
  border: 1px solid rgba(242, 237, 230, 0.1);
  padding: 34px 30px 26px;
  box-shadow: 0 30px 80px rgba(0,0,0,.6);
  animation: panel-in 320ms cubic-bezier(.2,.7,.2,1);
  max-height: 90vh; overflow: auto;
}
.panel-card-wide { width: min(94vw, 560px); }
@keyframes panel-in { from { transform: translateY(14px); opacity: 0; } to { transform: none; opacity: 1; } }
.panel-close {
  position: absolute; top: 8px; right: 12px;
  background: none; border: 0; color: rgba(242,237,230,.6); font-size: 26px; line-height: 1; cursor: pointer;
}
.panel-close:hover { color: #fff; }
.panel h2.chrome-text { font-size: clamp(2rem, 7vw, 2.8rem); font-weight: 800; font-stretch: condensed; letter-spacing: 0.08em; text-transform: uppercase; margin: 0 0 10px; line-height: 1; }
.panel-lead { margin: 0 0 18px; font-size: 0.95rem; letter-spacing: 0.06em; color: #f2ede6; }
.panel-body { margin: 0 0 12px; font-size: 0.9rem; line-height: 1.55; color: rgba(242,237,230,.8); }
.panel-fine { margin: 16px 0 0; font-size: 0.68rem; letter-spacing: 0.16em; text-transform: uppercase; color: rgba(242,237,230,.45); }
.panel-fine a { color: rgba(242,237,230,.7); }
.panel-form { display: flex; flex-direction: column; gap: 10px; }
/* input[type=tel] joined the list with plan 99's phone box (2026-09-22) — the
   same control, the same box, only a different keypad on a phone. */
.panel-form input[type=email], .panel-form input[type=password], .panel-form input[type=text], .panel-form input[type=tel] {
  width: 100%; box-sizing: border-box;
  background: #14110f; border: 1px solid rgba(242,237,230,.14); color: #f2ede6;
  padding: 12px 14px; font: inherit; font-size: 0.95rem; letter-spacing: 0.04em;
}
.panel-form input:focus { outline: none; border-color: rgba(242,237,230,.45); }
.panel-form label { display: flex; flex-direction: column; gap: 6px; font-size: 0.66rem; letter-spacing: 0.18em; text-transform: uppercase; color: rgba(242,237,230,.5); }
.btn-primary {
  padding: 13px 18px; background: #f2ede6; color: #0a0806; border: 0; cursor: pointer;
  font: inherit; font-size: 0.8rem; font-weight: 800; letter-spacing: 0.26em; text-transform: uppercase;
}
.btn-primary:hover { background: #fff; }
.btn-ghost {
  padding: 10px 14px; background: none; color: rgba(242,237,230,.75);
  border: 1px solid rgba(242,237,230,.18); cursor: pointer;
  font: inherit; font-size: 0.68rem; letter-spacing: 0.2em; text-transform: uppercase;
}
.btn-ghost:hover { color: #fff; border-color: rgba(242,237,230,.5); }
.btn-danger { color: #d97a6a; border-color: rgba(217,122,106,.35); }

/* account: the two states */
#panel-account[data-state="out"] .acct-in { display: none; }
#panel-account[data-state="in"]  .acct-out { display: none; }
.acct-head { display: flex; align-items: center; gap: 14px; margin-bottom: 18px; }
.acct-avatar { width: 48px; height: 48px; border-radius: 50%; object-fit: cover; background: #14110f; }
.acct-name { font-weight: 800; font-stretch: condensed; letter-spacing: 0.06em; font-size: 1.15rem; }
.acct-handle { font-size: 0.72rem; letter-spacing: 0.14em; color: rgba(242,237,230,.5); }
.acct-head .btn-ghost { margin-left: auto; }
.acct-tabs { display: flex; gap: 6px; border-bottom: 1px solid rgba(242,237,230,.1); margin-bottom: 18px; }
.acct-tab { background: none; border: 0; padding: 10px 14px; cursor: pointer; font: inherit; font-size: 0.72rem; letter-spacing: 0.22em; text-transform: uppercase; color: rgba(242,237,230,.5); border-bottom: 2px solid transparent; margin-bottom: -1px; }
.acct-tab.is-active { color: #f2ede6; border-bottom-color: #f2ede6; }
.acct-pane { display: none; }
.acct-pane.is-active { display: block; }
.acct-h3 { margin: 6px 0 10px; font-size: 0.66rem; letter-spacing: 0.24em; text-transform: uppercase; color: rgba(242,237,230,.45); }
.ev-list { list-style: none; margin: 0 0 18px; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.ev { display: flex; align-items: center; gap: 14px; padding: 12px 14px; background: #100d0b; border: 1px solid rgba(242,237,230,.08); }
.ev-when { display: flex; flex-direction: column; align-items: center; min-width: 40px; }
.ev-day { font-size: 0.6rem; letter-spacing: 0.2em; color: rgba(242,237,230,.5); }
.ev-date { font-size: 1.3rem; font-weight: 800; font-stretch: condensed; line-height: 1; }
.ev-body { flex: 1; min-width: 0; }
.ev-title { font-weight: 800; font-stretch: condensed; letter-spacing: 0.04em; }
.ev-meta { font-size: 0.7rem; letter-spacing: 0.1em; color: rgba(242,237,230,.5); margin-top: 2px; }
.ev-rsvp { padding: 8px 12px; background: none; border: 1px solid rgba(242,237,230,.25); color: #f2ede6; cursor: pointer; font: inherit; font-size: 0.64rem; letter-spacing: 0.2em; text-transform: uppercase; white-space: nowrap; }
.ev-rsvp.is-going { background: #f2ede6; color: #0a0806; border-color: #f2ede6; }
.acct-danger { display: flex; gap: 10px; margin-top: 18px; flex-wrap: wrap; }

/* the message slot under a form. It was only ever styled in /account/
   account.css, so the home page's waitlist reply has been unstyled body text
   since plan 80; the rules below are that file's, word for word, so /account/
   (which loads it after this one) renders exactly as it did. */
.panel-error { margin: 12px 0 0; font-size: .74rem; line-height: 1.5; letter-spacing: .04em; color: #d97a6a; padding-left: 12px; border-left: 2px solid #d97a6a; }
.panel-error[data-kind="ok"] { color: rgba(242,237,230,.7); border-left-color: rgba(242,237,230,.35); }
.panel-error[hidden] { display: none; }

/* ---- the waitlist fold-out + /list/ (plan 88 lane B, 2026-09-10) ------------
   The optional details. Two surfaces, one look: the fold-out
   under the home page's Waitlist panel, and the page the waitlist mail links
   to. The markup for both is rendered by /waitlist-fields.js — these are the
   only rules that decide how it reads, so this is where the design lives.
   Nothing here touches the waitlist's own email box or button: joining is the
   same two controls it has always been, and this all sits below them, shut. */

/* The fold-out sits BETWEEN the email box and the button (Red, 2026-09-10:
   "put the whole mailing list sheet thing above the button"), which is the
   right reading order — you finish the form, then you send it. Sitting between
   two controls it needs to read as its own band rather than as loose content,
   hence a rule above AND below; open, it gets room before the button. */
.wl-more {
  border-top: 1px solid rgba(242,237,230,.1);
  border-bottom: 1px solid rgba(242,237,230,.1);
  margin-top: 4px;
}
.wl-more[open] { padding-bottom: 14px; }
.wl-summary {
  list-style: none; cursor: pointer;
  display: flex; align-items: center; gap: 10px; padding: 13px 2px;
  font-size: .68rem; letter-spacing: .2em; text-transform: uppercase;
  color: rgba(242,237,230,.55);
}
.wl-summary::-webkit-details-marker { display: none; }
.wl-summary::after { content: "+"; margin-left: auto; font-size: 1.05rem; line-height: 1; color: rgba(242,237,230,.4); }
.wl-more[open] .wl-summary::after { content: "\2212"; }
.wl-summary:hover, .wl-more[open] .wl-summary { color: #f2ede6; }
.wl-summary:focus-visible { outline: 1px solid rgba(242,237,230,.5); outline-offset: 2px; }
.wl-more[open] .wl-fields, .wl-more[open] .wl-eligible { animation: panel-in 260ms cubic-bezier(.2,.7,.2,1); }

.wl-eligible { margin: 0 0 14px; font-size: .74rem; line-height: 1.55; letter-spacing: .03em; color: rgba(242,237,230,.6); }

.wl-grid { display: flex; flex-direction: column; gap: 12px; }
.wl-f { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.wl-lab { font-size: .6rem; letter-spacing: .2em; text-transform: uppercase; color: rgba(242,237,230,.45); }
.wl-row { display: grid; grid-template-columns: 1.25fr 1fr; gap: 12px; }
/* province + postal are the only pair narrow enough to sit together in a 420px
   card; below 380px even they stack rather than squeeze. */
@media (max-width: 380px) { .wl-row { grid-template-columns: 1fr; } }

.wl-f select {
  width: 100%; box-sizing: border-box; color-scheme: dark;
  background: #14110f; border: 1px solid rgba(242,237,230,.14); color: #f2ede6;
  padding: 12px 34px 12px 14px; font: inherit; font-size: .95rem; letter-spacing: .04em;
  appearance: none; -webkit-appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='7'%3E%3Cpath d='M1 1.5l4 4 4-4' fill='none' stroke='%23f2ede6' stroke-opacity='.55' stroke-width='1.4'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 13px center;
}
.wl-f select:focus { outline: none; border-color: rgba(242,237,230,.45); }
.wl-f select.is-empty { color: rgba(242,237,230,.42); }   /* reads as a placeholder */
.wl-f select option { background: #14110f; color: #f2ede6; }

/* the @ handles: the sign is furniture, not something to type */
.wl-at { display: flex; align-items: stretch; min-width: 0; }
.wl-at-sign {
  display: flex; align-items: center; padding: 0 2px 0 14px;
  background: #14110f; border: 1px solid rgba(242,237,230,.14); border-right: 0;
  color: rgba(242,237,230,.35); font-size: .95rem;
}
.panel-form .wl-at input[type=text] { border-left: 0; padding-left: 4px; flex: 1; min-width: 0; }

.wl-sizes { display: block; border: 0; padding: 0; margin: 0; min-width: 0; }
.wl-sizes legend { padding: 0; margin-bottom: 8px; }
.wl-chips { display: flex; flex-wrap: wrap; gap: 8px; }
.wl-chip { position: relative; display: inline-block; }
.wl-chip input { position: absolute; inset: 0; opacity: 0; width: 100%; height: 100%; margin: 0; cursor: pointer; }
.wl-chip span {
  display: block; min-width: 48px; text-align: center; cursor: pointer;
  padding: 10px 12px; background: #14110f; border: 1px solid rgba(242,237,230,.16);
  color: rgba(242,237,230,.7);
  font-size: .72rem; font-weight: 800; letter-spacing: .12em; text-transform: uppercase;
}
/* the radio covers the whole chip so the tap target IS the chip; that means the
   hover must be read off the label, not the span the pointer never reaches */
.wl-chip:hover span { color: #f2ede6; border-color: rgba(242,237,230,.45); }
.wl-chip input:checked + span { background: #f2ede6; border-color: #f2ede6; color: #0a0806; }
.wl-chip:hover input:checked + span { color: #0a0806; border-color: #fff; }
.wl-chip input:focus-visible + span { outline: 1px solid rgba(242,237,230,.6); outline-offset: 2px; }
/* radios cannot be un-picked by clicking again, and every field here is
   optional — so a mis-tapped chip needs a way back out */
.wl-clear {
  margin-top: 10px; padding: 0; background: none; border: 0; cursor: pointer;
  font: inherit; font-size: .6rem; letter-spacing: .18em; text-transform: uppercase;
  color: rgba(242,237,230,.4);
}
.wl-clear:hover { color: #f2ede6; }
.wl-clear[hidden] { display: none; }

.wl-f.is-bad input, .wl-f.is-bad select, .wl-f.is-bad .wl-at-sign { border-color: rgba(217,122,106,.65); }
.wl-f.is-bad .wl-lab { color: #d97a6a; }

.wl-plain { margin: 14px 0 0; font-size: .74rem; letter-spacing: .05em; color: rgba(242,237,230,.55); }

/* PLAN 99 R11 (2026-09-22): signed in, the waitlist panel's email box is
   replaced by this one line — "Joining as @handle · your details". */
.wl-as { margin: 2px 0 0; font-size: .78rem; letter-spacing: .05em; color: rgba(242,237,230,.7); }
.wl-as[hidden] { display: none; }
.wl-as strong { color: #f2ede6; font-weight: 800; letter-spacing: .06em; }
.wl-as a { color: rgba(242,237,230,.55); text-decoration: none; border-bottom: 1px solid rgba(242,237,230,.25); }
.wl-as a:hover { color: #fff; border-bottom-color: #fff; }

/* /list/ — the emailed link's page. One card on black, no page stack; the one
   menu (plan 108 W1) in the topbar like every other page. */
.wl-page { min-height: 100vh; display: grid; place-items: center; padding: 62px 20px 44px; }
.wl-page .panel-card { width: min(94vw, 480px); max-height: none; overflow: visible; }
.wl-title { font-size: clamp(2rem, 7vw, 2.8rem); font-weight: 800; font-stretch: condensed; letter-spacing: .08em; text-transform: uppercase; margin: 0 0 10px; line-height: 1; }
.wl-page .panel-form { gap: 16px; }
.wl-page .btn-primary { margin-top: 4px; }
.wl-end .panel-body { margin-bottom: 16px; }

.grain {
  position: fixed;
  inset: -50%;
  /* Above the whole page stack — pages carry ascending z-indexes now. */
  z-index: 100;
  pointer-events: none;
  opacity: 0.07;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='240' height='240'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  animation: grain 0.9s steps(4) infinite;
}

@keyframes grain {
  0%   { transform: translate(0, 0); }
  25%  { transform: translate(-2%, 1%); }
  50%  { transform: translate(1%, -2%); }
  75%  { transform: translate(-1%, 2%); }
  100% { transform: translate(2%, -1%); }
}

/* ---- the page stack (Red's spec, 2026-08-13: every page slides up and
   covers the last; a headline + its video scroll as ONE page) ----
   Each page is sticky with an opaque background and an ascending z-index
   (set in main.js, DOM order). Pages taller than the viewport get a
   NEGATIVE sticky top (viewport − height, measured in main.js) so a page
   pins only once it has been fully scrolled — inside a page, scrolling
   stays normal; the covering happens between pages. */

.page {
  position: sticky;
  top: 0;
  /* lvh, not svh: on phones the URL bar collapses mid-scroll and grows the
     viewport — an svh-sized page would leave a strip of the page underneath
     showing. lvh == svh on desktop, so this changes nothing there. */
  min-height: 100vh;
  min-height: 100lvh;
  background-color: #0a0806;
  /* Plain black. The suede lives only behind the feature text blocks
     (.page.feature, below) — Red, 2026-09-05. */
}

/* ---- suede, feature pages + the statement page (Red, 2026-09-05: "only
   behind the text bubbles like Convoy and Garage"; 2026-09-07: "for the
   ones who live it" gets it too — it was the one text page left plain) ----
   A seamless tile repeats instead of one stretched photo (BLUE's
   bg-texture.jpg). Top: the page-stack feather; middle: a soft pool of
   light (the softbox); bottom: the tile. Two more tiles drift over this
   in ::before/::after so the repeat never shows and the surface keeps
   changing. Calibrated to BLUE's photo: same brightness, same tint. */
.page.feature, .page.statement {
  background-image:
    linear-gradient(to bottom,
      rgba(10, 8, 6, 0.9) 0%, rgba(10, 8, 6, 0.45) 12%,
      rgba(10, 8, 6, 0.45) 88%, rgba(10, 8, 6, 0.9) 100%),
    radial-gradient(ellipse 70% 55% at 50% 42%,
      rgba(255, 244, 228, 0.035) 0%, rgba(255, 244, 228, 0.012) 45%, rgba(0, 0, 0, 0) 75%),
    url("/suede-a.jpg");
  background-size: cover, cover, 880px 880px;
  background-position: center, center, 0 0;
  background-repeat: no-repeat, no-repeat, repeat;
}

/* ---- suede drift layers (Red, 2026-09-05: "a texture that mixes up and
   replays… make it more random") ----
   Two more seamless tiles, cut from different patches of the same suede,
   sit over the base tile at scales that never line up with it (x1.618 and
   x0.68, the second tile pre-rotated 90°) and drift slowly in different
   directions on transforms (composited, cheap). Each page starts them at
   a different offset and direction (nth-child), so no two pages read the
   same. clip-path keeps the oversized layers inside their page; the
   garage-door #gate lives outside every .page so it is unaffected.
   overflow:hidden (not clip-path) — clip-path only hid the paint and the
   oversized layers still widened the document, which let iOS drag the
   site sideways (Red, 2026-09-05). Only the live page animates. */
.page { overflow: hidden; }
.page.feature::before, .page.feature::after,
.page.statement::before, .page.statement::after {
  content: "";
  position: absolute;
  inset: -12%;
  z-index: -1;
  pointer-events: none;
  background-repeat: repeat;
  will-change: transform;
}
.page.feature::before, .page.statement::before {
  background-image: url("/suede-b.jpg");
  background-size: 1424px 1424px;
  mix-blend-mode: soft-light;   /* tiles b/c are mid-grey texture maps: they change the surface, not the brightness */
  opacity: 0.85;
  animation: suede-drift-a 140s ease-in-out infinite alternate;
}
.page.feature::after, .page.statement::after {
  background-image: url("/suede-c.jpg");
  background-size: 600px 600px;
  mix-blend-mode: overlay;
  opacity: 0.45;
  animation: suede-drift-b 190s ease-in-out infinite alternate;
}
.page:nth-child(3n+1)::before { background-position: 31% 67%; animation-direction: alternate-reverse; }
.page:nth-child(3n+2)::before { background-position: 74% 12%; animation-delay: -47s; }
.page:nth-child(3n)::before   { background-position: 9% 41%;  animation-delay: -93s; }
.page:nth-child(2n)::after    { background-position: 58% 23%; animation-direction: alternate-reverse; }
.page:nth-child(2n+1)::after  { background-position: 13% 81%; animation-delay: -61s; }
.page:not(.page-live)::before, .page:not(.page-live)::after { animation-play-state: paused; }
@keyframes suede-drift-a {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(-8%, 6%, 0); }
}
@keyframes suede-drift-b {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(7%, -9%, 0); }
}
@media (prefers-reduced-motion: reduce) {
  .page.feature::before, .page.feature::after,
  .page.statement::before, .page.statement::after { animation: none; }
}

/* ---- hero ---- */

.hero {
  /* position comes from .page (sticky) — sticky is a positioned element,
     so the absolutely-placed video/vignette/content still anchor to it. */
  height: 100vh;
  height: 100lvh;
  overflow: hidden;
}

#hero {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* The grade lives HERE now, not baked into the files (Red, 2026-08-13):
     source mp4s are clean high-quality encodes; saturation matches the b/w-gold
     look BLUE tuned, the faint blur is Red's ask. Tune without re-encoding. */
  filter: saturate(0.3) blur(1.5px);
  /* A blurred edge bleeds transparent; the tiny scale hides it. */
  transform: scale(1.02);
}

.vignette {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    radial-gradient(ellipse at center, transparent 45%, rgba(6, 4, 2, 0.55) 100%),
    linear-gradient(to bottom, rgba(6, 4, 2, 0.5), transparent 22%, transparent 72%, rgba(6, 4, 2, 0.85));
}

.hero-content {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 0 5vw;
}

h1 {
  font-size: clamp(5rem, 22vw, 15rem);
  font-weight: 800;
  font-stretch: condensed;
  letter-spacing: 0.14em;
  margin-right: -0.14em;
  line-height: 1;
  text-shadow: 0 0 60px rgba(0, 0, 0, 0.6);
}

.tag {
  margin-top: 1.1rem;
  font-size: clamp(0.95rem, 2.4vw, 1.35rem);
  letter-spacing: 0.42em;
  margin-right: -0.42em;
  text-transform: uppercase;
  color: #f2ede6;
  text-shadow: 0 0 24px rgba(0, 0, 0, 0.8);
}

/* ---- typewriter (BLUE, 2026-09-05: hero tagline types in, ~100wpm,
   slightly clunky via main.js's jittered delay, not a smooth CSS steps()
   sweep) ---- */
.typing::after {
  content: "|";
  margin-left: 0.15em;
  animation: caretBlink 0.8s steps(1) infinite;
}
@keyframes caretBlink {
  0%, 49% { opacity: 1; }
  50%, 100% { opacity: 0; }
}

#sound {
  margin-top: 3rem;
  padding: 0.65rem 1.6rem;
  background: transparent;
  border: 1px solid rgba(242, 237, 230, 0.45);
  color: #f2ede6;
  font: inherit;
  font-size: 0.78rem;
  letter-spacing: 0.3em;
  margin-right: -0.3em;
  cursor: pointer;
  transition: border-color 0.2s, color 0.2s;
}

#sound:hover,
#sound[aria-pressed="true"] {
  border-color: #f2ede6;
  color: #f2ede6;
}

/* ---- statement ---- */

.statement {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 12vh 8vw;   /* was 18vh; the passage needs the room on phones */
}

.statement p {
  font-size: clamp(1.3rem, 4.2vw, 3rem);
  font-weight: 700;
  font-stretch: condensed;
  line-height: 1.35;
  letter-spacing: 0.06em;
}

.phrase { white-space: nowrap; }

/* statement reveal (Red, 2026-09-07: the feature pages' pop-in, here too).
   main.js marks the inner .statement-body `revealed` while it rides
   mid-viewport (same hysteresis as the teases; the section itself is a
   full-height pinned page, so its ratio never reads right — the wrapper does); the three lines rise in one after another and
   sink back out once the page is mostly gone, so it replays on the way up. */
.statement-body { display: flex; flex-direction: column; align-items: center; }
.statement-body > p {
  opacity: 0;
  transform: translateY(26px);
  transition: opacity 0.55s ease, transform 0.65s cubic-bezier(0.22, 0.61, 0.36, 1);
  will-change: transform, opacity;
}
.statement-body.revealed > p { opacity: 1; transform: none; }
.statement-body.revealed > p:nth-child(2) { transition-delay: 0.14s; }
.statement-body.revealed > p:nth-child(3) { transition-delay: 0.28s; }
@media (prefers-reduced-motion: reduce) {
  .statement-body > p { opacity: 1; transform: none; transition: none; }
}

/* the short passage under the punch (Red, 2026-09-07) — quiet, readable,
   never wider than a paragraph should be */
.statement .passage {
  margin-top: 2.4rem;
  max-width: 44ch;
  font-size: clamp(0.95rem, 1.9vw, 1.25rem);
  font-weight: 400;
  font-stretch: normal;
  line-height: 1.6;
  letter-spacing: 0.04em;
  color: rgba(242, 237, 230, 0.78);
}
.statement .sub {
  margin-top: 2.2rem;
  font-size: clamp(0.72rem, 2.6vw, 1.2rem);
  font-weight: 400;
  letter-spacing: 0.42em;
  margin-right: -0.42em;
  text-transform: uppercase;
  white-space: nowrap;
  /* was gold; now the same chrome accent as .num/.tease-desc (Red, 2026-09-07) */
  background: linear-gradient(100deg,
    #6c6f74 0%, #e9ebed 18%, #ffffff 30%, #9a9da2 42%,
    #4c4f53 52%, #cfd2d6 64%, #ffffff 78%, #7d8085 100%);
  background-size: 250% 100%;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  animation: chromeShine 7s ease-in-out infinite;
}

/* "live" — was a gold shimmer; now a chrome one, same sweep (Red, 2026-09-07) */
.shimmer {
  background: linear-gradient(100deg, #7d8085 38%, #cfd2d6 46%, #ffffff 50%, #cfd2d6 54%, #7d8085 62%);
  background-size: 250% 100%;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  animation: shimmer 4.5s ease-in-out infinite;
}

@keyframes shimmer {
  0%   { background-position: 120% 0; }
  60%  { background-position: -60% 0; }
  100% { background-position: -60% 0; }
}

/* ---- image breaks ---- */

.break {
  position: relative;
  /* Full viewport height, not 70vh: at 70vh the break could never fill the
     screen on its own, so the sticky pin's one held frame (its top offset is
     computed to land exactly at "tease scrolled off, break filling the
     viewport") always showed black bars above and below it instead — the
     image never got the fully-centered settled moment before the next
     section covered it. Full-height break gives that frame nothing to show
     but itself. */
  height: 100vh;
  height: 100lvh;
  overflow: hidden;
  background-color: #0a0806;
  /* Plain black. The suede lives only behind the feature text blocks
     (.page.feature, below) — Red, 2026-09-05. */
}
.break video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Red 2026-08-20, delivering the four trailers: "a small blur on top" —
     reverses his 2026-08-14 clean-video call, deliberately SMALLER than the
     hero's 1.5px so it reads as grade, not low quality. Saturation stays for
     the site's b/w-gold look. Tune here, never re-encode. */
  filter: saturate(0.3) blur(1px);
  /* A blurred edge bleeds transparent; the tiny scale hides it (hero's trick). */
  transform: scale(1.02);
}
.break::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  box-shadow:
    inset 0 60px 80px -40px #0a0806,
    inset 0 -60px 80px -40px #0a0806;
}

/* ---- teases (the headline half of each feature page) ---- */

.feature .tease {
  min-height: 100vh;
  min-height: 100lvh;
}

/* Every tease is now headline-only (Red, 2026-08-14: the b/w still beside the
   Garage headline is gone). The side-by-side .tease-garage / .tease-img
   treatment and its mobile stacking rules went with it. */
.tease-center {
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 16vh 8vw;
}

/* ---- tease reveal (Red, 2026-08-20) ----
   Desktop (real mouse): hovering a title screen slides the headline aside —
   alternating left / right down the page — and a description slides in beside
   it. The hover target is the WHOLE tease, not the text: a headline that moves
   away from the cursor would end its own hover and flicker.
   Mobile (no hover): main.js marks a tease `revealed` while it rides the middle
   of the viewport; the headline slides up, the description drops in below.
   Text page only — the video break is untouched, and the desc is absolute so no
   page height changes and main.js's page-stack arithmetic never notices.
   Nothing slides out of frame on either layout (13vw shift, desc width-capped). */
.feature .tease {
  position: relative;
}
.feature .tease-text {
  transition: transform 0.55s cubic-bezier(0.22, 0.61, 0.36, 1);
  will-change: transform;
}
.tease-desc {
  position: absolute;
  margin: 0;
  opacity: 0;
  pointer-events: none;
  font-size: clamp(0.85rem, 2.6vw, 1.05rem);
  line-height: 1.75;
  transition:
    opacity 0.45s ease 0.1s,
    transform 0.55s cubic-bezier(0.22, 0.61, 0.36, 1) 0.1s;
}

@media (hover: hover) and (pointer: fine) {
  .tease-desc {
    top: 50%;
    width: min(32ch, 25vw);
  }
  /* 63% / 14vw, not 57% / 13vw: "Clubs & Events" is the widest headline, and at
     mid-size windows its slid edge crossed ~2vw into the desc column (Red saw
     the C graze the text). Font and shift both scale with vw below the h2's
     clamp cap, so this clearance holds at every width — sized for the widest
     title, shared by all six so the motion stays uniform. */
  .alt-left .tease-desc  { left: 63%;  text-align: left;  transform: translate(28px, -50%); }
  .alt-right .tease-desc { right: 63%; text-align: right; transform: translate(-28px, -50%); }
  .alt-left  .tease:hover .tease-text { transform: translateX(-14vw); }
  .alt-right .tease:hover .tease-text { transform: translateX(14vw); }
  .feature .tease:hover .tease-desc { opacity: 1; transform: translate(0, -50%); }
}

@media (hover: none), (pointer: coarse) {
  .tease-desc {
    top: 55%;
    left: 8vw;
    right: 8vw;
    text-align: center;
    transform: translateY(-16px);
  }
  /* Softer clock than desktop: on a phone the reveal fires mid-scroll, and a
     quick snap reads as a stutter against the scroll motion. */
  .feature .tease-text { transition-duration: 0.7s; }
  .tease-desc { transition-duration: 0.6s, 0.7s; }
  .feature .tease.revealed .tease-text { transform: translateY(-7vh); }
  .feature .tease.revealed .tease-desc { opacity: 1; transform: translateY(0); }
}

.num {
  font-size: 0.8rem;
  letter-spacing: 0.5em;
}

/* .num (the "01".."06" beside each headline) and .tease-desc (the line that
   slides in beside it) are the accents that literally appear "when you
   scroll and the new one comes up" — gold -> chrome per BLUE, 2026-09-05. */
.num,
.tease-desc {
  background: linear-gradient(100deg,
    #6c6f74 0%, #e9ebed 18%, #ffffff 30%, #9a9da2 42%,
    #4c4f53 52%, #cfd2d6 64%, #ffffff 78%, #7d8085 100%);
  background-size: 250% 100%;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  animation: chromeShine 7s ease-in-out infinite;
}

.tease h2 {
  margin-top: 0.6rem;
  font-size: clamp(2.4rem, 7vw, 4.5rem);
  font-weight: 800;
  font-stretch: condensed;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  line-height: 1;
}

.tease p {
  margin-top: 1rem;
  font-size: clamp(1rem, 2.2vw, 1.25rem);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: rgba(242, 237, 230, 0.72);
}

/* ---- closer ---- */

.closer {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 15vh 5vw 0;
}

.closer h1 {
  font-size: clamp(4rem, 18vw, 12rem);
}

.closer .tag { margin-top: 1rem; }

footer {
  margin-top: auto;
  display: flex;
  justify-content: center;
  gap: 0.7em;
  padding: 6rem 1.2rem 1.4rem;
  font-size: 0.72rem;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: rgba(242, 237, 230, 0.6);
}

footer .dot { color: #cfd2d6; }

/* ---- the garage door (Red, 2026-08-14) ---- */
#wordmark { cursor: default; -webkit-tap-highlight-color: transparent; user-select: none; }
/* An author display beats the hidden attribute's UA display:none — without this
   the gate is just always open (Red found it live, 2026-08-14). */
#gate[hidden] { display: none !important; }
#gate {
  position: fixed; inset: 0; z-index: 999;
  background: rgba(10, 8, 6, 0.88);
  display: flex; align-items: center; justify-content: center;
  padding: 24px;
}
.gate-card {
  width: min(340px, 100%);
  background: #0a0806;
  border: 1px solid rgba(217, 160, 91, 0.45);
  padding: 28px 24px;
  text-align: center;
  /* The builds list grows one entry per publish, and a centered card taller
     than the phone clips BOTH ends with no way to reach them (Red, 2026-08-25).
     Cap it at the viewport and let the card itself scroll — every version
     stays choosable no matter how long the record gets. */
  max-height: min(640px, 85dvh);
  overflow-y: auto;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
}
.gate-card h2 { margin: 0 0 6px; font-size: 22px; letter-spacing: 0.08em; text-transform: uppercase; }
.gate-sub { margin: 0 0 18px; color: rgba(242, 237, 230, 0.65); font-size: 14px; }
#gate-pw {
  width: 100%; box-sizing: border-box;
  background: transparent; color: #f2ede6;
  border: 1px solid rgba(242, 237, 230, 0.3);
  padding: 10px 12px; font: inherit; letter-spacing: 0.04em;
}
#gate-pw:focus { outline: none; border-color: rgba(242, 237, 230, 0.7); }
.gate-actions { display: flex; gap: 10px; margin-top: 14px; justify-content: center; }
.gate-actions button {
  font: inherit; letter-spacing: 0.08em; text-transform: uppercase; font-size: 13px;
  padding: 9px 16px; cursor: pointer;
}
#gate-go { background: #f2ede6; border: 1px solid #f2ede6; color: #0a0806; }
#gate-go:hover { background: #fff; }
#gate-go:disabled { opacity: 0.6; cursor: default; }
#gate-cancel { background: transparent; border: 1px solid rgba(242, 237, 230, 0.3); color: #f2ede6; }
#gate-status { min-height: 1.2em; margin: 14px 0 0; font-size: 13px; color: #cfd2d6; }

/* ---- the builds panel behind the door (Red, 2026-08-19) ---- */
#gate-builds[hidden], #gate-ask[hidden] { display: none !important; }
#gate-dl-latest {
  width: 100%; font: inherit; letter-spacing: 0.08em; text-transform: uppercase;
  font-size: 14px; padding: 12px 16px; cursor: pointer;
  background: #f2ede6; border: 1px solid #f2ede6; color: #0a0806;
}
#gate-dl-latest:hover { background: #fff; }
.gate-build-meta { margin: 8px 0 0; font-size: 12px; color: rgba(242, 237, 230, 0.65); }
.gate-older-head {
  margin: 22px 0 8px; font-size: 12px; letter-spacing: 0.1em; text-transform: uppercase;
  color: rgba(242, 237, 230, 0.5); text-align: left;
}
#gate-older { list-style: none; margin: 0; padding: 0; text-align: left; }
#gate-older li { border-top: 1px solid rgba(242, 237, 230, 0.12); padding: 10px 0; }
.gate-build-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; font-size: 13px; }
.gate-dl-old {
  font: inherit; font-size: 11px; letter-spacing: 0.08em; text-transform: uppercase;
  padding: 5px 12px; cursor: pointer;
  background: transparent; border: 1px solid rgba(242, 237, 230, 0.5); color: #f2ede6;
}
.gate-gone { font-size: 11px; color: rgba(242, 237, 230, 0.4); font-style: italic; }
.gate-notes { margin-top: 6px; }
.gate-notes summary {
  cursor: pointer; font-size: 11px; letter-spacing: 0.08em; text-transform: uppercase;
  color: rgba(217, 160, 91, 0.8);
}
.gate-notes p { margin: 6px 0 0; font-size: 12px; line-height: 1.5; color: rgba(242, 237, 230, 0.75); }
#gate-close { background: transparent; border: 1px solid rgba(242, 237, 230, 0.3); color: #f2ede6; }
#gate-builds .gate-actions { margin-top: 20px; }
