/* ==========================================================================
   WARM BRAND THEME — customer-facing QR pages (body.theme-warm)
   Reference redesign (client screenshot, 2026-10-08):

     warm cream canvas · organic deep-green waves + gold accents ·
     solid white pill cards with real brand-logo badges · circular
     contact buttons · bold ink titles, quiet gray subtitles

   Scoped to body.theme-warm, so the control panel keeps its own look.
   The waves live in templates/partials/ambient_waves.html and recolor
   per brand through the CSS vars base.html injects (brand_colors).
   ========================================================================== */

body.theme-warm {
  background: #fff;
  color: var(--ink);
}

/* sage aurora off — the waves ARE the background now */
body.theme-warm::before { display: none; }

.ambient-waves,
body.theme-warm .ambient-waves { display: none; }

/* Client-provided background art fills the phone screen only. The layer is
   PINNED (position: fixed): the decorated corners stay on the frame edges
   while the cards scroll over the cream middle — the background never
   scrolls with the content. On real phones the fixed layer pins to the
   viewport (the screen IS the viewport). Inside the desktop mock frame,
   .device carries a translateZ(0) containing block (see the min-width:
   860px block below) so the layer pins to the phone body, box-matched to
   the screen. The flat colour is the image's own cream, so the pre-load
   frame matches the art instead of flashing a different tone. */
body.theme-warm .device-screen {
  background: transparent;
}
body.theme-warm .device-screen::before {
  content: "";
  position: fixed;
  /* Overscan 32px, then clip back to the exact box with the matching
     clip-path. A blurred layer has no content past its own edge, so the
     blur fades to transparent there and would show as a soft light ring
     on the frame edges; painting beyond the edge and clipping the result
     (filter runs BEFORE clip-path) removes that fringe. */
  inset: -32px;
  z-index: 0;
  pointer-events: none;
  background: #f8edda url("../img/updated_phone_bg.1d5ecc30f544.png") center / cover no-repeat;
  /* Slight softness so the art sits behind the cards instead of competing
     with them. saturate(1.04) keeps the blur from reading grey. */
  filter: blur(6px) saturate(1.04);
  clip-path: inset(32px);
}
body.theme-warm .device-screen > * {
  position: relative;
  z-index: 1;
}

/* Inside the desktop mock frame, pin the background layer to the phone
   body: translateZ(0) makes .device the containing block of the fixed
   layer, and .device's padding box (border-box 390x844 minus the 11px
   bezel = 368x822) is exactly the screen box. The layer gets the screen
   radius too — a fixed layer is not clipped by the screen's overflow. */
@media (min-width: 860px) {
  body.theme-warm .device {
    transform: translateZ(0);
  }
  body.theme-warm .device-screen::before {
    /* Clip back to the screen box with the screen's own corner radius; the
       blurred fringe in the 32px overscan is trimmed away. */
    clip-path: inset(32px round 46px);
  }
}

/* --------------------------------------------------------------------------
   Cards: solid warm white, soft double shadow, no glass blur
   -------------------------------------------------------------------------- */
body.theme-warm .glass {
  background: var(--card-white);
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
  border: 1px solid rgba(34, 48, 31, 0.055);
  box-shadow:
    0 1px 2px rgba(31, 55, 38, 0.05),
    0 12px 30px rgba(31, 55, 38, 0.09);
}

body.theme-warm .glass--lg {
  border-radius: 26px;
  box-shadow:
    0 2px 4px rgba(31, 55, 38, 0.05),
    0 18px 44px rgba(31, 55, 38, 0.12);
}

body.theme-warm .glass--strong {
  background: var(--card-white);
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
}

/* --------------------------------------------------------------------------
   Identity header — open on the canvas, no card around it
   -------------------------------------------------------------------------- */
body.theme-warm .scan-identity,
body.theme-warm .identity-card {
  background: transparent;
  border: none;
  box-shadow: none;
  padding: 4.25rem var(--sp-2) var(--sp-2);
}

/* Home screen matches the reference: logo, name, place, three contact
   circles, then the five buttons. The block scales to the phone height
   so the game button stays inside the frame. It does not scroll. */
/* The container query box lives on .device, NOT on .device-screen: the
   screen is the scroller, and container-type implies layout containment
   which makes an element the containing block for fixed descendants —
   on the scroller that would translate the pinned background with the
   scroll again. cqh values are unchanged: .device's content box is the
   screen box (368x822 in the frame, 100dvh on real phones). */
body.theme-warm .device:has(.outlet-actions) {
  container-type: size;
}

body.theme-warm .device-screen:has(.outlet-actions) {
  overflow-y: auto;
  overflow-x: hidden;
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  gap: clamp(6px, 1.2cqh, 12px);
  padding: 1.7rem 1rem 0.7rem;
  height: 100%;
  min-height: 0;
}

/* On a real phone there is no frame. The page itself is the screen,
   so the home view fills the phone and the game button stays on it. */
@media (max-width: 859px) {
  body.theme-warm main.page--device:has(.outlet-actions) {
    height: 100dvh;
    min-height: 0;
    max-height: 100dvh;
    overflow: hidden;
    padding: 0;
  }
  body.theme-warm .device-stage:has(.outlet-actions),
  body.theme-warm .device:has(.outlet-actions) {
    height: 100%;
  }
  body.theme-warm .device-screen:has(.outlet-actions) {
    height: 100dvh;
    padding-top: max(2.4rem, env(safe-area-inset-top));
    padding-bottom: max(0.7rem, env(safe-area-inset-bottom));
  }
}

body.theme-warm .device-screen:has(.outlet-actions) .scan-identity {
  padding: 0;
}

body.theme-warm .device-screen:has(.outlet-actions) .scan-identity .avatar {
  width: clamp(64px, 13cqh, 92px);
  height: clamp(64px, 13cqh, 92px);
  font-size: 1.45rem;
}

body.theme-warm .device-screen:has(.outlet-actions) .scan-outlet {
  font-size: clamp(1.05rem, 3.4cqh, 1.28rem);
  margin-top: 6px;
}

body.theme-warm .device-screen:has(.outlet-actions) .scan-loc {
  margin-top: 4px;
}

body.theme-warm .device-screen:has(.outlet-actions) .contact-row {
  gap: 18px;
  margin: 6px 0 4px;
}

body.theme-warm .device-screen:has(.outlet-actions) .contact-circle {
  width: clamp(42px, 7.4cqh, 54px);
  height: clamp(42px, 7.4cqh, 54px);
}

body.theme-warm .device-screen:has(.outlet-actions) .contact-circle--call .icon {
  width: 22px;
  height: 22px;
}

body.theme-warm .device-screen:has(.outlet-actions) .outlet-actions {
  /* grow to fill the frame when there is room, but never shrink below
     the cards' own size — when the five cards don't fit, the screen
     scrolls over the pinned background instead of squashing them */
  flex: 1 0 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: clamp(7px, 1.3cqh, 12px);
  margin-top: 4px;
  padding-bottom: 6px;
}

body.theme-warm .device-screen:has(.outlet-actions) .btn-action {
  flex: 1 1 0;
  padding: clamp(8px, 1.3cqh, 12px) 12px;
  gap: 10px;
  border-radius: 22px;
}

body.theme-warm .device-screen:has(.outlet-actions) .btn-action__icon {
  width: clamp(38px, 6.6cqh, 48px);
  height: clamp(38px, 6.6cqh, 48px);
}

body.theme-warm .device-screen:has(.outlet-actions) .btn-action__title {
  font-size: 0.92rem;
}

body.theme-warm .device-screen:has(.outlet-actions) .btn-action__sub {
  font-size: 0.72rem;
  margin-top: 1px;
}

body.theme-warm .avatar {
  background: var(--card-white);
  color: var(--wave-green);
  box-shadow:
    0 10px 28px rgba(31, 55, 38, 0.18),
    0 0 0 5px rgba(255, 255, 255, 0.65);
}

body.theme-warm .avatar img { object-fit: contain; padding: 12%; }

/* Donar Istanbul's plate is #231F20 (sampled from the logo file). Any other
   dark, and the disc reads as a different background behind the mark. */
body.theme-warm .avatar--on-dark {
  background: #231F20;
  /* No pale halo. A light ring reads as a second, lighter dark around the plate. */
  box-shadow: 0 10px 28px rgba(35, 31, 32, 0.22);
}

body.theme-warm .avatar--on-dark img {
  padding: 0;
  object-fit: cover;
}

body.theme-warm .scan-identity .avatar,
body.theme-warm .identity-card .avatar {
  width: 104px;
  height: 104px;
  font-size: 2.4rem;
  border-radius: 50%;
}

body.theme-warm .scan-brand {
  color: var(--gold-deep);
  font-size: var(--fs-caption);
  letter-spacing: var(--track-caps);
  text-transform: uppercase;
  font-weight: 800;
  margin: var(--sp-4) 0 0;
}

body.theme-warm .scan-outlet {
  font-size: 1.75rem;
  letter-spacing: -0.025em;
  line-height: 1.12;
  color: var(--ink);
  margin: 6px 0 0;
}

body.theme-warm .scan-sub {
  color: var(--link-sub);
  font-size: var(--fs-body);
  max-width: 30ch;
  margin: 8px auto 0;
}

/* location line under the name (reference: pin + district) */
.scan-loc {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin: 10px 0 0;
  color: var(--link-sub);
  font-size: var(--fs-sm);
  font-weight: 600;
}
.scan-loc .icon { width: 15px; height: 15px; color: var(--gold-deep); }

body.theme-warm .identity-name { color: var(--ink); }

/* --------------------------------------------------------------------------
   Contact circles — phone / WhatsApp / Instagram (reference row)
   -------------------------------------------------------------------------- */
.contact-row {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 20px;
  margin: var(--sp-3) 0 var(--sp-2);
}

.contact-circle {
  width: 62px;
  height: 62px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  /* Depth lives on the round anchor, never as a filter on the icon.
     filter: drop-shadow() promotes each img to its own compositor layer
     whose backing store is the RECTANGULAR filter region; after a
     back-navigation (bfcache restore) Chromium can composite that stale
     rectangle — the tinted box guests briefly saw behind the badges.
     box-shadow paints in the normal pass: same lift, no layer, no artifact. */
  box-shadow: 0 8px 16px rgba(31, 55, 38, 0.22);
  transition: transform var(--t-press) var(--ease-spring);
}

.contact-circle:active { transform: scale(0.91); transition-duration: var(--t-press); }

.contact-circle:focus-visible {
  outline: 3px solid var(--gold-deep);
  outline-offset: 3px;
}

.contact-circle--call {
  /* flat translucent green instead of backdrop-filter: same read over the
     cream/wave canvas, but no compositor layer that can go stale on bfcache */
  background: rgba(46, 91, 62, 0.9);
  border: 1px solid rgba(255, 255, 255, 0.35);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.35), 0 8px 16px rgba(31, 55, 38, 0.22);
  color: #fff;
}
.contact-circle--call .icon { width: 28px; height: 28px; }

.contact-circle .icon--badge {
  width: 100%;
  height: 100%;
}

/* generated badge images (media/icons/*.png) inside the contact circles */
/* Saved-guest profile circle. Same size as Call / WhatsApp / Instagram,
   cream face so it reads as "yours" rather than a brand badge. */
