/* ============================================================
   In Search Of Sunrise London - Outernet Live, Sat 30 Jan 2027
   Louder Entertainment. Built 2026-10-14 from the Korolova engine.

   Concept: the photograph IS the page. No poster in a frame: the
   client's layered artwork is rebuilt live on its own plate. The
   violet sun (Logo.png split at r=352 into sun + halo) rises over
   Westminster on load, the rose halo keeps turning slowly, the line-up
   and date sit on the river below the bridge, and the sign-up reads
   straight off the dusk at the right edge, on a scrim, not a card.

   Palette sampled from literal pixels of the layers:
     --night  #06040A  river at the foot of both plates (6,4,10)
     --dusk   #0D1A47  upper sky
     --violet #8245D6  the sun disk (130,69,214)
     --rose   #F9BFBD  halo rings (249,191,189)
     --ember  #F8903D  date line (248,144,61)
   Contrast on --night: rose 12.9:1, ember 8.0:1, white 19.6:1.
   CTA = ember with night ink, 8.0:1. Never white on ember (2.4:1).
   ============================================================ */

@font-face {
  font-family: "Archivo";
  src: url("/assets/fonts/Archivo-var.woff2?v=20261014-1") format("woff2");
  font-weight: 100 900;
  font-stretch: 62% 125%;
  font-display: swap;
}
/* Titles match the artwork's line-up/date lettering and the approved emails
   (Adam, 14 Oct): Helvetica capitals, medium weight, wide tracking, white
   over the date's ember. Nimbus Sans is URW's Helvetica (urw-base35, with
   its font-embedding exception), subset to Basic Latin. Medium = Regular
   plus a light stroke, the same method as the email headline images. */
@font-face {
  font-family: "Nimbus Sans";
  src: url("/assets/fonts/NimbusSans-Regular.woff2?v=20261014-1") format("woff2");
  font-weight: 400;
  font-display: swap;
}

:root {
  --night:  #06040A;
  --dusk:   #0D1A47;
  --violet: #8245D6;
  --rose:   #F9BFBD;
  --ember:  #F8903D;
  --ink:    #FFFFFF;
  --body:   #DCD6E6;
  --dim:    #A79FB8;
  --field:  #15101F;               /* OPAQUE on purpose, see the autofill rule */
  --line:   rgba(249,191,189,.30);
  --danger: #FF9C8F;
  --font: "Archivo", "Helvetica Neue", Helvetica, Arial, sans-serif;
  --title: "Nimbus Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
  --panel-w: 440px;
}

*, *::before, *::after { box-sizing: border-box; }
/* `hidden` is only display:none in the UA sheet, the weakest rule there is;
   any display on a class would beat it and un-hide the element. */
[hidden] { display: none !important; }

/* Ground colour on html, NOT body: an opaque body background would paint
   over the fixed plate behind it. */
html {
  background: var(--night);
  -webkit-text-size-adjust: 100%;
}
body {
  margin: 0;
  min-height: 100vh;
  min-height: 100svh;
  font-family: var(--font);
  font-stretch: 100%;
  color: var(--body);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}
img { max-width: 100%; }
a { color: inherit; }

/* ============================================================
   SCENE - phones / portrait first. A fixed-ratio hero carries the
   mobile plate; the sun, line-up and date are positioned in % of it,
   so they keep their places on the sky and the river at every width.
   The plate's foot is already --night, so the sign-up flows on below
   with no seam and no box.
   ============================================================ */
.page { display: flex; flex-direction: column; min-height: 100svh; }

.scene {
  position: relative;
  width: 100%;
  /* Adam 14 Oct: form was too far down on phones. Tighter crop of the same
     plate (less sky over the sun, less river under the date), anchored at
     38% so the skyline sits at ~44-58% of the scene. */
  aspect-ratio: 1080 / 1400;
  container-type: inline-size;
  background: var(--night) url("/assets/images/bg-mobile-1080.jpg?v=20261014-1") center 38% / cover no-repeat;
  background-image: image-set(
    url("/assets/images/bg-mobile-720.webp?v=20261014-1") type("image/webp") 1x,
    url("/assets/images/bg-mobile-1080.webp?v=20261014-1") type("image/webp") 2x);
  overflow: hidden;
}
/* soft fade into the night ground the form sits on */
.scene::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 16%;
  background: linear-gradient(to bottom, rgba(6,4,10,0), var(--night));
  pointer-events: none;
}

