/* ============================================================
   boleto-site — design system (Piece 1)
   Brand derives from the app (CLAUDE.md): coral accent used
   sparingly, warm neutrals, system type, light-mode committed.
   ============================================================ */

:root {
  /* Color — matched to the APP, not invented (Jack 2026-08-19: no
     off-white; the app's ground is systemBackground = pure white). */
  --coral: #FF7A59;          /* Color.boletoAccent */
  --coral-brand: #F05038;    /* the app ICON's coral (sampled) — the
                                wordmark wears this so icon + word read
                                as one mark; UI accents keep --coral */
  --coral-press: #F0663F;    /* hover/active on filled controls */
  --coral-text: #D64B2A;     /* coral for TEXT on white (AA) */
  --ink: #111111;            /* iOS label, light mode */
  --muted: #6E6E73;          /* ~secondaryLabel */
  --faint: #A9A9AE;          /* ~tertiaryLabel */
  --ground: #FFFFFF;         /* systemBackground */
  --card: #F2F2F7;           /* secondarySystemBackground */
  --line: rgba(0, 0, 0, 0.12);

  /* Type — the system stack, same voice as the app */
  --font-body: -apple-system, BlinkMacSystemFont, "SF Pro Text",
               "Segoe UI", Roboto, "Helvetica Neue", sans-serif;
  /* --font-display is decided in Piece 2 (hero face decision);
     until then display text uses the body stack, heavier. */
  --font-display: var(--font-body);
  /* Mono carries the departure-board language: eyebrows, times,
     countdowns, detail labels (adopted from the Lovable pass 08-19).
     Face candidates decided in Piece 2 alongside the display face. */
  --font-mono: ui-monospace, "SF Mono", SFMono-Regular, Menlo, monospace;

  /* Fluid scale */
  --text-hero: clamp(2.5rem, 6.5vw + 1rem, 4.25rem);
  --text-h2: clamp(1.5rem, 2.5vw + 0.75rem, 2.125rem);
  --text-body: 1.0625rem;
  --text-small: 0.9375rem;
  --text-caption: 0.8125rem;

  /* Rhythm */
  --space-1: 0.5rem;
  --space-2: 1rem;
  --space-3: 1.5rem;
  --space-4: 2.5rem;
  --space-5: 4rem;
  --space-6: 6.5rem;
  --radius: 14px;
  --radius-pill: 999px;
}

/* ---- Base ---- */
*, *::before, *::after { box-sizing: border-box; }

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

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}

body {
  margin: 0;
  background: var(--ground);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: var(--text-body);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  display: flex;
  flex-direction: column;
  min-height: 100dvh;
}

img { max-width: 100%; display: block; }

a { color: var(--coral-text); text-decoration: none; }
a:hover { text-decoration: underline; }

h1, h2, h3 {
  font-family: var(--font-display);
  line-height: 1.12;
  letter-spacing: -0.02em;
  margin: 0;
  text-wrap: balance;
}

:focus-visible {
  outline: 2px solid var(--coral);
  outline-offset: 3px;
  border-radius: 4px;
}

/* Numbers line up (dates, waitlist position) */
.tnum { font-variant-numeric: tabular-nums; }

/* ---- Layout ---- */
.wrap {
  width: 100%;
  max-width: 1080px;
  margin-inline: auto;
  padding-inline: clamp(20px, 5vw, 40px);
}

main { flex: 1; }

/* ---- Nav ---- */
.nav {
  padding-block: var(--space-2);
}

.nav .wrap {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
}

.brand {
  display: flex;
  align-items: baseline;
  color: var(--coral-brand);
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 2.125rem;
  letter-spacing: -0.01em;
}

.brand:hover { text-decoration: none; }

.brand img {
  width: 40px;
  height: 40px;
  border-radius: 9px;
  align-self: center;
  /* margin, not flex gap — gap also split "Boleto" from the ":" span */
  margin-right: 0.65rem;
}

/* "Boleto: Concert Tracker" — one coral lockup; only "Boleto" is
   heavy, the colon + descriptor run much lighter (Jack 2026-08-19,
   fourth iteration — this one). */
.brand-tag {
  margin-left: 0.12rem;
  font-family: var(--font-display);
  font-size: 1.75rem;
  font-weight: 300;
  letter-spacing: -0.01em;
  color: var(--coral-brand);
  white-space: nowrap;
}
/* Mobile keeps the full lockup (Jack 2026-08-21) — scaled to fit
   narrow screens instead of hiding the descriptor. */
@media (max-width: 699px) {
  .brand { font-size: clamp(1.5rem, 8.2vw, 2rem); }
  .brand-tag { font-size: clamp(1.24rem, 6.8vw, 1.65rem); }
  .brand img { width: clamp(34px, 9.7vw, 38px); height: auto; }
}

/* ---- Buttons ---- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.4rem;
  padding: 0.72rem 1.35rem;
  border: 0;
  border-radius: var(--radius-pill);
  background: var(--coral);
  color: #fff;
  font-family: var(--font-body);
  font-size: 1rem;
  font-weight: 600;
  cursor: pointer;
  transition: background 120ms ease;
}
.btn:hover { background: var(--coral-press); text-decoration: none; }

.btn-quiet {
  background: transparent;
  color: var(--ink);
  border: 1px solid var(--line);
}
.btn-quiet:hover { background: var(--card); }

/* ---- Placeholder (Piece 1 only — replaced by the Piece 2 hero) ---- */
.holding {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: var(--space-2);
  padding-block: var(--space-6);
}