.contact-circle--profile {
  background: var(--cream, #F5EFE3);
  border: 1px solid rgba(34, 48, 31, 0.12);
  color: var(--ink, #22301F);
  cursor: pointer;
  padding: 0;
}
.contact-circle--profile .icon { width: 28px; height: 28px; }

/* --------------------------------------------------------------------------
   SAVED-GUEST WALLET — iOS 26 liquid-glass bottom sheet
   -----------------------------------------------------------------------
   The sheet is a floating glass panel over the waves, same material family
   as the specials / menu / composer glass. Note the specificity: the
   body.theme-warm .device-screen > * rule above pins every direct child to
   position: relative; z-index: 1 (to clear the background layer), which
   overrode this overlay and left it rendering as an inline card. The
   doubled scope below wins over that rule on purpose. On desktop the
   .device translateZ(0) containing block pins the sheet to the phone
   screen; on real phones it pins to the viewport. */
body.theme-warm .guest-profile,
body.theme-warm .device-screen > .guest-profile {
  position: fixed;
  inset: 0;
  z-index: 40;
  display: grid;
  align-items: end;
  justify-items: center;
}
body.theme-warm .guest-profile[hidden] { display: none; }

.guest-profile__scrim {
  position: absolute;
  inset: 0;
  background: rgba(22, 34, 22, 0.38);
  opacity: 0;
  transition: opacity 300ms cubic-bezier(0.32, 0.72, 0, 1);
}
body.theme-warm .guest-profile.is-open .guest-profile__scrim { opacity: 1; }

.guest-profile__sheet {
  position: relative;
  width: min(430px, calc(100% - 20px));
  max-height: min(80dvh, 660px);
  margin-bottom: max(12px, env(safe-area-inset-bottom));
  overflow: auto;
  overscroll-behavior: contain;
  color: var(--ink, #22301F);
  border-radius: 30px;
  padding: 8px 18px 22px;
  /* liquid glass: lens highlight top-left, warm-white gradient body */
  background:
    radial-gradient(120% 70% at 16% 0%, rgba(255, 255, 255, 0.5), rgba(255, 255, 255, 0) 58%),
    linear-gradient(165deg, rgba(255, 255, 255, 0.88), rgba(255, 255, 255, 0.64));
  -webkit-backdrop-filter: blur(22px) saturate(180%);
  backdrop-filter: blur(22px) saturate(180%);
  border: 1px solid rgba(255, 255, 255, 0.66);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.85),
    inset 0 -1px 0 rgba(255, 255, 255, 0.14),
    0 24px 56px -20px rgba(23, 58, 36, 0.5);
  transform: translate3d(0, 18px, 0) scale(0.985);
  opacity: 0;
  transition: transform 300ms cubic-bezier(0.32, 0.72, 0, 1),
    opacity 300ms cubic-bezier(0.32, 0.72, 0, 1);
}
body.theme-warm .guest-profile.is-open .guest-profile__sheet {
  transform: translate3d(0, 0, 0) scale(1);
  opacity: 1;
}

/* grabber: the drag handle that makes the sheet feel physical */
.guest-profile__grab {
  width: 38px;
  height: 5px;
  margin: 6px auto 2px;
  border-radius: var(--r-pill, 999px);
  background: rgba(34, 48, 31, 0.22);
  cursor: grab;
  touch-action: none;
}

.guest-profile__head {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 12px;
  padding: 6px 2px 2px;
  touch-action: none;
}
.guest-profile__eyebrow {
  margin: 0;
  font-size: 0.68rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--gold-deep, #A8893E);
  font-weight: 700;
}
.guest-profile__head h2 {
  margin: 3px 0 0;
  font-size: 1.55rem;
  line-height: 1.15;
  letter-spacing: -0.02em;
}
.guest-profile__phone {
  margin: 3px 0 0;
  color: var(--link-sub, #6F7D6A);
  font-weight: 600;
  font-size: 0.92rem;
  letter-spacing: 0.01em;
  font-variant-numeric: tabular-nums;
}
.guest-profile__close {
  flex: none;
  width: 38px;
  height: 38px;
  border: 1px solid rgba(255, 255, 255, 0.7);
  border-radius: 50%;
  background: linear-gradient(165deg, rgba(255, 255, 255, 0.8), rgba(255, 255, 255, 0.5));
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.8),
    0 6px 14px -8px rgba(23, 58, 36, 0.4);
  color: var(--ink, #22301F);
  display: grid;
  place-items: center;
  cursor: pointer;
  transition: transform 100ms ease-out;
}
.guest-profile__close:active { transform: scale(0.92); }
.guest-profile__close .icon {
  width: 18px;
  height: 18px;
  transform: rotate(-90deg); /* chevron points down: dismiss downward */
}

.guest-profile__list {
  display: grid;
  gap: 10px;
  margin-top: 14px;
}
.guest-profile__empty {
  margin: 4px 0 0;
  padding: 14px 16px;
  border-radius: 18px;
  background: rgba(255, 255, 255, 0.5);
  border: 1px solid rgba(255, 255, 255, 0.6);
  color: var(--link-sub, #6F7D6A);
  font-size: var(--fs-sm, 0.78125rem);
  line-height: 1.55;
}

/* ------------------------------------------------------------------
   Wallet coupons: the win ticket, list size.

   The same object the guest is shown when a game is won (design draft 2),
   drawn small enough for a wallet list. A real ticket cut: a quarter circle
   bitten out of every corner, a round notch scooped out of the left and
   right edge at the tear line, the code ABOVE that line, the usage stub
   below it. Brushed silver with a looping light sweep.

   Two faces, one per prize kind: a dessert ticket glows warm gold while it
   is still usable, a discount ticket stays plain silver and lets the number
   be the prize. A spent ticket loses the sweep and its code is struck
   through, so state reads at a glance without dimming the text a staff
   member still has to read.

   The cut is a CSS mask, so the outer shadow sits on the shell wrapper and
   uses filter drop-shadow: that follows the real cut silhouette, where a
   box-shadow on the ticket would just draw a plain rectangle.
   ------------------------------------------------------------------ */
.guest-coupon {
  --gc-scoop: 17px;  /* the corner bites */
  --gc-bite: 10px;   /* the side notches at the tear line */
  --gc-stub: 84px;   /* bottom stub height, also where the tear line sits */
  --gc-pad: 20px;

  display: block;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: transparent;
  box-shadow: none;
}

.guest-coupon__shell {
  perspective: 900px;
  filter:
    drop-shadow(0 12px 20px rgba(34, 48, 31, 0.20))
    drop-shadow(0 2px 3px rgba(34, 48, 31, 0.10));
}

/* A usable dessert ticket carries the warm glow. */
.guest-coupon--dessert.guest-coupon--issued .guest-coupon__shell {
  filter:
    drop-shadow(0 12px 22px rgba(168, 137, 62, 0.32))
    drop-shadow(0 2px 3px rgba(34, 48, 31, 0.10));
}

/* A spent ticket pulls its shadow back and stops competing for attention. */
.guest-coupon--redeemed .guest-coupon__shell,
.guest-coupon--expired .guest-coupon__shell,
.guest-coupon--void .guest-coupon__shell {
  filter: drop-shadow(0 6px 12px rgba(34, 48, 31, 0.13));
}

.guest-coupon__ticket {
  position: relative;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  isolation: isolate;
  color: var(--ink, #22301F);
  background:
    linear-gradient(135deg,
      #FDFDFE 0%,
      #E4E8EC 16%,
      #C6CCD3 34%,
      #E9EDF1 50%,
      #AEB5BD 66%,
      #E4E8EC 84%,
      #C6CCD3 100%);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.95),
    inset 0 -1px 0 rgba(255, 255, 255, 0.40),
    inset 0 0 0 1px rgba(255, 255, 255, 0.22);

  -webkit-mask-image:
    radial-gradient(circle var(--gc-scoop) at 0 0,     transparent calc(var(--gc-scoop) - 0.8px), #000 var(--gc-scoop)),
    radial-gradient(circle var(--gc-scoop) at 100% 0,  transparent calc(var(--gc-scoop) - 0.8px), #000 var(--gc-scoop)),
    radial-gradient(circle var(--gc-scoop) at 0 100%,  transparent calc(var(--gc-scoop) - 0.8px), #000 var(--gc-scoop)),
    radial-gradient(circle var(--gc-scoop) at 100% 100%, transparent calc(var(--gc-scoop) - 0.8px), #000 var(--gc-scoop)),
    radial-gradient(circle var(--gc-bite) at 0 calc(100% - var(--gc-stub)),    transparent calc(var(--gc-bite) - 0.8px), #000 var(--gc-bite)),
    radial-gradient(circle var(--gc-bite) at 100% calc(100% - var(--gc-stub)), transparent calc(var(--gc-bite) - 0.8px), #000 var(--gc-bite));
  mask-image:
    radial-gradient(circle var(--gc-scoop) at 0 0,     transparent calc(var(--gc-scoop) - 0.8px), #000 var(--gc-scoop)),
    radial-gradient(circle var(--gc-scoop) at 100% 0,  transparent calc(var(--gc-scoop) - 0.8px), #000 var(--gc-scoop)),
    radial-gradient(circle var(--gc-scoop) at 0 100%,  transparent calc(var(--gc-scoop) - 0.8px), #000 var(--gc-scoop)),
    radial-gradient(circle var(--gc-scoop) at 100% 100%, transparent calc(var(--gc-scoop) - 0.8px), #000 var(--gc-scoop)),
    radial-gradient(circle var(--gc-bite) at 0 calc(100% - var(--gc-stub)),    transparent calc(var(--gc-bite) - 0.8px), #000 var(--gc-bite)),
    radial-gradient(circle var(--gc-bite) at 100% calc(100% - var(--gc-stub)), transparent calc(var(--gc-bite) - 0.8px), #000 var(--gc-bite));
  -webkit-mask-composite: source-in;
  mask-composite: intersect;

  animation: gcTicketIn 560ms cubic-bezier(0.2, 0.9, 0.25, 1.1) calc(var(--i, 0) * 90ms) both;
}

@keyframes gcTicketIn {
  from {
    opacity: 0;
    transform: translateY(16px) scale(0.965);
  }

  to {
    opacity: 1;
    transform: translateY(0) scale(1);
  }
}

/* brushed metal hairlines */
.guest-coupon__brushed {
  position: absolute;
  inset: 0;
  z-index: 1;
  background:
    repeating-linear-gradient(112deg,
      rgba(255, 255, 255, 0.08) 0 1px,
      transparent 1px 4px),
    repeating-linear-gradient(112deg,
      rgba(34, 48, 31, 0.035) 0 1px,
      transparent 1px 7px);
  mix-blend-mode: soft-light;
  pointer-events: none;
}

/* the light sweep: the single moving element, so a list stays calm */
.guest-coupon__sheen {
  position: absolute;
  inset: -40% -60%;
  z-index: 2;
  background: linear-gradient(104deg,
      transparent 38%,
      rgba(255, 255, 255, 0.55) 47%,
      rgba(255, 255, 255, 0.85) 50%,
      rgba(255, 255, 255, 0.35) 54%,
      transparent 62%);
  transform: translateX(-70%) rotate(0.001deg);
  mix-blend-mode: screen;
  opacity: 0.72;
  pointer-events: none;
  animation: gcSheen 6.5s ease-in-out calc(var(--i, 0) * 1.35s + 1.1s) infinite;
}

@keyframes gcSheen {
  0% {
    transform: translateX(-70%);
  }

  42% {
    transform: translateX(70%);
  }

  100% {
    transform: translateX(70%);
  }
}

.guest-coupon__body {
  position: relative;
  z-index: 3;
  flex: 1 0 auto;
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 18px var(--gc-pad) 14px;
}

.guest-coupon__top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}

.guest-coupon__kicker {
  margin: 0;
  font-size: 0.62rem;
  font-weight: 700;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--gold-deep, #A8893E);
}

/* The state chip wears the ticket's own translucent pill, not the old
   flat rounded badge. */
.guest-coupon__state {
  flex: none;
  padding: 4px 11px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.62);
  border: 1px solid rgba(34, 48, 31, 0.10);
  font-size: 0.6rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  white-space: nowrap;
}

.guest-coupon--issued .guest-coupon__state {
  color: var(--wave-green, #2E5B3E);
  border-color: rgba(46, 91, 62, 0.30);
}

.guest-coupon--redeemed .guest-coupon__state {
  color: #7A5E17;
  border-color: rgba(168, 137, 62, 0.38);
}

.guest-coupon--expired .guest-coupon__state,
.guest-coupon--void .guest-coupon__state {
  color: #8A4B3A;
  border-color: rgba(138, 75, 58, 0.34);
}

/* The prize: the number is the hero on a discount ticket. */
.guest-coupon__value {
  margin: 0;
  font-family: var(--font-display, "Fraunces", Georgia, serif);
  font-weight: 600;
  font-size: 1.95rem;
  line-height: 1;
  letter-spacing: -0.03em;
  color: var(--ink, #22301F);
}

.guest-coupon__value em {
  font-style: italic;
  font-weight: 500;
}

.guest-coupon__value .pct {
  font-size: 0.5em;
  letter-spacing: -0.01em;
  vertical-align: 0.62em;
  margin-left: 0.06em;
}

.guest-coupon__sub {
  margin: 0;
  max-width: 30ch;
  font-size: 0.84rem;
  line-height: 1.35;
  color: rgba(34, 48, 31, 0.68);
}

.guest-coupon__branch {
  margin: 0;
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.01em;
  color: rgba(34, 48, 31, 0.72);
}

/* The code panel. Solid frosted, so the tear line stays the only dashed
   element on the ticket. */
.guest-coupon__codewrap {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 10px 13px;
  border-radius: 15px;
  background: rgba(255, 255, 255, 0.56);
  border: 1px solid rgba(168, 137, 62, 0.38);
}

.guest-coupon__codelabel {
  margin: 0;
  font-size: 0.58rem;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: rgba(34, 48, 31, 0.55);
}

.guest-coupon__code {
  margin: 1px 0 0;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 1.06rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  color: #2A2F36;
  overflow-wrap: anywhere;
}

/* A spent code is struck through: instant to read, and the text stays
   legible for the staff member who has to look at it. */
.guest-coupon--redeemed .guest-coupon__code,
.guest-coupon--expired .guest-coupon__code,
.guest-coupon--void .guest-coupon__code {
  text-decoration: line-through;
  text-decoration-thickness: 1.5px;
  color: rgba(34, 48, 31, 0.55);
}

.guest-coupon__seal {
  flex: none;
  width: 40px;
  height: 40px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  border: 1px solid rgba(168, 137, 62, 0.50);
  background:
    conic-gradient(from 210deg,
      rgba(255, 255, 255, 0.85),
      rgba(168, 137, 62, 0.22),
      rgba(255, 255, 255, 0.90),
      rgba(168, 137, 62, 0.18),
      rgba(255, 255, 255, 0.85));
  color: #7A5E17;
}

.guest-coupon__seal svg {
  width: 20px;
  height: 20px;
  display: block;
}

/* The dashed tear line, landing exactly on the side notches. */
.guest-coupon__perf {
  position: absolute;
  left: 0;
  right: 0;
  bottom: calc(var(--gc-stub) - 1px);
  height: 2px;
  z-index: 3;
  background: repeating-linear-gradient(90deg,
      rgba(34, 48, 31, 0.34) 0 12px,
      transparent 12px 21px);
  pointer-events: none;
}

/* The stub below the line. Its height MUST equal --gc-stub or the notches
   drift away from the tear line. */
.guest-coupon__stub {
  position: relative;
  z-index: 3;
  flex: none;
  height: var(--gc-stub);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  padding: 12px var(--gc-pad);
}

.guest-coupon__stublabel {
  margin: 0 0 3px;
  font-size: 0.56rem;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: rgba(34, 48, 31, 0.50);
}

.guest-coupon__stubcopy {
  margin: 0;
  max-width: 20ch;
  font-size: 0.68rem;
  line-height: 1.35;
  color: rgba(34, 48, 31, 0.72);
}

.guest-coupon__stubaside {
  text-align: right;
}

.guest-coupon__stubvalid {
  margin: 0;
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  white-space: nowrap;
  color: rgba(34, 48, 31, 0.85);
}

.guest-coupon__stubfine {
  margin: 1px 0 0;
  font-size: 0.58rem;
  letter-spacing: 0.06em;
  white-space: nowrap;
  color: rgba(34, 48, 31, 0.50);
}

/* A list of tickets needs more air than a list of flat cards. */
.guest-profile__list {
  gap: 16px;
}

/* Pointer-only lift. No tilt here: the list scrolls, so following the
   pointer would fight the finger. */
@media (hover: hover) and (pointer: fine) {
  .guest-coupon__shell {
    transition: transform 240ms cubic-bezier(0.16, 1, 0.3, 1);
  }

  .guest-coupon:hover .guest-coupon__shell {
    transform: translateY(-3px);
  }
}

/* Reduced motion: no reveal, no sweep. The static sheen keeps the metal. */
@media (prefers-reduced-motion: reduce) {
  .guest-coupon__ticket {
    animation: none;
  }

  .guest-coupon__sheen {
    animation: none;
    opacity: 0.45;
  }

  .guest-coupon__shell {
    transition: none;
  }

  .guest-coupon:hover .guest-coupon__shell {
    transform: none;
  }
}

/* Reduced transparency: near-solid sheet, text stays legible. The ticket
   itself is already opaque silver and uses no backdrop filter, so it needs
   no override here. Painting a background on .guest-coupon would fill in the
   corner bites and turn the cut ticket back into a plain rectangle. */
@media (prefers-reduced-transparency: reduce) {
  .guest-profile__sheet {
    background: var(--glass-fill-solid, rgba(255, 255, 255, 0.95));
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }
}

/* Reduced motion: short opacity cross-fade only. Drag stays live (direct
   manipulation); its inline transform still wins over these rules. */
@media (prefers-reduced-motion: reduce) {
  .guest-profile__sheet {
    transform: none;
    transition: opacity 120ms linear;
    scroll-behavior: auto;
  }
  .guest-profile.is-open .guest-profile__sheet { transform: none; }
  .guest-profile__scrim { transition: opacity 120ms linear; }
  .guest-profile__close { transition: none; }
}

.contact-circle img {
  width: 100%;
  height: 100%;
  border-radius: 50%;
  object-fit: contain;
}

/* --------------------------------------------------------------------------
   Pill action cards — white rounded rows, brand badge, title/sub, chevron
   -------------------------------------------------------------------------- */
body.theme-warm .outlet-actions { gap: 13px; }

body.theme-warm .btn-action {
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.46), rgba(255, 255, 255, 0.22));
  -webkit-backdrop-filter: blur(22px) saturate(170%);
  backdrop-filter: blur(22px) saturate(170%);
  border: 1px solid rgba(255, 255, 255, 0.62);
  border-radius: 24px;
  padding: 13px 15px;
  gap: 13px;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.9),
    inset 0 -1px 0 rgba(255, 255, 255, 0.28),
    0 10px 26px rgba(31, 55, 38, 0.08);
}

body.theme-warm .btn-action:active { transform: scale(0.975); }

body.theme-warm .btn-action__icon {
  width: 54px;
  height: 54px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background: var(--tint-cream);
  color: var(--gold-deep);
  box-shadow: none;
}

body.theme-warm .btn-action__icon .icon--badge {
  width: 100%;
  height: 100%;
}

body.theme-warm .btn-action__icon .icon:not(.icon--badge) {
  width: 25px;
  height: 25px;
}

/* generated badge images (media/icons/*.png) inside the action-card icon */
body.theme-warm .btn-action__icon img {
  width: 100%;
  height: 100%;
  border-radius: 50%;
  object-fit: contain;
}

body.theme-warm .btn-action__title {
  color: var(--link-title);
  font-size: 1.02rem;
  font-weight: 800;
  letter-spacing: -0.012em;
  text-transform: none;
}

body.theme-warm .btn-action__sub {
  color: var(--link-sub);
  font-size: 0.8125rem;
  font-weight: 500;
  margin-top: 2px;
}

body.theme-warm .btn-action__arrow { color: var(--link-arrow); }
body.theme-warm .btn-action__arrow svg { width: 20px; height: 20px; }

/* pastel tints — the reference's alternating card rhythm */
body.theme-warm .btn-action--tint-cream {
  background: linear-gradient(180deg, rgba(245, 239, 227, 0.55), rgba(245, 239, 227, 0.28));
}
body.theme-warm .btn-action--tint-green {
  background: linear-gradient(180deg, rgba(223, 232, 214, 0.55), rgba(223, 232, 214, 0.26));
}
body.theme-warm .btn-action--tint-blue {
  background: linear-gradient(180deg, rgba(226, 236, 244, 0.55), rgba(226, 236, 244, 0.26));
}
body.theme-warm .btn-action--tint-pink {
  background: linear-gradient(180deg, rgba(248, 228, 232, 0.58), rgba(248, 228, 232, 0.28));
}

/* badge tints */
body.theme-warm .btn-action__icon--gold  { background: #F8EEC8; color: var(--gold-deep); }
body.theme-warm .btn-action__icon--green { background: var(--tint-green); color: var(--wave-green); }
body.theme-warm .btn-action__icon--rose  { background: var(--tint-pink); color: #B23A5B; }

/* --------------------------------------------------------------------------
   Info strip + section furniture
   -------------------------------------------------------------------------- */
body.theme-warm .outlet-info-strip {
  background: rgba(255, 255, 255, 0.82);
  text-align: center;
}

body.theme-warm .section-label,
body.theme-warm .sheet-title { color: var(--ink); letter-spacing: -0.015em; }

body.theme-warm .sheet-head {
  background: transparent;
  border: none;
  box-shadow: none;
  padding-inline: 0;
}

body.theme-warm .sheet-back {
  background: var(--card-white);
  border-radius: 50%;
  color: var(--ink);
  box-shadow: 0 6px 16px rgba(31, 55, 38, 0.14);
}

body.theme-warm .caption,
body.theme-warm .sheet-meta,
body.theme-warm .muted { color: var(--link-sub); }

@media (prefers-reduced-transparency: reduce) {
  body.theme-warm .btn-action,
  body.theme-warm .btn-action--tint-cream,
  body.theme-warm .btn-action--tint-green,
  body.theme-warm .btn-action--tint-blue,
  body.theme-warm .btn-action--tint-pink,
  body.theme-warm .contact-circle--call {
    background: #fff;
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }
  body.theme-warm .contact-circle--call { background: var(--wave-green); color: #fff; }
}

body.theme-warm .chip--open  { background: #DFF0D4; color: #35682B; }
body.theme-warm .chip--gold  { background: #F3E4AE; color: #7A5E17; }
body.theme-warm .chip--warn  { background: #F7E6C8; color: #8A5A18; }

body.theme-warm .btn-primary {
  background: var(--wave-green);
  color: #fff;
  box-shadow: 0 8px 20px rgba(31, 55, 38, 0.28);
}
body.theme-warm .btn-secondary {
  background: var(--card-white);
  color: var(--wave-green);
  border-color: rgba(31, 55, 38, 0.14);
}

/* --------------------------------------------------------------------------
   SVG icon sizing rules
   -------------------------------------------------------------------------- */
.icon { display: block; width: 24px; height: 24px; flex: none; }

body.theme-warm .stars { color: var(--gold-deep); display: inline-flex; gap: 2px; }
body.theme-warm .stars .icon { width: 1em; height: 1em; }

/* social dots: brand SVGs carry their own colored circle */
body.theme-warm .social-dot {
  background: var(--dot, var(--sage));
  color: #fff;
}
body.theme-warm .social-dot .icon { width: 100%; height: 100%; }
body.theme-warm .social-dot .icon:not(.icon--badge) { width: 21px; height: 21px; }

/* action bar glyphs become inline SVG */
.action-bar .ico { display: inline-flex; }
.action-bar .ico .icon { width: 1.15em; height: 1.15em; }

/* --------------------------------------------------------------------------
   Missing component styles (template drift fixes)
   -------------------------------------------------------------------------- */
.menu-search-wrap {
  position: relative;
  display: flex;
  align-items: center;
  height: 50px;
  padding-inline: 16px 14px;
  background: var(--card-white);
  border-radius: var(--r-pill);
  border: 1px solid rgba(34, 48, 31, 0.07);
  box-shadow: 0 6px 18px rgba(31, 55, 38, 0.08);
}

.menu-search-ico {
  position: absolute;
  inset-inline-start: 16px;
  display: flex;
  color: var(--link-sub);
}
.menu-search-ico .icon { width: 19px; height: 19px; }

.menu-search {
  width: 100%;
  height: 100%;
  border: none;
  background: transparent;
  font: inherit;
  font-size: 0.9375rem;
  color: var(--ink);
  padding-inline-start: 32px;
}
.menu-search:focus { outline: none; }
.menu-search::placeholder { color: var(--link-sub); opacity: 0.8; }

.offer-scroller {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 80%;
  gap: var(--sp-3);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
  padding-block: 2px 4px;
}
.offer-scroller::-webkit-scrollbar { display: none; }
.offer-scroller > * { scroll-snap-align: start; }
@media (min-width: 520px) { .offer-scroller { grid-auto-columns: 46%; } }

/* --------------------------------------------------------------------------
   Home directory + footer on the warm canvas
   -------------------------------------------------------------------------- */
body.theme-warm .dir-tile {
  background: linear-gradient(145deg, var(--wave-green), var(--wave-green-soft));
  color: var(--cream);
}
body.theme-warm .dir-rule { background: var(--gold-line); }
body.theme-warm .dir-kicker { color: var(--gold-deep); }
body.theme-warm .display { color: var(--ink); }

body.theme-warm main.page--device:has(.outlet-actions) > .site-footer { display: none; }

body.theme-warm .site-footer {
  color: var(--ink);
  border: none;
  background: rgba(245, 239, 227, 0.82);
  border-radius: var(--r-pill);
  padding: 8px 18px;
  align-self: center;
}
body.theme-warm .stage-caption {
  color: var(--ink);
  background: rgba(245, 239, 227, 0.82);
  border-radius: var(--r-pill);
  padding: 8px 18px;
}

/* dish placeholders on tinted plates */
body.theme-warm .dish-photo {
  background: var(--tint-cream);
  color: var(--gold-deep);
}

body.theme-warm .menu-empty .glyph {
  background: var(--tint-cream);
  color: var(--gold-deep);
}

/* footer/CTA link tone */
body.theme-warm .info-links a { color: var(--wave-green); font-weight: 700; }
body.theme-warm .info-links svg { width: 18px; height: 18px; }

/* dark-text-on-cream contrast pass */
body.theme-warm .h1,
body.theme-warm .h2,
body.theme-warm h1, body.theme-warm h2, body.theme-warm h3 {
  color: var(--ink);
}

/* reduced motion: kill the press scaling too */
@media (prefers-reduced-motion: reduce) {
  body.theme-warm .contact-circle,
  body.theme-warm .btn-action,
  body.theme-warm .social-dot { transition: none; transform: none; }
}

/* ==========================================================================
   iOS 26 liquid-glass specials page (body.theme-warm .page--glass)
   --------------------------------------------------------------------------
   The approved reference uses SOLID white cards. This opt-in variant turns
   the Specials sheet into true liquid glass: translucent frosted panels that
   blur and saturate the green wave art behind them, with a bright 1px top
   edge (light catching the material), a soft inner highlight, and a
   press-down spring. Scoped to .page--glass so the landing / menu / smart
   pages keep their approved solid-card look.
   ========================================================================== */

/* Frost the phone screen a touch so the glass reads as one material layer.
   Keep the wave art visible but cool it slightly behind the panels. The
   blur matches the base layer (filter is one property, so it must be
   repeated here or this more-specific rule would drop the softness). */
body.theme-warm .page--glass .device-screen::before {
  filter: blur(6px) saturate(1.05) brightness(1.02);
}

/* True glass: translucent white fill, backdrop blur + saturate, bright top
   edge, inner highlight, layered forest-tinted shadow. Overrides the solid
   white card override above. */
body.theme-warm .page--glass .glass,
body.theme-warm .page--glass .glass--strong {
  background: var(--glass-fill);
  -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
  backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
  border: 1px solid var(--glass-border-alpha);
  box-shadow: var(--shadow-glass);
}

/* Larger dish cards read as thicker glass: a touch more blur + deeper shadow. */
body.theme-warm .page--glass .dish-card.glass--strong {
  background: var(--glass-fill-strong);
  -webkit-backdrop-filter: blur(calc(var(--glass-blur) + 6px)) saturate(var(--glass-saturate));
  backdrop-filter: blur(calc(var(--glass-blur) + 6px)) saturate(var(--glass-saturate));
  border-radius: var(--r-2xl);
  box-shadow: var(--shadow-glass-lg);
}

/* The back control becomes a frosted glass circle instead of solid white. */
body.theme-warm .page--glass .sheet-back {
  background: var(--glass-fill);
  -webkit-backdrop-filter: blur(12px) saturate(160%);
  backdrop-filter: blur(12px) saturate(160%);
  border: 1px solid var(--glass-border-alpha);
}

/* Dish photo tiles go translucent so the waves glow through the icon well. */
body.theme-warm .page--glass .dish-photo {
  background: rgba(255, 255, 255, 0.38);
  -webkit-backdrop-filter: blur(8px) saturate(150%);
  backdrop-filter: blur(8px) saturate(150%);
  border: 1px solid rgba(255, 255, 255, 0.5);
  color: var(--wave-green);
}

/* Chips: translucent tinted glass, not solid fills. */
body.theme-warm .page--glass .chip--open {
  background: rgba(223, 240, 212, 0.6);
  -webkit-backdrop-filter: blur(8px) saturate(150%);
  backdrop-filter: blur(8px) saturate(150%);
  border: 1px solid rgba(255, 255, 255, 0.55);
}
body.theme-warm .page--glass .chip--gold {
  background: rgba(243, 228, 174, 0.62);
  -webkit-backdrop-filter: blur(8px) saturate(150%);
  backdrop-filter: blur(8px) saturate(150%);
  border: 1px solid rgba(255, 255, 255, 0.55);
}

/* Spring press feedback on the cards (critically damped, no overshoot). */
body.theme-warm .page--glass .dish-card {
  transition: transform var(--t-hover) var(--ease-spring),
    box-shadow var(--t-hover) var(--ease-spring);
}
body.theme-warm .page--glass .dish-card:active {
  transform: scale(0.985);
  box-shadow: 0 1px 2px rgba(49, 69, 45, 0.06),
    0 6px 18px var(--shadow-soft), var(--glass-hi);
}

/* Reduced transparency: fall back to near-solid so text stays legible. */
@media (prefers-reduced-transparency: reduce) {
  body.theme-warm .page--glass .glass,
  body.theme-warm .page--glass .glass--strong,
  body.theme-warm .page--glass .dish-card.glass--strong {
    background: var(--glass-fill-solid);
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }
  body.theme-warm .page--glass .sheet-back {
    background: var(--card-white);
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }
}

/* Reduced motion: drop the press scaling. */
@media (prefers-reduced-motion: reduce) {
  body.theme-warm .page--glass .dish-card {
    transition: none;
  }
  body.theme-warm .page--glass .dish-card:active {
    transform: none;
  }
}

/* ==========================================================================
   REVIEW COMPOSER — write here, polish, copy, post on Google (spec §39)
   ========================================================================== */

/* Lead note: a frosted band, so the intro line never sits bare on the waves. */
body.theme-warm .sheet-lead {
  margin: var(--sp-3) 0 0;
  padding: var(--sp-3) var(--sp-4);
  border-radius: 20px;
  background: linear-gradient(160deg, rgba(255, 255, 255, 0.62), rgba(255, 255, 255, 0.44));
  -webkit-backdrop-filter: blur(14px) saturate(170%);
  backdrop-filter: blur(14px) saturate(170%);
  border: 1px solid rgba(255, 255, 255, 0.55);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.5),
              0 12px 26px -20px rgba(23, 58, 36, 0.55);
  font-size: var(--fs-sm);
  line-height: 1.55;
  color: var(--text-secondary);
  font-weight: 600;
}

/* The writing sheet: one deep liquid-glass surface. */
body.theme-warm .composer-card {
  margin-top: var(--sp-3);
  padding: var(--sp-4);
  border-radius: 28px;
  background: linear-gradient(165deg, rgba(255, 255, 255, 0.78), rgba(255, 255, 255, 0.56));
  -webkit-backdrop-filter: blur(22px) saturate(180%);
  backdrop-filter: blur(22px) saturate(180%);
  border: 1px solid rgba(255, 255, 255, 0.6);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.65),
              inset 0 -1px 0 rgba(255, 255, 255, 0.18),
              0 26px 50px -30px rgba(23, 58, 36, 0.55);
}

body.theme-warm .composer-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
}

body.theme-warm .composer-label {
  margin: 0;
  font-family: "Fraunces", Georgia, serif;
  font-optical-sizing: auto;
  font-size: 1.32rem;
  font-weight: 600;
  letter-spacing: -0.015em;
  line-height: 1.15;
  color: var(--ink);
}

/* Character counter as a frosted chip. */
body.theme-warm .composer-count {
  padding: 4px 10px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.6);
  border: 1px solid rgba(255, 255, 255, 0.65);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.55);
  font-size: var(--fs-caption);
  color: var(--muted);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

body.theme-warm .composer-hint {
  margin: var(--sp-1) 0 var(--sp-3);
  font-size: var(--fs-sm);
  line-height: 1.5;
  color: var(--muted);
}

body.theme-warm .composer-hint--fine {
  margin: var(--sp-1) 0 0;
  font-size: var(--fs-caption);
  letter-spacing: 0.01em;
  text-transform: none;
  color: var(--muted);
}

body.theme-warm .composer-hint--fine a {
  color: var(--leaf);
  font-weight: 700;
}

/* The box itself: an inset glass well inside the sheet. */
body.theme-warm .composer-textarea {
  width: 100%;
  box-sizing: border-box;
  padding: var(--sp-3);
  border-radius: 18px;
  border: 1px solid rgba(28, 44, 32, 0.14);
  background: rgba(255, 255, 255, 0.66);
  box-shadow: inset 0 2px 6px rgba(23, 58, 36, 0.06);
  font-family: var(--font-body);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  color: var(--text-primary);
  resize: vertical;
  transition: border-color var(--t-quick) var(--ease-out),
              box-shadow var(--t-quick) var(--ease-out),
              background-color var(--t-quick) var(--ease-out);
}

body.theme-warm .composer-textarea::placeholder {
  color: rgba(60, 74, 62, 0.45);
}

body.theme-warm .composer-textarea:focus {
  outline: none;
  border-color: var(--sage);
  background: rgba(255, 255, 255, 0.88);
  box-shadow: inset 0 1px 4px rgba(23, 58, 36, 0.05),
              0 0 0 3px var(--chip-ai-bg);
}

body.theme-warm .composer-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  margin-top: var(--sp-3);
}

/* Copy (left) + Suggest (right), side by side under the box. */
body.theme-warm .composer-row--buttons {
  align-items: stretch;
}

body.theme-warm .composer-row--buttons .btn {
  margin-top: 0;
}

body.theme-warm .composer-row--buttons .btn-sm {
  flex: 0 0 auto;
  white-space: nowrap;
}

body.theme-warm .composer-row--buttons .btn-primary {
  flex: 1 1 auto;
}

/* Frosted secondary (Copy review). */
body.theme-warm .composer-row--buttons .btn-secondary {
  background: rgba(255, 255, 255, 0.58);
  -webkit-backdrop-filter: blur(12px) saturate(160%);
  backdrop-filter: blur(12px) saturate(160%);
  border: 1px solid rgba(255, 255, 255, 0.65);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.55),
              0 8px 18px -12px rgba(23, 58, 36, 0.4);
  color: var(--ink);
}

/* Deep-green glass primary (Suggest + Google hand-off). */
body.theme-warm .composer-card .btn-primary,
body.theme-warm .composer-google {
  background: linear-gradient(180deg, #357455, #1e4634);
  border: 1px solid rgba(255, 255, 255, 0.22);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.28),
              0 16px 30px -18px rgba(23, 58, 36, 0.65);
  color: #fff;
}

body.theme-warm .composer-google {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  border-radius: 999px;
  font-weight: 700;
  letter-spacing: 0.01em;
}

body.theme-warm .composer-google svg {
  width: 18px;
  height: 18px;
  flex: 0 0 auto;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

body.theme-warm .composer-error {
  margin: var(--sp-2) 0 0;
  padding: var(--sp-2) var(--sp-3);
  border-radius: var(--r-chip);
  background: rgba(179, 69, 47, 0.12);
  border: 1px solid rgba(179, 69, 47, 0.28);
  color: #8c3a2b;
  font-size: var(--fs-sm);
  font-weight: 600;
}

body.theme-warm .composer-actions {
  display: grid;
  justify-items: center;
  gap: var(--sp-3);
  margin-top: var(--sp-4);
}

body.theme-warm .composer-actions .composer-google {
  width: 100%;
}

/* Secondary hand-off as a frosted outline pill. */
body.theme-warm .composer-link {
  display: inline-flex;
  align-items: center;
  padding: 8px 16px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.42);
  -webkit-backdrop-filter: blur(10px) saturate(160%);
  backdrop-filter: blur(10px) saturate(160%);
  border: 1px solid rgba(255, 255, 255, 0.6);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.5);
  font-size: var(--fs-caption);
  font-weight: 700;
  color: #2e6b4f;
  text-decoration: none;
}

/* Hover only where a real pointer hovers: on touch this rule would otherwise
   latch on after a tap and stay lit until something else was touched. The
   :active twin keeps the same feedback on press, so touch loses nothing. */
@media (hover: hover) and (pointer: fine) {
  body.theme-warm .composer-link:hover {
    background: rgba(255, 255, 255, 0.6);
  }
}

body.theme-warm .composer-link:active {
  background: rgba(255, 255, 255, 0.6);
}

/* Status line as a centered glass toast. */
body.theme-warm .composer-status {
  margin: 0;
  min-height: 1.2em;
  padding: 6px 14px;
  border-radius: 999px;
  background: var(--chip-ai-bg);
  color: var(--chip-ai-fg);
  font-size: var(--fs-sm);
  font-weight: 600;
}

body.theme-warm .composer-status:empty {
  padding: 0;
  background: transparent;
}

body.theme-warm .variant-list {
  display: grid;
  gap: var(--sp-2);
}

/* Suggestions head: Fraunces title + gold provider chip. */
body.theme-warm .composer-variants .section-head h2 {
  font-family: "Fraunces", Georgia, serif;
  font-optical-sizing: auto;
  font-size: 1.22rem;
  font-weight: 600;
  letter-spacing: -0.012em;
  color: var(--ink);
}

body.theme-warm #variants-provider {
  padding: 4px 10px;
  border-radius: 999px;
  background: linear-gradient(180deg, rgba(246, 216, 121, 0.92), rgba(217, 168, 60, 0.86));
  border: 1px solid rgba(255, 255, 255, 0.5);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.55);
  font-size: var(--fs-caption);
  font-weight: 700;
  letter-spacing: var(--track-caps);
  text-transform: uppercase;
  color: #4a3413;
  white-space: nowrap;
}

body.theme-warm #variants-provider:empty {
  display: none;
}

/* Tap-to-use suggestion rows: frosted glass, hint chip on the right. */
body.theme-warm .variant-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--sp-3);
  width: 100%;
  text-align: left;
  padding: var(--sp-3) var(--sp-4);
  border-radius: 22px;
  background: linear-gradient(160deg, rgba(255, 255, 255, 0.7), rgba(255, 255, 255, 0.5));
  -webkit-backdrop-filter: blur(18px) saturate(170%);
  backdrop-filter: blur(18px) saturate(170%);
  border: 1px solid rgba(255, 255, 255, 0.55);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.6),
              0 16px 32px -24px rgba(23, 58, 36, 0.5);
  font: inherit;
  cursor: pointer;
  transition: transform var(--t-press) var(--ease-out),
              border-color var(--t-quick) var(--ease-out),
              box-shadow var(--t-quick) var(--ease-out);
}

body.theme-warm .variant-row:active {
  transform: scale(0.98);
}

body.theme-warm .variant-row__text {
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  color: var(--text-primary);
  white-space: pre-wrap;
}

body.theme-warm .variant-row__hint {
  padding: 4px 10px;
  border-radius: 999px;
  background: rgba(23, 58, 36, 0.08);
  font-size: var(--fs-caption);
  font-weight: 700;
  letter-spacing: var(--track-caps);
  text-transform: uppercase;
  color: var(--muted);
  white-space: nowrap;
}

body.theme-warm .variant-row--used {
  border-color: var(--sage);
  box-shadow: 0 0 0 2px var(--chip-ai-bg),
              inset 0 1px 0 rgba(255, 255, 255, 0.6);
}

body.theme-warm .variant-row--used .variant-row__hint {
  background: var(--chip-ai-bg);
  color: var(--chip-ai-fg);
}

#variants-wrap[hidden] {
  display: none;
}

@media (prefers-reduced-motion: reduce) {
  body.theme-warm .composer-textarea,
  body.theme-warm .variant-row,
  body.theme-warm .composer-google,
  body.theme-warm .composer-link {
    transition: none;
  }
  body.theme-warm .variant-row:active {
    transform: none;
  }
}

/* Reduced transparency: solidify every composer material. */
@media (prefers-reduced-transparency: reduce) {
  body.theme-warm .sheet-lead,
  body.theme-warm .composer-card,
  body.theme-warm .composer-count,
  body.theme-warm .composer-textarea,
  body.theme-warm .variant-row,
  body.theme-warm .composer-link,
  body.theme-warm .composer-row--buttons .btn-secondary {
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
    background: rgba(255, 255, 255, 0.96);
  }
}

/* ==========================================================================
   SPECIALS — iOS 26 liquid glass + typography pass (body.theme-warm .page--glass)
   --------------------------------------------------------------------------
   Second glass pass, dedicated to the specials sheet. Every surface the
   guest sees becomes a liquid-glass material: a frosted floating header
   pill, a dark tinted glass copy sheet over the hero photo, a glass dot
   capsule, glass row arrows, and promo cards as frosted frames around the
   dish photo. Each carries the material signature: translucent fill,
   backdrop blur + saturate, a bright 1px top edge where light catches the
   glass, and a forest-tinted depth shadow. Bigger surfaces read thicker
   (more blur, deeper shadow) than the small controls.
   Typography: Fraunces (bundled variable serif, latin subset) for display
   names over the SF-native body stack — negative tracking and tight leading
   as the size grows, tracked caps on micro labels, tabular figures on
   prices. Vibrancy: text on glass is heavier and higher contrast, never
   flat grey — the hero title stays white on the dark sheet, overriding the
   theme's ink-on-h2 rule.
   ========================================================================== */

@font-face {
  font-family: "Fraunces";
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url("../fonts/Fraunces-var.5d2835174326.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}

body.theme-warm .page--glass {
  --font-display: "Fraunces", "Iowan Old Style", Georgia, "Times New Roman", serif;
}

/* ---- header: floating frosted pill so the meta line stays legible over waves ----
   Sticky again: the wave stack rule (device-screen > * = relative, z1) and the
   desktop mock rule both out-specify the base sticky header, so the pill
   re-claims position and z here (this selector beats both). */
body.theme-warm .page--glass .sheet-head {
  position: sticky;
  top: 6px;
  z-index: 6;
  /* one compact row: glass circle left, left-aligned title block, chip right.
     Re-claims align-items from the device-screen rule (end = sunken button). */
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: 10px;
  margin: 0 0 var(--sp-3);
  padding: 8px 10px 8px 8px;
  background: rgba(255, 255, 255, 0.52);
  -webkit-backdrop-filter: blur(22px) saturate(180%);
  backdrop-filter: blur(22px) saturate(180%);
  border: 1px solid rgba(255, 255, 255, 0.65);
  border-radius: 24px;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.85),
    inset 0 -1px 0 rgba(31, 55, 38, 0.05),
    0 14px 34px -20px rgba(31, 55, 38, 0.45);
}

body.theme-warm .page--glass .sheet-head > div {
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 2px;
}

/* iOS 26 glass back control: frosted circle, bright top edge, spring press. */
body.theme-warm .page--glass .sheet-back {
  position: relative; /* anchor for the extended hit area below */
  width: 40px;
  height: 40px;
  flex: none;
  background: rgba(255, 255, 255, 0.55);
  -webkit-backdrop-filter: blur(14px) saturate(180%);
  backdrop-filter: blur(14px) saturate(180%);
  border: 1px solid rgba(255, 255, 255, 0.72);
  border-radius: 50%;
  color: var(--ink);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.9),
    0 8px 18px -10px rgba(31, 55, 38, 0.5);
  transition: transform var(--t-hover) var(--ease-spring),
    background var(--t-hover) ease;
}
/* Apple's minimum tap target is 44px; the approved visual is a 40px circle.
   Extend the hit area instead of the artwork: a transparent 2px outset ring
   brings the tappable box to 44x44 while the frosted circle stays exactly the
   size the client signed off. Paints nothing, so it cannot change the look. */
body.theme-warm .page--glass .sheet-back::before {
  content: "";
  position: absolute;
  inset: -2px; /* 40px + 2px each side = 44px */
  border-radius: 50%;
}
body.theme-warm .page--glass .sheet-back:active {
  transform: scale(0.88);
  background: rgba(255, 255, 255, 0.78);
}
body.theme-warm .page--glass .sheet-back:focus-visible {
  outline: 2px solid var(--leaf);
  outline-offset: 2px;
}
body.theme-warm .page--glass .sheet-back svg {
  width: 18px;
  height: 18px;
}

body.theme-warm .page--glass .sheet-title {
  font-family: var(--font-display);
  font-optical-sizing: auto;
  font-size: 1.22rem;
  font-weight: 600;
  letter-spacing: -0.015em;
  line-height: 1.1;
  text-align: left;
}

body.theme-warm .page--glass .sheet-meta {
  font-size: 0.6rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-align: left;
  /* one line, ellipsised: a wrapped meta is what made the bar tall */
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 100%;
}

/* brand dash sits under the left-aligned meta, not centred */
body.theme-warm .page--glass .sheet-meta::after {
  margin: 5px 0 0;
  width: 18px;
}

@media (prefers-reduced-motion: reduce) {
  body.theme-warm .page--glass .sheet-back {
    transition: none;
  }
}

/* ---- hero: deeper radius, calmer scrim, copy on a dark tinted glass sheet ---- */
body.theme-warm .page--glass .spot-track {
  border-radius: 30px;
  box-shadow: 0 26px 60px -30px rgba(18, 30, 20, 0.6);
  /* mid-swipe the 12px gutter shows this, not the raw wave: an intentional
     cream canvas between cards, exactly like the promo rows below */
  background: #F7F2E6;
}

body.theme-warm .page--glass .spot-slide {
  min-height: 264px;
  border-radius: 30px;
  /* warm canvas while a hero photo decodes; never a flat green slab */
  background: #F7F2E6;
  /* promote the slide to its own compositor layer: photo and glass sheet
     then raster and scroll as ONE texture, so the sheet's backdrop blur
     below can never lag or detach from its photo during a live swipe */
  transform: translateZ(0);
}

body.theme-warm .page--glass .spot-scrim {
  background: linear-gradient(to top,
    rgba(14, 22, 16, 0.68) 0%,
    rgba(14, 22, 16, 0.26) 46%,
    rgba(14, 22, 16, 0) 74%);
}

body.theme-warm .page--glass .spot-copy {
  inset-inline: 10px;
  bottom: 10px;
  padding: 14px 16px 15px;
  border-radius: 24px;
  /* iOS 26 liquid glass: frosted dark material, specular top edge and a
     lens highlight catching light at the top-left, all in one stack */
  background:
    radial-gradient(120% 70% at 16% 0%, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0) 58%),
    linear-gradient(to top, rgba(12, 18, 14, 0.74), rgba(12, 18, 14, 0.52) 62%, rgba(255, 255, 255, 0.08)),
    rgba(14, 20, 16, 0.35);
  -webkit-backdrop-filter: blur(22px) saturate(180%);
  backdrop-filter: blur(22px) saturate(180%);
  border: 1px solid rgba(255, 255, 255, 0.26);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.34),
    inset 0 -1px 0 rgba(255, 255, 255, 0.08),
    0 18px 44px -22px rgba(0, 0, 0, 0.62);
}

/* kind label as a frosted chip with a gold pulse dot */
body.theme-warm .page--glass .spot-kind {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-bottom: 8px;
  padding: 4px 10px 4px 8px;
  border-radius: var(--r-pill);
  background: rgba(255, 255, 255, 0.16);
  border: 1px solid rgba(255, 255, 255, 0.26);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.28);
  font-size: 0.58rem;
  letter-spacing: 0.14em;
  color: rgba(255, 248, 226, 0.96);
}

body.theme-warm .page--glass .spot-kind::before {
  content: "";
  flex: none;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--gold);
  box-shadow: 0 0 8px rgba(230, 190, 80, 0.9);
}

body.theme-warm .page--glass .spot-title {
  font-family: var(--font-display);
  font-optical-sizing: auto;
  font-size: 1.62rem;
  font-weight: 600;
  letter-spacing: -0.018em;
  line-height: 1.05;
  color: #fff; /* vibrancy on the dark sheet; beats the theme ink-on-h2 rule */
  text-shadow: 0 1px 14px rgba(0, 0, 0, 0.38);
}

body.theme-warm .page--glass .spot-desc {
  font-size: 0.82rem;
  line-height: 1.5;
  color: rgba(255, 255, 255, 0.85);
  text-shadow: 0 1px 8px rgba(0, 0, 0, 0.3);
}

/* foot row: hairline separator, badge left, price right */
body.theme-warm .page--glass .spot-foot {
  justify-content: space-between;
  gap: 10px;
  margin-top: 11px;
  padding-top: 10px;
  border-top: 1px solid rgba(255, 255, 255, 0.16);
}

body.theme-warm .page--glass .spot-foot:empty { display: none; }

body.theme-warm .page--glass .spot-badge {
  padding: 5px 11px;
  background: linear-gradient(180deg, #F6D879, #D9A83C);
  color: #2A1E04;
  letter-spacing: 0.08em;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.55),
    0 6px 16px -8px rgba(0, 0, 0, 0.5);
}

body.theme-warm .page--glass .spot-price {
  color: #fff;
  font-size: 1rem;
  text-shadow: 0 1px 8px rgba(0, 0, 0, 0.3);
}

body.theme-warm .page--glass .spot-price del {
  color: rgba(255, 255, 255, 0.58);
  font-size: 0.8em;
  text-decoration-color: rgba(255, 138, 101, 0.9);
  text-decoration-thickness: 1.5px;
}

/* ---- dots: glass capsule, active dot a leaf pill ---- */
body.theme-warm .page--glass .spot-dots {
  gap: 7px;
  width: max-content;
  margin: 10px auto 0;
  padding: 7px 9px;
  border-radius: var(--r-pill);
  background: rgba(255, 255, 255, 0.5);
  -webkit-backdrop-filter: blur(16px) saturate(170%);
  backdrop-filter: blur(16px) saturate(170%);
  border: 1px solid rgba(255, 255, 255, 0.65);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.8),
    0 8px 20px -12px rgba(31, 55, 38, 0.35);
}

body.theme-warm .page--glass .spot-dot { background: rgba(31, 55, 38, 0.25); }
body.theme-warm .page--glass .spot-dot[aria-current="true"] {
  width: 18px;
  background: var(--wave-green);
}

/* ---- section heads + glass row arrows ---- */
body.theme-warm .page--glass .section-label {
  font-size: 0.66rem;
  letter-spacing: 0.15em;
  color: var(--ink);
}

body.theme-warm .page--glass .row-arrow {
  background: rgba(255, 255, 255, 0.55);
  -webkit-backdrop-filter: blur(14px) saturate(170%);
  backdrop-filter: blur(14px) saturate(170%);
  border: 1px solid rgba(255, 255, 255, 0.7);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.85),
    0 6px 16px -8px rgba(31, 55, 38, 0.4);
  transition: transform var(--t-hover) var(--ease-spring),
    box-shadow var(--t-hover) var(--ease-spring);
}

body.theme-warm .page--glass .row-arrow:active { transform: scale(0.9); }
body.theme-warm .page--glass .row-arrow[disabled] { opacity: 0.35; transform: none; }

/* ---- promo cards: frosted frames around the dish photo ---- */
body.theme-warm .page--glass .promo-card {
  padding: 7px;
  background: rgba(255, 255, 255, 0.5);
  -webkit-backdrop-filter: blur(20px) saturate(180%);
  backdrop-filter: blur(20px) saturate(180%);
  border: 1px solid rgba(255, 255, 255, 0.68);
  border-radius: 28px;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.85),
    0 20px 44px -24px rgba(31, 55, 38, 0.5);
  transition: transform var(--t-hover) var(--ease-spring),
    box-shadow var(--t-hover) var(--ease-spring);
}

