/* ============================================================
   SavvySocials — Landing page
   Vanilla, #nobuild CSS (no Tailwind, no preprocessor) — Campfire style.
   Responsive without a single viewport @media query: layout adapts via
   flex-wrap, intrinsic flex-basis, auto-fit grids and clamp(). The only
   media queries are capability-based (hover/pointer) — no device is "mobile".

   Lifting into the Rails app:
     • Canonical tokens below mirror the app's @theme 1:1 (--color-*).
     • Wire: root "pages#home"; a landing layout linking this file + fonts;
       Stimulus for the audience toggle + venue carousel; t("brand.name")
       for the wordmark; image_tag for the poster.
   ============================================================ */

/* Switzer, self-hosted — see README "One sans, no serif". */
@font-face {
  font-family: 'Switzer';
  src: url("/fonts/Switzer-Variable.woff2") format('woff2-variations');
  font-weight: 100 900; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Switzer';
  src: url("/fonts/Switzer-VariableItalic.woff2") format('woff2-variations');
  font-weight: 100 900; font-style: italic; font-display: swap;
}

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

:root {
  /* Canonical Editorial tokens — identical values to the app's @theme.
     Parity is enforced by test/assets/palette_parity_test.rb, not by this note. */
  --color-canvas:      #F3E7D3;
  --color-surface:     #E7D8BE;
  --color-card:        #FDF8EE;
  --color-ink:         #241B14;
  --color-ink-strong:  #130C07;
  --color-muted:       #6B5848;
  --color-ink-faint:   #9C8775;
  --color-brand:       #B6780C;
  --color-brand-dark:  #8C5B06;
  --color-brand-light: #D58C0E;
  --color-brand-soft:  #EDCD97;
  --on-brand:           #241B14;
  --color-accent:      #8E2927;
  --color-accent-soft: #E8C9C4;
  --on-accent:          #F3E7D3;
  --color-sage:        #4F7A3C;
  --color-sage-soft:   #C9D9B9;
  --on-positive:        #FFFFFF;
  --on-scrim:           #FFFFFF;
  --color-border:      #D8C3A3;
  --color-border-soft: #E7DACD;

  /* Short aliases used throughout this file (terse + portable) */
  --canvas: var(--color-canvas);   --surface: var(--color-surface);   --card: var(--color-card);
  --ink: var(--color-ink);         --ink-strong: var(--color-ink-strong);
  --muted: var(--color-muted);     --ink-faint: var(--color-ink-faint);
  --brand: var(--color-brand);     --brand-dark: var(--color-brand-dark);
  --brand-light: var(--color-brand-light); --brand-soft: var(--color-brand-soft);
  --accent: var(--color-accent);   --accent-soft: var(--color-accent-soft);
  --sage: var(--color-sage);       --sage-soft: var(--color-sage-soft);
  --border: var(--color-border);   --border-soft: var(--color-border-soft);

  --font-sans:  'Switzer', ui-sans-serif, system-ui, sans-serif;
  /* --font-serif points at Switzer too; keep the token, don't rewrite call sites. */
  --font-serif: 'Switzer', ui-sans-serif, system-ui, sans-serif;
  --font-hand:  'Caveat', ui-serif, cursive;

  /* Fluid ramp, capped at the 1440px canvas — see README "Two type scales". */
  --text-x-small:    clamp(0.6875rem, 0.8333vw, 0.75rem);
  --text-small:      clamp(0.8125rem, 0.9722vw, 0.875rem);
  --text:            clamp(0.9375rem, 1.1111vw, 1rem);
  --text-medium:     clamp(1rem, 1.1806vw, 1.0625rem);
  --text-large:      clamp(1.125rem, 1.3889vw, 1.25rem);
  --text-x-large:    clamp(1.3125rem, 1.875vw, 1.6875rem);
  --text-2x-large:   clamp(1.75rem, 2.2917vw, 2.0625rem);
  --text-3x-large:   clamp(2rem, 2.7778vw, 2.5rem);
  --text-4x-large:   clamp(2.5rem, 3.3333vw, 3rem);

  /* --tracking-wide is for uppercase micro-labels, the one place spacing opens up. */
  --tracking-tight: -0.022em;
  --tracking:       -0.012em;
  --tracking-wide:   0.08em;

  --leading-tight: 1.15;
  --leading-snug:  1.3;
  --leading:       1.5;
}

/* Dark — mirrors every light token 1:1 (also in application.css) — see design-system.md "Theming". */
html[data-theme="dark"] {
  color-scheme: dark;
  --color-canvas:      #15110D;
  --color-surface:     #1E1813;
  --color-card:        #251E17;
  --color-ink:         #EDE3D2;
  --color-ink-strong:  #FBF4E6;
  --color-muted:       #A99884;
  --color-ink-faint:   #7A6B5A;
  --color-brand:       #F4B02C;   /* 9.9:1 */
  --color-brand-dark:  #C18615;
  --color-brand-light: #F6BF55;   /* 11.2:1 */
  --color-brand-soft:  #493513;
  --on-brand:           #241B14;   /* 8.9:1 on gold */
  --color-accent:      #C9584A;
  --color-accent-soft: #4A2A22;
  --on-accent:          #130C07;
  --color-sage:        #7FB05F;
  --color-sage-soft:   #2A3A20;
  --on-positive:        #241B14;
  --on-scrim:           #FFFFFF;
  --color-border:      #3A2F23;
  --color-border-soft: #241D16;
}

@media (prefers-color-scheme: dark) {
  html:not([data-theme]) {
    /* Identical to html[data-theme="dark"] above — PaletteParityTest holds them together. */
    color-scheme: dark;
    --color-canvas:      #15110D;
    --color-surface:     #1E1813;
    --color-card:        #251E17;
    --color-ink:         #EDE3D2;
    --color-ink-strong:  #FBF4E6;
    --color-muted:       #A99884;
    --color-ink-faint:   #7A6B5A;
    --color-brand:       #F4B02C;   /* 9.9:1 */
    --color-brand-dark:  #C18615;
    --color-brand-light: #F6BF55;   /* 11.2:1 */
    --color-brand-soft:  #493513;
    --on-brand:           #241B14;   /* 8.9:1 on gold */
    --color-accent:      #C9584A;
    --color-accent-soft: #4A2A22;
    --on-accent:          #130C07;
    --color-sage:        #7FB05F;
    --color-sage-soft:   #2A3A20;
    --on-positive:        #241B14;
    --on-scrim:           #FFFFFF;
    --color-border:      #3A2F23;
    --color-border-soft: #241D16;
  }
}

/* Print-correct subtrees opt out (mirrors application.css) — see design-system.md. */
.force-light {
  color-scheme: light;
  --color-canvas:      #F3E7D3;
  --color-surface:     #E7D8BE;
  --color-card:        #FDF8EE;
  --color-ink:         #241B14;
  --color-ink-strong:  #130C07;
  --color-muted:       #6B5848;
  --color-ink-faint:   #9C8775;
  --color-brand:       #B6780C;
  --color-brand-dark:  #8C5B06;
  --color-brand-light: #D58C0E;
  --color-brand-soft:  #EDCD97;
  --on-brand:           #241B14;
  --color-accent:      #8E2927;
  --color-accent-soft: #E8C9C4;
  --on-accent:          #F3E7D3;
  --color-sage:        #4F7A3C;
  --color-sage-soft:   #C9D9B9;
  --on-positive:        #FFFFFF;
  --on-scrim:           #FFFFFF;
  --color-border:      #D8C3A3;
  --color-border-soft: #E7DACD;

  --canvas: var(--color-canvas);   --surface: var(--color-surface);   --card: var(--color-card);
  --ink: var(--color-ink);         --ink-strong: var(--color-ink-strong);
  --muted: var(--color-muted);     --ink-faint: var(--color-ink-faint);
  --brand: var(--color-brand);     --brand-dark: var(--color-brand-dark);
  --brand-light: var(--color-brand-light); --brand-soft: var(--color-brand-soft);
  --accent: var(--color-accent);   --accent-soft: var(--color-accent-soft);
  --sage: var(--color-sage);       --sage-soft: var(--color-sage-soft);
  --border: var(--color-border);   --border-soft: var(--color-border-soft);
}

html { scroll-behavior: smooth; }
body {
  background: var(--canvas);
  color: var(--ink);
  font-family: var(--font-sans);
  -webkit-font-smoothing: antialiased;
  line-height: 1.5;
}
/* Fluid full-bleed-ish container: uses the viewport up to a wide cap,
   with side gutters that shrink on small screens (no breakpoints). */
.wrap { width: min(100%, 1400px); margin-inline: auto; padding-inline: clamp(1.25rem, 4vw, 4rem); }

/* ── Appbar ─────────────────────────────────────────────── */
.appbar {
  position: sticky; top: 0; z-index: 50;
  background: color-mix(in srgb, var(--canvas) 85%, transparent);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--border-soft);
  container-type: inline-size;   /* lets the appbar restyle by its OWN width */
  padding-top: var(--injected-safe-inset-top, env(safe-area-inset-top, 0px)); /* bridge/insets_controller.js in the app */
}
.appbar-inner {
  display: flex; align-items: center; justify-content: space-between; gap: 10px 16px;
  min-height: 56px; padding-block: 8px;
}

/* Audience toggle — a sticky row just below the appbar. The band carries a
   solid canvas-matched background so it reads as empty page (no distinct
   colour, no separator) but page content scrolls UNDER it, not through it —
   it behaves like a nav bar rather than a floating see-through pill. */
.audience-bar {
  position: sticky; top: 64px; z-index: 40;
  padding: 6px clamp(1.25rem, 4vw, 4rem) 12px;
  display: flex; justify-content: center;
  background: var(--canvas);
}
/* Fill the seam between the appbar and this band: a canvas strip above the
   band that tucks behind the appbar (lower z-index), so no scroll content
   shows through the gap regardless of the appbar's exact height. */