.holding img {
  width: 84px;
  height: 84px;
  border-radius: 20px;
  box-shadow: 0 10px 30px rgba(72, 52, 40, 0.18);
}

.holding p {
  margin: 0;
  color: var(--muted);
  font-size: var(--text-small);
}

/* ---- Footer ---- */
.footer {
  border-top: 1px solid var(--line);
  padding-block: var(--space-3);
  margin-top: var(--space-5);
}

.footer .wrap {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
}

.footer nav {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
}

.footer a {
  color: var(--muted);
  font-size: var(--text-small);
}
.footer a:hover { color: var(--ink); }

.footer .legal {
  color: var(--faint);
  font-size: var(--text-caption);
}

/* Small screens: footer stacks, stays airy */
@media (max-width: 560px) {
  .footer .wrap {
    flex-direction: column;
    align-items: flex-start;
  }
}

/* ============================================================
   Piece 2 — hero (headline, waitlist, departure board, phone)
   ============================================================ */

/* Candidate faces, self-hosted (bake-off; losers removed on pick) */
@font-face {
  font-family: "Bricolage Grotesque";
  src: url("/assets/fonts/bricolage-800.woff2") format("woff2");
  font-weight: 800; font-display: swap;
}
@font-face {
  font-family: "Archivo Expanded";
  src: url("/assets/fonts/archivo-exp-800.woff2") format("woff2");
  font-weight: 800; font-display: swap;
}
@font-face {
  font-family: "Hanken Grotesk";
  src: url("/assets/fonts/hanken-800.woff2") format("woff2");
  font-weight: 800; font-display: swap;
}
@font-face {
  font-family: "Hanken Grotesk";
  src: url("/assets/fonts/hanken-300.woff2") format("woff2");
  font-weight: 300; font-display: swap;
}
@font-face {
  font-family: "IBM Plex Mono";
  src: url("/assets/fonts/plex-mono-400.woff2") format("woff2");
  font-weight: 400; font-display: swap;
}
@font-face {
  font-family: "Space Mono";
  src: url("/assets/fonts/space-mono-400.woff2") format("woff2");
  font-weight: 400; font-display: swap;
}
@font-face {
  font-family: "Spline Sans Mono";
  src: url("/assets/fonts/spline-mono-400.woff2") format("woff2");
  font-weight: 400; font-display: swap;
}

/* Pairings — switched by ?pair= (default A) for the bake-off */
:root,
[data-pair="c"] {
  --font-display: "Hanken Grotesk", var(--font-body);
  --font-mono: "Spline Sans Mono", ui-monospace, SFMono-Regular, monospace;
}
[data-pair="a"] {
  --font-display: "Bricolage Grotesque", var(--font-body);
  --font-mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, monospace;
}
[data-pair="b"] {
  --font-display: "Archivo Expanded", var(--font-body);
  --font-mono: "Space Mono", ui-monospace, SFMono-Regular, monospace;
}
/* ---- Hero layout ---- */
.hero {
  display: grid;
  gap: var(--space-4);
  padding-block: var(--space-4) var(--space-5);
  align-items: center;
}
@media (max-width: 1023px) {
  .hero { padding-block-start: var(--space-1); }
}
@media (min-width: 1024px) {
  .hero {
    grid-template-columns: 1.1fr 0.9fr;
    grid-template-areas: "copy phone" "board phone";
    gap: var(--space-3) var(--space-5);
    padding-block: var(--space-5) var(--space-6);
  }
  .hero-copy  { grid-area: copy; }
  .hero-phone { grid-area: phone; justify-self: end; }
  .hero-board { grid-area: board; align-self: start; }
}

.eyebrow {
  margin: 0 0 var(--space-2);
  font-family: var(--font-mono);
  font-size: 0.9375rem;
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--coral-text);
}

.hero-copy { container-type: inline-size; }

.hero h1 {
  /* Sized against the copy column so "Never forget a night." (the
     longest line, ~11.4em in Hanken 800) always fits on ONE line —
     no clause may wrap (Jack 2026-08-19). 8.6cqi ≈ 98cqi / 11.4em. */
  font-size: min(4.25rem, 8.6cqi);
  font-weight: 800;
  line-height: 1.06;
  /* Manual <br> breaks; text-wrap: balance overflowed the right
     padding on iOS Safari (found on Jack's device 2026-08-19). */
  text-wrap: wrap;
  overflow-wrap: break-word;
}

.subhead {
  margin: var(--space-3) 0 0;
  max-width: 34rem;
  font-size: 1.1875rem;
  line-height: 1.55;
  color: var(--muted);
}
@media (max-width: 699px) {
  .subhead { margin-top: var(--space-2); }
}

/* ---- Waitlist form ---- */
.waitlist {
  margin-top: var(--space-3);
  display: flex;
  gap: 0.6rem;
  flex-wrap: wrap;
}
.waitlist input[type="email"] {
  flex: 1 1 14rem;
  min-width: 0;
  padding: 0.72rem 1.1rem;
  font: inherit;
  color: var(--ink);
  background: #fff;
  border: 1px solid var(--line);
  border-radius: var(--radius-pill);
}
.waitlist input[type="email"]::placeholder { color: var(--faint); }
/* Honeypot — invisible to people, tempting to bots (wired in Piece 3) */
.waitlist .hp { position: absolute; left: -9999px; }