body.theme-warm .page--glass .promo-card:active { transform: scale(0.985); }

body.theme-warm .page--glass .promo-media {
  border-radius: 21px;
  overflow: hidden;
}

body.theme-warm .page--glass .promo-badge {
  top: 8px;
  inset-inline-start: 8px;
  background: rgba(243, 228, 174, 0.82);
  -webkit-backdrop-filter: blur(10px) saturate(160%);
  backdrop-filter: blur(10px) saturate(160%);
  border: 1px solid rgba(255, 255, 255, 0.6);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.7);
}

body.theme-warm .page--glass .promo-body { padding: 12px 10px; }

body.theme-warm .page--glass .promo-title {
  font-family: var(--font-display);
  font-optical-sizing: auto;
  font-size: 1.08rem;
  font-weight: 600;
  letter-spacing: -0.01em;
  line-height: 1.15;
  color: var(--ink);
}

body.theme-warm .page--glass .promo-price {
  font-size: 1rem;
  font-weight: 800;
  color: var(--wave-green);
}

body.theme-warm .page--glass .spec-empty h2 {
  font-family: var(--font-display);
  font-weight: 600;
  letter-spacing: -0.01em;
}

/* ---- reduced transparency: solidify the materials, keep the hierarchy ---- */
@media (prefers-reduced-transparency: reduce) {
  body.theme-warm .page--glass .sheet-head,
  body.theme-warm .page--glass .spot-copy,
  body.theme-warm .page--glass .spot-dots,
  body.theme-warm .page--glass .row-arrow,
  body.theme-warm .page--glass .promo-card,
  body.theme-warm .page--glass .promo-badge {
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }
  body.theme-warm .page--glass .sheet-head { background: rgba(255, 255, 255, 0.94); }
  body.theme-warm .page--glass .spot-copy { background: rgba(16, 24, 18, 0.9); }
  body.theme-warm .page--glass .spot-dots { background: rgba(255, 255, 255, 0.92); }
  body.theme-warm .page--glass .row-arrow { background: #fff; }
  body.theme-warm .page--glass .promo-card { background: rgba(255, 255, 255, 0.95); }
  body.theme-warm .page--glass .promo-badge { background: #F3E4AE; }
}

/* ---- reduced motion: no press scaling on the glass ---- */
@media (prefers-reduced-motion: reduce) {
  body.theme-warm .page--glass .promo-card,
  body.theme-warm .page--glass .row-arrow { transition: none; }
  body.theme-warm .page--glass .promo-card:active,
  body.theme-warm .page--glass .row-arrow:active { transform: none; }
}

/* ==========================================================================
   MENU — iOS 26 liquid-glass dish cards (body.theme-warm .page--glass)
   Frosted rows over the warm canvas: PDF hand-off card, category sections,
   dish cards with plate fallback, booklet pages. Same material family as
   the specials pass so the two pages read as one product.
   ========================================================================== */

/* ---- PDF hand-off card: iOS 26 Liquid-Glass Live Tile ---- */
body.theme-warm .page--glass .menu-pdf {
  position: relative;
  overflow: hidden;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  /* The desktop phone frame is a flex column. Without a floor the tile
     shrinks to the kicker line and overflow:hidden hides the title and
     the Open button. min-height: min-content keeps the whole button. */
  flex-shrink: 0;
  min-height: min-content;
  height: auto;
  gap: 14px;
  padding: 13px 13px 13px 13px;
  border-radius: 26px;
  background:
    radial-gradient(120% 90% at 14% 0%, rgba(255, 255, 255, 0.72), rgba(255, 255, 255, 0) 60%),
    radial-gradient(90% 80% at 92% 100%, rgba(213, 201, 138, 0.24), rgba(213, 201, 138, 0) 64%),
    linear-gradient(165deg, rgba(255, 255, 255, 0.68) 0%, rgba(255, 255, 255, 0.44) 52%, rgba(255, 255, 255, 0.56) 100%);
  -webkit-backdrop-filter: blur(22px) saturate(185%);
  backdrop-filter: blur(22px) saturate(185%);
  border: 1px solid rgba(255, 255, 255, 0.78);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.92),
    inset 0 -1px 0 rgba(31, 55, 38, 0.08),
    0 2px 6px rgba(31, 55, 38, 0.07),
    0 18px 38px -18px rgba(31, 55, 38, 0.34);
  color: var(--ink);
  text-decoration: none;
  transform: translateZ(0);
  transition:
    transform var(--t-hover) var(--ease-spring),
    box-shadow var(--t-hover) var(--ease-spring),
    border-color var(--t-quick) var(--ease-out);
}

/* Soft ambient glass sheen inside the live tile */
body.theme-warm .page--glass .menu-pdf-glow {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    linear-gradient(115deg,
      rgba(255, 255, 255, 0) 18%,
      rgba(255, 255, 255, 0.42) 48%,
      rgba(255, 255, 255, 0) 78%);
  opacity: 0.55;
  transform: translateX(-18%);
  transition: transform 520ms var(--ease-spring), opacity 320ms var(--ease-out);
}

/* Tactile press response: immediate on pointer-down (apple-design §1) */
body.theme-warm .page--glass .menu-pdf:active {
  transform: scale(0.976);
  border-color: rgba(255, 255, 255, 0.94);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.95),
    0 8px 20px -12px rgba(31, 55, 38, 0.42);
}
body.theme-warm .page--glass .menu-pdf:focus-visible {
  outline: 2px solid var(--leaf);
  outline-offset: 3px;
}