.scene__h1 { margin: 0; }

.sun {
  position: absolute;
  left: 50%;
  top: 22%;
  width: 40cqw;
  aspect-ratio: 1;
  transform: translate(-50%, -50%);
}
.sun__halo,
.sun__disk {
  position: absolute;
  left: 50%; top: 50%;
  display: block;
  height: auto;
  max-width: none;
}
/* halo canvas 964 vs disk 704 -> 1.369x the sun */
.sun__halo {
  width: 136.9%;
  margin: -68.45% 0 0 -68.45%;
  animation: haloIn 2.2s .5s cubic-bezier(.2,.7,.1,1) both, haloTurn 60s 2.7s linear infinite;
}
/* A mirrored, fainter copy of the rings turning the other way, so the
   hand-drawn loops weave past each other like orbits (Adam 14 Oct: keep the
   circle moving). */
.sun__halo--echo {
  opacity: .5;
  animation: echoIn 2.2s .9s cubic-bezier(.2,.7,.1,1) both, echoTurn 90s 3.1s linear infinite;
}
@keyframes echoIn {
  from { opacity: 0; transform: scaleX(-1) rotate(30deg) scale(.92); }
  to   { opacity: .5; transform: scaleX(-1); }
}
@keyframes echoTurn { from { transform: scaleX(-1) rotate(0); } to { transform: scaleX(-1) rotate(360deg); } }
.sun__disk {
  width: 100%;
  margin: -50% 0 0 -50%;
  animation: sunrise 1.9s cubic-bezier(.16,.8,.12,1) both;
}
/* The one orchestrated moment: the sun comes up over the skyline. */
@keyframes sunrise {
  from { opacity: 0; transform: translateY(34%) scale(.94); }
  to   { opacity: 1; transform: none; }
}
@keyframes haloIn {
  from { opacity: 0; transform: rotate(-24deg) scale(.9); }
  to   { opacity: 1; transform: none; }
}
@keyframes haloTurn { to { transform: rotate(360deg); } }
/* A step change in the form gives the halo a quick extra turn, so the
   move from one state to the next reads as a response (app.js). */
/* `rotate` is its own property, so the kick stacks on the slow turn (a
   transform) without resetting it; a full turn ends where it started. */
.is-turning .sun__halo {
  animation: haloIn 2.2s .5s cubic-bezier(.2,.7,.1,1) both, haloTurn 60s 2.7s linear infinite,
             haloKick 1.2s cubic-bezier(.3,.6,.2,1);
}
.is-turning .sun__halo--echo {
  animation: echoIn 2.2s .9s cubic-bezier(.2,.7,.1,1) both, echoTurn 90s 3.1s linear infinite,
             haloKick 1.2s cubic-bezier(.3,.6,.2,1) reverse;
}
@keyframes haloKick { from { rotate: 0deg; } to { rotate: 360deg; } }

/* ---------- moving plate (river + bridge loop) ----------
   Phones: covers exactly the scene box (same ratio, same top crop as the
   scene's own background). Desktop: fixed full-window like .page::before.
   Invisible until app.js sees it playing, so the still plate shows first. */
.page { position: relative; }
.plate {
  position: absolute;
  top: 0; left: 0;
  z-index: 0;
  width: 100%;
  aspect-ratio: 1080 / 1400;        /* same box and crop as .scene on phones */
  object-fit: cover;
  object-position: center 38%;
  opacity: 0;
  transition: opacity 1.2s ease;
  pointer-events: none;
}
.plate.is-playing { opacity: 1; }

/* ---------- the sun's reflection on the river ----------
   A column of broken violet light under the sun, from the waterline down,
   shimmering. Two layers of streaks drift at different speeds; screen blend
   so it only ever adds light. Sits under the line-up. */