.waitlist-note {
  margin: 0.6rem 0 0;
  font-size: var(--text-caption);
  color: var(--faint);
}

/* Social proof as the app's avatar-stack idiom, not a gray caption
   (Jack 2026-08-20). */
.waitlist-count {
  margin: 0.8rem 0 0;
  display: flex;
  align-items: center;
  gap: 0.6rem;
  font-size: var(--text-small);
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}
.waitlist-count .avs { display: flex; }
.waitlist-count .avs i {
  width: 24px; height: 24px;
  border-radius: 50%;
  border: 2px solid var(--ground);
  display: inline-flex;
  align-items: flex-end;
  justify-content: center;
  overflow: hidden;   /* the silhouette's shoulders crop at the rim */
}
.waitlist-count .avs i svg { width: 70%; height: 70%; display: block; }
.waitlist-count .avs i + i { margin-left: -8px; }
.waitlist-count strong {
  color: var(--coral-text);
  font-weight: 700;
}

/* Author display values beat the hidden attribute's UA rule — make
   hidden mean hidden for the flexed waitlist pieces. */
.waitlist[hidden], .waitlist-success[hidden], .waitlist-count[hidden] { display: none; }

/* Success replaces the form — loud and unambiguous (Jack 2026-08-20). */
.waitlist-success {
  margin-top: var(--space-3);
  display: flex;
  align-items: flex-start;
  gap: 0.8rem;
  padding: 1rem 1.15rem;
  background: rgba(255, 122, 89, 0.10);
  border: 1px solid rgba(255, 122, 89, 0.35);
  border-radius: var(--radius);
}
.waitlist-success .check {
  flex: none;
  width: 28px; height: 28px;
  border-radius: 50%;
  background: var(--coral);
  color: #fff;
  display: flex; align-items: center; justify-content: center;
}
.waitlist-success .check svg { width: 14px; height: 14px; }
.waitlist-success .headline {
  display: block;
  font-weight: 700;
  font-size: 1.0625rem;
  color: var(--ink);
}
.waitlist-success .sub {
  display: block;
  margin-top: 0.15rem;
  font-size: var(--text-small);
  color: var(--muted);
}

/* ---- The app's UPCOMING card, replicated (source: Shows tab) ---- */
.hero-board {
  margin-top: var(--space-4);
  border: 1px solid var(--line);
  border-radius: 22px;
  background: #fff;
  box-shadow: 0 8px 28px rgba(0, 0, 0, 0.07);
  padding-bottom: 0.4rem;
}
@media (min-width: 1024px) { .hero-board { margin-top: 0; } }

.board-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  padding: 0.85rem 1rem 0.65rem;
}
.board-head span {
  font-weight: 700;
  font-size: 0.9375rem;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--ink);
}

.board-row {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: 0.9rem;
  padding: 0.65rem 1rem;
  border-top: 1px solid var(--line);
  margin-inline: 0.15rem;
}

.board-days {
  display: flex; flex-direction: column; align-items: center;
  min-width: 3rem;
}
.board-days .n {
  font-size: 1.375rem;
  font-weight: 800;
  line-height: 1.05;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}
.board-days .l {
  font-size: 0.5625rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
}