/* Left live-tile emblem: deep forest squircle housing a stacked paper deck */
body.theme-warm .page--glass .menu-pdf-ico {
  position: relative;
  flex: none;
  width: 52px;
  height: 52px;
  border-radius: 17px;
  display: grid;
  place-items: center;
  background:
    radial-gradient(110% 90% at 25% 15%, rgba(127, 160, 107, 0.38), rgba(127, 160, 107, 0) 62%),
    linear-gradient(155deg, #35684a 0%, #1f3f2b 100%);
  color: #F6D879;
  border: 1px solid rgba(255, 255, 255, 0.24);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.36),
    inset 0 -1px 0 rgba(0, 0, 0, 0.24),
    0 10px 20px -10px rgba(22, 43, 29, 0.55);
  transition: transform var(--t-hover) var(--ease-spring);
}

/* Stacked back sheet behind the main PDF page */
body.theme-warm .page--glass .menu-pdf-sheet {
  display: grid;
  place-items: center;
  transition: transform var(--t-hover) var(--ease-spring);
}
body.theme-warm .page--glass .menu-pdf-sheet--back {
  position: absolute;
  width: 24px;
  height: 28px;
  border-radius: 6px;
  background: rgba(246, 216, 121, 0.18);
  border: 1px solid rgba(246, 216, 121, 0.34);
  transform: translate(4px, -3px) rotate(7deg);
}
body.theme-warm .page--glass .menu-pdf-sheet--front {
  position: relative;
  z-index: 1;
  transform: translate(-1px, 1px);
}
body.theme-warm .page--glass .menu-pdf-ico svg {
  width: 23px;
  height: 23px;
  fill: rgba(246, 216, 121, 0.12);
  stroke: currentColor;
  stroke-width: 1.65;
  stroke-linecap: round;
  stroke-linejoin: round;
  filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.28));
}

/* Micro gold PDF pill tucked at the bottom-right of the emblem */
body.theme-warm .page--glass .menu-pdf-tag {
  position: absolute;
  right: -3px;
  bottom: -3px;
  z-index: 2;
  padding: 1.5px 5px;
  border-radius: 6px;
  background: linear-gradient(180deg, #F6D879 0%, #D9A83C 100%);
  color: #231802;
  font-size: 0.5rem;
  font-weight: 800;
  letter-spacing: 0.08em;
  line-height: 1.2;
  border: 1px solid rgba(255, 255, 255, 0.72);
  box-shadow: 0 3px 8px rgba(0, 0, 0, 0.28);
}

/* Center editorial stack: live status kicker + display title + subtitle */
body.theme-warm .page--glass .menu-pdf-copy {
  position: relative;
  z-index: 1;
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 2px;
}
body.theme-warm .page--glass .menu-pdf-kicker {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 0.56rem;
  font-weight: 700;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  white-space: nowrap;
  color: var(--wave-green);
}
body.theme-warm .page--glass .menu-pdf-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: #429e5d;
  box-shadow: 0 0 0 3px rgba(66, 158, 93, 0.2);
}
body.theme-warm .page--glass .menu-pdf-copy strong {
  font-family: var(--font-display);
  font-optical-sizing: auto;
  font-size: 1.08rem;
  font-weight: 600;
  letter-spacing: -0.015em;
  line-height: 1.14;
  color: var(--ink);
}
body.theme-warm .page--glass .menu-pdf-copy small {
  font-size: 0.73rem;
  font-weight: 500;
  letter-spacing: 0.01em;
  line-height: 1.25;
  color: rgba(31, 45, 32, 0.68);
}