.audience-bar::before {
  content: ""; position: absolute; left: 0; right: 0;
  bottom: 100%; height: 24px; background: var(--canvas);
}
/* Close to but not exactly --shadow-ink (31,26,18) — a shadow tint, physics-fixed either way. */
.audience-bar .toggle { box-shadow: 0 6px 20px rgba(40,30,20,0.12); }
/* Italic 400 is the mark's identity, guarded by wordmark_consistency_test. */
.wordmark {
  font-family: var(--font-serif); font-style: italic; font-weight: 400; font-size: 22px;
  letter-spacing: -0.02em; color: var(--ink-strong); text-decoration: none;
}
.wordmark .wordmark-dot { color: var(--brand); }

/* Lockup mode — only when the bell mark is present (appbar). Scoped via
   :has() so the text-only footer wordmark keeps its plain inline layout.
   Mark = the 3D bell-only (brand-mark.svg), matching the app chrome. */
.wordmark:has(.wordmark-mark) { display: inline-flex; align-items: center; gap: 0.3em; }
.wordmark-mark { display: inline-flex; flex: none; }
.wordmark-mark :is(svg, img) { display: block; height: 1.45em; width: auto; }

/* segmented toggle */
.toggle {
  display: inline-flex; padding: 3px;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: 999px;
}
.toggle button {
  appearance: none; border: 0; cursor: pointer;
  font-family: var(--font-sans); font-size: var(--text-small); font-weight: 600;
  color: var(--muted); background: transparent;
  padding: 7px 18px; border-radius: 999px;
  transition: all .18s ease;
}
.toggle button.is-active {
  background: var(--brand); color: var(--on-brand);
  box-shadow: 0 2px 8px color-mix(in srgb, var(--brand) 32%, transparent);
}
.signin {
  font-size: var(--text-small); font-weight: 600; color: var(--brand-dark);
  text-decoration: none; white-space: nowrap;
}
.signin:hover { color: var(--brand); }
.appbar-actions { display: flex; align-items: center; gap: 16px; }