.board-main { min-width: 0; }
.board-artist {
  display: block;
  font-weight: 700;
  font-size: 1rem;
  line-height: 1.3;
  color: var(--ink);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.board-venue {
  display: block;
  font-size: 0.875rem;
  color: var(--muted);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

.board-when { text-align: right; }
.board-when .meta {
  display: flex; align-items: center; justify-content: flex-end;
  gap: 0.4rem;
  margin-bottom: 0.15rem;
}
.friends-wrap { position: relative; display: inline-flex; }

.friends-btn {
  display: inline-flex;
  border: 0; padding: 2px; margin: -2px;
  background: none; cursor: pointer;
  color: var(--coral);
  border-radius: 6px;
}
.friends-btn svg { width: 19px; height: 13px; }

/* "Friends going" preview — hover on desktop, tap on touch (#84,
   Jack's idea 2026-08-19). */
.friends-pop {
  position: absolute;
  bottom: calc(100% + 10px);
  right: -8px;
  width: 232px;
  padding: 0.75rem 0.85rem;
  background: #fff;
  border: 1px solid var(--line);
  border-radius: 14px;
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.14);
  text-align: left;
  opacity: 0;
  visibility: hidden;
  transform: translateY(4px);
  transition: opacity 140ms ease, transform 140ms ease, visibility 140ms;
  z-index: 10;
}
.friends-wrap:hover .friends-pop,
.friends-btn:focus-visible + .friends-pop,
.friends-wrap.open .friends-pop {
  opacity: 1; visibility: visible; transform: none;
}

.pop-avatars { display: flex; margin-bottom: 0.45rem; }
.pop-avatars i {
  width: 26px; height: 26px;
  border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  font-style: normal;
  font-size: 0.75rem; font-weight: 700;
  color: rgba(0, 0, 0, 0.55);
  border: 2px solid #fff;
}
.pop-avatars i + i { margin-left: -7px; }

.pop-text {
  display: block;
  font-size: 0.8425rem;
  line-height: 1.45;
  color: var(--ink);
}
.pop-cap {
  display: block;
  margin-top: 0.3rem;
  font-size: 0.75rem;
  line-height: 1.4;
  color: var(--muted);
}
.board-when .chip {
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--muted);
  background: #F2F2F7;   /* lightest — the card gray (Jack 2026-08-21) */
  border-radius: 6px;
  padding: 0.1rem 0.5rem;
}
.board-when .date {
  display: block;
  font-size: 0.9375rem;
  font-weight: 600;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* ---- Phone: real frame composite (Piece 4) ----
   The screenshot sits UNDER assets/frame.webp (a device frame with a
   transparent screen cutout, trimmed to 1373×2831). Screen-cutout
   insets measured from the PNG's alpha channel; the elliptical
   border-radius pair approximates the device's circular screen
   corners at any render width (12% of W ≈ 5.56% of H). */
.hero-phone { display: flex; flex-direction: column; align-items: center; gap: var(--space-2); }

.phone {
  margin: 0;   /* figure's UA 40px side margins broke edge alignment */
  position: relative;
  width: min(92vw, 340px);
  aspect-ratio: 294 / 601;
  filter: drop-shadow(0 2px 6px rgba(0, 0, 0, 0.08))
          drop-shadow(0 24px 40px rgba(0, 0, 0, 0.16));
}
.phone-frame {
  position: absolute;
  inset: 0;
  width: 100%; height: 100%;
  z-index: 2;
  pointer-events: none;
}
/* Clip box = the SVG frame's body rect (3,1.5 288×598 r52.5 in its
   294×601 viewBox) — the geometry is authored, so clip and frame
   agree by construction. Screenshot corners can't escape it. */
.phone-clip {
  position: absolute;
  inset: 0.25% 1.02% 0.25% 1.02%;
  border-radius: 18.23% / 8.78%;
  overflow: hidden;
}
.phone-screen {
  position: absolute;
  /* Screenshot rect = the SVG's screen window (14,12 265×576) plus a
     2px tuck under the bezel per side, in clip-box percentages. */
  inset: 1.42% 3.47% 1.59% 3.13%;
  /* Apple's true display corner radius (62pt = 40.9px at this scale,
     +2px tuck) on the screenshot's own box. The real curve is a
     continuous squircle; circular is CSS's closest. */
  border-radius: 15.95% / 7.4%;
  background: var(--card);
  overflow: hidden;
  display: flex; align-items: center; justify-content: center;
}
/* fill, not cover: the shot's aspect is within 0.6% of the cutout's,
   and stretching that hair keeps the shot's Dynamic Island locked
   under the frame's island artwork at every render size. */
.phone-screen img { width: 100%; height: 100%; object-fit: fill; }
.phone-screen .slot-label {
  font-family: var(--font-mono);
  font-size: 0.6875rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--faint);
  text-align: center;
}

.phone-caption {
  margin: 0;
  font-size: var(--text-caption);
  color: var(--faint);
  text-align: center;
}

/* ============================================================
   Piece 4 — home body (clause sections + punched-ticket CTA)
   ============================================================ */

.feature {
  display: grid;
  gap: var(--space-4);
  padding-block: var(--space-5);
  align-items: center;
}

@media (min-width: 900px) {
  .feature {
    /* shots column wider so the pairs render larger */
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.35fr);
    gap: var(--space-4);
    /* Symmetric, generous — sections were colliding when the shots
       column ran taller than the copy (Jack 2026-08-20). */
    padding-block: var(--space-6);
  }
  /* Alternate sides so the page zig-zags — the wide (shots) column
     mirrors with it */
  .feature:nth-of-type(odd) {
    grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr);
  }
  .feature:nth-of-type(odd) .feature-copy { order: 2; }
}

.feature h2 {
  font-size: var(--text-h2);
  font-weight: 800;
}
.feature-copy p:not(.eyebrow) {
  margin: var(--space-2) 0 0;
  max-width: 30rem;
  color: var(--muted);
}
.feature-copy .eyebrow { margin-bottom: var(--space-1); }

/* Phone pair: front shot + a smaller, receded second one */
.feature-shots {
  display: flex;
  justify-content: center;
  align-items: flex-start;
  gap: clamp(0.5rem, 1.5vw, 1rem);
}
/* Half the column each (minus the gap) so a pair always fills the
   available width — critical on mobile (Jack 2026-08-21) */
.phone--sm {
  width: min(calc(50% - 0.25rem), 300px);
}
/* A lone shot (Stubs section) gets to be larger still */
.feature-shots .phone--sm:only-child {
  width: min(80%, 330px);
}
/* Equal size to its partner (Jack 2026-08-21) — only the vertical
   stagger remains for composition */
.phone--back {
  margin-top: var(--space-4);
}

/* Day-of detail table — board language (mono labels), app-card body */
.detail-table {
  margin-top: var(--space-3);
  max-width: 24rem;
  background: #fff;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.05);
  /* no overflow clip — the row popovers float above the card; the
     head/last-row carry the corner rounding instead */
}
.dt-head { border-radius: calc(var(--radius) - 1px) calc(var(--radius) - 1px) 0 0; }
.dt-head {
  padding: 0.6rem 1rem;
  background: var(--card);
  font-family: var(--font-mono);
  font-size: 0.6875rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted);
}
.dt-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--space-2);
  padding: 0.55rem 1rem;
}
.dt-row + .dt-row { border-top: 1px solid var(--line); }
.dt-label {
  font-family: var(--font-mono);
  font-size: 0.6875rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--faint);
}
.dt-value {
  font-size: var(--text-small);
  font-weight: 600;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
  text-align: right;
}