/* Right action capsule: forest liquid-glass pill with gold launch orb */
body.theme-warm .page--glass .menu-pdf-cta {
  position: relative;
  z-index: 1;
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 6px 6px 6px 13px;
  border-radius: 999px;
  background:
    radial-gradient(100% 90% at 25% 0%, rgba(255, 255, 255, 0.22), rgba(255, 255, 255, 0) 60%),
    linear-gradient(180deg, #35684a 0%, #244730 100%);
  color: #fff;
  font-size: 0.76rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  border: 1px solid rgba(255, 255, 255, 0.24);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.34),
    0 8px 18px -8px rgba(22, 43, 29, 0.5);
  transition:
    transform var(--t-hover) var(--ease-spring),
    box-shadow var(--t-hover) var(--ease-spring);
}
body.theme-warm .page--glass .menu-pdf-cta-orb {
  width: 24px;
  height: 24px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background: linear-gradient(180deg, #F6D879 0%, #D9A83C 100%);
  color: #231802;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.65),
    0 2px 5px rgba(0, 0, 0, 0.22);
  transition: transform var(--t-hover) var(--ease-spring);
}
body.theme-warm .page--glass .menu-pdf-cta-orb svg {
  width: 13px;
  height: 13px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2.2;
  stroke-linecap: round;
  stroke-linejoin: round;
  transition: transform var(--t-hover) var(--ease-spring);
}

/* Active press choreography: pages fan out and arrow nudges toward launch */
body.theme-warm .page--glass .menu-pdf:active .menu-pdf-sheet--back {
  transform: translate(6px, -4px) rotate(11deg);
}
body.theme-warm .page--glass .menu-pdf:active .menu-pdf-cta-orb svg {
  transform: translate(1.5px, -1.5px);
}

/* Pointer hover choreography guarded for devices that genuinely hover */
@media (hover: hover) {
  body.theme-warm .page--glass .menu-pdf:hover {
    transform: translateY(-1.5px);
    border-color: rgba(255, 255, 255, 0.92);
    box-shadow:
      inset 0 1px 0 rgba(255, 255, 255, 0.96),
      inset 0 -1px 0 rgba(31, 55, 38, 0.08),
      0 6px 14px rgba(31, 55, 38, 0.09),
      0 22px 44px -18px rgba(31, 55, 38, 0.42);
  }
  body.theme-warm .page--glass .menu-pdf:hover .menu-pdf-glow {
    transform: translateX(18%);
    opacity: 0.8;
  }
  body.theme-warm .page--glass .menu-pdf:hover .menu-pdf-ico {
    transform: scale(1.03) rotate(-1.5deg);
  }
  body.theme-warm .page--glass .menu-pdf:hover .menu-pdf-sheet--back {
    transform: translate(6px, -4px) rotate(11deg);
  }
  body.theme-warm .page--glass .menu-pdf:hover .menu-pdf-cta-orb {
    transform: scale(1.06);
  }
  body.theme-warm .page--glass .menu-pdf:hover .menu-pdf-cta-orb svg {
    transform: translate(1.5px, -1.5px);
  }
  body.theme-warm .page--glass .menu-pdf:hover:active {
    transform: scale(0.976);
  }
}

/* ---- category sections: display-serif title + chip + glass rail arrows ---- */
body.theme-warm .page--glass .menu-section-head {
  align-items: center;
}
body.theme-warm .page--glass .menu-cat-title {
  margin: 0;
  font-family: var(--font-display);
  font-optical-sizing: auto;
  font-size: 1.3rem;
  font-weight: 600;
  letter-spacing: -0.016em;
  color: var(--ink);
}
/* ---- dish cards: the specials glass card (frosted frame + 4:3 photo),
       name-only body. The old 78px row-card rules are gone; .menu-card now
       only marks the article for tests and analytics. ---- */
body.theme-warm .page--glass .menu-card .promo-body {
  padding: 11px 12px 13px;
}
body.theme-warm .page--glass .menu-card .promo-title {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  overflow-wrap: anywhere;
}

/* placeholder art fills the photo well until staff upload a picture:
   warm plate for dishes, pale-green glass for drinks */
body.theme-warm .page--glass .menu-plate {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background:
    radial-gradient(120% 90% at 50% 0%,
      rgba(255, 255, 255, 0.9), rgba(255, 255, 255, 0) 62%),
    var(--tint-cream);
  color: var(--gold-deep);
}
body.theme-warm .page--glass .menu-plate svg {
  width: 54px;
  height: 54px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
  opacity: 0.85;
}
body.theme-warm .page--glass .menu-plate--drink {
  background:
    radial-gradient(120% 90% at 50% 0%,
      rgba(255, 255, 255, 0.9), rgba(255, 255, 255, 0) 62%),
    #E4EED9;
  color: var(--wave-green);
}

/* ---- booklet pages inside the menu page ---- */
body.theme-warm .page--glass .booklet--menu {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
body.theme-warm .page--glass .booklet--menu .booklet-page {
  margin: 0;
  border-radius: 18px;
  overflow: hidden;
}
body.theme-warm .page--glass .booklet--menu .booklet-page img {
  width: 100%;
  display: block;
}
body.theme-warm .page--glass .booklet--menu .caption {
  padding: 7px 10px;
  text-align: center;
}

/* ---- reduced transparency: solidify the menu materials ---- */
@media (prefers-reduced-transparency: reduce) {
  body.theme-warm .page--glass .menu-pdf {
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
    background: rgba(255, 255, 255, 0.96);
  }
  body.theme-warm .page--glass .menu-pdf-glow {
    display: none;
  }
}

/* ---- reduced motion: no press scaling on the PDF card ---- */
@media (prefers-reduced-motion: reduce) {
  body.theme-warm .page--glass .menu-pdf,
  body.theme-warm .page--glass .menu-pdf-glow,
  body.theme-warm .page--glass .menu-pdf-ico,
  body.theme-warm .page--glass .menu-pdf-sheet,
  body.theme-warm .page--glass .menu-pdf-cta,
  body.theme-warm .page--glass .menu-pdf-cta-orb,
  body.theme-warm .page--glass .menu-pdf-cta-orb svg {
    transition: none;
  }
  body.theme-warm .page--glass .menu-pdf:active,
  body.theme-warm .page--glass .menu-pdf:hover {
    transform: none;
  }
}

/* ================================================================
   GAMES ZONE — hub cards and the full-bleed play surface
   (GAMES_ZONE_PLAN.md). Same iOS 26 liquid-glass language as the
   specials and menu sheets. Games are pure play: no reward,
   discount or offer surfaces exist anywhere in this section.
   ================================================================ */

/* ---- hub: frosted lead band ---- */
body.theme-warm .page--games .games-lead {
  margin: 10px 10px 0;
  padding: 10px 14px;
  border-radius: 16px;
  background: rgba(255, 255, 255, 0.55);
  -webkit-backdrop-filter: blur(14px) saturate(170%);
  backdrop-filter: blur(14px) saturate(170%);
  border: 1px solid rgba(255, 255, 255, 0.72);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.6);
  color: rgba(42, 59, 46, 0.85);
  font-size: 0.8rem;
  line-height: 1.45;
}

/* ---- hub: game cards ---- */
body.theme-warm .page--games .games-grid {
  display: grid;
  gap: 10px;
  padding: 12px 10px 4px;
}

body.theme-warm .page--games .game-card {
  display: grid;
  grid-template-columns: 46px minmax(0, 1fr) auto;
  align-items: center;
  gap: 12px;
  padding: 12px 14px;
  border-radius: 20px;
  text-decoration: none;
  color: inherit;
  background: rgba(255, 255, 255, 0.62);
  -webkit-backdrop-filter: blur(18px) saturate(170%);
  backdrop-filter: blur(18px) saturate(170%);
  border: 1px solid rgba(255, 255, 255, 0.75);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.6),
    0 10px 22px -12px rgba(31, 55, 38, 0.35);
  transition: transform 160ms cubic-bezier(0.16, 1, 0.3, 1);
}

body.theme-warm .page--games .game-card:active { transform: scale(0.97); }

body.theme-warm .page--games .game-card__glyph {
  width: 46px;
  height: 46px;
  border-radius: 50%;
  display: grid;
  place-items: center;
}

body.theme-warm .page--games .game-card__glyph svg {
  width: 24px;
  height: 24px;
}

body.theme-warm .page--games .game-card--gold .game-card__glyph {
  background: rgba(217, 168, 60, 0.18);
  color: #9a7420;
}

body.theme-warm .page--games .game-card--green .game-card__glyph {
  background: rgba(127, 160, 107, 0.22);
  color: #3f6b46;
}

body.theme-warm .page--games .game-card--red .game-card__glyph {
  background: rgba(196, 87, 74, 0.16);
  color: #a34437;
}

body.theme-warm .page--games .game-card--pink .game-card__glyph {
  background: rgba(232, 121, 158, 0.16);
  color: #b04a72;
}

body.theme-warm .page--games .game-card__name {
  display: block;
  font-family: "Fraunces", Georgia, serif;
  font-size: 1.02rem;
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--forest);
}

body.theme-warm .page--games .game-card__tag {
  display: block;
  font-size: 0.74rem;
  color: rgba(42, 59, 46, 0.72);
}

body.theme-warm .page--games .game-card__lic {
  display: inline-block;
  margin-top: 3px;
  padding: 1px 7px;
  border-radius: 999px;
  background: rgba(127, 160, 107, 0.16);
  color: #3f6b46;
  font-size: 0.56rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

body.theme-warm .page--games .game-card__play {
  padding: 5px 12px;
  border-radius: 999px;
  background: linear-gradient(135deg, #f6d879, #d9a83c);
  color: #4a3608;
  font-size: 0.62rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.5);
}

body.theme-warm .page--games .games-note {
  padding: 8px 18px 14px;
  text-align: center;
  font-size: 0.68rem;
  color: rgba(42, 59, 46, 0.6);
}

/* ---- play page: the game is the hero ----
   One compact glass sheet at the top (title bar + status strip), then the
   game card claiming EVERY remaining pixel, top to bottom. The old layout
   capped the host at min(68dvh, 560px) inside a page taller than the
   viewport, so the card slid below the fold and games were cut mid-content
   on short screens (2048's board, Flappy's splash). */
body.theme-warm .page--play .device-screen {
  display: flex;
  flex-direction: column;
  gap: 0;
  overflow: hidden;
}

/* On real phones the play page IS the viewport: no page scroll, no side
   gutters, no footer under the fold - the game gets the whole screen. */
@media (max-width: 859px) {
  body.theme-warm .page--play {
    --page-max: none;
    max-width: none;
    height: 100vh;
    height: 100dvh;
    padding: 0;
    gap: 0;
    overflow: hidden;
  }
  body.theme-warm .page--play .device-stage,
  body.theme-warm .page--play .device {
    display: flex;
    flex: 1;
    min-height: 0;
    flex-direction: column;
  }
  body.theme-warm .page--play .device-screen {
    flex: 1;
    min-height: 0;
  }
  body.theme-warm:has(.page--play) .site-footer { display: none; }
}

/* Inside the desktop mock: keep the notch clearance, drop the reading
   padding so the game fills the simulated screen too. */
@media (min-width: 860px) {
  body.theme-warm .page--play .device-screen {
    padding: 2.55rem 0 1.35rem;
    gap: 0;
    overflow: hidden;
  }
}

/* Title bar: first row of the sheet. */
body.theme-warm .page--play .sheet-head {
  position: static;
  margin: max(8px, env(safe-area-inset-top)) 8px 0;
  padding: 8px 10px;
  border-radius: var(--r-lg) var(--r-lg) 0 0;
}

/* Status strip: second row of the same glass sheet (score left, best
   right). Attached to the title bar - one material, two rows - so the
   game keeps the height a floating pill used to waste. */
body.theme-warm .page--play .game-hud {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  margin: 0 8px;
  padding: 0 14px 7px;
  border-radius: 0 0 var(--r-lg) var(--r-lg);
  background: rgba(250, 252, 248, 0.82);
  -webkit-backdrop-filter: blur(16px) saturate(160%);
  backdrop-filter: blur(16px) saturate(160%);
  font-variant-numeric: tabular-nums;
}

body.theme-warm .page--play .game-hud__score {
  font-family: "Fraunces", Georgia, serif;
  font-size: 1.05rem;
  font-weight: 700;
  color: var(--forest);
}

body.theme-warm .page--play .game-hud__best {
  font-size: 0.68rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: rgba(42, 59, 46, 0.65);
}

/* ---- play page: ONE glass bar for the title and the status ------------
   The two rows used to be two separate backdrop-filter surfaces stacked
   flush. Each blur is its own compositor layer, and two adjacent ones
   repaint against each other whenever either changes (the score ticks on
   every point), which is the shimmer this page had on iOS. One surface, one
   layer, and a hairline border between the rows instead of a second
   material.
   ---------------------------------------------------------------------- */
body.theme-warm .page--play .game-bar {
  position: relative;
  isolation: isolate;
  margin: max(8px, env(safe-area-inset-top)) 8px 0;
  border-radius: var(--r-lg);
  overflow: hidden;
  box-shadow: 0 10px 24px -16px rgba(18, 32, 22, 0.5);
}

body.theme-warm .page--play .game-bar::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  border-radius: inherit;
  pointer-events: none;
  background: linear-gradient(
    180deg,
    rgba(255, 255, 255, 0.74) 0%,
    rgba(250, 252, 248, 0.68) 100%
  );
  -webkit-backdrop-filter: blur(22px) saturate(180%);
  backdrop-filter: blur(22px) saturate(180%);
  border: 1px solid rgba(255, 255, 255, 0.6);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.85);
  transform: translateZ(0);
}

body.theme-warm .page--play .game-bar > * {
  position: relative;
  z-index: 1;
}

/* the rows give up their own material inside the bar */
body.theme-warm .page--play .game-bar .sheet-head {
  margin: 0;
  padding: 8px 10px;
  border: 0;
  border-radius: 0;
  background: none;
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
  box-shadow: none;
}

body.theme-warm .page--play .game-bar .game-hud {
  margin: 0;
  padding: 4px 14px 7px;
  border-radius: 0;
  border-top: 1px solid rgba(34, 48, 31, 0.07);
  background: none;
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
}

/* the pause circle sits on the bar now, so it needs no blur of its own */
body.theme-warm .page--play .game-bar .game-pause {
  background: rgba(34, 48, 31, 0.06);
  border-color: rgba(255, 255, 255, 0.65);
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.7);
}

body.theme-warm .page--play .game-host {
  position: relative;
  flex: 1;
  min-height: 0;
  margin: 8px 8px max(10px, env(safe-area-inset-bottom));
  border-radius: 24px;
  overflow: hidden;
  background: linear-gradient(180deg, rgba(31, 55, 38, 0.92), rgba(24, 40, 29, 0.96));
  border: 1px solid rgba(255, 255, 255, 0.14);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.18),
    0 18px 34px -18px rgba(31, 55, 38, 0.6);
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
  -webkit-touch-callout: none;
}

body.theme-warm .page--play .game-host canvas,
body.theme-warm .page--play .game-frame {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  touch-action: none;
}

/* the vendored open-source game runs unmodified inside this frame */
body.theme-warm .page--play .game-frame {
  border: 0;
  background: transparent;
}

/* The host is flex: 1 on every screen size now (see the play page block
   above): it claims all remaining height instead of a fixed 68dvh cap,
   so nothing is cut on short screens and the card runs top to bottom. */

/* ---- play page: credit line removed (client request, 2026-10-14).
   Licence attribution lives in the source form (registry.py, CREDITS.md,
   each vendored LICENSE); the hub card keeps its licence chip. ---- */

/* ---- play page: overlay (ready / paused / game over) ---- */
body.theme-warm .page--play .game-overlay {
  position: absolute;
  inset: 0;
  z-index: 2;
  display: grid;
  place-content: center;
  justify-items: center;
  gap: 10px;
  padding: 24px;
  text-align: center;
  color: #f7f2e6;
  background: rgba(24, 40, 29, 0.62);
  -webkit-backdrop-filter: blur(10px) saturate(140%);
  backdrop-filter: blur(10px) saturate(140%);
  transition: opacity 220ms ease;
}

body.theme-warm .page--play .game-overlay[data-state="hidden"] {
  opacity: 0;
  pointer-events: none;
}

body.theme-warm .page--play .game-overlay__title {
  font-family: "Fraunces", Georgia, serif;
  font-size: 1.7rem;
  letter-spacing: -0.02em;
  color: #ffffff;
}

body.theme-warm .page--play .game-overlay__sub {
  max-width: 26ch;
  font-size: 0.8rem;
  line-height: 1.5;
  color: rgba(247, 242, 230, 0.82);
}

body.theme-warm .page--play .game-overlay__score {
  font-family: "Fraunces", Georgia, serif;
  font-size: 2.2rem;
  font-variant-numeric: tabular-nums;
  color: #f6d879;
}

body.theme-warm .page--play .game-overlay__row {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 10px;
}

/* ---- play page: the result dock (deferred games) ----
   Chess Master ends on a screen of its own: who won, how, and a Review Board
   button over the final position. Throwing the dark result sheet over that
   the instant the game ends hides the only thing worth seeing, so the shell
   waits here instead, on the bottom edge of the card, out of the board's
   way. One tap opens the full result. Gold when a prize is waiting, because
   a win the guest cannot see is a win they never claim. */
body.theme-warm .page--play .game-dock {
  position: absolute;
  left: 50%;
  bottom: 10px;
  z-index: 3;
  display: flex;
  align-items: center;
  gap: 10px;
  max-width: calc(100% - 20px);
  padding: 9px 12px 9px 15px;
  border: 1px solid rgba(255, 255, 255, 0.22);
  border-radius: 999px;
  background: rgba(20, 34, 25, 0.94);
  color: #f7f2e6;
  font-family: inherit;
  font-size: 0.76rem;
  font-weight: 600;
  letter-spacing: 0.01em;
  text-align: left;
  cursor: pointer;
  transform: translate(-50%, 0);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.16),
    0 14px 26px -14px rgba(0, 0, 0, 0.8);
  -webkit-backdrop-filter: blur(8px) saturate(140%);
  backdrop-filter: blur(8px) saturate(140%);
  animation: gameDockIn 280ms cubic-bezier(0.16, 1, 0.3, 1) both;
}

body.theme-warm .page--play .game-dock:active {
  transform: translate(-50%, 0) scale(0.985);
}

body.theme-warm .page--play .game-dock__main {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

body.theme-warm .page--play .game-dock__go {
  flex: none;
  color: #f6d879;
  font-weight: 700;
  white-space: nowrap;
}

body.theme-warm .page--play .game-dock[data-state="won"] {
  border-color: rgba(246, 216, 121, 0.68);
  background: rgba(38, 58, 32, 0.96);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.22),
    0 0 0 1px rgba(246, 216, 121, 0.18),
    0 16px 30px -14px rgba(0, 0, 0, 0.85);
}

body.theme-warm .page--play .game-dock[data-state="won"] .game-dock__main {
  color: #f9e6a8;
}

@keyframes gameDockIn {
  from { opacity: 0; transform: translate(-50%, 12px); }
  to { opacity: 1; transform: translate(-50%, 0); }
}

body.theme-warm .page--play .game-cta {
  padding: 12px 26px;
  border: 0;
  border-radius: 999px;
  /* the brand colour, lit across the top left. It used to be a hardcoded
     green, which read as someone else's button on a maroon branded outlet
     (King Chef). --forest is the brand's deep tone on every page, and white
     already sits on it in the wave art, so contrast is safe. */
  background:
    linear-gradient(135deg, rgba(255, 255, 255, 0.16), rgba(0, 0, 0, 0.16)),
    var(--forest);
  color: #ffffff;
  font-size: 0.82rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.26),
    0 10px 20px -10px rgba(0, 0, 0, 0.5);
  cursor: pointer;
  transition: transform 140ms cubic-bezier(0.16, 1, 0.3, 1);
}

body.theme-warm .page--play .game-cta:active { transform: scale(0.96); }

body.theme-warm .page--play .game-cta--ghost {
  background: rgba(255, 255, 255, 0.14);
  border: 1px solid rgba(255, 255, 255, 0.35);
  color: #f7f2e6;
  box-shadow: none;
}

/* ---- play page: pause button matches the glass back circle ---- */
body.theme-warm .page--play .game-pause {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  border: 1px solid rgba(255, 255, 255, 0.7);
  background: rgba(255, 255, 255, 0.5);
  -webkit-backdrop-filter: blur(14px) saturate(180%);
  backdrop-filter: blur(14px) saturate(180%);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.6);
  color: var(--forest);
  cursor: pointer;
  transition: transform 140ms cubic-bezier(0.16, 1, 0.3, 1);
}

body.theme-warm .page--play .game-pause:active { transform: scale(0.88); }

body.theme-warm .page--play .game-pause svg {
  width: 16px;
  height: 16px;
}

/* ---- reduced motion: no press scaling, no overlay fade ---- */
@media (prefers-reduced-motion: reduce) {
  body.theme-warm .page--games .game-card,
  body.theme-warm .page--play .game-cta,
  body.theme-warm .page--play .game-pause { transition: none; }
  body.theme-warm .page--games .game-card:active,
  body.theme-warm .page--play .game-cta:active,
  body.theme-warm .page--play .game-pause:active { transform: none; }
  body.theme-warm .page--play .game-overlay { transition: none; }
  body.theme-warm .page--play .game-dock { animation: none; }
  body.theme-warm .page--play .game-dock:active { transform: translate(-50%, 0); }
}