/* CSS-mask icon system, duplicated from icons.css as inline data URIs — see design-system.md "Theming". */
.icon {
  background-color: currentColor;
  display: inline-block;
  flex-shrink: 0;
  block-size: var(--icon-size, 1em);
  inline-size: var(--icon-size, 1em);
  mask-image: var(--svg);
  mask-position: center;
  mask-repeat: no-repeat;
  mask-size: contain;
  pointer-events: none;
  user-select: none;
}
/* Mirrors app/assets/images/instagram.svg — used by venue_screens/_auto_post + _connect. */
.icon--instagram  { --svg: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='2' y='2' width='20' height='20' rx='5.5'/%3E%3Ccircle cx='12' cy='12' r='4.2'/%3E%3Ccircle cx='17.5' cy='6.5' r='1.2' fill='black' stroke='none'/%3E%3C/svg%3E"); }

/* Mobile: keep the toggle a centred pill, just smaller — the band is sticky,
   so stay compact. Container query on the appbar's own width (no breakpoint). */
@container (max-width: 30rem) {
  .audience-bar { padding-block: 8px; }
  .audience-bar .toggle button { padding: 6px 16px; font-size: var(--text-small); }
}

/* ── Buttons ────────────────────────────────────────────── */
.btn {
  display: inline-flex; align-items: center; gap: 8px;
  font-family: var(--font-sans); font-weight: 600; font-size: var(--text);
  padding: 14px 26px; border-radius: 12px; border: 0; cursor: pointer;
  text-decoration: none; transition: transform .12s ease, box-shadow .18s ease;
}
.btn-primary { background: var(--brand); color: var(--on-brand); box-shadow: 0 4px 14px color-mix(in srgb, var(--brand) 32%, transparent); }
.btn-primary:hover { transform: translateY(-1px); box-shadow: 0 6px 20px color-mix(in srgb, var(--brand) 40%, transparent); }
.btn:disabled, .btn[disabled] { opacity: .5; cursor: not-allowed; box-shadow: none; }
.btn:disabled:hover, .btn[disabled]:hover { transform: none; box-shadow: none; }
.btn-ghost { background: transparent; color: var(--ink-strong); padding: 14px 8px; }
.btn-ghost:hover { color: var(--brand-dark); }
.btn-sage { background: var(--sage); color: var(--on-positive); box-shadow: 0 4px 14px color-mix(in srgb, var(--sage) 28%, transparent); }
.btn-sage:hover { transform: translateY(-1px); }

/* ── Hero ───────────────────────────────────────────────── */
.hero { padding-block: clamp(36px, 5vw, 60px) clamp(36px, 6vw, 56px); text-align: center; }
.eyebrow {
  display: inline-block; font-size: var(--text-small); font-weight: 600;
  letter-spacing: 0.08em; text-transform: uppercase; color: var(--accent);
  margin-bottom: 18px;
}
.hero h1 {
  font-family: var(--font-serif); font-weight: 600;
  font-size: var(--text-4x-large); line-height: 1.02;
  letter-spacing: -0.025em; color: var(--ink-strong);
  margin-bottom: 22px;
}
.hero .kicker-line {
  font-family: var(--font-serif); font-style: italic;
  font-size: var(--text-x-large); line-height: 1.2;
  color: var(--brand); margin: -8px auto 22px; max-width: 560px;
}
.hero p.sub {
  font-size: var(--text-medium); color: var(--muted); max-width: 640px;
  margin: 0 auto 34px;
}
/* Nothing here uses --check-mask any more; pricing.css does, and loads after this file. */
:root { --check-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='3.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E"); }
.hero-cta { display: flex; gap: 10px; align-items: center; justify-content: center; flex-wrap: wrap; }
/* Annotated nav in the hero column (basecamp.com): the link carries a reason to
   click, so the price reaches people who never click at all. */
.hero-links { list-style: none; margin: 30px 0 0; padding: 0; }
.hero-links li { font-size: var(--text-small); color: var(--muted); line-height: 1.5; }
.hero-links li + li { margin-top: 10px; }
.hero-links a {
  font-weight: 600; color: var(--brand-dark); text-decoration: none;
  border-bottom: 1.5px solid var(--border); padding-bottom: 1px;
}
.hero-links a:hover { color: var(--brand); border-color: var(--brand); }
/* locals hero — copy left, phone right */
/* Locals hero: copy + fixed-width phone. Center the pair and stop the copy
   growing, so widening the page doesn't push the phone away — they stay
   one gap apart no matter the viewport. */
.hero--split { display: flex; flex-wrap: wrap; align-items: flex-start; justify-content: center; gap: clamp(2rem, 4vw, 3.5rem); text-align: left; container-type: inline-size; padding-top: clamp(1.5rem, 4vw, 3rem); }
.hero--split .hero-copy { flex: 0 1 46rem; min-width: 0; padding-top: clamp(0.75rem, 2vw, 1.75rem); }
.hero--split .hero-copy p.sub { margin-left: 0; margin-right: 0; max-width: 34rem; font-size: var(--text-medium); }
.hero--split .hero-cta, .hero--venue-split .hero-cta { justify-content: flex-start; }
/* Locals hero phone carousel — same .venue-stage/.vframe chrome as the venue side. */
.hero--split .venue-stage { margin: 0; }

/* ── Venue hero split: copy left, real-app browser carousel right ── */
.hero--venue-split { display: flex; flex-wrap: wrap; align-items: flex-start; justify-content: center; gap: clamp(2rem, 4vw, 2.75rem); text-align: left; padding-top: clamp(1.5rem, 4vw, 3rem); padding-bottom: 34px; container-type: inline-size; }
/* Non-growing basis: widening the page must not push copy left and carousel right. */
.hero--venue-split .hero-copy { flex: 0 1 46rem; padding-top: clamp(0.75rem, 2vw, 1.75rem); }
.hero--venue-split .hero-copy p.sub { margin-left: 0; margin-right: 0; font-size: var(--text-medium); }
/* Both heroes share a 46rem basis so copy starts at the same x on toggle. */
@container (max-width: 67rem) {
  .hero--venue-split .hero-copy { text-align: center; margin-inline: auto; }
  .hero--venue-split .hero-copy .hero-cta { justify-content: center; }
  /* .hero-copy zeroes the sub's auto margins; restore them or its box hugs the left. */
  .hero--venue-split .hero-copy p.sub { margin-inline: auto; }
  /* The list keeps its hard left edge when the hero centres: ragged link
     starts read as broken, and the eye scans this column downwards.
     Block-centred instead, so it still sits under the centred copy. */
  .hero-links { width: fit-content; margin-inline: auto; text-align: left; }
}
@container (max-width: 67rem) {
  .hero--split .hero-copy { text-align: center; }
  .hero--split .hero-copy .hero-cta { justify-content: center; }
  .hero--split .hero-copy p.sub { margin-inline: auto; }
  /* The list keeps its hard left edge when the hero centres: ragged link
     starts read as broken, and the eye scans this column downwards.
     Block-centred instead, so it still sits under the centred copy. */
  .hero-links { width: fit-content; margin-inline: auto; text-align: left; }
}

/* Shrink-wraps the phone; a grow factor here pushes the hero copy to the gutter. */
.venue-stage { flex: 0 0 auto; min-width: 0; position: relative; }
/* brand-hued glow behind the app snip (Fizzy-style halo, tuned for the warm Editorial canvas) */
.venue-stage::before {
  content: ""; position: absolute; z-index: -1; inset: -26px -22px -40px -28px; border-radius: 40px;
  background:
    radial-gradient(48% 44% at 22% 16%, color-mix(in srgb, var(--brand) 34%, transparent), transparent 70%),
    radial-gradient(44% 44% at 86% 28%, color-mix(in srgb, var(--accent) 22%, transparent), transparent 70%),
    radial-gradient(58% 56% at 58% 106%, color-mix(in srgb, var(--sage) 16%, transparent), transparent 72%);
  filter: blur(30px);
}
/* All 8 slides stack in one grid cell and crossfade — every slide is a phone frame now,
   so centering lives on the base rule rather than a "--phone" modifier only some carried. */
.vframes { display: grid; }
.vframe { grid-area: 1 / 1; display: grid; place-items: center; opacity: 0; visibility: hidden; pointer-events: none; transition: opacity .45s ease, visibility 0s linear .45s; }
.vframe--on { opacity: 1; visibility: visible; pointer-events: auto; transition: opacity .45s ease, visibility 0s; }

/* screen 1: board */
.v-h1 { font-family: var(--font-serif); font-weight: 600; font-size: 18px; color: var(--ink-strong); line-height: 1.1; }
.v-h1 em { font-style: italic; }
.v-sub { font-size: 11px; color: var(--ink-faint); margin-top: 3px; }
.vboard-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 10px; }
.vbtn { font-size: 11px; font-weight: 600; color: var(--on-brand); background: var(--brand); padding: 6px 11px; border-radius: 8px; }
.vfilters { display: flex; gap: 8px; margin: 14px 0 4px; font-size: 11px; color: var(--ink-faint); }
.vfilters .on { color: var(--ink-strong); font-weight: 600; }
.vfilters-count { opacity: .7; }
.vrow { display: flex; align-items: center; gap: 11px; padding: 10px 0; border-top: 1px solid var(--border-soft); }
.vrow-meta { flex: 1; min-width: 0; }
.vrow-title { font-family: var(--font-serif); font-size: 13px; color: var(--ink-strong); line-height: 1.2; }
.vrow-sub { font-size: 10.5px; color: var(--ink-faint); margin-top: 2px; }
.vbadge { font-size: 9px; font-weight: 700; letter-spacing: .03em; padding: 2px 7px; border-radius: 100px; flex-shrink: 0; }
.vbadge--live { background: color-mix(in srgb, var(--sage) 20%, transparent); color: var(--sage); }
.vbadge--sched { background: color-mix(in srgb, var(--accent) 18%, transparent); color: var(--accent); }
.vrow-ico svg { width: 16px; height: 16px; color: var(--ink-faint); display: block; }
/* collapsed-by-default paused/expired count — mirrors the real board's disclosure, non-interactive art */
.vboard-disclosure { display: flex; align-items: center; gap: 6px; margin-top: 14px; font-size: 10.5px; color: var(--ink-faint); }
.vboard-disclosure-chev { font-size: 10px; }
/* Social accounts slide — mirrors venues/social_connections/index: one row
   per platform (icon swatch, name, meta, badge/CTA), not the board's .vrow shape. */
.vconn-row { display: flex; align-items: center; gap: 9px; padding: 11px 0; border-top: 1px solid var(--border-soft); }
.vconn-row:first-of-type { border-top: none; margin-top: 12px; }
.vconn-ic { width: 26px; height: 26px; border-radius: 7px; display: grid; place-items: center; flex-shrink: 0; }
.vconn-ic svg { width: 15px; height: 15px; display: block; }
.vconn-ic--google { background: #fff; box-shadow: inset 0 0 0 1px var(--border-soft); }
.vconn-ic--fb { background: #1877f2; color: #fff; font-family: var(--font-serif); font-weight: 700; font-size: 13px; }
.vconn-ic--ig { background: linear-gradient(135deg, #f9ce34 4%, #ee2a7b 45%, #6228d7 90%); color: #fff; }
.vconn-name { font-size: 11.5px; font-weight: 600; color: var(--ink-strong); }
.vconn-meta { font-size: 9px; color: var(--ink-faint); margin-top: 1px; }
.vconn-badge { font-size: 7.5px; font-weight: 700; letter-spacing: .03em; padding: 2px 7px; border-radius: 100px; margin-left: auto; flex-shrink: 0; white-space: nowrap; }
.vconn-badge--live { background: color-mix(in srgb, var(--sage) 20%, transparent); color: var(--sage); }
.vconn-badge--off { background: var(--surface); color: var(--ink-faint); }
.vconn-cta { font-size: 9px; font-weight: 600; color: var(--brand); flex-shrink: 0; margin-left: auto; }

/* slide 3: scan & validate — full staff-PWA phone, lands back in the app */
/* Sized to iPhone's ~0.461 screen aspect ratio (393×852pt), scaled down to fit the hero.
   Wider than a strict scale-down would give (270px, not ~240px) — the extra width is what
   keeps venue names, row titles, and filter chips from wrapping inside the mock. */
/* Physics-fixed: the phone's own bezel plastic, same in both themes. */
.scan-phone { width: 270px; height: 585px; background: linear-gradient(160deg, #2c2824, var(--ink-strong)); border-radius: 44px; padding: 9px; box-shadow: 0 34px 68px color-mix(in srgb, var(--shadow-ink) 38%, transparent); }
.vscan-screen { position: relative; width: 100%; height: 100%; border-radius: 36px; overflow: hidden; background: var(--canvas); display: flex; flex-direction: column; }
.vphone-body { position: relative; flex: 1; min-height: 0; padding: 13px 13px 0; overflow: hidden; }
.vphone-body--center { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 14px; padding: 13px; }

/* Consumer top strip — mirrors shared/_search_field, the whole mobile top bar. */
.vphone-search { display: inline-flex; align-items: center; gap: 6px; max-width: 100%; padding: 7px 12px; border-radius: 999px; background: var(--canvas); border: 1px solid var(--border-soft); color: var(--ink-faint); font-size: 10.5px; }
.vphone-search svg { width: 13px; height: 13px; flex-shrink: 0; }
.vphone-search span { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* Crier ID card — the flipped face of shared/_crier_flip, at rest for the mock. */
.pf-idcard { background: var(--card); border-radius: 16px; padding: 22px 24px; text-align: center; box-shadow: 0 10px 26px color-mix(in srgb, var(--shadow-ink) 16%, transparent); }
.pf-idcard-qr { width: 64px; height: 64px; display: block; margin: 0 auto 12px; color: var(--ink-strong); }
.pf-idcard-label { font-family: var(--font-serif); font-weight: 600; font-size: 15px; color: var(--ink-strong); }
.pf-idcard-sub { font-size: 11px; color: var(--ink-faint); margin-top: 4px; }

/* Shared phone chrome — every slide's own top strip + bottom tab bar, baked
   into that slide's markup (no shared DOM to swap between slides). Mirrors
   shared/_shell_topbar (mobile: mark + name + location, no burger) and
   shared/_bottom_nav (Offers/Events/Scan/Alerts/More, identical every role). */
/* Centered as a unit, not left-hung — matches shared/_shell_topbar's mobile layout,
   where the venue identity is the whole bar's content (bell/pins live elsewhere on mobile). */
.vphone-top { display: flex; align-items: center; justify-content: center; gap: 8px; padding: 10px 13px; border-bottom: 1px solid var(--border-soft); flex-shrink: 0; }
.vphone-top-mark { width: 26px; height: 26px; border-radius: 7px; background: var(--brand); color: var(--on-brand); display: grid; place-items: center; font-family: var(--font-serif); font-weight: 700; font-size: 12px; flex-shrink: 0; }
/* Plain block, left-aligned — the venue name and location share the same start edge as
   two lines of one block, rather than each independently centering on its own width. The
   block itself is still centered as a unit within .vphone-top (justify-content: center). */
.vphone-top-id { min-width: 0; max-width: 100%; }
.vphone-top-venue { max-width: 100%; font-family: var(--font-serif); font-weight: 600; font-size: 12.5px; color: var(--ink-strong); line-height: 1.15; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.vphone-top-loc { font-size: 9px; color: var(--ink-faint); margin-top: 1px; }

.vphone-tabbar { display: grid; grid-template-columns: repeat(5, 1fr); gap: 2px; padding: 6px 4px 8px; border-top: 1px solid var(--border-soft); background: var(--canvas); flex-shrink: 0; }
.vphone-tab { position: relative; display: flex; flex-direction: column; align-items: center; gap: 2px; color: var(--ink-faint); }
.vphone-tab svg { width: 17px; height: 17px; display: block; }
.vphone-tab-label { font-size: 7px; font-weight: 600; letter-spacing: .01em; }
.vphone-tab--active { color: var(--brand); }
.vphone-tab-dot { position: absolute; top: -6px; left: 50%; transform: translateX(-50%); width: 12px; height: 2px; border-radius: 3px; background: var(--brand); opacity: 0; }
.vphone-tab--active .vphone-tab-dot { opacity: 1; }
/* redemption confirmation modal — scrim is physics-fixed (dims the phone screen behind it) */
.vscan-scrim { position: absolute; inset: 0; background: rgba(20,16,9,0.5); }
.vscan-success { position: absolute; left: 16px; right: 16px; top: 50%; transform: translateY(-50%); background: var(--card); border-radius: 16px; padding: 18px 16px; text-align: center; box-shadow: 0 20px 40px rgba(0,0,0,0.42); }
.vsc-check-ic { width: 38px; height: 38px; margin: 0 auto 10px; border-radius: 50%; background: color-mix(in srgb, var(--sage) 18%, transparent); color: var(--sage); display: grid; place-items: center; font-size: 20px; font-weight: 700; }
.vsc-ok-title { font-family: var(--font-serif); font-size: 15px; font-weight: 600; color: var(--ink-strong); line-height: 1.2; }
.vsc-ok-sub { font-size: 11px; color: var(--ink-faint); margin-top: 4px; }
.vsc-next { display: inline-block; margin-top: 13px; font-size: 11px; font-weight: 600; color: var(--on-brand); background: var(--brand); border-radius: 7px; padding: 6px 15px; }

/* ── Auto-post slide — same reassurance language as the redemption-success
   modal (.vsc-check-ic etc.): "posted" and "redeemed" are both a done state. ── */
.vautopost-card { position: absolute; left: 16px; right: 16px; top: 50%; transform: translateY(-50%); background: var(--card); border-radius: 16px; padding: 18px 16px; text-align: center; box-shadow: 0 20px 40px rgba(0,0,0,0.42); }
.vautopost-apps { display: flex; justify-content: center; gap: 8px; margin-top: 13px; }
.vshare-ic--google { background: #fff; box-shadow: inset 0 0 0 1px var(--border-soft); }

/* ── Share slide — the poster behind a risen OS share sheet. On-brand, not a
   literal iOS copy: poster thumbnail + a row of recognisable social targets.
   Mirrors poster_download_controller's navigator.share({ files: [poster] }). ── */
.vshare-poster { position: absolute; inset: 0; display: grid; place-items: center; padding: 14px; background: linear-gradient(170deg, #2c2824, var(--ink-strong)); }
.vshare-poster-img { width: 74%; border-radius: 8px; box-shadow: 0 10px 26px rgba(0,0,0,0.4); }
.vscan-screen .vshare-poster + .vscan-scrim { background: rgba(20,16,9,0.58); }
.vshare-sheet {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 5;
  background: color-mix(in srgb, var(--canvas) 92%, transparent);
  backdrop-filter: blur(14px) saturate(1.4); -webkit-backdrop-filter: blur(14px) saturate(1.4);
  border-top-left-radius: 20px; border-top-right-radius: 20px;
  padding: 8px 13px 15px; box-shadow: 0 -8px 26px color-mix(in srgb, var(--shadow-ink) 22%, transparent);
}
.vshare-grab { display: block; width: 34px; height: 4px; margin: 0 auto 11px; border-radius: 100px; background: color-mix(in srgb, var(--ink-faint) 40%, transparent); }
.vshare-file { display: flex; align-items: center; gap: 9px; padding-bottom: 11px; margin-bottom: 11px; border-bottom: 1px solid var(--border-soft); }
.vshare-thumb { width: 34px; height: 42px; object-fit: cover; border-radius: 5px; box-shadow: 0 2px 6px color-mix(in srgb, var(--shadow-ink) 20%, transparent); flex-shrink: 0; }
.vshare-file-name { font-size: 11px; font-weight: 600; color: var(--ink-strong); line-height: 1.2; }
.vshare-file-sub { font-size: 10px; color: var(--ink-faint); margin-top: 2px; }
.vshare-apps { display: flex; gap: 3px; }
.vshare-app { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; align-items: center; gap: 4px; }
.vshare-ic { width: 30px; height: 30px; border-radius: 8px; display: grid; place-items: center; }
.vshare-ic svg { width: 18px; height: 18px; display: block; }
.vshare-ic--ig { background: linear-gradient(135deg, #f9ce34 4%, #ee2a7b 45%, #6228d7 90%); color: #fff; }
.vshare-ic--fb { background: #1877f2; color: #fff; font-family: var(--font-serif); font-weight: 700; font-size: 18px; line-height: 1; }
.vshare-ic--wa { background: #25d366; }
.vshare-ic--msg { background: #34c759; }
.vshare-ic--email { background: var(--ink-faint); }
.vshare-ic--copy { background: var(--surface); color: var(--ink); box-shadow: inset 0 0 0 1px var(--border-soft); }
.vshare-ic--print { background: var(--ink-strong); color: var(--canvas); }
.vshare-ic--save { background: var(--sage); color: var(--on-positive); }
.vshare-al { font-size: 7.5px; color: var(--ink-faint); max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* screen 4: pulse */
.vvitals { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; margin-top: 13px; }
.vvital { background: var(--card); border: 1px solid var(--border-soft); border-radius: 10px; padding: 9px 10px; }
/* Two lines reserved on every label: "Redeem rate" wraps at this width and the
   others don't, which knocked the three numbers off a shared baseline. The
   tallest tile already sets the row height, so holding two lines costs none. */
.vvital-l { font-size: 8.5px; font-weight: 600; letter-spacing: .04em; text-transform: uppercase; color: var(--ink-faint);
            line-height: 1.2; min-height: 2.4em; }
.vvital-n { font-family: var(--font-serif); font-size: 21px; font-weight: 600; color: var(--ink-strong); line-height: 1.05; margin-top: 3px; }
.vvital-u { font-size: 12px; }
.vvital-d { font-size: 9px; font-weight: 700; color: var(--sage); margin-top: 2px; }
.vheat-head { font-family: var(--font-serif); font-size: 12px; color: var(--ink-strong); margin: 14px 0 7px; }
.vheat-head em { font-style: italic; }
.vheat-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 3px; }
.vcell { height: 19px; border-radius: 3px; background: var(--surface); }
.vcell[data-d="1"] { background: color-mix(in srgb, var(--brand) 14%, var(--surface)); }
.vcell[data-d="2"] { background: color-mix(in srgb, var(--brand) 30%, var(--surface)); }
.vcell[data-d="3"] { background: color-mix(in srgb, var(--brand) 48%, var(--surface)); }
.vcell[data-d="4"] { background: color-mix(in srgb, var(--brand) 68%, var(--surface)); }
.vcell[data-d="5"] { background: var(--brand); }
.vheat-days { display: grid; grid-template-columns: repeat(7, 1fr); gap: 3px; margin-top: 4px; }
.vheat-days span { font-size: 8px; color: var(--ink-faint); text-align: center; }
.vtop5-head { font-size: 9px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--ink-faint); margin: 14px 0 4px; }
.vt5 { display: flex; align-items: center; gap: 9px; padding: 6px 0; border-top: 1px solid var(--border-soft); }
.vt5-rank { width: 16px; font-family: var(--font-serif); font-size: 12px; color: var(--ink-faint); flex-shrink: 0; }
.vt5-name { flex: 1; font-family: var(--font-serif); font-size: 12px; color: var(--ink-strong); }
.vt5-n { font-size: 12px; font-weight: 700; color: var(--brand); }
/* loyalty card — a miniature of the app's "Brass Foil" card (app: .loy-card in
   loyalty.css). Deliberately duplicated: the landing ships its own stylesheet and
   imports no app CSS, so these two have to be kept in step by hand. */
/* The bell's own brass — brand-fixed, mirrors loyalty.css. */
:root {
  --gradient-brass:       linear-gradient(150deg, #FCEBB8, #E0AC46 52%, #7E5314);
  --gradient-brass-sheen: linear-gradient(103deg, #FCEBB8, #E0AC46 46%, #9C7024 72%, #FCEBB8);
  /* Physics-fixed: a drop shadow doesn't invert, so it sits outside the theme blocks. */
  --shadow-ink: #1F1A12;
}
/* No ID-1 aspect here — these are thumbnails inside a device mock, so they take their
   height from their content and stay compact. The material carries the recognition. */
/* Physics-fixed to .vloy-stamp--reward-on: card material doesn't invert. */
.vloy-frame {
  position: relative; margin-top: 14px; overflow: hidden;
  padding: 11px 12px; border-radius: 12px;
  display: flex; flex-direction: column; color: #EFE7D6;
  background: radial-gradient(120% 100% at 22% 8%, #3A352E, #1C1813 52%, #0F0C07);
  box-shadow: 0 10px 24px rgba(15,12,7,.32);
}
/* Raking foil highlight. */
.vloy-frame::before {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(115deg, transparent 34%, rgba(252,235,184,.09) 47%, transparent 58%);
}
.vloy-frame > * { position: relative; }
/* Bell watermark. Fixed px, not the app card's %: with no aspect-ratio the height is
   content-driven, so a % of the width would overshoot it and crop to a sliver. */
.vloy-wm { position: absolute; right: -5px; bottom: -9px; width: 46px; opacity: .16; transform: rotate(-9deg); }
.vloy-wm img { width: 100%; display: block; }
.vloy-top { display: flex; align-items: center; gap: 7px; min-width: 0; }
.vloy-logo {
  width: 24px; height: 24px; border-radius: 7px; flex-shrink: 0;
  display: grid; place-items: center; font-size: 11px; font-weight: 700; color: #3A2509;
  background: var(--gradient-brass);
}
.vloy-venue {
  flex: 1 1 auto; min-width: 0;
  font-family: var(--font-serif); font-weight: 600; font-size: 12px; line-height: 1.15;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  background: var(--gradient-brass-sheen);
  -webkit-background-clip: text; background-clip: text; color: transparent;
}
.vloy-deal { margin-top: 10px; }
.vloy-deal-l { display: block; font-size: 7px; font-weight: 800; letter-spacing: .2em; text-transform: uppercase; color: #E0AC46; }
/* Near --color-card but not it: possible drift, left as card material. */
.vloy-deal-r { display: block; font-family: var(--font-serif); font-style: italic; font-size: 14px; line-height: 1.18; color: #FBF6E8; margin-top: 1px; }
.vloy-stamps { margin-top: 8px; display: flex; align-items: center; gap: 4px; }
.vloy-stamp { flex: 0 1 14px; aspect-ratio: 1; border-radius: 50%; border: 1.2px solid rgba(224,172,70,.42); }
.vloy-stamp--on { border: 0; background: var(--gradient-brass); }
/* Claret is the milestone's alone — it stays off the brass, as the brand rules require. */
.vloy-stamp--reward { flex-basis: 16px; border: 1.2px solid color-mix(in srgb, var(--accent) 55%, transparent); }
.vloy-stamp--reward-on { border: 0; background: radial-gradient(circle at 34% 28%, var(--brand-light), #7C2D3A 75%); }
/* Caption under the card, not on it — the qualifying rule left the front face. */
.vloy-foot { margin-top: 8px; font-size: 9.5px; letter-spacing: .03em; color: var(--muted); text-align: center; }
/* loyalty wallet — screen 2 of the locals hero phone carousel */
.loy-wallet-h { font-family: var(--font-serif); font-style: italic; font-size: 18px; color: var(--ink-strong); line-height: 1.15; }
.loy-wallet-sub { font-size: 11px; color: var(--ink-faint); margin: 2px 0 12px; }
.vloy-frame--mini { margin-top: 12px; }
.vloy-frame--ready {
  margin-top: 0;
  box-shadow: 0 0 0 1px rgba(224,172,70,.5), 0 10px 26px rgba(190,138,44,.3);
}
/* Keep the venue name out from under the tag; the name ellipsises rather than collide. */
.vloy-frame--ready .vloy-top { padding-right: 68px; }
/* Inside the card, not overhanging it — the frame clips now that it holds a watermark. */
.vloy-ready-tag {
  position: absolute; top: 6px; right: 8px; font-size: 7px; font-weight: 700; letter-spacing: .05em;
  text-transform: uppercase; padding: 2px 6px; border-radius: 100px; background: var(--accent); color: var(--on-accent);
  box-shadow: 0 2px 5px rgba(0,0,0,.3);
}
/* dots + caption */
.vdots { display: flex; justify-content: center; gap: 8px; margin-top: 14px; }
.vdot { width: 8px; height: 8px; border-radius: 50%; background: var(--border); border: 0; cursor: pointer; padding: 0; transition: all .25s ease; }
.vdot--active { background: var(--brand); width: 22px; border-radius: 5px; }
/* Two lines are reserved: the captions differ in length, and without this the
   dots below shift every time a wrapping one comes round. */
.vcaption { text-align: center; margin-top: 16px; min-height: 2.7em; font-family: var(--font-serif); font-size: var(--text); line-height: 1.35; color: var(--muted); }

/* product glimpse */
.glimpse {
  margin: 56px auto 0; max-width: 860px;
  display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 18rem), 1fr)); gap: 20px;
}
.glimpse-card {
  background: var(--card); border: 1px solid var(--border-soft);
  border-radius: 18px; padding: 22px; box-shadow: 0 12px 40px color-mix(in srgb, var(--shadow-ink) 8%, transparent);
  text-align: left;
}
/* ── Hanging discount-tag rail — infinite gliding marquee ── */
.tag-rail {
  position: relative; margin: 18px 0 8px; padding-top: 14px; overflow: hidden;
  /* #000 here is mask opacity, not a rendered colour — any opaque value masks identically. */
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 9%, #000 91%, transparent);
          mask-image: linear-gradient(90deg, transparent, #000 9%, #000 91%, transparent);
}
.rail-bar {
  position: absolute; top: 14px; left: 0; right: 0; height: 3px; z-index: 3;
  background: var(--border);
}
.tags {
  display: flex; width: max-content; align-items: flex-start;
  animation: marquee 44s linear infinite;
}
.tag-rail:hover .tags { animation-play-state: paused; }
@keyframes marquee { from { transform: translateX(0); } to { transform: translateX(-50%); } }
.htag {
  --rot: 3deg; --dur: 4.4s; --delay: 0s; --w: 118px;
  position: relative; width: var(--w); margin-top: 22px; margin-right: clamp(10px, 1.6vw, 22px); flex: 0 0 auto;
  padding: 30px 12px 18px; text-align: center;
  border-radius: 13px;
  clip-path: polygon(50% 0, 100% 15%, 100% 100%, 0 100%, 0 15%);
  transform-origin: 50% 5px;
  animation: swing var(--dur) ease-in-out var(--delay) infinite alternate;
  box-shadow: 0 14px 30px color-mix(in srgb, var(--shadow-ink) 16%, transparent);
}
/* the cord from rail to eyelet */
.htag::before {
  content: ""; position: absolute; top: -22px; left: 50%; transform: translateX(-50%);
  width: 2px; height: 22px; background: var(--border);
}
/* the eyelet hole */
.htag::after {
  content: ""; position: absolute; top: 8px; left: 50%; transform: translateX(-50%);
  width: 12px; height: 12px; border-radius: 50%; background: var(--canvas);
  box-shadow: inset 0 1px 2px rgba(0,0,0,0.4);
}
.htag .label { display: block; font-family: var(--font-serif); font-weight: 600; font-size: 19px; letter-spacing: -0.01em; line-height: 1.1; }
.htag .off   { display: block; font-size: 11px; letter-spacing: .05em; opacity: .85; margin-top: 4px; }
@keyframes swing {
  from { transform: rotate(calc(var(--rot) * -1)); }
  to   { transform: rotate(var(--rot)); }
}
/* Tag colourways — the second gradient stop has no token match; left literal. */
.htag.c-brand  { background: linear-gradient(155deg, var(--brand), var(--brand-dark)); color: var(--on-brand); }
.htag.c-gold   { background: linear-gradient(155deg, var(--accent), #936419); color: var(--on-accent); }
.htag.c-sage   { background: linear-gradient(155deg, var(--sage), #38502a); color: var(--on-positive); }
.htag.c-dark   { background: linear-gradient(155deg, var(--brand-dark), #5e2820); color: var(--on-brand); }
.htag.c-soft   { background: linear-gradient(155deg, var(--brand-soft), var(--accent-soft)); color: var(--ink-strong); }
.htag.c-soft::after { background: var(--card); }
.htag.lift { margin-top: 4px; --w: 132px; }   /* a couple hang higher / larger for rhythm */
@media (prefers-reduced-motion: reduce) {
  .htag { animation: none; transform: rotate(0); }
  .tags { animation: none; }
}
/* subtle two-line lead-in above the rail: typed question, handwritten answer */
.rail-cap {
  text-align: center; margin: 0 auto; max-width: 44ch;
  font-size: var(--text-large); letter-spacing: 0.01em; color: var(--ink);
  line-height: 1.5;
}
/* handwritten answer half — same Caveat as the .vt-current selector, no highlighter */
.rail-cap .rail-hand {
  display: inline-block; margin-top: 2px;
  font-family: var(--font-hand); font-weight: 600; font-size: 31px;
  color: var(--ink-strong); line-height: 1;
}

.feed-mini-label { font-size: 12px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--ink-faint); margin-bottom: 12px; }
.feed-row {
  display: flex; gap: 12px; align-items: center; padding: 12px;
  border: 1px solid var(--border-soft); border-radius: 12px; margin-bottom: 10px; background: var(--canvas);
}
.feed-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--brand); flex-shrink: 0; }
.feed-dot.soon { background: var(--accent); }
.feed-row .fr-body { flex: 1; }
.feed-row .fr-title { font-weight: 600; font-size: 14px; color: var(--ink-strong); }
.feed-row .fr-meta { font-size: 12px; color: var(--muted); }
.type-chip {
  flex-shrink: 0; font-size: 10.5px; font-weight: 600; letter-spacing: .05em; text-transform: uppercase;
  padding: 3px 9px; border-radius: 999px;
}
.type-chip.t-gym    { background: var(--sage); color: var(--on-positive); }
.type-chip.t-pub    { background: var(--brand); color: var(--on-brand); }
.type-chip.t-salon  { background: var(--brand-dark); color: var(--on-brand); }
.type-chip.t-studio { background: var(--accent); color: var(--on-accent); }
/* No token matches this literal (close to --brand-dark, not exact) — left, flagged for review. */
.type-chip.t-cafe   { background: #936419; color: var(--on-brand); }

/* ── Sections ───────────────────────────────────────────── */
section.band { padding: 64px 0; }
section.band.alt { background: var(--surface); border-top: 1px solid var(--border-soft); border-bottom: 1px solid var(--border-soft); }
.section-head { text-align: center; margin-bottom: 44px; }
.section-head .kicker { font-size: var(--text-small); font-weight: 600; letter-spacing: .08em; text-transform: uppercase; color: var(--brand); }
.section-head h2 { font-family: var(--font-serif); font-weight: 600; font-size: var(--text-2x-large); letter-spacing: -0.02em; color: var(--ink-strong); margin-top: 8px; }
.section-lead { max-width: 480px; margin: 14px auto 0; color: var(--muted); font-size: var(--text); }

.steps { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 11rem), 1fr)); gap: 20px; container-type: inline-size; }
.step { text-align: left; }
/* When the grid collapses to a single column (narrow), centre each step —
   numbered circle, heading and text — so it doesn't read as left-leaning.
   Container query on the steps' own width; 23rem ≈ the 2-column threshold. */
@container (max-width: 23rem) {
  .step { text-align: center; }
  .step .num { margin-inline: auto; }
}
/* numbered circle — matches .prom-group-count on the venue promotions page */
.step .num {
  width: 38px; height: 38px; border-radius: 999px; display: grid; place-items: center;
  font-family: var(--font-sans); font-weight: 600; font-size: var(--text-medium);
  background: var(--brand); color: var(--on-brand); margin-bottom: 14px;
}
.step h3 { font-size: var(--text-medium); color: var(--ink-strong); margin-bottom: 6px; }
.step p { font-size: var(--text-small); color: var(--muted); }
.howto-note {
  max-width: 600px; margin: 44px auto 0; text-align: center;
  border: 1.5px dashed var(--border); border-radius: 16px; padding: 22px 28px;
  background: color-mix(in srgb, var(--card) 55%, transparent);
}
.howto-note .nlabel { display: block; font-size: var(--text-x-small); font-weight: 600; letter-spacing: .08em; text-transform: uppercase; color: var(--brand); margin-bottom: 7px; }
.howto-note p { font-size: var(--text); color: var(--ink); }
.howto-note b { color: var(--ink-strong); font-weight: 600; }
/* two side-by-side notes (compounds + multi-venue) */
.howto-notes { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 16rem), 1fr)); gap: 18px; max-width: 1120px; margin: 44px auto 0; align-items: stretch; }
.howto-notes .howto-note { max-width: none; margin: 0; height: 100%; }

/* ── Owner's-night story timeline ──────────────────────── */
/* The head sits over a left-aligned timeline, so centring it left the section
   reading off-centre once the page margins shrink. It shares the timeline's
   680px measure and its rail+gap indent, so the kicker, the headline and every
   beat heading start on one edge. */
#how .section-head { text-align: left; max-width: 680px; margin-inline: auto; padding-left: calc(clamp(30px, 7vw, 34px) + clamp(8px, 1.5vw, 12px)); }
#how .section-head h2.story-headline { margin-inline: 0; }

/* One 680px measure shared with h2.story-headline above, so the two line up. */
.timeline { max-width: 680px; margin: 0 auto; counter-reset: beat; container-type: inline-size; }
.beat { display: grid; grid-template-columns: clamp(30px, 7vw, 34px) 1fr; gap: 0 clamp(8px, 1.5vw, 12px); counter-increment: beat; }
.b-rail { position: relative; }
.b-rail::before {
  content: ""; position: absolute; left: 50%; transform: translateX(-50%);
  top: 34px; bottom: -14px; width: 2px; background: var(--border);
}
.beat:last-child .b-rail::before { display: none; }
/* numbered circle — brand-filled, matches .prom-group-count on the venue promotions page */
.b-dot {
  position: absolute; left: 50%; transform: translateX(-50%); top: 0;
  width: 30px; height: 30px; border-radius: 50%;
  border: none; background: var(--brand);
  display: grid; place-items: center;
  font-family: var(--font-sans); font-weight: 600; font-size: var(--text-small); color: var(--on-brand);
}
.b-dot::before { content: counter(beat); }
/* bookend beats (problem / proof) — story framing, not numbered steps */
.beat--note { counter-increment: none; }
.beat--note .b-dot { border: none; background: transparent; }
.beat--note .b-dot::before {
  content: ""; width: 9px; height: 9px; border-radius: 50%;
  background: var(--border);
}
.b-content { padding-bottom: 32px; padding-top: 2px; }
.beat:last-child .b-content { padding-bottom: 0; }
.b-role { display: inline-block; font-size: var(--text-x-small); font-weight: 600; letter-spacing: .08em; text-transform: uppercase; color: var(--ink-faint); margin-bottom: 6px; }
/* 500, not 600: a grotesque at 27px carries the emphasis without shouting. */
.b-content h3 { font-family: var(--font-serif); font-weight: 500; font-size: var(--text-x-large); line-height: 1.16; letter-spacing: -0.015em; text-wrap: balance; color: var(--ink-strong); margin-bottom: 7px; }
/* No ch cap: the sub-text shares the heading's measure, or it wraps first. */
.b-content p { color: var(--muted); font-size: var(--text-small); }
.b-content p b { color: var(--ink-strong); font-weight: 600; }

/* inline artifact: push notification (the nudge beat) */
.notif {
  display: flex; align-items: flex-start; gap: 11px; margin-top: 15px;
  max-width: 308px; padding: 12px 14px;
  background: color-mix(in srgb, var(--card) 92%, transparent); border: 1px solid var(--border-soft);
  border-radius: 15px; box-shadow: 0 12px 28px color-mix(in srgb, var(--shadow-ink) 10%, transparent);
}
.notif-icon {
  width: 30px; height: 30px; border-radius: 8px; flex-shrink: 0;
  background: linear-gradient(150deg, var(--brand), var(--brand-dark)); color: var(--on-brand);
  display: grid; place-items: center; font-family: var(--font-serif); font-weight: 700; font-size: 15px;
}
.notif-body { flex: 1; min-width: 0; }
.notif-top { display: flex; justify-content: space-between; align-items: baseline; gap: 8px; }
.notif-app { font-size: 10.5px; font-weight: 600; letter-spacing: .05em; text-transform: uppercase; color: var(--ink-faint); }
.notif-time { font-size: 11px; color: var(--ink-faint); }
.notif-title { font-weight: 600; font-size: 14px; color: var(--ink-strong); margin-top: 3px; }
.notif-text { font-size: 13px; color: var(--muted); margin-top: 1px; }

/* locals hero — real in-app feed snapshot (push notification + pinned promotion) */
/* Web Push banner — floats over the in-app grid, drops in like a real push.
   Frosted card + Crier app-icon tile, mirroring the OS notification chrome. */
.pf-push {
  position: absolute; top: 8px; left: 8px; right: 8px; z-index: 7;
  display: flex; align-items: flex-start; gap: 9px; padding: 9px 11px;
  background: color-mix(in srgb, var(--canvas) 80%, transparent);
  backdrop-filter: blur(16px) saturate(1.5); -webkit-backdrop-filter: blur(16px) saturate(1.5);
  /* Frosted-glass specular edge highlight — physics-fixed, same in both themes. */
  border: 1px solid color-mix(in srgb, #fff 55%, transparent); border-radius: 16px;
  box-shadow: 0 12px 30px color-mix(in srgb, var(--shadow-ink) 22%, transparent), 0 2px 8px color-mix(in srgb, var(--shadow-ink) 10%, transparent);
  animation: pf-push-in 0.7s cubic-bezier(0.22,1,0.36,1) both;
}
@keyframes pf-push-in { from { opacity: 0; transform: translateY(-16px); } to { opacity: 1; transform: translateY(0); } }
/* Real Crier app icon (the 3D bell) — this is what iOS shows in a push. */
.pf-push-icon { flex-shrink: 0; width: 27px; height: 27px; border-radius: 7px; object-fit: cover; }
.pf-push-body { flex: 1; min-width: 0; }
.pf-push-top { display: flex; justify-content: space-between; align-items: baseline; gap: 8px; }
.pf-push-app { font-size: 9px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--ink-faint); }
.pf-push-time { font-size: 9.5px; color: var(--ink-faint); white-space: nowrap; }
.pf-push-title { font-weight: 600; font-size: 12px; color: var(--ink-strong); margin-top: 2px; line-height: 1.2; }
.pf-push-text { font-size: 11px; color: var(--muted); margin-top: 1px; line-height: 1.25; }
/* in-app feed — mirrors customers/feed + shared/_promotion_row */
.pf-greet-1 { font-family: var(--font-serif); font-style: italic; font-size: 18px; color: var(--ink-strong); line-height: 1.15; }
.pf-greet-2 { font-family: var(--font-serif); font-style: italic; font-size: 12.5px; color: var(--ink-faint); margin-top: 2px; }
.pf-group {
  display: flex; align-items: center; gap: 7px; margin-top: 14px; padding-bottom: 8px;
  border-bottom: 1px solid var(--border-soft);
  font-size: 10.5px; font-weight: 700; letter-spacing: .09em; text-transform: uppercase; color: var(--ink-faint);
}
.pf-count {
  display: inline-grid; place-items: center; min-width: 17px; height: 17px; padding: 0 5px;
  border-radius: 9px; background: var(--surface); color: var(--muted); font-size: 10px; font-weight: 700; letter-spacing: 0;
}
.pf-row { display: flex; align-items: flex-start; justify-content: space-between; gap: 8px; padding: 11px 0; }
.pf-divider { height: 1px; background: var(--border-soft); }
.pf-row-main { flex: 1; min-width: 0; }
.pf-venue { font-family: var(--font-serif); font-style: italic; font-size: 10.5px; color: var(--ink-faint); line-height: 1.2; }
.pf-caption { font-family: var(--font-serif); font-size: 14px; color: var(--ink-strong); line-height: 1.25; margin-top: 2px; }
.pf-meta { font-size: 11px; color: var(--ink-faint); margin-top: 3px; }
.pf-actions { flex-shrink: 0; display: flex; align-items: center; gap: 2px; }
.pf-qr, .pf-pin { width: 30px; height: 30px; display: grid; place-items: center; border-radius: 8px; }
.pf-qr { color: var(--brand); }
.pf-qr svg { width: 18px; height: 18px; }
.pf-pin { color: var(--ink-faint); }            /* pushpin glyph (bookmark.svg) */
.pf-pin svg { width: 16px; height: 16px; }
.pf-pin--active { color: var(--brand); }         /* pinned = brand fill */
/* expanded pin tray — mirrors shared/_bottom_bar pin-tray modal */
.pf-tray {
  position: absolute; left: 11px; right: 32px; bottom: 64px; z-index: 5;
  background: var(--canvas); border: 1px solid var(--border); border-radius: 14px; overflow: hidden;
  box-shadow: 0 16px 40px color-mix(in srgb, var(--shadow-ink) 18%, transparent), 0 4px 12px color-mix(in srgb, var(--shadow-ink) 8%, transparent);
}
.pf-tray-head { padding: 10px 13px; border-bottom: 1px solid var(--border-soft); font-family: var(--font-serif); font-size: 13px; font-weight: 500; color: var(--ink-strong); }
.pf-tray-row { position: relative; display: flex; flex-direction: column; padding: 9px 34px 9px 13px; border-bottom: 1px solid var(--border-soft); }
.pf-tray-row:last-child { border-bottom: 0; }
.pf-tray-caption { font-family: var(--font-serif); font-size: 13px; font-weight: 500; color: var(--ink-strong); line-height: 1.2; }
.pf-tray-venue { font-size: 11px; color: var(--ink-faint); margin-top: 2px; }
.pf-tray-meta { font-size: 10.5px; font-weight: 600; letter-spacing: .02em; margin-top: 4px; }
.pf-tray-meta--live { color: var(--brand); }
.pf-tray-meta--upcoming { color: var(--brand-light); }
.pf-tray-unpin { position: absolute; top: 50%; right: 11px; transform: translateY(-50%); width: 22px; height: 22px; display: grid; place-items: center; border-radius: 50%; border: 1px solid var(--border); color: var(--ink-faint); }
.pf-tray-unpin svg { width: 13px; height: 13px; }
/* venue-type story switcher — custom on-brand control (no native select) */
.section-head h2.story-headline {
  font-family: var(--font-serif); font-weight: 600; font-size: var(--text-2x-large);
  letter-spacing: -0.02em; line-height: 1.45; color: var(--ink-strong);
  max-width: 680px; margin: 12px auto 0;
}
.vt { position: relative; display: inline-block; vertical-align: baseline; }
.vt-trigger {
  appearance: none; border: 0; background: transparent; cursor: pointer; padding: 0;
  font: inherit; color: var(--brand); display: inline-flex; align-items: center; gap: 8px;
}
.vt-current {
  font-family: var(--font-hand); font-weight: 700; font-size: 1.5em; line-height: 1;
  color: var(--ink-strong); padding: 0 0.18em; white-space: nowrap;
  background-image: linear-gradient(101deg, transparent 1%, color-mix(in srgb, var(--brand) 46%, transparent) 6%, color-mix(in srgb, var(--brand) 46%, transparent) 94%, transparent 99%);
  background-repeat: no-repeat; background-size: 100% 44%; background-position: 0 82%;
}
.vt-caret { width: 15px; height: 10px; flex-shrink: 0; transition: transform .18s ease; }
.vt[data-open] .vt-caret { transform: rotate(180deg); }
.vt-trigger:hover .vt-current { color: var(--brand-dark); background-size: 100% 58%; }
.vt-menu {
  position: absolute; top: calc(100% + 9px); left: 50%;
  transform: translateX(-50%) scale(0.96); transform-origin: top center;
  min-width: 168px; list-style: none; padding: 6px; margin: 0; z-index: 20;
  background: var(--card); border: 1px solid var(--border); border-radius: 13px;
  box-shadow: 0 14px 34px color-mix(in srgb, var(--shadow-ink) 18%, transparent);
  opacity: 0; visibility: hidden;
  transition: opacity .16s ease, transform .16s ease, visibility .16s;
}
.vt[data-open] .vt-menu { opacity: 1; visibility: visible; transform: translateX(-50%) scale(1); }
.vt-opt {
  font-family: var(--font-hand); font-weight: 600; font-size: 23px; color: var(--ink);
  padding: 7px 14px; border-radius: 9px; cursor: pointer; text-align: left; white-space: nowrap;
  display: flex; align-items: center; justify-content: space-between; gap: 12px; line-height: 1.1;
}
.vt-opt:hover { background: var(--surface); color: var(--brand-dark); }
.vt-opt[aria-selected="true"] { color: var(--brand-dark); }
.vt-opt[aria-selected="true"]::after { content: "✓"; color: var(--brand); font-size: 14px; }
.story-switch [data-story] { display: none; }
.story-switch[data-story-type="pub"]    [data-story="pub"],
.story-switch[data-story-type="studio"] [data-story="studio"],
.story-switch[data-story-type="salon"]  [data-story="salon"] { display: block; }

.makers { display: inline-flex; margin-bottom: 14px; }
/* Unused today; the background is supplied inline, so white is the safe default. */
.maker { width: 30px; height: 30px; border-radius: 50%; border: 2px solid var(--canvas); margin-left: -8px; display: grid; place-items: center; font-size: 13px; font-weight: 700; color: #fff; }
.maker:first-child { margin-left: 0; }

/* "made by humans" beat at the CTA */
.human-note { margin: 32px 0 0; padding-inline: clamp(12px, 3vw, 32px); text-align: left; }
.human-note p { font-size: var(--text); color: var(--muted); line-height: 1.55; }
.human-note p + p { margin-top: 1.55em; }
.human-note b { color: var(--ink-strong); font-weight: 600; }
.human-note .signoff { display: block; margin-top: 6px; font-family: var(--font-hand); font-size: 26px; color: var(--brand-dark); }

.venuetypes { text-align: center; }
.venuetypes .types { font-family: var(--font-serif); font-size: var(--text-x-large); color: var(--ink-strong); font-weight: 500; letter-spacing: -0.01em; }
.venuetypes .types span { color: var(--ink-faint); }
.venuetypes p { color: var(--muted); margin-top: 14px; font-size: 16px; }

.bridge {
  display: inline-flex; align-items: center; gap: 8px; margin-top: 28px;
  font-size: var(--text); font-weight: 600; color: var(--brand-dark); cursor: pointer;
  background: none; border: 0; font-family: var(--font-sans);
}
.bridge:hover { color: var(--brand); }
.story-bridge { text-align: center; }

/* CTA band */
/* Founder letter — the villain lives inside it, Basecamp/HEY style. Measure is
   capped for readability; .human-note supplies the body type. */
.letter { max-width: 46rem; margin-inline: auto; }
.letter h2 {
  font-family: var(--font-serif); font-weight: 600; font-size: var(--text-2x-large);
  color: var(--ink-strong); letter-spacing: -0.02em; line-height: 1.15; margin-bottom: 26px;
}
.letter ul {
  list-style: disc; padding-left: 22px; margin: 0.8em 0 0; display: grid; gap: 8px;
  font-size: var(--text); color: var(--muted); line-height: 1.55;
}
.letter ul + p { margin-top: 1.55em; }
.letter-role { margin-top: 2px; font-size: var(--text-small); color: var(--ink-faint); }
.letter-role a { color: inherit; }

.cta-band { text-align: center; }
/* auto, not 0: this is a .wrap, and past 1400px its side margins do the centring. */
.rail-cta { display: flex; justify-content: center; margin: 30px auto 42px; }
/* soft brand-hue closing band — tinted glow, not a saturated block */
.cta-card {
  position: relative; overflow: hidden; max-width: 760px; margin: 0 auto;
  background: var(--card); border: 1.5px solid var(--brand);
  border-radius: 30px;
  /* Horizontal padding shrinks on narrow screens so the heading + note don't
     wrap so hard on mobile; caps at 44px on desktop (fluid, no media query). */
  padding: clamp(40px, 9vw, 56px) clamp(20px, 6vw, 44px);
  box-shadow: 0 18px 44px -30px color-mix(in srgb, var(--brand-dark) 30%, transparent);
}
.cta-card::before {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background:
    radial-gradient(58% 50% at 18% 0%, color-mix(in srgb, var(--brand) 30%, transparent), transparent 64%),
    radial-gradient(50% 50% at 92% 8%, color-mix(in srgb, var(--accent) 17%, transparent), transparent 62%),
    radial-gradient(72% 62% at 62% 112%, color-mix(in srgb, var(--sage) 14%, transparent), transparent 66%);
}
.cta-card > * { position: relative; }
.cta-band h2 { font-family: var(--font-serif); font-weight: 600; font-size: var(--text-3x-large); color: var(--ink-strong); letter-spacing: -0.02em; margin-bottom: 26px; }

/* privacy section — the locals tab's centre of gravity (anti-big-tech) */
.privacy-lead {
  max-width: 820px; margin: 0 auto; text-align: center;
  font-family: var(--font-serif); font-size: var(--text-large); line-height: 1.45; color: var(--ink-strong);
}
.privacy-lead b { color: var(--brand); font-weight: 600; }
/* punchline: the payoff of the privacy argument (venues pay → it's free) */
.privacy-free { text-align: center; margin-top: 40px; font-family: var(--font-serif); font-weight: 600; font-size: var(--text-2x-large); letter-spacing: -0.02em; color: var(--ink-strong); }
.privacy-free em { font-style: italic; color: var(--brand); }
.privacy-grid { margin-top: 36px; display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 14rem), 1fr)); gap: 16px; }
.privacy-card {
  background: var(--card); border: 1px solid var(--border);
  border-radius: 18px; padding: 26px 22px; text-align: center;
}
.privacy-ic { font-size: 26px; margin-bottom: 11px; line-height: 1; }
.privacy-card h3 { font-family: var(--font-serif); font-size: var(--text-large); font-weight: 600; color: var(--ink-strong); margin-bottom: 8px; }
.privacy-card p { color: var(--muted); font-size: var(--text-small); line-height: 1.5; }
.free-line { text-align: center; margin-top: 36px; font-family: var(--font-serif); font-size: var(--text-large); color: var(--muted); }
.free-line b { color: var(--ink-strong); }

/* Narrow screens: turn the stacked card groups (venue how-to notes, locals
   how-it-works steps, privacy cards) into a single-height horizontal swipe row.
   Native scroll-snap = touch swipe, no JS. Full-bleed to the viewport edge by
   cancelling the wrap padding, then re-adding it as scroll padding so the first
   and last cards still line up with the content column. Cuts vertical scroll. */
@media (max-width: 40rem) {
  .howto-notes, .steps, .privacy-grid {
    display: flex;
    gap: 14px;
    margin-top: 24px;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    margin-inline: calc(-1 * clamp(1.25rem, 4vw, 4rem));
    padding-inline: clamp(1.25rem, 4vw, 4rem);
    scroll-padding-inline: clamp(1.25rem, 4vw, 4rem);
  }
  .howto-notes::-webkit-scrollbar,
  .steps::-webkit-scrollbar,
  .privacy-grid::-webkit-scrollbar { display: none; }

  .howto-notes > .howto-note,
  .steps > .step,
  .privacy-grid > .privacy-card {
    /* Constant 24px peek. The row is full-bleed and padding doesn't clip overflow, so the strip runs to the viewport edge, not the content edge. */
    flex: 0 0 calc(100% - 18px);
    /* Inset > peek, so the strip can only ever hold card edge. Text starts at the padding whatever the copy does; chasing glyph positions doesn't survive a re-wrap. */
    padding-inline: 34px;
    scroll-snap-align: start;
    /* Drop the desktop height:100% (resolves to content height against the
       indefinite row) so align-items:stretch equalises every card to the tallest. */
    height: auto;
  }
}

/* ── Legal pages (privacy / terms) ──────────────────────── */
.legal { max-width: 760px; padding-block: clamp(2.5rem, 6vw, 4.5rem); }
.legal h1 {
  font-family: var(--font-serif); font-weight: 600;
  font-size: var(--text-3x-large); line-height: 1.05;
  letter-spacing: -0.025em; color: var(--ink-strong); margin: 6px 0 4px;
}
.legal .eyebrow { margin-bottom: 4px; }
.legal-meta { font-size: var(--text-small); color: var(--ink-faint); margin-bottom: 40px; }
.legal-body { color: var(--muted); font-size: var(--text); line-height: 1.65; }
.legal-body > p { margin-bottom: 18px; }
.legal-body section { margin-top: 40px; }
.legal-body h2 {
  font-family: var(--font-serif); font-weight: 600; font-size: var(--text-large);
  color: var(--ink-strong); margin-bottom: 14px; letter-spacing: -0.01em;
}
.legal-body h3 {
  font-weight: 600; font-size: var(--text); color: var(--ink); margin: 20px 0 8px;
}
.legal-body p { margin-bottom: 14px; }
.legal-body ul {
  list-style: disc; padding-left: 22px; margin: 0 0 16px; display: grid; gap: 6px;
}
.legal-body strong { color: var(--ink-strong); font-weight: 600; }
.legal-body a { color: var(--brand-dark); text-decoration: underline; text-underline-offset: 2px; }
.legal-body a:hover { color: var(--brand); }
.legal-parties { display: grid; gap: 18px; margin-top: 4px; }
.legal-party-name { color: var(--ink); font-weight: 600; margin-bottom: 2px; }
.legal-contact { border-top: 1px solid var(--border-soft); padding-top: 32px; }
.legal-company { font-size: var(--text-small); color: var(--ink-faint); margin-bottom: 2px; }

/* ── Footer ─────────────────────────────────────────────── */
footer {
  border-top: 1px solid var(--border-soft); padding: 16px 0;
}
.footer-inner { display: flex; align-items: center; gap: 18px; flex-wrap: wrap; }
/* The wordmark keeps its own colour — it is the mark, not a link. */
.footer-inner a:not(.wordmark) { color: var(--brand-dark); text-decoration: none; font-size: var(--text-small); }
.footer-inner a:not(.wordmark):hover { color: var(--brand); }
.footer-spacer { flex: 1; }

/* ── Audience switching ─────────────────────────────────── */
[data-panel] { display: none; }
[data-audience="venues"] [data-panel="venues"] { display: block; }
[data-audience="locals"] [data-panel="locals"] { display: block; }

/* ── Responsive ───────────────────────────────────────────
   No viewport @media queries by design. Every layout above reflows
   intrinsically — flex-wrap + intrinsic flex-basis for the hero splits,
   repeat(auto-fit, minmax(min(100%, …), 1fr)) for the card/step grids,
   and clamp() for fluid type, padding and the beat columns. The layout
   adapts to whatever container it sits in, in any orientation, with no
   width "asserted" as mobile. Capability (hover/pointer) queries only. */

/* ── Venue spotlight strip — landing-native tile (Tailwind-free) reproducing the
   /places tile look, fed REAL venue data. No app partial / no Tailwind = no cascade
   collisions. Explicit square via width+height (aspect-ratio is unreliable on flex
   items). ── */
.vstrip { display: flex; gap: 16px; align-items: flex-start; overflow-x: auto; padding: 4px 4px 18px; scroll-snap-type: x mandatory; -webkit-overflow-scrolling: touch; }
.vstrip::-webkit-scrollbar { height: 8px; }
.vstrip::-webkit-scrollbar-thumb { background: var(--border); border-radius: 100px; }
.vstrip::-webkit-scrollbar-track { background: transparent; }

.vspot-tile { position: relative; flex: 0 0 auto; width: clamp(15rem, 40vw, 18rem); height: clamp(15rem, 40vw, 18rem); border-radius: 18px; overflow: hidden; display: block; text-decoration: none; background-size: cover; background-position: center; box-shadow: 0 3px 12px color-mix(in srgb, var(--shadow-ink) 14%, transparent); scroll-snap-align: start; transition: transform .15s ease, box-shadow .15s ease; }
.vspot-tile:hover { transform: translateY(-3px); box-shadow: 0 16px 34px color-mix(in srgb, var(--shadow-ink) 22%, transparent); }
.vspot-tile--fallback { display: flex; align-items: center; justify-content: center; background: linear-gradient(135deg, var(--v), color-mix(in srgb, var(--v) 55%, #000)); }
/* Gold fallback tile, not a photo — on-brand, not on-scrim (white was 3.08:1). */
.vspot-initial { font-family: var(--font-serif); font-weight: 700; font-size: 64px; color: color-mix(in srgb, var(--on-brand) 85%, transparent); }
.vspot-scrim { position: absolute; inset: 0; background:
  linear-gradient(180deg, rgba(15,15,14,.42) 0%, rgba(15,15,14,0) 40%),
  linear-gradient(0deg,  rgba(15,15,14,.82) 0%, rgba(15,15,14,0) 60%); }
/* Type — brand-gold vertical spine on the left edge, matching venues/_venue. */
.vspot-type { position: absolute; top: 14px; left: 0; z-index: 2; writing-mode: vertical-rl; font-size: 10.5px; font-weight: 700; letter-spacing: .12em; text-transform: uppercase; padding: 11px 5px; border-radius: 0 10px 10px 0; background: linear-gradient(180deg, var(--brand-light), var(--brand)); color: var(--on-brand); text-shadow: 0 1px 2px rgba(0,0,0,.3); box-shadow: 2px 2px 10px rgba(0,0,0,.28); }
.vspot-panel { position: absolute; left: 0; right: 0; bottom: 0; z-index: 2; padding: 15px; }
/* Google rating — inline in the panel above the name, multicolour G SVG (matches _venue). */
.vspot-rate { display: flex; align-items: center; gap: 5px; margin-bottom: 8px; font-size: 13px; font-weight: 600; color: var(--on-scrim); text-shadow: 0 1px 2px rgba(0,0,0,.92), 0 0 10px rgba(0,0,0,.6); }
.vspot-rate svg { filter: drop-shadow(0 1px 2px rgba(0,0,0,.75)); }
.vspot-star { color: #FBBC05; filter: drop-shadow(0 1px 2px rgba(0,0,0,.75)); }
.vspot-count { font-weight: 400; color: color-mix(in srgb, var(--on-scrim) 85%, transparent); }
.vspot-name { font-family: var(--font-serif); font-weight: 600; font-size: 18px; color: var(--on-scrim); line-height: 1.15; text-shadow: 0 1px 3px rgba(0,0,0,.55); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.vspot-loc { font-family: var(--font-serif); font-style: italic; font-size: 12.5px; color: color-mix(in srgb, var(--on-scrim) 86%, transparent); text-shadow: 0 1px 3px rgba(0,0,0,.55); margin-top: 2px; }

.vstrip-all { flex: 0 0 10rem; height: clamp(15rem, 40vw, 18rem); display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 8px; border: 1.5px dashed var(--border); border-radius: 18px; color: var(--muted); text-decoration: none; scroll-snap-align: start; transition: color .15s, border-color .15s; }
.vstrip-all:hover { color: var(--brand); border-color: var(--brand); }
.vstrip-all-arw { font-family: var(--font-serif); font-size: 34px; line-height: 1; }
.vstrip-all span:last-child { font-size: 14px; font-weight: 600; }

/* ── Owner-side social-proof + solidarity P.S. (venue CTA founder note) ── */
.proof-ps { margin-top: 20px; font-size: var(--text-small); color: var(--muted); line-height: 1.6; }
.proof-ps b { color: var(--ink-strong); font-weight: 700; }
.proof-link { display: inline-flex; align-items: center; gap: 5px; margin-top: 8px; font-size: var(--text-small); font-weight: 600; color: var(--brand-dark); text-decoration: none; border-bottom: 1.5px solid var(--border); padding-bottom: 1px; }
.proof-link:hover { color: var(--brand); border-color: var(--brand); }

/* ── Places tile stack — mini facsimile of venues/_venue for the locals demo screen.
   Single column of full-width square tiles = how /places reflows on a real phone. ── */
.mini-stack { display: flex; flex-direction: column; gap: 12px; margin-top: 13px; }
.mtile { position: relative; aspect-ratio: 1/1; border-radius: 14px; overflow: hidden; background-size: cover; background-position: center; }
.mscrim { position: absolute; inset: 0; background:
  linear-gradient(180deg, rgba(15,15,14,.40) 0%, rgba(15,15,14,0) 34%),
  linear-gradient(0deg,  rgba(15,15,14,.82) 0%, rgba(15,15,14,0) 58%); }
.mrate { position: absolute; top: 9px; left: 9px; z-index: 2; font-size: 10.5px; font-weight: 700; padding: 3px 8px; border-radius: 100px; background: color-mix(in srgb, var(--card) 92%, transparent); color: var(--ink-strong); }
.mrate .g { color: #4285F4; }
.mtype { position: absolute; top: 0; left: 50%; transform: translateX(-50%); z-index: 2; font-size: 10.5px; font-weight: 600; padding: 3px 11px; border-radius: 0 0 8px 8px; background: color-mix(in srgb, var(--card) 92%, transparent); color: var(--ink-strong); }
.mpanel { position: absolute; left: 0; right: 0; bottom: 0; z-index: 2; padding: 12px; }
.mname { font-family: var(--font-serif); font-weight: 600; font-size: 17px; color: var(--on-scrim); line-height: 1.15; text-shadow: 0 1px 3px rgba(0,0,0,.6); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mloc { font-family: var(--font-serif); font-style: italic; font-size: 12px; color: color-mix(in srgb, var(--on-scrim) 88%, transparent); text-shadow: 0 1px 3px rgba(0,0,0,.6); margin-bottom: 9px; }
.mfollow { font-size: 12px; font-weight: 600; padding: 7px 15px; border-radius: 9px; background: var(--brand); color: var(--on-brand); border: none; box-shadow: 0 2px 8px color-mix(in srgb, var(--brand) 50%, transparent); }


/* Mirrors application.css: landing, pricing and legal load this sheet instead. */
[data-platform~="native"] .sells { display: none !important; }
.sells-elsewhere { display: none !important; }
[data-platform~="native"] .sells-elsewhere { display: block !important; }

/* ── The launch splash ──────────────────────────────────────────
   Mirrors application.css; declared here too because the marketing sheet never
   imports it and `/` is the app's start_url, so a standalone launch lands on a
   landing page as often as on the app shell. Same reasoning throughout — see
   design-system.md "The launch splash". */
.app-splash {
  display: none;
  position: fixed;
  inset: 0;
  z-index: 100;
  place-items: center;
  /* The manifest's background_color, by hand — see application.css. */
  background: #15110D;
  pointer-events: none;
  animation: app-splash-out 1s ease-in forwards;
}
@media (display-mode: standalone) {
  /* Only the session's first paint carries the flag — see _app_splash. */
  html[data-splash-first] .app-splash { display: grid; }
}
/* Both shells' web views report display-mode: browser; ~= matches the word in "native ios". */
html[data-platform~="native"][data-splash-first] .app-splash { display: grid; }
.app-splash-mark { animation: app-splash-lift 1s ease-in forwards; }
.app-splash .wordmark {
  display: inline-flex; align-items: center; gap: 0.34em;
  font-family: var(--font-serif); font-style: italic;
  font-size: var(--text-2x-large); color: #FBF4E6;
}
.app-splash .wordmark-mark img { height: 1.6em; width: auto; }

@keyframes app-splash-out {
  0%, 45% { opacity: 1; }
  100%    { opacity: 0; visibility: hidden; }
}
@keyframes app-splash-lift {
  0%, 45% { transform: translateY(0); }
  100%    { transform: translateY(-28px); }
}
@media (prefers-reduced-motion: reduce) {
  .app-splash-mark { animation: none; }
}