/* ---- Punched-ticket CTA (reference: classic admit-one ticket —
   corner scoops, scalloped side edges, inner frame; Jack 2026-08-21).
   Shape system: the SHELL paints coral and masks the ticket shape;
   the INNER paints white and masks the same shape inset by the
   border width — every cut (scoop + scallop) is concentric, so the
   coral rim follows all the arcs. A CSS border can't trace a mask. ---- */
.ticket-wrap {
  margin-block: var(--space-6);
  filter: drop-shadow(0 1px 1.5px rgba(0, 0, 0, 0.10))
          drop-shadow(0 10px 30px rgba(0, 0, 0, 0.08));
}
.ticket-cta {
  --scoop: 26px;    /* corner indent radius */
  --tb: 2px;        /* coral border width */
  --bite: 5px;      /* side scallop radius */
  --pitch: 22px;    /* scallop spacing */
  position: relative;
  padding: var(--tb);
  background: var(--coral);
  -webkit-mask-image:
    radial-gradient(circle var(--scoop) at 0 0,       transparent calc(var(--scoop) - 0.5px), #000 var(--scoop)),
    radial-gradient(circle var(--scoop) at 100% 0,    transparent calc(var(--scoop) - 0.5px), #000 var(--scoop)),
    radial-gradient(circle var(--scoop) at 0 100%,    transparent calc(var(--scoop) - 0.5px), #000 var(--scoop)),
    radial-gradient(circle var(--scoop) at 100% 100%, transparent calc(var(--scoop) - 0.5px), #000 var(--scoop)),
    radial-gradient(circle var(--bite) at 0 50%,      transparent calc(var(--bite) - 0.5px), #000 var(--bite)),
    radial-gradient(circle var(--bite) at 100% 50%,   transparent calc(var(--bite) - 0.5px), #000 var(--bite));
  -webkit-mask-size: 100% 100%, 100% 100%, 100% 100%, 100% 100%, 100% var(--pitch), 100% var(--pitch);
  -webkit-mask-repeat: no-repeat, no-repeat, no-repeat, no-repeat, repeat-y, repeat-y;
  -webkit-mask-composite: source-in;
  mask-image:
    radial-gradient(circle var(--scoop) at 0 0,       transparent calc(var(--scoop) - 0.5px), #000 var(--scoop)),
    radial-gradient(circle var(--scoop) at 100% 0,    transparent calc(var(--scoop) - 0.5px), #000 var(--scoop)),
    radial-gradient(circle var(--scoop) at 0 100%,    transparent calc(var(--scoop) - 0.5px), #000 var(--scoop)),
    radial-gradient(circle var(--scoop) at 100% 100%, transparent calc(var(--scoop) - 0.5px), #000 var(--scoop)),
    radial-gradient(circle var(--bite) at 0 50%,      transparent calc(var(--bite) - 0.5px), #000 var(--bite)),
    radial-gradient(circle var(--bite) at 100% 50%,   transparent calc(var(--bite) - 0.5px), #000 var(--bite));
  mask-size: 100% 100%, 100% 100%, 100% 100%, 100% 100%, 100% var(--pitch), 100% var(--pitch);
  mask-repeat: no-repeat, no-repeat, no-repeat, no-repeat, repeat-y, repeat-y;
  mask-composite: intersect;
}
.ticket-inner {
  position: relative;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  gap: var(--space-3);
  padding: clamp(2rem, 4.5vw, 3rem);
  background: #fff;
  /* every cut grows by the border width; centers stay put (this box
     sits --tb inside the shell, so centers offset back by --tb and
     the repeating scallops shift up by --tb to stay concentric) */
  --iscoop: calc(var(--scoop) + var(--tb));
  --ibite: calc(var(--bite) + var(--tb));
  --ioff: calc(-1 * var(--tb));
  --iend: calc(100% + var(--tb));
  -webkit-mask-image:
    radial-gradient(circle var(--iscoop) at var(--ioff) var(--ioff), transparent calc(var(--iscoop) - 0.5px), #000 var(--iscoop)),
    radial-gradient(circle var(--iscoop) at var(--iend) var(--ioff), transparent calc(var(--iscoop) - 0.5px), #000 var(--iscoop)),
    radial-gradient(circle var(--iscoop) at var(--ioff) var(--iend), transparent calc(var(--iscoop) - 0.5px), #000 var(--iscoop)),
    radial-gradient(circle var(--iscoop) at var(--iend) var(--iend), transparent calc(var(--iscoop) - 0.5px), #000 var(--iscoop)),
    radial-gradient(circle var(--ibite) at var(--ioff) 50%,          transparent calc(var(--ibite) - 0.5px), #000 var(--ibite)),
    radial-gradient(circle var(--ibite) at var(--iend) 50%,          transparent calc(var(--ibite) - 0.5px), #000 var(--ibite));
  -webkit-mask-size: 100% 100%, 100% 100%, 100% 100%, 100% 100%, 100% var(--pitch), 100% var(--pitch);
  -webkit-mask-repeat: no-repeat, no-repeat, no-repeat, no-repeat, repeat-y, repeat-y;
  -webkit-mask-position: 0 0, 0 0, 0 0, 0 0, 0 var(--ioff), 0 var(--ioff);
  -webkit-mask-composite: source-in;
  mask-image:
    radial-gradient(circle var(--iscoop) at var(--ioff) var(--ioff), transparent calc(var(--iscoop) - 0.5px), #000 var(--iscoop)),
    radial-gradient(circle var(--iscoop) at var(--iend) var(--ioff), transparent calc(var(--iscoop) - 0.5px), #000 var(--iscoop)),
    radial-gradient(circle var(--iscoop) at var(--ioff) var(--iend), transparent calc(var(--iscoop) - 0.5px), #000 var(--iscoop)),
    radial-gradient(circle var(--iscoop) at var(--iend) var(--iend), transparent calc(var(--iscoop) - 0.5px), #000 var(--iscoop)),
    radial-gradient(circle var(--ibite) at var(--ioff) 50%,          transparent calc(var(--ibite) - 0.5px), #000 var(--ibite)),
    radial-gradient(circle var(--ibite) at var(--iend) 50%,          transparent calc(var(--ibite) - 0.5px), #000 var(--ibite));
  mask-size: 100% 100%, 100% 100%, 100% 100%, 100% 100%, 100% var(--pitch), 100% var(--pitch);
  mask-repeat: no-repeat, no-repeat, no-repeat, no-repeat, repeat-y, repeat-y;
  mask-position: 0 0, 0 0, 0 0, 0 0, 0 var(--ioff), 0 var(--ioff);
  mask-composite: intersect;
}
/* The inner frame line (reference's inside border): the ticket's own
   shape minus the scallops — concave corner arcs CONCENTRIC with the
   corner scoops (parallel curve: radius grows by the inset). Drawn as
   an ink fill masked to the frame-outer shape, with a white fill
   masked 1.5px further in — what remains visible is the line. */
.ticket-frame {
  --finset: 16px;   /* frame inset from the white surface */
  --fline: 1.5px;   /* frame line width */
  --foff: calc(-1 * (var(--tb) + var(--finset)));
  --fend: calc(100% + var(--tb) + var(--finset));
  --frad: calc(var(--scoop) + var(--tb) + var(--finset));
  position: absolute;
  inset: var(--finset);
  background: var(--ink);
  opacity: 0.85;
  pointer-events: none;
  -webkit-mask-image:
    radial-gradient(circle var(--frad) at var(--foff) var(--foff), transparent calc(var(--frad) - 0.5px), #000 var(--frad)),
    radial-gradient(circle var(--frad) at var(--fend) var(--foff), transparent calc(var(--frad) - 0.5px), #000 var(--frad)),
    radial-gradient(circle var(--frad) at var(--foff) var(--fend), transparent calc(var(--frad) - 0.5px), #000 var(--frad)),
    radial-gradient(circle var(--frad) at var(--fend) var(--fend), transparent calc(var(--frad) - 0.5px), #000 var(--frad));
  -webkit-mask-composite: source-in;
  mask-image:
    radial-gradient(circle var(--frad) at var(--foff) var(--foff), transparent calc(var(--frad) - 0.5px), #000 var(--frad)),
    radial-gradient(circle var(--frad) at var(--fend) var(--foff), transparent calc(var(--frad) - 0.5px), #000 var(--frad)),
    radial-gradient(circle var(--frad) at var(--foff) var(--fend), transparent calc(var(--frad) - 0.5px), #000 var(--frad)),
    radial-gradient(circle var(--frad) at var(--fend) var(--fend), transparent calc(var(--frad) - 0.5px), #000 var(--frad));
  mask-composite: intersect;
}
.ticket-frame::after {
  content: "";
  position: absolute;
  inset: var(--fline);
  background: #fff;
  --f2off: calc(-1 * (var(--tb) + var(--finset) + var(--fline)));
  --f2end: calc(100% + var(--tb) + var(--finset) + var(--fline));
  --f2rad: calc(var(--scoop) + var(--tb) + var(--finset) + var(--fline));
  -webkit-mask-image:
    radial-gradient(circle var(--f2rad) at var(--f2off) var(--f2off), transparent calc(var(--f2rad) - 0.5px), #000 var(--f2rad)),
    radial-gradient(circle var(--f2rad) at var(--f2end) var(--f2off), transparent calc(var(--f2rad) - 0.5px), #000 var(--f2rad)),
    radial-gradient(circle var(--f2rad) at var(--f2off) var(--f2end), transparent calc(var(--f2rad) - 0.5px), #000 var(--f2rad)),
    radial-gradient(circle var(--f2rad) at var(--f2end) var(--f2end), transparent calc(var(--f2rad) - 0.5px), #000 var(--f2rad));
  -webkit-mask-composite: source-in;
  mask-image:
    radial-gradient(circle var(--f2rad) at var(--f2off) var(--f2off), transparent calc(var(--f2rad) - 0.5px), #000 var(--f2rad)),
    radial-gradient(circle var(--f2rad) at var(--f2end) var(--f2off), transparent calc(var(--f2rad) - 0.5px), #000 var(--f2rad)),
    radial-gradient(circle var(--f2rad) at var(--f2off) var(--f2end), transparent calc(var(--f2rad) - 0.5px), #000 var(--f2rad)),
    radial-gradient(circle var(--f2rad) at var(--f2end) var(--f2end), transparent calc(var(--f2rad) - 0.5px), #000 var(--f2rad));
  mask-composite: intersect;
}

/* Content rides above the frame's paint (the frame is absolutely
   positioned, which otherwise paints over in-flow content) */
.ticket-main, .ticket-divider, .ticket-stub, .ticket-serial { position: relative; z-index: 1; }

/* The side serial, reading bottom-up like a real stub; its border
   paints on the visual RIGHT after the 180-degree turn — the line
   separating numbers from the ticket body. */
.ticket-serial {
  writing-mode: vertical-rl;
  transform: rotate(180deg);
  align-self: stretch;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-mono);
  font-size: 1.125rem;
  letter-spacing: 0.3em;
  color: var(--ink);
  opacity: 0.8;
  border-left: 1.5px solid rgba(17, 17, 17, 0.55);
  padding-left: 0.9rem;
}
/* Right-side twin: unrotated so its top faces the right edge, the
   separator (border-left) lands between it and the ticket body */
.ticket-serial--r { transform: none; }

/* Mobile-only head: the copy lives ABOVE the ticket so the card
   holds just the form (Jack 2026-08-21, proportions). Desktop keeps
   the copy inside. */
.ticket-head { margin-bottom: var(--space-3); }
.ticket-head h2 { font-size: var(--text-h2); font-weight: 800; }
.ticket-head p:not(.eyebrow) { margin: var(--space-1) 0 0; color: var(--muted); }
.ticket-head .eyebrow { margin-bottom: var(--space-1); }
@media (min-width: 900px) { .ticket-head { display: none; } }
@media (max-width: 899px) { .ticket-copy-desktop { display: none; } }

/* The note is an error slot now — invisible until JS fills it */
.waitlist-note:empty { display: none; }

.ticket-main h2 { font-size: var(--text-h2); font-weight: 800; }
.ticket-main p:not(.eyebrow):not(.waitlist-note) {
  margin: var(--space-2) 0 0;
  color: var(--muted);
}
.ticket-main .eyebrow { margin-bottom: var(--space-1); }
.ticket-main .signup { min-width: 0; }
.ticket-main .waitlist { margin-top: 0; }
@media (min-width: 900px) {
  .ticket-main .waitlist { margin-top: var(--space-3); }
}

/* Perforation: dashed rule between body and stub, inside the frame */
.ticket-divider { border-top: 2px dashed var(--line); }

/* Stub: a REAL QR code (getboleto.com + utm_source=ticket-qr) */
.ticket-stub {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.8rem;
  min-width: 0;
}
.stub-qr {
  width: min(40vw, 116px);
  height: auto;
  aspect-ratio: 1;
  color: var(--ink);
}
.stub-label {
  font-family: var(--font-mono);
  font-size: 0.6875rem;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--faint);
}

/* Mobile: no QR stub — nobody scans their own screen (Jack
   2026-08-21). The ticket is serial | form | serial, copy above;
   spacing + serial size tightened so the form keeps real width. */
@media (max-width: 899px) {
  .ticket-stub, .ticket-divider { display: none; }
  .ticket-wrap { margin-top: 0; }
  .ticket-head { margin: var(--space-5) 0 var(--space-3); }
  .ticket-inner {
    grid-template-columns: minmax(0, 1fr);
    gap: var(--space-2);
    padding: 1.5rem 1.25rem;
  }
  .ticket-frame { --finset: 8px; }
  .ticket-serial { display: none; }
}

/* Desktop: horizontal ticket — serial | main | perforation | stub */
@media (min-width: 900px) {
  .ticket-inner {
    grid-template-columns: auto minmax(0, 1fr) auto 175px auto;
    gap: clamp(1.5rem, 4vw, 2.75rem);
    align-items: center;
  }
  .ticket-divider {
    border-top: 0;
    border-left: 2px dashed var(--line);
    align-self: stretch;
  }
  .stub-qr { width: 128px; }
}

/* Small screens: the form stacks and the button matches the input's
   full width and height (Jack 2026-08-21) — hero and ticket alike. */
@media (max-width: 560px) {
  .waitlist { flex-direction: column; }
  .waitlist input[type="email"],
  .waitlist .btn {
    flex: none;
    width: 100%;
    height: 3.1rem;
    padding-block: 0;
  }
}

/* ---- Live board refresh (Piece 4) ----
   The button sits OUTSIDE the card (above its top-right corner) so
   the card itself stays a faithful replica of the app's (Jack
   2026-08-20). DOM-wise it lives inside .hero-board for layout. */
.hero-board { position: relative; }
.board-refresh {
  position: absolute;
  bottom: calc(100% + 6px);
  left: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px; height: 36px;
  padding: 0;
  border: 0;
  border-radius: 8px;
  background: none;
  color: var(--coral);   /* the accent coral, same as buttons/countdowns */
  cursor: pointer;
  transition: color 120ms ease;
}
.board-refresh:hover { color: var(--coral-press); }
.board-refresh svg { width: 24px; height: 24px; }
.board-refresh.spin svg {
  transition: transform 450ms ease;
  transform: rotate(360deg);
}
/* Desktop: the board is beside the phone with no headroom above it in
   the grid — give it just enough to host the floating button. */
@media (min-width: 1024px) {
  .hero-board { margin-top: 44px; }
}

/* Feature bullets (Track shows section) — terse board-style lines */
.feature-list {
  margin: var(--space-2) 0 0;
  padding: 0;
  list-style: none;
  max-width: 30rem;
  display: flex;
  flex-direction: column;
  gap: 0.55rem;
  color: var(--muted);
}
.feature-list li {
  position: relative;
  padding-left: 1.15rem;
}
.feature-list li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.62em;
  width: 7px;
  height: 7px;
  border-radius: 2px;
  background: var(--coral);
}

/* Detail-table accents: coral handle, app-green amenity check */
.dt-handle { color: var(--coral-text); font-weight: 700; }
.dt-check {
  width: 13px; height: 13px;
  margin-right: 0.35rem;
  vertical-align: -1px;
  color: #34C759;   /* iOS systemGreen, as the app renders amenities */
}

/* "Sample ..." card labels (Jack 2026-08-21) */
.card-label {
  margin: var(--space-3) 0 0.5rem;
  font-family: var(--font-mono);
  font-size: 0.6875rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--faint);
}
.card-label--board {
  position: absolute;
  bottom: calc(100% + 13px);
  right: 0;
  margin: 0;
}

/* Detail-table label matches the board's (above top-right) */
.detail-wrap {
  position: relative;
  max-width: 24rem;
  margin-top: calc(var(--space-3) + 26px);
}
.detail-wrap .detail-table { margin-top: 0; }

/* Venue row's directions affordance */
.dt-nav {
  width: 12px; height: 12px;
  margin-left: 0.4rem;
  vertical-align: -1px;
  color: var(--coral);
}


/* Detail-table popover triggers */
.dt-handle-btn {
  font: inherit;
  font-weight: 700;
  color: var(--coral-text);
}
.dt-nav, .dt-check { display: block; }
.detail-table .friends-wrap { vertical-align: -2px; }
/* the icon nudge must not drop the TEXT trigger off the baseline */
.detail-table .friends-wrap:has(.dt-handle-btn) { vertical-align: baseline; }
/* Optical alignment: trailing triggers' ink stops short of their box
   (arrow tip, button padding) — pull them right to the shared edge */
.detail-table .dt-value .friends-wrap:last-child { margin-right: -4px; }
.detail-table .friends-btn { margin-left: 0.4rem; }
.detail-table .dt-check + span, .detail-table .friends-btn .dt-check { margin: 0; }
.detail-table .friends-wrap:first-child .friends-btn { margin-left: 0; margin-right: 0.4rem; }

/* Board row time — the app's faint third line */
.board-when .time {
  display: block;
  font-size: 0.75rem;
  color: var(--faint);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* QR-scan easter egg: a mini ticket greeting the scanner */
.scan-ticket {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  margin-bottom: var(--space-3);
  padding: 0.85rem 1.1rem;
  background: var(--coral);
  color: #fff;
  font-size: var(--text-small);
  --mini: 10px;
  -webkit-mask-image:
    radial-gradient(circle var(--mini) at 0 0,       transparent calc(var(--mini) - 0.5px), #000 var(--mini)),
    radial-gradient(circle var(--mini) at 100% 0,    transparent calc(var(--mini) - 0.5px), #000 var(--mini)),
    radial-gradient(circle var(--mini) at 0 100%,    transparent calc(var(--mini) - 0.5px), #000 var(--mini)),
    radial-gradient(circle var(--mini) at 100% 100%, transparent calc(var(--mini) - 0.5px), #000 var(--mini));
  -webkit-mask-composite: source-in;
  mask-image:
    radial-gradient(circle var(--mini) at 0 0,       transparent calc(var(--mini) - 0.5px), #000 var(--mini)),
    radial-gradient(circle var(--mini) at 100% 0,    transparent calc(var(--mini) - 0.5px), #000 var(--mini)),
    radial-gradient(circle var(--mini) at 0 100%,    transparent calc(var(--mini) - 0.5px), #000 var(--mini)),
    radial-gradient(circle var(--mini) at 100% 100%, transparent calc(var(--mini) - 0.5px), #000 var(--mini));
  mask-composite: intersect;
}
.scan-ticket[hidden] { display: none; }
.scan-eyebrow {
  font-family: var(--font-mono);
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
}

/* ============================================================
   Subpages (Piece 5) — privacy / terms / support / press.
   Prose column narrower than .wrap; same voice as the home page.
   ============================================================ */

.page {
  width: 100%;
  max-width: 720px;
  margin-inline: auto;
  padding: var(--space-5) clamp(20px, 5vw, 40px) var(--space-6);
  flex: 1;                       /* short pages still pin the footer down */
}

.page h1 {
  font-family: var(--font-display);
  font-size: var(--text-h2);
  line-height: 1.15;
  margin: 0 0 var(--space-1);
}

.page-updated {
  color: var(--muted);
  font-size: var(--text-small);
  margin: 0 0 var(--space-4);
}

.page h2 {
  font-size: 1.25rem;
  line-height: 1.3;
  margin: var(--space-4) 0 var(--space-1);
}

.page h3 {
  font-size: 1.0625rem;
  margin: var(--space-3) 0 var(--space-1);
}

.page p { margin: 0 0 var(--space-2); }

.page ul {
  margin: 0 0 var(--space-2);
  padding-left: 1.25rem;
}
.page li { margin-bottom: var(--space-1); }

.page a { color: var(--coral-text); }

.page code {
  font-family: var(--font-mono);
  font-size: 0.875em;
  background: var(--card);
  padding: 0.1em 0.35em;
  border-radius: 6px;
}

.page-cta { margin: var(--space-3) 0; }

/* Footer marks the page you're on */
.footer nav a[aria-current="page"] { color: var(--ink); }

/* ---- Press kit ---- */

.press-asset {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  text-decoration: none;
}
.press-asset img { border-radius: 22px; display: block; }
.press-asset span { font-size: var(--text-small); }

.press-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: var(--space-2);
  margin: var(--space-2) 0 var(--space-3);
}
.press-grid img {
  width: 100%;
  height: auto;
  display: block;
  border-radius: 14px;
  border: 1px solid var(--line);
}