/* ---- reduced transparency: solidify the games materials ---- */
@media (prefers-reduced-transparency: reduce) {
  body.theme-warm .page--games .games-lead,
  body.theme-warm .page--games .game-card,
  body.theme-warm .page--play .game-hud,
  body.theme-warm .page--play .game-pause {
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
    background: rgba(255, 255, 255, 0.94);
  }
  body.theme-warm .page--play .game-overlay {
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
    background: rgba(24, 40, 29, 0.92);
  }
  body.theme-warm .page--play .game-dock {
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
    background: #1b2a1f;
  }
  body.theme-warm .page--play .game-dock[data-state="won"] { background: #263a20; }
}

/* --------------------------------------------------------------------------
   Instagram lucky-draw popup (client copy 2026-10-14)
   "Follow and win a special gift": tapping the Instagram card celebrates
   the entry first ("You are entered in the lucky draw!"), then hands off
   to the tap-tracked Instagram redirect, which stays the single
   draw-entry log. Pinned to the phone screen exactly like the background
   art: .device is the containing block for fixed descendants on this page
   (container-type, and translateZ(0) inside the desktop mock frame), so
   the scrim covers the screen box on real phones and in the mock alike.
   -------------------------------------------------------------------------- */
body.theme-warm .device-screen > .ig-draw {
  position: fixed;
  inset: 0;
  z-index: 50;
  display: grid;
  place-items: center;
  padding: 22px;
}

/* the class rule sets display: grid, which would defeat the hidden
   attribute's UA display: none — restore it explicitly */
body.theme-warm .device-screen > .ig-draw[hidden] { display: none; }

/* The scrim is what makes the sheet the first thing read. Client report
   2026-10-19: over the games the page behind showed THROUGH the sign-in card
   and the two sets of words collided. Two changes answer it:
     1. this scrim is deep enough to push the page back, and
     2. the sheet itself is now an opaque warm cream surface (below).
   No backdrop-filter here on purpose. A blur on this layer is re-sampled on
   every frame of a live game canvas running under it, which is the same
   flicker the play page already removed elsewhere. A flat dim does the same
   job for the eye and costs nothing per frame. */
body.theme-warm .ig-draw__backdrop {
  position: absolute;
  inset: 0;
  background:
    radial-gradient(120% 90% at 50% 8%, rgba(20, 34, 25, 0.58), rgba(12, 21, 15, 0.78) 70%, rgba(9, 16, 11, 0.86) 100%);
  animation: ig-draw-fade 180ms ease;
}

/* ---- the sheet: a thick warm material, built as two layers -------------
   Layer 1 .ig-draw__glass  the surface: warm cream, a lit top rim, a soft
                            sheen. It NEVER moves, scrolls or animates.
   Layer 2 .ig-draw__scroll the content, on its own scrolling surface.

   Why the surface is opaque and not see-through (client 2026-10-19): this
   card opens on top of the chess board, the score bar and the game's own
   setup panel. Thin glass let all of that read through the form, so the
   guest saw two sets of words in the same place. iOS calls this a thick
   material: you feel the page behind in the SCRIM, never through the card.
   Keeping the page behind the scrim also keeps the "you are still in the
   game" context, which is what the glass was for in the first place.

   Splitting the two layers is still the anti flicker measure. A
   backdrop-filter on the scrolling element re-blurs the whole page behind
   it on every frame of a scroll, which on iOS reads as shimmer, worst on
   the tall form panel.
   ------------------------------------------------------------------------ */
body.theme-warm .ig-draw__sheet {
  position: relative;
  isolation: isolate;
  display: flex;
  flex-direction: column;
  width: min(320px, 100%);
  max-height: 100%;
  overflow: hidden;
  border-radius: 28px;
  text-align: center;
  box-shadow:
    0 2px 6px rgba(18, 32, 22, 0.1),
    0 30px 70px -20px rgba(10, 20, 14, 0.64);
  animation: ig-sheet-in 160ms ease-out both;
}

body.theme-warm .ig-draw__glass {
  position: absolute;
  inset: 0;
  z-index: 0;
  border-radius: inherit;
  pointer-events: none;
  /* opaque base first: no single pixel of the page behind can ever reach the
     copy, whatever the contrast of what is open underneath */
  background-color: #fbf7ec;
  background-image: linear-gradient(
    180deg,
    #fffefa 0%,
    #fdfaf2 42%,
    #f7f0e0 100%
  );
  border: 1px solid rgba(255, 255, 255, 0.95);
  box-shadow:
    inset 0 1px 0 #ffffff,
    inset 0 -1px 0 rgba(255, 255, 255, 0.6),
    inset 0 0 0 1px rgba(168, 137, 62, 0.06);
}

/* The specular sheen. A single soft light from the top left plus a whisper of
   gold from the bottom right is what makes a flat translucent panel read as a
   curved material rather than a white box. */
body.theme-warm .ig-draw__glass::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background:
    radial-gradient(120% 58% at 20% 0%, rgba(255, 255, 255, 0.62), rgba(255, 255, 255, 0) 62%),
    radial-gradient(94% 44% at 94% 104%, rgba(194, 162, 75, 0.1), rgba(255, 255, 255, 0) 74%);
}

body.theme-warm .ig-draw__scroll {
  position: relative;
  z-index: 1;
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
  /* the bar itself is hidden: on a 320px card the operating system's scroll
     track drew a pale line down the right edge of the form and read as a
     broken border. The content still scrolls, and the copy is short enough
     that the end of it is visible without a hint. */
  scrollbar-width: none;
  padding: 20px 20px 16px;
  border-radius: inherit;
  animation: ig-body-in 260ms cubic-bezier(0.16, 1, 0.3, 1) both;
}

body.theme-warm .ig-draw__scroll::-webkit-scrollbar {
  width: 0;
  height: 0;
}

body.theme-warm .ig-draw__icon {
  width: 48px;
  height: 48px;
  margin: 0 auto 10px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background: linear-gradient(180deg, #fdf8ec, var(--tint-cream));
  color: var(--gold-deep);
  box-shadow:
    inset 0 1px 0 #ffffff,
    0 0 0 1px rgba(168, 137, 62, 0.16);
}

body.theme-warm .ig-draw__icon svg { width: 23px; height: 23px; }

body.theme-warm .ig-draw__title {
  font-family: "Fraunces", Georgia, serif;
  font-size: 1.34rem;
  line-height: 1.18;
  letter-spacing: -0.02em;
  color: var(--ink);
  text-wrap: balance;
}

body.theme-warm .ig-draw__sub {
  margin: 7px auto 0;
  max-width: 31ch;
  font-size: 0.8rem;
  line-height: 1.5;
  color: var(--link-sub);
  text-wrap: pretty;
}

body.theme-warm .ig-draw__cta {
  display: block;
  margin-top: 16px;
  padding: 12px 26px;
  border-radius: 999px;
  /* the outlet's own colour, not a fixed green: this card opens on four
     different brands and the button has to belong to the one it is on */
  background:
    linear-gradient(135deg, rgba(255, 255, 255, 0.16), rgba(0, 0, 0, 0.16)),
    var(--forest);
  color: #ffffff;
  font-size: 0.85rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  text-decoration: none;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.26),
    0 10px 20px -10px rgba(0, 0, 0, 0.5);
  transition:
    transform 140ms cubic-bezier(0.16, 1, 0.3, 1),
    box-shadow 180ms cubic-bezier(0.16, 1, 0.3, 1);
}

body.theme-warm .ig-draw__cta:active { transform: scale(0.96); }

/* Readiness, not action.

   Client direction 2026-10-19: a full six digit code must not verify
   itself. The guest types or autofills it, looks at it, and taps. So the
   only thing a complete code changes is this ring: a gold breath that says
   "ready when you are". Box-shadow and colour only, so the blurred layers
   behind the sheet are never repainted by a keystroke. */
body.theme-warm .ig-draw__cta[data-ready="true"] {
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.34),
    0 0 0 3px rgba(194, 162, 75, 0.30),
    0 12px 24px -10px rgba(0, 0, 0, 0.55);
}

body.theme-warm .ig-draw__cta[aria-busy="true"] {
  cursor: default;
  opacity: 0.82;
}

body.theme-warm .ig-draw__close {
  margin-top: 6px;
  padding: 10px 18px;
  border: 0;
  background: none;
  color: var(--link-sub);
  font-size: 0.8125rem;
  font-weight: 600;
  cursor: pointer;
}

@keyframes ig-draw-fade {
  from { opacity: 0; }
  to { opacity: 1; }
}

@keyframes ig-draw-rise {
  from { opacity: 0; transform: translateY(10px) scale(0.96); }
  to { opacity: 1; transform: none; }
}

/* The sheet fades, the content slides on top of it. Nothing that carries a
   backdrop-filter is ever transformed mid-animation: that is the other half
   of the no flicker rule. */
@keyframes ig-sheet-in {
  from { opacity: 0; }
  to { opacity: 1; }
}

@keyframes ig-body-in {
  from { opacity: 0; transform: translateY(14px); }
  to { opacity: 1; transform: none; }
}

@keyframes ig-picker-in {
  from { opacity: 0; transform: translateY(16px) scale(0.985); }
  to { opacity: 1; transform: none; }
}

/* desktop mock: a fixed layer is not clipped by the screen's overflow, so
   round the scrim to the screen corners the same way the background art does */
@media (min-width: 860px) {
  body.theme-warm .device-screen > .ig-draw { clip-path: inset(0 round 46px); }
}

/* ---- reduced motion: no entrance animation, no press scaling ---- */
@media (prefers-reduced-motion: reduce) {
  body.theme-warm .ig-draw__backdrop,
  body.theme-warm .ig-draw__sheet { animation: none; }
  body.theme-warm .ig-draw__cta { transition: none; }
  body.theme-warm .ig-draw__cta:active { transform: none; }
}

/* ---- reduced transparency: solidify the scrim ---- */
@media (prefers-reduced-transparency: reduce) {
  body.theme-warm .ig-draw__backdrop {
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
    background: rgba(24, 40, 29, 0.92);
  }
}

/* --------------------------------------------------------------------------
   Guest identity sheet (plan 2026-10-16, task 2).

   Same .ig-draw material as the lucky-draw popup above: this only adds the
   ask / form / done panels inside that sheet, so the component keeps one
   visual language instead of growing a second one.
   -------------------------------------------------------------------------- */
/* long forms must stay reachable on a short phone screen. The sheet itself
   no longer scrolls: .ig-draw__scroll inside it does, so the blurred glass
   layer underneath stays still while the form moves. */
body.theme-warm .ig-draw__sheet {
  max-height: min(92vh, 92%);
}

/* Short phone (375x667 and the like). The form is taller than the card once
   the decorative icon is counted, so "Continue" fell below the fold, and
   with the scrollbar hidden there was nothing to say "scroll". Compact mode
   is the fix: the card takes more of the screen, the margins tighten, and
   the icon steps aside so the primary action is visible without scrolling. */
@media (max-height: 720px) {
  body.theme-warm .device-screen > .ig-draw { padding: 14px; }
  body.theme-warm .ig-draw__sheet { max-height: 98%; }
  body.theme-warm .ig-draw__scroll { padding-top: 16px; }
  body.theme-warm .ig-draw__icon { display: none; }
}

body.theme-warm .ig-draw__panel[hidden] { display: none; }

body.theme-warm .ig-draw__actions { margin-top: 16px; }

/* the CTA class now lands on <button> as well as <a> */
body.theme-warm button.ig-draw__cta {
  width: 100%;
  border: 0;
  cursor: pointer;
  font-family: inherit;
  font-size: 0.85rem;
}

body.theme-warm .ig-draw__already {
  margin-top: 10px;
  font-size: 0.8125rem;
  color: var(--link-sub);
}

body.theme-warm .ig-draw__link {
  padding: 2px 4px;
  border: 0;
  background: none;
  color: var(--gold-deep);
  font: inherit;
  font-weight: 700;
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 2px;
}

body.theme-warm .ig-draw__error {
  margin: 10px 0 0;
  padding: 8px 12px;
  border-radius: 12px;
  background: rgba(147, 51, 31, 0.09);
  color: #93331f;
  font-size: 0.78rem;
  font-weight: 600;
  line-height: 1.4;
}

body.theme-warm .ig-draw__form {
  margin-top: 12px;
  text-align: left;
}

body.theme-warm .ig-draw__field { display: block; margin-top: 9px; }

body.theme-warm .ig-draw__label {
  display: block;
  margin-bottom: 4px;
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--link-sub);
}

body.theme-warm .ig-draw__field input {
  width: 100%;
  padding: 11px 14px;
  border: 1px solid rgba(34, 48, 31, 0.14);
  border-radius: 14px;
  background: var(--card-white);
  color: var(--ink);
  font: inherit;
  font-size: 0.9rem;
}

body.theme-warm .ig-draw__field input:focus-visible {
  outline: 2px solid var(--gold-deep);
  outline-offset: 1px;
  border-color: transparent;
}

/* ---- country code + mobile ---------------------------------------------
   ONE control, not two boxes. The dial chip and the number share a single
   well, the way a phone's own dialler shows them, so the guest reads
   "+971 56 466 9930" as one number. The divider is the chip's own tinted
   background, so there is no hairline to get wrong at any width.
   ------------------------------------------------------------------------ */
body.theme-warm .ig-draw__phone {
  display: flex;
  align-items: center;
  gap: 2px;
  padding: 4px;
  border: 1px solid rgba(34, 48, 31, 0.12);
  border-radius: 18px;
  background: rgba(255, 255, 255, 0.7);
  box-shadow: inset 0 1px 2px rgba(34, 48, 31, 0.05);
  transition: border-color 160ms ease, box-shadow 160ms ease;
}

body.theme-warm .ig-draw__phone:focus-within {
  border-color: rgba(168, 137, 62, 0.55);
  box-shadow:
    0 0 0 3px rgba(168, 137, 62, 0.14),
    inset 0 1px 2px rgba(34, 48, 31, 0.04);
}

/* the dial chip: flag + code + caret, and nothing else */
body.theme-warm .ig-draw__dial {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  flex: 0 0 auto;
  padding: 8px 9px 8px 10px;
  border: 0;
  border-radius: 14px;
  background: rgba(34, 48, 31, 0.055);
  color: var(--ink);
  font: inherit;
  font-size: 0.95rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  cursor: pointer;
  transition: background-color 140ms ease, transform 140ms ease;
}

body.theme-warm .ig-draw__dial:active {
  transform: scale(0.96);
  background: rgba(34, 48, 31, 0.1);
}

body.theme-warm .ig-draw__dial:focus-visible {
  outline: 2px solid var(--gold-deep);
  outline-offset: 1px;
}

body.theme-warm .ig-draw__dial-flag {
  width: 22px;
  height: 15px;
  border-radius: 3px;
  object-fit: cover;
  box-shadow: 0 0 0 1px rgba(34, 48, 31, 0.12);
}

body.theme-warm .ig-draw__dial-caret {
  display: grid;
  color: rgba(34, 48, 31, 0.42);
}

body.theme-warm .ig-draw__dial-caret svg {
  width: 11px;
  height: 11px;
  transform: rotate(90deg);
}

/* The number itself has no chrome of its own: the well is the field. 16px
   (1rem) is deliberate, not styling: anything smaller makes iOS Safari zoom
   the whole page the moment the field takes focus. */
body.theme-warm .ig-draw__field .ig-draw__phone input {
  flex: 1 1 auto;
  width: auto;
  min-width: 0;
  padding: 9px 10px;
  border: 0;
  border-radius: 14px;
  background: transparent;
  box-shadow: none;
  font-size: 1rem;
}

body.theme-warm .ig-draw__field .ig-draw__phone input:focus-visible {
  outline: none;
}

body.theme-warm .ig-draw__field input {
  font-size: 1rem;
}

/* ---- the six digit code ------------------------------------------------
   One field, widely spaced digits, styled like a code rather than a text
   input. `autocomplete="one-time-code"` lets iOS and Android offer the code
   straight from the WhatsApp notification, which is how most guests will
   fill it. */
body.theme-warm .ig-draw__code {
  width: 100%;
  padding: 13px 14px;
  border: 1px solid rgba(34, 48, 31, 0.14);
  border-radius: 14px;
  background: var(--card-white);
  color: var(--ink);
  font-family: ui-monospace, "SFMono-Regular", Menlo, monospace;
  font-size: 1.5rem;
  font-weight: 700;
  letter-spacing: 0.55em;
  text-align: center;
  text-indent: 0.55em;
}

body.theme-warm .ig-draw__code:focus-visible {
  outline: 2px solid var(--gold-deep);
  outline-offset: 1px;
  border-color: transparent;
}

/* Resend, and the wait before it is allowed. The countdown is the honest
   part: the server enforces 60 seconds, so the button says when, instead of
   failing silently when the guest taps too early. */
body.theme-warm .ig-draw__resend {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  align-items: baseline;
  justify-content: center;
  margin: 14px 0 0;
  font-size: 0.78rem;
  color: var(--link-sub);
}

body.theme-warm .ig-draw__timer {
  color: var(--gold-deep);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

body.theme-warm .ig-draw__resend .ig-draw__link[disabled] {
  opacity: 0.45;
  cursor: default;
  text-decoration: none;
}

body.theme-warm .ig-draw__edit {
  display: block;
  margin: 10px auto 0;
  font-size: 0.78rem;
}

/* The mobile number is the handle staff match at the counter when a guest
   redeems, so the warning sits right under the field, where the guest types.
   It has to read as a note, not as an error: warm gold, never the red box. */
body.theme-warm .ig-draw__note {
  margin: 9px 0 0;
  padding: 8px 10px;
  border-radius: 12px;
  /* a quiet aside, not a warning banner: it explains why the number has to be
     right, so it must be read, not obeyed. The tint and the hairline carry
     it; the weight stays light so it does not compete with Continue. */
  background: rgba(168, 137, 62, 0.09);
  border: 1px solid rgba(168, 137, 62, 0.2);
  color: #77602a;
  font-size: 0.735rem;
  font-weight: 500;
  line-height: 1.45;
}

body.theme-warm .ig-draw__consent {
  display: flex;
  gap: 9px;
  align-items: flex-start;
  margin-top: 10px;
  font-size: 0.735rem;
  line-height: 1.45;
  color: var(--link-sub);
}

body.theme-warm .ig-draw__consent input {
  flex: none;
  width: 18px;
  height: 18px;
  margin-top: 1px;
  accent-color: var(--forest);
}

body.theme-warm .ig-draw__form .ig-draw__cta { margin-top: 12px; }

/* Instagram fallback page: the one link back to the shop window */
body.theme-warm .id-back {
  margin: 22px auto 0;
  text-align: center;
  font-size: 0.8125rem;
}

body.theme-warm .id-back a {
  color: var(--link-sub);
  font-weight: 600;
}

/* Continue with Google, above the manual fields */
body.theme-warm .ig-draw__google {
  margin-top: 14px;
  display: grid;
  justify-items: center;
  gap: 8px;
}

body.theme-warm .ig-draw__or {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 14px 0 0;
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--link-sub);
}

body.theme-warm .ig-draw__or::before,
body.theme-warm .ig-draw__or::after {
  content: "";
  flex: 1;
  height: 1px;
  background: rgba(34, 48, 31, 0.12);
}

/* ---- country calling code picker --------------------------------------
   Client direction 2026-10-19: no country names in the sheet. Every row is a
   flag and a dial code, and a search box finds a country by what guests
   actually type ("uae", "india", "91", "dubai").

   This replaces a native <select>. On a desktop that rendered the operating
   system's own list, which spilled outside the card, carried a scrollbar the
   theme could not touch, and could not be searched; on a phone it opened a
   wheel with no flags at all.

   Same two layer construction as the sheet: a still glass surface, and the
   scrolling list on top of it.
   ------------------------------------------------------------------------ */
body.theme-warm .ig-picker {
  position: fixed;
  inset: 0;
  z-index: 60; /* above the sheet (50): this is the top layer */
  display: grid;
  place-items: center;
  padding: 22px;
}

body.theme-warm .ig-picker[hidden] { display: none; }

body.theme-warm .ig-picker__backdrop {
  position: absolute;
  inset: 0;
  background: rgba(18, 30, 22, 0.34);
  -webkit-backdrop-filter: blur(7px) saturate(130%);
  backdrop-filter: blur(7px) saturate(130%);
  animation: ig-draw-fade 160ms ease;
}

body.theme-warm .ig-picker__panel {
  position: relative;
  isolation: isolate;
  display: flex;
  flex-direction: column;
  width: min(320px, 100%);
  max-height: min(430px, 82%);
  overflow: hidden;
  border-radius: 26px;
  box-shadow: 0 22px 54px -20px rgba(18, 32, 22, 0.55);
  animation: ig-picker-in 240ms cubic-bezier(0.16, 1, 0.3, 1) both;
}