.glint {
  position: absolute;
  left: 50%;
  top: 61%;
  bottom: 2%;
  width: 40cqw;
  transform: translateX(-50%);
  pointer-events: none;
  mix-blend-mode: screen;
  -webkit-mask-image: linear-gradient(to bottom, #000 0%, rgba(0,0,0,.75) 45%, transparent 100%),
                      linear-gradient(to right, transparent 0%, #000 30%, #000 70%, transparent 100%);
  -webkit-mask-composite: source-in;
          mask-image: linear-gradient(to bottom, #000 0%, rgba(0,0,0,.75) 45%, transparent 100%),
                      linear-gradient(to right, transparent 0%, #000 30%, #000 70%, transparent 100%);
          mask-composite: intersect;
  opacity: 0;
  animation: glintIn 2.4s 1.5s ease both;
}
.glint i {
  position: absolute;
  inset: 0;
}
/* Adam 14 Oct: hard stripes read as a glitch behind the line-up. Now a soft
   column of violet light (the sun on the water), with a gently breathing
   shimmer: wide, heavily blurred bands only, no visible lines. */
.glint i:nth-child(1) {
  background: radial-gradient(50% 60% at 50% 20%, rgba(150,96,236,.55), rgba(130,69,214,0) 70%);
  filter: blur(6px);
  animation: glintBreathe 5s ease-in-out infinite alternate;
}
.glint i:nth-child(2) {
  background: repeating-linear-gradient(to bottom,
    rgba(160,110,240,0) 0 10px, rgba(170,124,246,.28) 16px, rgba(160,110,240,0) 22px 30px);
  filter: blur(5px);
  animation: glintDrift 7s linear infinite, glintSway 3.6s ease-in-out infinite alternate;
}
@keyframes glintIn  { to { opacity: .9; } }
@keyframes glintBreathe { from { opacity: .7; transform: scaleX(.9); } to { opacity: 1; transform: scaleX(1.05); } }
@keyframes glintDrift { to { background-position: 0 60px; } }
@keyframes glintSway {
  from { transform: scaleX(.85) translateX(-3%); }
  to   { transform: scaleX(1.05) translateX(3%); }
}


.bill {
  position: absolute;
  left: 50%;
  top: 63%;
  width: 64cqw;
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 3cqw;
  z-index: 1;
}
.bill__lineup { display: block; width: 100%; height: auto; }
.bill__date   { display: block; width: 98%; height: auto; }

/* ============================================================
   SIGN-UP - no card. Type and fields straight on the night river
   (phones) or on the dusk scrim at the right edge (desktop).
   ============================================================ */
.signup {
  position: relative;
  z-index: 2;
  width: 100%;
  max-width: 480px;
  margin: 28px auto 0;              /* clear space under the date lines (was overlapping, -6vw) */
  padding: 0 22px 36px;
  flex: 1 0 auto;
}
.panel { position: relative; }
.panel__state { display: none; }
.panel[data-form-state="idle"]    .panel__idle,
.panel[data-form-state="otp"]     .panel__otp,
.panel[data-form-state="success"] .panel__success {
  display: block;
  animation: stateIn .45s ease both;
}
@keyframes stateIn { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }

/* Step track: three real steps (form, SMS code, email link), drawn as
   three arcs of the halo. The current one is rose, done ones ember. */
.spine {
  list-style: none;
  margin: 0 0 22px;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 8px;
}
.spine__step {
  display: flex;
  flex-direction: column;
  gap: 8px;
  font-size: 12.5px;
  color: var(--dim);
}
.spine__step::before {
  content: "";
  display: block;
  height: 3px;
  border-radius: 3px;
  background: rgba(249,191,189,.18);
  transition: background-color .3s ease;
}
.spine__n { display: none; }
.panel[data-form-state="idle"]    .spine__step:nth-child(1),
.panel[data-form-state="otp"]     .spine__step:nth-child(2),
.panel[data-form-state="success"] .spine__step:nth-child(3) { color: var(--ink); }
.panel[data-form-state="idle"]    .spine__step:nth-child(1)::before,
.panel[data-form-state="otp"]     .spine__step:nth-child(2)::before,
.panel[data-form-state="success"] .spine__step:nth-child(3)::before { background: var(--rose); }
.panel[data-form-state="otp"]     .spine__step:nth-child(1)::before,
.panel[data-form-state="success"] .spine__step:nth-child(1)::before,
.panel[data-form-state="success"] .spine__step:nth-child(2)::before { background: var(--ember); }

.panel__title {
  margin: 0 0 14px;
  font-family: var(--title);
  font-weight: 400;
  font-size: clamp(1.7rem, 7.4vw, 2.2rem);
  line-height: 1.12;
  letter-spacing: .1em;
  text-transform: uppercase;
  -webkit-text-stroke: .022em currentColor;   /* Regular -> medium, as the poster */
  color: var(--ink);
}
/* House pattern: the second line carries the hook, in the date's ember. */
.panel__title em { font-style: normal; color: var(--ember); }
.panel__lede {
  margin: 0 0 18px;
  font-size: 16px;
  line-height: 1.55;
  color: var(--body);
  max-width: 38ch;
}
.panel__lede strong { color: var(--ink); font-weight: 600; }
.panel__success-note { margin: 0 0 10px; color: var(--ink); }

/* Sale dates: not on the artwork, so they earn a place here. */
.sale {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0;
  margin: 0 0 22px;
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
}
.sale__date { padding: 10px 0; }
.sale__date + .sale__date { padding-left: 16px; border-left: 1px solid var(--line); }
.sale dt { font-size: 13px; color: var(--dim); }
.sale dd { margin: 2px 0 0; font-stretch: 112%; font-weight: 600; font-size: 15.5px; color: var(--ember); }

/* ============================================================
   FORM
   ============================================================ */
.form__row { margin: 0 0 12px; }
/* labels stay for screen readers; placeholders carry the meaning visually */
.form__label {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}
.form__input {
  width: 100%;
  padding: 14px 20px;
  font-family: var(--font);
  font-size: 16px;                /* 16px minimum or iOS zooms on focus */
  color: var(--ink);
  background: var(--field);
  border: 1px solid var(--line);
  border-radius: 999px;           /* the sun's curve, not a card corner */
  transition: border-color .18s ease, box-shadow .18s ease;
}
.form__input::placeholder { color: #8E86A0; }
.form__input:focus {
  outline: none;
  border-color: var(--rose);
  box-shadow: 0 0 0 3px rgba(249,191,189,.20);
}
.form__input--otp {
  font-weight: 600;
  font-size: 22px;
  letter-spacing: .42em;
  text-align: center;
  text-indent: .42em;
}

/* Chrome paints autofilled inputs pale lavender and IGNORES background on
   :-webkit-autofill; a huge inset box-shadow is the only override, and it
   cannot be translucent. The field is opaque (--field) precisely so this
   value IS its rendered colour. Change --field and nothing else is needed. */
.form__input:-webkit-autofill,
.form__input:-webkit-autofill:hover,
.form__input:-webkit-autofill:focus,
.form__input:-webkit-autofill:active {
  -webkit-box-shadow: 0 0 0 1000px var(--field) inset !important;
          box-shadow: 0 0 0 1000px var(--field) inset !important;
  -webkit-text-fill-color: var(--ink) !important;
  caret-color: var(--ink);
  transition: background-color 9999s ease-in-out 0s;
}

.form__error { margin: 7px 0 0 20px; font-size: 14px; color: var(--danger); }
.form__error--global { margin: 14px 0 0; }

/* Honeypot. display:none ONLY - off-screen positioning stays an autofill
   target in Chrome/Edge, which fills it and silently blocks real signups.
   The markup carries the `hidden` attribute as a second guard. */
.hp-row { display: none !important; }

.form__row--check { margin: 16px 0 20px; }
.form__check {
  display: flex;
  align-items: flex-start;
  gap: 11px;
  font-size: 13.5px;
  line-height: 1.5;
  color: var(--body);
  cursor: pointer;
}
.form__check input {
  flex: 0 0 auto;
  width: 18px; height: 18px;
  margin: 1px 0 0;
  accent-color: var(--rose);
  cursor: pointer;
}
.form__check a { color: var(--ink); text-decoration: underline; text-underline-offset: 2px; }
.form__check a:hover { color: var(--rose); }

.form__resend { margin: 14px 0 0; font-size: 14px; color: var(--dim); text-align: center; }
.form__resend-btn {
  font: inherit;
  color: var(--rose);
  background: none;
  border: 0;
  padding: 0;
  text-decoration: underline;
  text-underline-offset: 2px;
  cursor: pointer;
}
.form__resend-btn:disabled { color: var(--dim); cursor: default; text-decoration: none; }

/* ---------- buttons ---------- */
.btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  width: 100%;
  padding: 16px 20px;
  font-family: var(--font);
  font-weight: 600;
  font-size: 1.04rem;
  white-space: nowrap;
  text-align: center;
  text-decoration: none;
  border: 0;
  border-radius: 999px;
  cursor: pointer;
  transition: transform .12s ease, box-shadow .2s ease, filter .18s ease;
}
.btn:active { transform: translateY(1px); }
.btn:disabled { opacity: .6; cursor: default; }
/* Ember, the date line's colour, with night ink (8.0:1). The extended
   cut echoes the line-up lettering. Hover = the sun's glow. */
.btn--primary {
  font-stretch: 125%;
  font-size: clamp(.95rem, 4vw, 1.05rem);
  letter-spacing: .02em;
  color: var(--night);
  background: var(--ember);
}
.btn--primary:hover:not(:disabled),
.btn--primary:focus-visible {
  box-shadow: 0 0 0 4px rgba(248,144,61,.22), 0 10px 40px -8px rgba(248,144,61,.65);
}
/* WhatsApp brand green; dark green type on it, as fleet-wide. */
.btn--whatsapp { color: #06301A; background: #25D366; margin-top: 4px; }
.btn--whatsapp:hover { filter: brightness(1.05); }
.btn__icon { flex: 0 0 auto; width: 20px; height: 20px; }

.wa-hook { margin: 4px 0 12px; font-size: 15px; color: var(--body); }
.wa-hook strong { color: var(--ink); font-weight: 600; }

/* ============================================================
   intl-tel-input v25
   ============================================================ */
.iti { width: 100%; display: block; }
/* app.js re-measures and sets padding-left inline; sane default first.
   Anything >= 80px breaks 320-390px viewports. */
.iti input.form__input { padding-left: calc(52px + 0.7rem); }
.iti__country-container { z-index: 3; }
.iti--inline-dropdown .iti__dropdown-content { z-index: 50; }
/* Until the vendor stylesheet loads the hidden state does not exist and the
   whole list plus search box flashes open on first paint. */
.iti__dropdown-content.iti__hide { display: none !important; }
.iti__dropdown-content {
  background: #17121F;
  border: 1px solid var(--line);
  border-radius: 14px;
  box-shadow: 0 26px 56px -18px rgba(0,0,0,.7);
  overflow: hidden;
}
.iti__search-input {
  /* Keep the vendor's horizontal reservation (icon left, clear right). */
  padding: 10px 30px 10px 32px;
  width: 100%;
  font-family: var(--font);
  font-size: 15px;
  color: var(--ink);
  background: #1E1829;
  border: 0;
  border-bottom: 1px solid var(--line);
}
.iti__search-input::placeholder { color: #8E86A0; }
.iti__search-input:focus { outline: none; background: #251E33; }
.iti__search-icon svg, .iti__search-clear svg { color: var(--dim); stroke: currentColor; }
.iti__country-list { background: #17121F; max-height: 240px; }
.iti__country { padding: 9px 12px; font-family: var(--font); font-size: 15px; color: var(--ink); }
.iti__country:hover,
.iti__country.iti__highlight { background: rgba(249,191,189,.12); }
.iti__dial-code { color: var(--dim); }
.iti__country-name { color: var(--ink); }
.iti__selected-country { border-radius: 999px 0 0 999px; padding-left: 8px; }
.iti__selected-country:hover,
.iti__selected-country-primary:hover { background: rgba(249,191,189,.08); }
.iti__selected-dial-code { color: var(--ink); font-family: var(--font); font-size: 16px; }
.iti__arrow { border-top-color: var(--dim); }
.iti__arrow--up { border-bottom-color: var(--dim); }

/* ============================================================
   FOOTER - house pattern, credit in a pill, no band: it sits on
   the same night/scrim as the form.
   ============================================================ */
.foot {
  position: relative;
  z-index: 2;
  padding: 18px 22px 26px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px 18px;
  flex-wrap: wrap;
  border-top: 1px solid rgba(249,191,189,.14);
}
.foot__left { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; }
.foot__legal { margin: 0; font-size: 13px; color: var(--dim); }
.foot__legal a { color: var(--dim); text-decoration: none; }
.foot__legal a:hover { color: var(--ink); text-decoration: underline; text-underline-offset: 2px; }
.foot__links { display: flex; flex-wrap: wrap; gap: 6px 18px; }
.site-built { margin: 0; }
.site-built a {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 5px 11px;
  font-size: 12.5px;
  color: var(--dim);
  text-decoration: none;
  border: 1px solid rgba(255,255,255,.22);
  border-radius: 999px;
  transition: border-color .18s ease, color .18s ease;
}
.site-built a:hover { color: var(--ink); border-color: var(--rose); }
.site-built img { display: block; opacity: .9; }

@media (max-width: 899px) {
  .foot { justify-content: center; text-align: center; max-width: 480px; margin: 0 auto; width: 100%; }
  .foot__left, .foot__links { justify-content: center; }
}
/* Phones: stack the footer rather than relying on the row wrapping. */
@media (max-width: 480px) {
  .foot { flex-direction: column; gap: 10px; }
  .foot__left { flex-direction: column; gap: 10px; }
}

/* Wide portrait (tablets): same scene at full width, form centred. */
@media (min-width: 600px) and (max-aspect-ratio: 5/4) {
  .signup { margin-top: 32px; }
}

/* ============================================================
   TWO COLUMN - the plate covers the whole window; the scene owns
   the left, the sign-up reads off a scrim on the right. Aspect-ratio
   threshold, not width alone, so squarish windows never fall into a
   gap between the two treatments.
   ============================================================ */
@media (min-width: 900px) and (min-aspect-ratio: 5/4) {
  .page {
    display: grid;
    grid-template-columns: minmax(0, 1fr) var(--panel-w);
    grid-template-rows: 1fr auto;
    min-height: 100svh;
  }
  /* Fixed plate behind everything. background-position 55% pins the river
     line (55% of the plate) to 55% of the window at every aspect. */
  .page::before {
    content: "";
    position: fixed;
    inset: 0;
    z-index: 0;
    background: var(--night) url("/assets/images/bg-desktop-1920.jpg?v=20261014-1") center 55% / cover no-repeat;
    background-image: image-set(
      url("/assets/images/bg-desktop-1600.webp?v=20261014-1") type("image/webp") 1x,
      url("/assets/images/bg-desktop-2560.webp?v=20261014-1") type("image/webp") 2x);
  }
  /* The scrim: dusk deepening into night toward the right edge. No edge,
     no border; the form sits in the darkest part of the sky. */
  /* Adam 14 Oct: the first scrim (.55-.88) left the form hard to read over
     the lit buildings. Now: a short fade, then near-solid night under the
     whole form column, with the photo behind it blurred so window lights
     cannot sparkle through the type. Still no edge and no box. */
  .page::after {
    content: "";
    position: fixed;
    top: 0; bottom: 0; right: 0;
    width: calc(var(--panel-w) + 14vw);
    z-index: 0;
    background: linear-gradient(to right,
      rgba(6,4,10,0) 0%, rgba(6,4,10,.70) calc(100% - var(--panel-w) - 40px),
      rgba(6,4,10,.92) calc(100% - var(--panel-w) + 24px), rgba(6,4,10,.94) 100%);
    -webkit-backdrop-filter: blur(6px);
            backdrop-filter: blur(6px);
    -webkit-mask-image: linear-gradient(to right, transparent 0, #000 calc(100% - var(--panel-w) - 40px));
            mask-image: linear-gradient(to right, transparent 0, #000 calc(100% - var(--panel-w) - 40px));
    pointer-events: none;
  }
  .scene {
    position: sticky;
    top: 0;
    z-index: 1;
    height: 100vh;
    height: 100svh;
    aspect-ratio: auto;
    background: none;
    container-type: size;
    grid-row: 1 / span 2;
  }
  .scene::after { display: none; }
  .plate {
    position: fixed;
    inset: 0;
    width: 100%;
    height: 100%;
    aspect-ratio: auto;
    object-position: center 55%;
  }
  .glint { top: 58%; width: min(28cqh, 40cqw); }
  .sun {
    top: 27%;
    width: min(36cqh, 52cqw);
  }
  .bill {
    top: 63%;
    width: min(42cqh, 48cqw);
    gap: 2.4cqh;
  }
  .signup {
    grid-column: 2;
    grid-row: 1;
    align-self: center;
    z-index: 1;
    max-width: none;
    margin: 0;
    padding: 48px 44px 28px 8px;
  }
  .foot {
    grid-column: 2;
    grid-row: 2;
    z-index: 1;
    padding: 16px 44px 22px 8px;
    border-top: 0;
    flex-direction: column;
    align-items: center;
    justify-content: flex-start;
    text-align: center;
  }
  .foot__left, .foot__links { justify-content: center; }
  .panel__title { font-size: clamp(1.9rem, 2.5vw, 2.3rem); }
}
/* very wide windows: give the form a little more air */
@media (min-width: 1600px) and (min-aspect-ratio: 5/4) {
  :root { --panel-w: 480px; }
}

/* --- landscape phones are a first-class layout ---
   844x390, 932x430, 667x375: wide but almost no height. Compact
   side-by-side, scene height-capped, form scrolls. AFTER the desktop
   blocks so it wins at equal specificity. */
@media (min-width: 640px) and (min-aspect-ratio: 7/10) and (max-height: 520px) {
  :root { --panel-w: 360px; }
  .page {
    display: grid;
    grid-template-columns: minmax(0, 1fr) var(--panel-w);
    grid-template-rows: 1fr auto;
    min-height: 0;
  }
  .page::before {
    content: "";
    position: fixed;
    inset: 0;
    z-index: 0;
    background: var(--night) url("/assets/images/bg-desktop-1920.jpg?v=20261014-1") center 55% / cover no-repeat;
    background-image: image-set(url("/assets/images/bg-desktop-1600.webp?v=20261014-1") type("image/webp"));
  }
  .page::after {
    content: "";
    position: fixed;
    top: 0; bottom: 0; right: 0;
    width: calc(var(--panel-w) + 12vw);
    z-index: 0;
    background: linear-gradient(to right, rgba(6,4,10,0), rgba(6,4,10,.93) calc(100% - var(--panel-w) + 10px), rgba(6,4,10,.95));
    -webkit-backdrop-filter: blur(6px);
            backdrop-filter: blur(6px);
    -webkit-mask-image: linear-gradient(to right, transparent 0, #000 calc(100% - var(--panel-w) - 20px));
            mask-image: linear-gradient(to right, transparent 0, #000 calc(100% - var(--panel-w) - 20px));
    pointer-events: none;
  }
  .scene {
    position: sticky;
    top: 0;
    z-index: 1;
    height: 100vh;
    height: 100svh;
    aspect-ratio: auto;
    background: none;
    container-type: size;
    grid-row: 1 / span 2;
  }
  .scene::after { display: none; }
  .plate {
    position: fixed;
    inset: 0;
    width: 100%;
    height: 100%;
    aspect-ratio: auto;
    object-position: center 55%;
  }
  .glint { top: 58%; width: min(22cqh, 26cqw); }
  .sun { top: 26%; width: min(38cqh, 44cqw); }
  .bill { top: 60%; width: min(46cqh, 52cqw); gap: 2.2cqh; }
  .signup {
    grid-column: 2;
    grid-row: 1;
    z-index: 1;
    max-width: none;
    margin: 0;
    padding: 18px 22px 12px 4px;
  }
  .foot { grid-column: 2; grid-row: 2; z-index: 1; padding: 10px 22px 16px 4px; border-top: 0; flex-direction: column; align-items: center; justify-content: flex-start; text-align: center; }
  .foot__links { justify-content: center; }
  .foot__left { flex-direction: row; }
  .spine { margin-bottom: 14px; }
  .panel__title { font-size: 1.45rem; margin-bottom: 8px; }
  .panel__lede { font-size: 14.5px; margin-bottom: 12px; }
  .sale { margin-bottom: 14px; }
  .sale__date { padding: 7px 0; }
  .form__input { padding: 11px 18px; }
  .btn { padding: 13px 18px; }
  .form__row--check { margin: 10px 0 14px; }
}

/* phones: get the form up the screen */
@media (max-width: 599px) {
  .spine { margin-bottom: 16px; }
  .panel__title { margin-bottom: 10px; }
  .panel__lede { margin-bottom: 16px; }
  /* sale dates drop below the button so the fields reach the first screen
     (visual order only: the dates are not interactive, tab order unchanged) */
  .panel[data-form-state="idle"] .panel__idle { display: flex; flex-direction: column; }
  .panel__idle .form { order: 2; }
  .panel__idle .sale { order: 3; margin: 22px 0 0; }
}

/* small phones */
@media (max-width: 360px) {
  .signup { padding: 0 16px 30px; }
  .sale dd { font-size: 14px; }
}

/* ============================================================
   UTILITIES / A11Y
   ============================================================ */
.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}
:focus-visible { outline: 2px solid var(--rose); outline-offset: 3px; }
.btn:focus-visible { outline-offset: 4px; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
  }
  .sun__halo { animation: none !important; }
  .sun__halo--echo { opacity: .5; transform: scaleX(-1); }
  .glint { opacity: .7; animation: none !important; }
  .glint i { animation: none !important; }
  .plate { display: none !important; }
}