body.theme-warm .ig-picker__glass {
  position: absolute;
  inset: 0;
  z-index: 0;
  border-radius: inherit;
  pointer-events: none;
  /* same thick warm material as the sheet, so the picker reads as the sheet's
     own child rather than a different kind of surface */
  background-color: #fbf7ec;
  background-image: linear-gradient(180deg, #fffefa, #f8f2e4);
  border: 1px solid rgba(255, 255, 255, 0.95);
  box-shadow:
    inset 0 1px 0 #ffffff,
    inset 0 0 0 1px rgba(168, 137, 62, 0.06);
}

body.theme-warm .ig-picker__head {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 14px 10px 10px 14px;
  border-bottom: 1px solid rgba(34, 48, 31, 0.07);
}

body.theme-warm .ig-picker__search {
  position: relative;
  display: flex;
  align-items: center;
  flex: 1 1 auto;
  min-width: 0;
}

body.theme-warm .ig-picker__search-icon {
  position: absolute;
  left: 11px;
  display: grid;
  color: rgba(34, 48, 31, 0.38);
  pointer-events: none;
}

body.theme-warm .ig-picker__search-icon svg {
  width: 15px;
  height: 15px;
}

body.theme-warm .ig-picker__input {
  width: 100%;
  padding: 10px 12px 10px 33px;
  border: 1px solid rgba(34, 48, 31, 0.12);
  border-radius: 13px;
  background: rgba(255, 255, 255, 0.72);
  color: var(--ink);
  font: inherit;
  font-size: 1rem;
  -webkit-appearance: none;
  appearance: none;
}

body.theme-warm .ig-picker__input::placeholder { color: rgba(34, 48, 31, 0.4); }

body.theme-warm .ig-picker__input:focus-visible {
  outline: 2px solid var(--gold-deep);
  outline-offset: 1px;
  border-color: transparent;
}

/* iOS paints its own cancel glyph inside type=search, which fights the close
   button sitting right next to it. */
body.theme-warm .ig-picker__input::-webkit-search-cancel-button,
body.theme-warm .ig-picker__input::-webkit-search-decoration {
  -webkit-appearance: none;
  appearance: none;
}

body.theme-warm .ig-picker__close {
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border: 0;
  border-radius: 50%;
  background: rgba(34, 48, 31, 0.06);
  color: rgba(34, 48, 31, 0.66);
  cursor: pointer;
  transition: transform 140ms cubic-bezier(0.16, 1, 0.3, 1);
}

body.theme-warm .ig-picker__close:active { transform: scale(0.9); }

body.theme-warm .ig-picker__close svg {
  width: 14px;
  height: 14px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
}

body.theme-warm .ig-picker__list {
  position: relative;
  z-index: 1;
  flex: 1 1 auto;
  min-height: 0;
  margin: 0;
  padding: 6px;
  list-style: none;
  overflow-y: auto;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
}

body.theme-warm .ig-picker__item[hidden] { display: none; }

body.theme-warm .ig-picker__row {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  padding: 10px 12px;
  border: 0;
  border-radius: 14px;
  background: transparent;
  color: var(--ink);
  font: inherit;
  text-align: left;
  cursor: pointer;
  transition: background-color 120ms ease;
}

body.theme-warm .ig-picker__row:active { background: rgba(34, 48, 31, 0.07); }

body.theme-warm .ig-picker__row:focus-visible {
  outline: 2px solid var(--gold-deep);
  outline-offset: -2px;
}

body.theme-warm .ig-picker__row[aria-selected="true"] {
  background: rgba(168, 137, 62, 0.13);
}

body.theme-warm .ig-picker__flag {
  flex: 0 0 auto;
  width: 26px;
  height: 18px;
  border-radius: 4px;
  object-fit: cover;
  box-shadow: 0 0 0 1px rgba(34, 48, 31, 0.1);
}

body.theme-warm .ig-picker__dial {
  flex: 1 1 auto;
  font-size: 0.95rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.01em;
}

body.theme-warm .ig-picker__tick {
  display: grid;
  width: 16px;
  opacity: 0;
  transition: opacity 120ms ease;
}

body.theme-warm .ig-picker__tick svg {
  width: 16px;
  height: 16px;
  fill: none;
  stroke: var(--gold-deep);
  stroke-width: 2.4;
  stroke-linecap: round;
  stroke-linejoin: round;
}

body.theme-warm .ig-picker__row[aria-selected="true"] .ig-picker__tick { opacity: 1; }

body.theme-warm .ig-picker__empty {
  position: relative;
  z-index: 1;
  margin: 0;
  padding: 20px 18px 26px;
  text-align: center;
  font-size: 0.82rem;
  line-height: 1.5;
  color: var(--link-sub);
}

body.theme-warm .ig-picker__empty[hidden] { display: none; }

/* no press scaling when the guest asked for reduced motion */
@media (prefers-reduced-motion: reduce) {
  body.theme-warm button.ig-draw__cta { transition: none; }
  body.theme-warm button.ig-draw__cta:active { transform: none; }
  body.theme-warm .ig-picker__panel,
  body.theme-warm .ig-picker__backdrop,
  body.theme-warm .ig-draw__sheet,
  body.theme-warm .ig-draw__scroll { animation: none; }
  body.theme-warm .ig-draw__dial:active,
  body.theme-warm .ig-picker__close:active { transform: none; }
  body.theme-warm .ig-draw__dial,
  body.theme-warm .ig-picker__row,
  body.theme-warm .ig-picker__tick,
  body.theme-warm .ig-draw__phone { transition: none; }
}

/* reduced transparency: the glass becomes a solid warm card. A guest who
   asked for this gets the layout, not the material. */
@media (prefers-reduced-transparency: reduce) {
  body.theme-warm .ig-draw__glass,
  body.theme-warm .ig-picker__glass {
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
    background: #fdfbf6;
  }
  body.theme-warm .ig-picker__backdrop {
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
    background: rgba(18, 30, 22, 0.62);
  }
  body.theme-warm .ig-picker__input { background: #ffffff; }
}

/* --------------------------------------------------------------------------
   Play page: the won coupon, shown inside the game-over overlay.

   The overlay centres its children, so the reward card can make the stack
   taller than a short phone screen. `overflow-y: auto` plus a SAFE centre
   lets it scroll instead of clipping the top of the title off-screen; a
   browser that does not know `safe` ignores that one line and keeps the
   previous centred layout, so nothing regresses.
   -------------------------------------------------------------------------- */
body.theme-warm .page--play .game-overlay {
  overflow-y: auto;
  align-content: safe center;
}

body.theme-warm .page--play .game-reward {
  width: min(280px, 100%);
  margin-top: 6px;
  padding: 14px 16px 12px;
  border-radius: 18px;
  border: 1px solid rgba(217, 168, 60, 0.55);
  background: #fffdf7;
  color: #1f3726;
  text-align: center;
  box-shadow:
    0 2px 4px rgba(0, 0, 0, 0.12),
    0 14px 30px rgba(0, 0, 0, 0.28);
}

body.theme-warm .page--play .game-reward[hidden] { display: none; }

body.theme-warm .page--play .game-reward__tag {
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: #5e7f52;
}

body.theme-warm .page--play .game-reward__prize {
  margin-top: 2px;
  font-family: "Fraunces", Georgia, serif;
  font-size: 1.32rem;
  line-height: 1.15;
  letter-spacing: -0.02em;
  color: #1f3726;
}

body.theme-warm .page--play .game-reward__code {
  margin-top: 8px;
  padding: 8px 10px;
  border-radius: 12px;
  background: rgba(217, 168, 60, 0.18);
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 1.05rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  color: #7a5210;
}

body.theme-warm .page--play .game-reward__hint {
  margin-top: 8px;
  font-size: 0.72rem;
  line-height: 1.45;
  color: #5b6b55;
}

body.theme-warm .page--play .game-reward__nudge {
  /* Rendered as a <button> when the identity sheet is on the play page, so a
     refusal opens the form in place instead of leaving the round, and as an
     <a> when there is no sheet to open. The reset below makes both read as
     the same quiet underlined link. */
  appearance: none;
  -webkit-appearance: none;
  background: none;
  border: 0;
  padding: 0;
  font-family: inherit;
  cursor: pointer;
  display: inline-block;
  margin-top: 8px;
  font-size: 0.72rem;
  font-weight: 700;
  color: var(--forest);
  text-decoration: underline;
  text-underline-offset: 2px;
}

/* ---- play page: where the guest stands (ladder rung / round run) --------
   The climb is the point of asking for one, so it is on screen, not hidden
   in the rules. Filled by core/shell.js from #games-progress.
   ------------------------------------------------------------------------ */
body.theme-warm .page--play .game-ladder {
  margin: 0 12px 2px;
  padding: 7px 12px;
  border-radius: 12px;
  border: 1px solid rgba(217, 168, 60, 0.32);
  background: rgba(217, 168, 60, 0.12);
  font-size: 0.72rem;
  line-height: 1.45;
  color: var(--forest);
  text-align: center;
}

body.theme-warm .page--play .game-ladder[hidden] { display: none; }

/* ---- play page: the pre-game prompt for a guest who is not verified -----
   Shown before the game starts and never in the way of it: "Play without
   rewards" drops it at once and the game is already running underneath.
   Client rule 2026-10-16: playing is open to everyone at every level, this
   only says what verifying is worth.
   ------------------------------------------------------------------------ */
body.theme-warm .page--play .game-nudge {
  position: absolute;
  inset: 0;
  z-index: 3;
  display: grid;
  place-content: center;
  justify-items: center;
  padding: 20px;
  text-align: center;
  color: #f7f2e6;
  /* A veil that thickens toward the bottom, not a flat 88% wall: the game
     stays legible behind the copy, so the page reads as "about to start"
     instead of "blocked". Deliberately no backdrop-filter here, because the
     game keeps running at 60 frames underneath and a blur over a live canvas
     is recomputed on every one of them. */
  background:
    radial-gradient(120% 70% at 50% 0%, rgba(24, 40, 29, 0.26), rgba(16, 26, 19, 0.72) 62%, rgba(12, 20, 15, 0.9) 100%);
}

/* The copy on its own card, in the SAME warm material as the sign-in sheet.
   Client 2026-10-19: it used to be smoked glass at 16% and the chess setup
   panel behind it ("Play vs Stockfish", LEVEL, PLAY AS) read straight
   through, so the two sets of words collided. It is now opaque cream, which
   also makes the invitation and the form that follows it look like one
   thing: tap the cream card, the cream sheet opens. */
body.theme-warm .page--play .game-nudge__card {
  display: grid;
  justify-items: center;
  gap: 8px;
  width: 100%;
  max-width: 296px;
  padding: 20px 18px 16px;
  border-radius: 26px;
  background-color: #fbf7ec;
  background-image: linear-gradient(180deg, #fffefa 0%, #fdfaf2 46%, #f7f0e0 100%);
  border: 1px solid rgba(255, 255, 255, 0.92);
  box-shadow:
    inset 0 1px 0 #ffffff,
    inset 0 0 0 1px rgba(168, 137, 62, 0.08),
    0 26px 52px -24px rgba(0, 0, 0, 0.78);
  animation: ig-body-in 300ms cubic-bezier(0.16, 1, 0.3, 1) both;
}

body.theme-warm .page--play .game-nudge__eyebrow {
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--gold-deep);
}

body.theme-warm .page--play .game-nudge__title {
  font-family: "Fraunces", Georgia, serif;
  font-size: 1.3rem;
  line-height: 1.18;
  letter-spacing: -0.02em;
  color: var(--ink);
  text-wrap: balance;
}

body.theme-warm .page--play .game-nudge__body {
  max-width: 30ch;
  font-size: 0.79rem;
  line-height: 1.5;
  color: var(--link-sub);
  text-wrap: pretty;
}

/* the quiet choice stays quiet, but it has to be legible on cream, so it is
   ink on a tint of the card rather than white on a dark wash */
body.theme-warm .page--play .game-nudge__card .game-cta--ghost {
  background: rgba(34, 48, 31, 0.055);
  border: 1px solid rgba(34, 48, 31, 0.14);
  color: var(--ink);
  box-shadow: none;
}

body.theme-warm .page--play .game-nudge__card .game-cta--ghost:active {
  background: rgba(34, 48, 31, 0.1);
}

body.theme-warm .page--play .game-nudge__row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  justify-content: center;
  margin-top: 4px;
}

@media (prefers-reduced-motion: reduce) {
  body.theme-warm .page--play .game-nudge { backdrop-filter: none; -webkit-backdrop-filter: none; }
}

/* ---- play page: the SILVER WIN TICKET ---------------------------------
   The client-approved win card (design draft 2, 2026-10-16): a real ticket
   cut. A quarter-circle bite out of all four corners, a dashed tear line
   with a round notch scooped out of the left and right edges exactly at the
   line, the code ABOVE the line and a usage stub below it. One ticket, two
   faces: a warm gold dessert face, and a plain silver discount face where
   the number is the prize. Built by renderReward() in core/shell.js.

   The cut is a CSS mask, so the outer shadow lives on the wrapper and uses
   filter drop-shadow: it follows the real cut silhouette, where a box
   shadow on the card would draw a plain clipped rectangle.
   ------------------------------------------------------------------------ */
body.theme-warm .page--play .game-reward--ticket {
  width: min(320px, 100%);
  padding: 0;
  border: 0;
  border-radius: 0;
  background: transparent;
  box-shadow: none;
  color: var(--ink, #22301F);
}

body.theme-warm .page--play .game-reward__shell {
  perspective: 1100px;
  filter:
    drop-shadow(0 14px 26px rgba(34, 48, 31, 0.18))
    drop-shadow(0 2px 4px rgba(34, 48, 31, 0.10));
}

body.theme-warm .page--play .game-reward__shell[data-variant="dessert"] {
  filter:
    drop-shadow(0 14px 28px rgba(168, 137, 62, 0.30))
    drop-shadow(0 2px 4px rgba(34, 48, 31, 0.10));
}

body.theme-warm .page--play .game-reward__ticket {
  --gr-scoop: 19px;  /* the corner bites */
  --gr-bite: 12px;   /* the side notches at the tear line */
  --gr-stub: 84px;   /* bottom stub height, also where the tear line sits */
  --gr-pad: 20px;

  position: relative;
  width: 100%;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  isolation: isolate;
  background:
    linear-gradient(135deg,
      #FDFDFE 0%,
      #E4E8EC 16%,
      #C6CCD3 34%,
      #E9EDF1 50%,
      #AEB5BD 66%,
      #E4E8EC 84%,
      #C6CCD3 100%);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.95),
    inset 0 -1px 0 rgba(255, 255, 255, 0.4),
    inset 0 0 0 1px rgba(255, 255, 255, 0.22);
  transform-style: preserve-3d;
  transition: transform 0.5s cubic-bezier(0.2, 0.9, 0.25, 1.1), opacity 0.5s ease;
  opacity: 0;
  transform: translateY(20px) scale(0.96);

  /* the ticket cut: a bite out of every corner plus a notch out of the left
     and right edge exactly at the tear line */
  -webkit-mask-image:
    radial-gradient(circle var(--gr-scoop) at 0 0,   transparent calc(var(--gr-scoop) - 0.8px), #000 var(--gr-scoop)),
    radial-gradient(circle var(--gr-scoop) at 100% 0, transparent calc(var(--gr-scoop) - 0.8px), #000 var(--gr-scoop)),
    radial-gradient(circle var(--gr-scoop) at 0 100%, transparent calc(var(--gr-scoop) - 0.8px), #000 var(--gr-scoop)),
    radial-gradient(circle var(--gr-scoop) at 100% 100%, transparent calc(var(--gr-scoop) - 0.8px), #000 var(--gr-scoop)),
    radial-gradient(circle var(--gr-bite) at 0 calc(100% - var(--gr-stub)),   transparent calc(var(--gr-bite) - 0.8px), #000 var(--gr-bite)),
    radial-gradient(circle var(--gr-bite) at 100% calc(100% - var(--gr-stub)), transparent calc(var(--gr-bite) - 0.8px), #000 var(--gr-bite));
  mask-image:
    radial-gradient(circle var(--gr-scoop) at 0 0,   transparent calc(var(--gr-scoop) - 0.8px), #000 var(--gr-scoop)),
    radial-gradient(circle var(--gr-scoop) at 100% 0, transparent calc(var(--gr-scoop) - 0.8px), #000 var(--gr-scoop)),
    radial-gradient(circle var(--gr-scoop) at 0 100%, transparent calc(var(--gr-scoop) - 0.8px), #000 var(--gr-scoop)),
    radial-gradient(circle var(--gr-scoop) at 100% 100%, transparent calc(var(--gr-scoop) - 0.8px), #000 var(--gr-scoop)),
    radial-gradient(circle var(--gr-bite) at 0 calc(100% - var(--gr-stub)),   transparent calc(var(--gr-bite) - 0.8px), #000 var(--gr-bite)),
    radial-gradient(circle var(--gr-bite) at 100% calc(100% - var(--gr-stub)), transparent calc(var(--gr-bite) - 0.8px), #000 var(--gr-bite));
  -webkit-mask-composite: source-in;
  mask-composite: intersect;
}

body.theme-warm .page--play .game-reward__ticket.is-in {
  opacity: 1;
  transform: translateY(0) scale(1);
  animation: gameRewardFloat 9s ease-in-out 0.6s infinite alternate;
}

@keyframes gameRewardFloat {
  from { translate: 0 0; }
  to   { translate: 0 -9px; }
}

/* brushed metal hairlines */
body.theme-warm .page--play .game-reward__brushed {
  position: absolute;
  inset: 0;
  z-index: 1;
  background:
    repeating-linear-gradient(112deg,
      rgba(255, 255, 255, 0.08) 0 1px,
      transparent 1px 4px),
    repeating-linear-gradient(112deg,
      rgba(34, 48, 31, 0.035) 0 1px,
      transparent 1px 7px);
  mix-blend-mode: soft-light;
  pointer-events: none;
}

/* the light sweep */
body.theme-warm .page--play .game-reward__sheen {
  position: absolute;
  inset: -40% -60%;
  z-index: 2;
  background: linear-gradient(104deg,
    transparent 38%,
    rgba(255, 255, 255, 0.55) 47%,
    rgba(255, 255, 255, 0.85) 50%,
    rgba(255, 255, 255, 0.35) 54%,
    transparent 62%);
  transform: translateX(-70%) rotate(0.001deg);
  animation: gameRewardSheen 6.5s ease-in-out 1.1s infinite;
  pointer-events: none;
  mix-blend-mode: screen;
  opacity: 0.75;
}

@keyframes gameRewardSheen {
  0%   { transform: translateX(-70%); }
  42%  { transform: translateX(70%); }
  100% { transform: translateX(70%); }
}

body.theme-warm .page--play .game-reward__body {
  position: relative;
  z-index: 3;
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 16px;
  padding: 18px var(--gr-pad) 14px;
}

body.theme-warm .page--play .game-reward__top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}

body.theme-warm .page--play .game-reward__brand {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-size: 0.62rem;
  font-weight: 700;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: rgba(34, 48, 31, 0.72);
}

body.theme-warm .page--play .game-reward__brand svg {
  width: 17px;
  height: 17px;
  display: block;
}

body.theme-warm .page--play .game-reward__game {
  padding: 5px 10px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.52);
  border: 1px solid rgba(34, 48, 31, 0.10);
  font-size: 0.62rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--wave-green, #2E5B3E);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 60%;
}

body.theme-warm .page--play .game-reward__prizeblock { min-height: 104px; }

body.theme-warm .page--play .game-reward__kicker {
  margin: 0;
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--gold-deep, #A8893E);
}

body.theme-warm .page--play .game-reward__value {
  margin: 2px 0 0;
  font-family: var(--font-display, "Fraunces", Georgia, serif);
  font-weight: 600;
  font-size: clamp(2.15rem, 1.8rem + 1.6vw, 2.85rem);
  line-height: 0.98;
  letter-spacing: -0.035em;
  color: var(--ink, #22301F);
}

body.theme-warm .page--play .game-reward__value em {
  font-style: italic;
  font-weight: 500;
}

body.theme-warm .page--play .game-reward__value .pct {
  font-size: 0.52em;
  letter-spacing: -0.01em;
  vertical-align: 0.62em;
  margin-left: 0.06em;
}

body.theme-warm .page--play .game-reward__sub {
  margin: 7px 0 0;
  font-size: 0.86rem;
  color: rgba(34, 48, 31, 0.68);
  max-width: 30ch;
}

/* the code box: solid frosted panel, ABOVE the tear line. The only dashed
   element on the ticket is the tear line itself. */
body.theme-warm .page--play .game-reward__codewrap {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 10px 13px;
  border-radius: 14px;
  background: rgba(255, 255, 255, 0.56);
  border: 1px solid rgba(168, 137, 62, 0.38);
}

body.theme-warm .page--play .game-reward__codelabel {
  margin: 0;
  font-size: 0.58rem;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: rgba(34, 48, 31, 0.55);
}

body.theme-warm .page--play .game-reward__codevalue {
  margin: 1px 0 0;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 1.04rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  color: #2A2F36;
}

body.theme-warm .page--play .game-reward__seal {
  flex: none;
  width: 42px;
  height: 42px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  border: 1px solid rgba(168, 137, 62, 0.5);
  background:
    conic-gradient(from 210deg, rgba(255,255,255,0.85), rgba(168,137,62,0.22), rgba(255,255,255,0.9), rgba(168,137,62,0.18), rgba(255,255,255,0.85));
}

body.theme-warm .page--play .game-reward__seal svg {
  width: 20px;
  height: 20px;
  display: block;
}

/* the dashed tear line, centered on the side notches */
body.theme-warm .page--play .game-reward__perf {
  position: absolute;
  left: 0;
  right: 0;
  bottom: calc(var(--gr-stub) - 1px);
  height: 2px;
  z-index: 3;
  background: repeating-linear-gradient(90deg,
    rgba(34, 48, 31, 0.34) 0 12px,
    transparent 12px 21px);
  pointer-events: none;
}

/* the stub, below the tear line */
body.theme-warm .page--play .game-reward__stub {
  position: relative;
  z-index: 3;
  height: var(--gr-stub);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 10px var(--gr-pad);
}

body.theme-warm .page--play .game-reward__stublabel {
  margin: 0 0 3px;
  font-size: 0.56rem;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: rgba(34, 48, 31, 0.5);
}

body.theme-warm .page--play .game-reward__stubcopy {
  margin: 0;
  font-size: 0.68rem;
  line-height: 1.35;
  color: rgba(34, 48, 31, 0.72);
  max-width: 22ch;
}

body.theme-warm .page--play .game-reward__stubaside { text-align: right; }

body.theme-warm .page--play .game-reward__stubvalid {
  margin: 0;
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.03em;
  color: rgba(34, 48, 31, 0.85);
  white-space: nowrap;
}

body.theme-warm .page--play .game-reward__stubfine {
  margin: 1px 0 0;
  font-size: 0.58rem;
  letter-spacing: 0.06em;
  color: rgba(34, 48, 31, 0.5);
  white-space: nowrap;
}

/* dessert face: the warm gold glow, the discount face stays plain silver */
body.theme-warm .page--play .game-reward__ticket[data-variant="dessert"] {
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.95),
    inset 0 -1px 0 rgba(255, 255, 255, 0.4),
    inset 0 0 0 1px rgba(168, 137, 62, 0.30);
}

@media (max-width: 420px) {
  body.theme-warm .page--play .game-reward__ticket {
    --gr-scoop: 17px;
    --gr-bite: 11px;
    --gr-stub: 78px;
    --gr-pad: 16px;
  }
}

@media (prefers-reduced-motion: reduce) {
  body.theme-warm .page--play .game-reward__ticket,
  body.theme-warm .page--play .game-reward__ticket.is-in {
    animation: none;
    transition: opacity 0.2s ease;
    transform: none;
  }
  body.theme-warm .page--play .game-reward__sheen {
    animation: none;
    opacity: 0.4;
  }
}

/* ================================================================
   DEDICATED GUEST PROFILE PAGE (/q/<key>/profile/)
   iOS 26 liquid-glass pass, instant name editing, and once-per-month
   mobile number change guard.
   ================================================================ */

body.theme-warm .page--profile .device-screen {
  display: flex;
  flex-direction: column;
  gap: 14px;
  padding-bottom: 28px;
}

/* The desktop phone frame (.device-screen) is a fixed-height flex column.
   Without flex-shrink: 0 and min-height: min-content, any child with
   overflow: hidden (.profile-pass) has an automatic minimum height of 0
   and gets crushed vertically into a thin strip when the page scrolls. */
body.theme-warm .page--profile .device-screen > * {
  flex-shrink: 0;
}

/* ---- Hero identity card ---- */
body.theme-warm .page--profile .profile-pass {
  position: relative;
  overflow: hidden;
  flex-shrink: 0;
  min-height: min-content;
  height: auto;
  border-radius: 26px;
  padding: 18px 18px 16px;
  background:
    radial-gradient(125% 95% at 12% 0%, rgba(246, 216, 121, 0.24), rgba(246, 216, 121, 0) 56%),
    linear-gradient(155deg, rgba(28, 56, 38, 0.94) 0%, rgba(20, 40, 27, 0.90) 100%);
  -webkit-backdrop-filter: blur(22px) saturate(180%);
  backdrop-filter: blur(22px) saturate(180%);
  border: 1px solid rgba(255, 255, 255, 0.24);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.34),
    inset 0 -1px 0 rgba(255, 255, 255, 0.08),
    0 22px 46px -22px rgba(16, 34, 22, 0.62);
  color: #F7F2E6;
}

body.theme-warm .page--profile .profile-pass__glow {
  position: absolute;
  top: -40px;
  right: -30px;
  width: 140px;
  height: 140px;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(246, 216, 121, 0.28) 0%, rgba(246, 216, 121, 0) 70%);
  pointer-events: none;
}

body.theme-warm .page--profile .profile-pass__top {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: center;
  gap: 14px;
}

body.theme-warm .page--profile .profile-pass__avatar {
  flex: none;
  width: 56px;
  height: 56px;
  border-radius: 19px;
  display: grid;
  place-items: center;
  background:
    radial-gradient(100% 90% at 25% 15%, rgba(255, 255, 255, 0.35), rgba(255, 255, 255, 0) 60%),
    linear-gradient(155deg, rgba(246, 216, 121, 0.24), rgba(168, 137, 62, 0.14));
  border: 1px solid rgba(246, 216, 121, 0.48);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.42),
    0 10px 22px -12px rgba(0, 0, 0, 0.45);
  color: #F6D879;
}

body.theme-warm .page--profile .profile-pass__avatar .icon {
  width: 28px;
  height: 28px;
}

body.theme-warm .page--profile .profile-pass__identity {
  min-width: 0;
  flex: 1;
}

body.theme-warm .page--profile .profile-pass__eyebrow {
  display: block;
  font-size: 0.62rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: #F6D879;
}

body.theme-warm .page--profile .profile-pass__name {
  margin: 3px 0 0;
  font-family: var(--font-display, "Fraunces", Georgia, serif);
  font-size: 1.48rem;
  font-weight: 600;
  line-height: 1.15;
  letter-spacing: -0.02em;
  color: #FFFFFF;
  overflow-wrap: anywhere;
  word-break: break-word;
}

body.theme-warm .page--profile .profile-pass__phone {
  margin: 4px 0 0;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 0.88rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  color: rgba(247, 242, 230, 0.84);
  font-variant-numeric: tabular-nums;
}

body.theme-warm .page--profile .profile-pass__pills {
  position: relative;
  z-index: 1;
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 14px;
  padding-top: 12px;
  border-top: 1px solid rgba(255, 255, 255, 0.14);
}

body.theme-warm .page--profile .profile-pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 10px;
  border-radius: 999px;
  font-size: 0.64rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  background: rgba(255, 255, 255, 0.12);
  border: 1px solid rgba(255, 255, 255, 0.22);
  color: rgba(247, 242, 230, 0.94);
}

body.theme-warm .page--profile .profile-pill__dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: #5cd67d;
  box-shadow: 0 0 8px rgba(92, 214, 125, 0.85);
}

body.theme-warm .page--profile .profile-pill--gold {
  background: rgba(246, 216, 121, 0.18);
  border-color: rgba(246, 216, 121, 0.42);
  color: #F6D879;
}

body.theme-warm .page--profile .profile-pill--locked {
  background: rgba(255, 255, 255, 0.10);
  border-color: rgba(255, 255, 255, 0.20);
  color: rgba(247, 242, 230, 0.78);
}

/* ---- Status / error banners ---- */
body.theme-warm .page--profile .profile-banner {
  flex-shrink: 0;
  min-height: min-content;
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 13px 15px;
  border-radius: 20px;
  -webkit-backdrop-filter: blur(18px) saturate(170%);
  backdrop-filter: blur(18px) saturate(170%);
  font-size: 0.8rem;
  line-height: 1.45;
}

body.theme-warm .page--profile .profile-banner strong {
  display: block;
  font-size: 0.84rem;
  margin-bottom: 2px;
}

body.theme-warm .page--profile .profile-banner p {
  margin: 0;
}

body.theme-warm .page--profile .profile-banner--ok {
  background: linear-gradient(165deg, rgba(235, 250, 239, 0.90), rgba(220, 244, 227, 0.78));
  border: 1px solid rgba(53, 104, 74, 0.32);
  color: #1d462c;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.85);
}

body.theme-warm .page--profile .profile-banner__dot {
  flex: none;
  width: 8px;
  height: 8px;
  margin-top: 5px;
  border-radius: 50%;
  background: #2e7d47;
  box-shadow: 0 0 0 3px rgba(46, 125, 71, 0.18);
}

body.theme-warm .page--profile .profile-banner--error {
  background: linear-gradient(165deg, rgba(253, 237, 234, 0.94), rgba(249, 222, 217, 0.84));
  border: 1px solid rgba(180, 65, 50, 0.36);
  color: #7a271c;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.85);
}

/* ---- Liquid-glass cards (edit details + reward wallet) ---- */
body.theme-warm .page--profile .profile-card {
  flex-shrink: 0;
  min-height: min-content;
  border-radius: 26px;
  padding: 18px 16px 18px;
  background:
    radial-gradient(120% 70% at 14% 0%, rgba(255, 255, 255, 0.62), rgba(255, 255, 255, 0) 58%),
    linear-gradient(165deg, rgba(255, 255, 255, 0.82), rgba(255, 255, 255, 0.58));
  -webkit-backdrop-filter: blur(22px) saturate(180%);
  backdrop-filter: blur(22px) saturate(180%);
  border: 1px solid rgba(255, 255, 255, 0.72);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.90),
    inset 0 -1px 0 rgba(34, 48, 31, 0.05),
    0 20px 44px -22px rgba(23, 58, 36, 0.38);
  color: var(--ink, #22301F);
}

body.theme-warm .page--profile .profile-card__head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 14px;
}

body.theme-warm .page--profile .profile-card__kicker {
  display: block;
  font-size: 0.62rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--gold-deep, #A8893E);
}

body.theme-warm .page--profile .profile-card__title {
  margin: 2px 0 0;
  font-family: var(--font-display, "Fraunces", Georgia, serif);
  font-size: 1.18rem;
  font-weight: 600;
  line-height: 1.15;
  letter-spacing: -0.015em;
  color: var(--ink, #22301F);
}

body.theme-warm .page--profile .profile-card__badge,
body.theme-warm .page--profile .profile-card__count {
  flex: none;
  padding: 4px 10px;
  border-radius: 999px;
  background: rgba(46, 91, 62, 0.10);
  border: 1px solid rgba(46, 91, 62, 0.18);
  font-size: 0.62rem;
  font-weight: 700;
  letter-spacing: 0.10em;
  text-transform: uppercase;
  color: var(--wave-green, #2E5B3E);
}

/* ---- Edit form & fields ---- */
body.theme-warm .page--profile .profile-form {
  display: grid;
  gap: 13px;
}

body.theme-warm .page--profile .profile-form__grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
}

@media (max-width: 350px) {
  body.theme-warm .page--profile .profile-form__grid {
    grid-template-columns: 1fr;
  }
}

body.theme-warm .page--profile .profile-field {
  display: grid;
  gap: 6px;
  min-width: 0;
}

body.theme-warm .page--profile .profile-field__row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}

body.theme-warm .page--profile .profile-field__label {
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: rgba(34, 48, 31, 0.78);
}

body.theme-warm .page--profile .profile-field__tag {
  padding: 2px 8px;
  border-radius: 999px;
  font-size: 0.58rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

body.theme-warm .page--profile .profile-field__tag--open {
  background: rgba(168, 137, 62, 0.16);
  color: #7A5E17;
}

body.theme-warm .page--profile .profile-field__tag--locked {
  background: rgba(34, 48, 31, 0.09);
  color: rgba(34, 48, 31, 0.65);
}

body.theme-warm .page--profile .profile-field__input {
  width: 100%;
  min-width: 0;
  padding: 11px 13px;
  border-radius: 14px;
  border: 1px solid rgba(34, 48, 31, 0.16);
  background: rgba(255, 255, 255, 0.88);
  box-shadow: inset 0 1px 2px rgba(34, 48, 31, 0.05);
  color: var(--ink, #22301F);
  font-size: 0.94rem;
  font-weight: 600;
  transition: border-color 160ms ease, box-shadow 160ms ease, background 160ms ease;
}

body.theme-warm .page--profile .profile-field__input--mono {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  letter-spacing: 0.03em;
  font-variant-numeric: tabular-nums;
}

body.theme-warm .page--profile .profile-field__input:focus {
  outline: none;
  border-color: var(--wave-green, #2E5B3E);
  background: #FFFFFF;
  box-shadow: 0 0 0 3px rgba(46, 91, 62, 0.16);
}

body.theme-warm .page--profile .profile-field--locked .profile-field__input {
  background: rgba(34, 48, 31, 0.05);
  border-style: dashed;
  border-color: rgba(34, 48, 31, 0.20);
  color: rgba(34, 48, 31, 0.62);
  cursor: not-allowed;
}

body.theme-warm .page--profile .profile-field__note {
  margin: 2px 0 0;
  font-size: 0.74rem;
  line-height: 1.45;
  color: var(--link-sub, #6F7D6A);
}

body.theme-warm .page--profile .profile-field__note--locked {
  padding: 8px 11px;
  border-radius: 12px;
  background: rgba(168, 137, 62, 0.11);
  border: 1px solid rgba(168, 137, 62, 0.25);
  color: #5e4710;
}

/* ---- Primary save button (forest liquid-glass capsule + gold orb) ---- */
body.theme-warm .page--profile .profile-submit {
  display: inline-flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  margin-top: 2px;
  padding: 9px 10px 9px 18px;
  border-radius: 999px;
  border: 1px solid rgba(255, 255, 255, 0.28);
  background:
    radial-gradient(100% 90% at 20% 0%, rgba(255, 255, 255, 0.22), rgba(255, 255, 255, 0) 60%),
    linear-gradient(180deg, #35684a 0%, #21422d 100%);
  color: #FFFFFF;
  font-size: 0.9rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.35),
    0 12px 24px -12px rgba(22, 43, 29, 0.55);
  cursor: pointer;
  transition: transform 140ms cubic-bezier(0.16, 1, 0.3, 1);
}

body.theme-warm .page--profile .profile-submit:active {
  transform: scale(0.98);
}

body.theme-warm .page--profile .profile-submit__orb {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background: linear-gradient(180deg, #F6D879 0%, #D9A83C 100%);
  color: #231802;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.7);
}

body.theme-warm .page--profile .profile-submit__orb .icon {
  width: 17px;
  height: 17px;
}

body.theme-warm .page--profile .profile-wallet-list {
  margin-top: 4px;
}

/* ---- Sign out: a quiet row at the bottom of the page ---- */
body.theme-warm .page--profile .profile-signout {
  flex-shrink: 0;
  margin-top: 2px;
  padding: 16px;
  border-radius: 24px;
  background: rgba(255, 255, 255, 0.4);
  border: 1px solid rgba(255, 255, 255, 0.6);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.7);
}

body.theme-warm .page--profile .profile-signout__title {
  margin: 0;
  font-size: 0.92rem;
  font-weight: 700;
  letter-spacing: 0.01em;
  color: var(--ink, #22301F);
}

body.theme-warm .page--profile .profile-signout__note {
  margin: 5px 0 0;
  font-size: 0.79rem;
  line-height: 1.5;
  color: var(--link-sub, #6F7D6A);
}

body.theme-warm .page--profile .profile-signout__form {
  margin: 12px 0 0;
}

body.theme-warm .page--profile .profile-signout__button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  width: 100%;
  padding: 11px 16px;
  border-radius: 999px;
  border: 1px solid rgba(34, 48, 31, 0.16);
  background: rgba(255, 255, 255, 0.55);
  color: var(--ink, #22301F);
  font: inherit;
  font-size: 0.87rem;
  font-weight: 700;
  letter-spacing: 0.01em;
  cursor: pointer;
  transition: transform 120ms cubic-bezier(0.16, 1, 0.3, 1),
    background 160ms ease;
}

body.theme-warm .page--profile .profile-signout__button:active {
  transform: scale(0.985);
  background: rgba(255, 255, 255, 0.75);
}

body.theme-warm .page--profile .profile-signout__button:focus-visible {
  outline: 2px solid var(--gold-deep, #A8893E);
  outline-offset: 2px;
}

body.theme-warm .page--profile .profile-signout__button svg {
  width: 17px;
  height: 17px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.7;
  stroke-linecap: round;
  stroke-linejoin: round;
  opacity: 0.7;
}

@media (prefers-reduced-transparency: reduce) {
  body.theme-warm .page--profile .profile-pass {
    background: #1c3826;
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }
  body.theme-warm .page--profile .profile-card {
    background: rgba(255, 255, 255, 0.96);
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  body.theme-warm .page--profile .profile-submit {
    transition: none;
  }
  body.theme-warm .page--profile .profile-submit:active {
    transform: none;
  }
  body.theme-warm .page--profile .profile-signout__button {
    transition: none;
  }
  body.theme-warm .page--profile .profile-signout__button:active {
    transform: none;
  }
}

