/* ============================================================
   ROSSI. A 360 Experience - O2 City Hall Newcastle, Fri 29 Jan 2027
   Louder Entertainment. Built 2026-10-16 from the isos.london engine.

   Concept: the poster, rebuilt live. Rossi and his light-trail orbits
   own the left (the client's own plate, cropped around him), the
   ROSSI. lockup sits over his head exactly as printed, date and venue
   on his sweater, Louder's marks in the corners. The sign-up is a slab
   of the lockup's own material - the grainy grey-white of the
   letters - laid on the plate's red-orange field at the right.

   The one moving thing: the 360 badge, split out of the lockup,
   turns a full 360 on load and again at every step of the sign-up.

   Palette sampled from literal pixels of the layers:
     --plate  #C8030C  left edge of desktop_background (200,3,12)
     --ember  #C93D13  right edge of the plate (201,61,19)
     --glow   #FA933B  the spotlight behind his head (250,147,59)
     --paper  #E3E0E0  the lockup ink (216,213,214), lifted a step for reading
     --ink    #1C1617  under the sweater (61,55,57), deepened for type
   Contrast on --paper: ink 13.6:1, body 7.4:1, title red 4.6:1 (large
   type only). CTA --cta with --paper-hi text 6.2: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;
}

:root {
  --plate:    #C8030C;
  --ember:    #C93D13;
  --glow:     #FA933B;
  --paper:    #E3E0E0;
  --paper-hi: #F6F3F3;
  --ink:      #1C1617;
  --body:     #4A4244;
  --cta:      #B8020B;
  --field:    #F7F5F5;               /* OPAQUE on purpose, see the autofill rule */
  --line:     rgba(28,22,23,.26);
  --danger:   #A3000A;
  --on-red:   #FFF4EE;               /* footer text on the plate, 5.6:1 */
  --font: "Archivo", "Helvetica Neue", Helvetica, Arial, sans-serif;
  --panel-w: 440px;
  /* print grain, the same speckle the poster carries */
  --grain: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 .55 0'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23n)'/%3E%3C/svg%3E");
  /* panel: a lighter speckle, so the slab still reads as the lockup's grey-white */
  --grain-soft: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 .16 0'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23n)'/%3E%3C/svg%3E");
}

*, *::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 anything positioned behind it. The field is the plate's own red
   running into its right-hand ember, with the print grain over it. */
html {
  background:
    var(--grain),
    radial-gradient(120% 70% at 70% 0%, rgba(250,147,59,.38), rgba(250,147,59,0) 60%),
    linear-gradient(170deg, #D2200F 0%, var(--ember) 45%, #A52A09 100%);
  background-color: var(--plate);
  background-attachment: fixed;
  background-blend-mode: soft-light, normal, normal;
  -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; }

/* ============================================================
   ART - phones / portrait first. A fixed-ratio box carries the
   phone plate (top crop: glow, then his head at ~29%); the lockup,
   date and marks are placed in % / cqw of it so they hold their
   places on the photograph at every width.
   ============================================================ */
.page { position: relative; display: flex; flex-direction: column; min-height: 100svh; }

.art {
  position: relative;
  width: 100%;
  aspect-ratio: 1080 / 1500;
  container-type: inline-size;
  overflow: hidden;
  isolation: isolate;
}
.art__plate,
.art__plate img {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  max-width: none;
  object-fit: cover;
  object-position: 50% 0%;
  z-index: -1;
}
/* foot of the photo melts into the field the panel sits on */
.art::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 22%;
  background: linear-gradient(to bottom, rgba(170,30,10,0), #B4250C);
  pointer-events: none;
  z-index: 0;
}

.art__presents {
  position: absolute;
  left: 50%;
  top: 4.2%;
  width: 30cqw;
  height: auto;
  transform: translateX(-50%);
}

/* lockup: ROSSI. + "A 360 EXPERIENCE", with the badge laid back over
   its own hole. Badge box measured off logo.png (1920x471):
   x 1358-1858, y 252-471. */
.lockup {
  position: absolute;
  left: 50%;
  top: 8.5%;
  width: 88cqw;
  margin: 0;
  transform: translateX(-50%);
  perspective: 700px;
  z-index: 1;
}
.lockup__main { display: block; width: 100%; height: auto; }
.lockup__badge {
  position: absolute;
  left: 70.7292%;
  top: 53.5032%;
  width: 26.0417%;
  height: auto;
  transform-origin: 50% 50%;
  backface-visibility: visible;
  animation: badgeIn 1.5s .45s cubic-bezier(.55,0,.2,1) both;
}
/* The one orchestrated moment: the 360 turns a full 360. */
@keyframes badgeIn {
  from { transform: rotateY(-360deg) scale(.86); }
  to   { transform: none; }
}
/* A step change in the form gives it another full turn (app.js adds
   .is-turning). `rotate` is its own property, so the kick stacks on
   the load animation without restarting it; 360 ends where it began. */
.is-turning .lockup__badge {
  animation: badgeIn 1.5s .45s cubic-bezier(.55,0,.2,1) both,
             badgeKick 1.2s cubic-bezier(.55,0,.2,1);
}
@keyframes badgeKick { from { rotate: y 0deg; } to { rotate: y 360deg; } }

.art__date {
  position: absolute;
  left: 50%;
  bottom: 21%;
  width: 62cqw;
  height: auto;
  transform: translateX(-50%);
  z-index: 1;
}
.art__rings,
.art__louder {
  position: absolute;
  bottom: 23%;
  height: auto;
  z-index: 1;
}
.art__rings  { left: 4cqw;  width: 7cqw; }
.art__louder { right: 4cqw; width: 11cqw; }

/* ============================================================
   SIGN-UP - a slab of the lockup's grey-white, grain and all,
   pulled up over the foot of the photo on phones.
   ============================================================ */
.signup {
  position: relative;
  z-index: 2;
  width: 100%;
  max-width: 480px;
  margin: -16vw auto 0;
  padding: 0 14px 28px;
  flex: 1 0 auto;
}
@media (min-width: 520px) { .signup { margin-top: -84px; } }

.panel {
  position: relative;
  padding: 26px 24px 26px;
  background: var(--grain-soft), var(--paper);
  background-blend-mode: multiply, normal;
  background-size: 180px 180px, auto;
  color: var(--body);
  border-radius: 6px;
  box-shadow: 0 1px 0 rgba(255,255,255,.5) inset, 0 34px 70px -34px rgba(70,0,0,.75);
}
.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). Current =
   plate red, done = ink, to come = faint ink. */
.spine {
  list-style: none;
  margin: 0 0 20px;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 8px;
}
.spine__step {
  display: flex;
  flex-direction: column;
  gap: 7px;
  font-size: 12.5px;
  font-weight: 500;
  color: rgba(28,22,23,.55);
}
.spine__step::before {
  content: "";
  display: block;
  height: 3px;
  border-radius: 3px;
  background: rgba(28,22,23,.14);
  transition: background-color .3s ease;
}
.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(--plate); }
.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(--ink); }

/* Titles in the lockup's voice: extended, heavy, capitals, tight. */
.panel__title {
  margin: 0 0 12px;
  font-family: var(--font);
  font-weight: 820;
  font-stretch: 125%;
  font-size: clamp(1.65rem, 7.6vw, 2.15rem);
  line-height: 1;
  letter-spacing: -.012em;
  text-transform: uppercase;
  color: var(--ink);
  text-wrap: balance;
}
/* House pattern: the second line carries the hook, in the plate's red. */
.panel__title em { font-style: normal; color: var(--plate); }
.panel__lede {
  margin: 0 0 18px;
  font-size: 15.5px;
  line-height: 1.55;
  color: var(--body);
  max-width: 40ch;
}
.panel__lede strong { color: var(--ink); font-weight: 650; }
.panel__success-note { margin: 0 0 10px; color: var(--ink); }

/* ============================================================
   FORM
   ============================================================ */
.form__row { margin: 0 0 11px; }
/* 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: 1.5px solid var(--line);
  border-radius: 999px;           /* the 360 badge's ellipse */
  transition: border-color .18s ease, box-shadow .18s ease;
}
.form__input::placeholder { color: #7A7173; }
.form__input:focus {
  outline: none;
  border-color: var(--plate);
  box-shadow: 0 0 0 3px rgba(200,3,12,.16);
}
.form__input--otp {
  font-weight: 650;
  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; font-weight: 500; 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: 15px 0 18px; }
.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(--plate);
  cursor: pointer;
}
.form__check a { color: var(--ink); text-decoration: underline; text-underline-offset: 2px; }
.form__check a:hover { color: var(--plate); }

.form__resend { margin: 14px 0 0; font-size: 14px; color: var(--body); text-align: center; }
.form__resend-btn {
  font: inherit;
  font-weight: 600;
  color: var(--cta);
  background: none;
  border: 0;
  padding: 0;
  text-decoration: underline;
  text-underline-offset: 2px;
  cursor: pointer;
}
.form__resend-btn:disabled { color: var(--body); 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: 700;
  font-size: 1.02rem;
  white-space: nowrap;
  text-align: center;
  text-decoration: none;
  border: 0;
  border-radius: 999px;
  cursor: pointer;
  transition: transform .12s ease, box-shadow .2s ease, background-color .18s ease, filter .18s ease;
}
.btn:active { transform: translateY(1px); }
.btn:disabled { opacity: .6; cursor: default; }
/* Plate red, extended capitals like the lockup; hover = the sweater ink. */
.btn--primary {
  font-stretch: 125%;
  font-weight: 800;
  font-size: clamp(.92rem, 4vw, 1.02rem);
  letter-spacing: .02em;
  text-transform: uppercase;
  color: var(--paper-hi);
  background: var(--cta);
}
.btn--primary:hover:not(:disabled),
.btn--primary:focus-visible {
  background: var(--ink);
  box-shadow: 0 12px 30px -12px rgba(70,0,0,.7);
}
/* 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: 650; }

/* ============================================================
   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: var(--field);
  border: 1px solid var(--line);
  border-radius: 14px;
  box-shadow: 0 26px 56px -18px rgba(60,0,0,.55);
  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: #EEEBEB;
  border: 0;
  border-bottom: 1px solid var(--line);
}
.iti__search-input::placeholder { color: #7A7173; }
.iti__search-input:focus { outline: none; background: #E6E2E2; }
.iti__search-icon svg, .iti__search-clear svg { color: var(--body); stroke: currentColor; }
.iti__country-list { background: var(--field); 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(200,3,12,.08); }
.iti__dial-code { color: #6A6163; }
.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(28,22,23,.05); }
.iti__selected-dial-code { color: var(--ink); font-family: var(--font); font-size: 16px; }
.iti__arrow { border-top-color: var(--body); }
.iti__arrow--up { border-bottom-color: var(--body); }

/* ============================================================
   FOOTER - house pattern, credit in a pill, straight on the field.
   ============================================================ */
.foot {
  position: relative;
  z-index: 2;
  padding: 6px 22px 26px;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  gap: 12px 18px;
  flex-wrap: wrap;
  max-width: 480px;
  width: 100%;
  margin: 0 auto;
}
.foot__left { display: flex; align-items: center; justify-content: center; gap: 16px; flex-wrap: wrap; }
.foot__legal { margin: 0; font-size: 13px; color: var(--on-red); }
.foot__legal a { color: var(--on-red); text-decoration: none; }
.foot__legal a:hover { text-decoration: underline; text-underline-offset: 2px; }
.foot__links { display: flex; flex-wrap: wrap; justify-content: center; 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(--on-red);
  text-decoration: none;
  border: 1px solid rgba(255,244,238,.42);
  border-radius: 999px;
  transition: border-color .18s ease, background-color .18s ease;
}
.site-built a:hover { border-color: var(--on-red); background: rgba(28,22,23,.18); }
.site-built img { display: block; opacity: .95; }

/* 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; }
}

/* ============================================================
   TWO COLUMN - artwork left, sign-up right. Aspect-ratio threshold,
   not width alone, so squarish windows never fall into a gap between
   the two treatments. The art column is a full-height crop of the
   desktop plate centred on Rossi; its right edge melts into the field.
   ============================================================ */
@media (min-width: 900px) and (min-aspect-ratio: 5/4) {
  .page {
    display: grid;
    grid-template-columns: minmax(0, 1fr) calc(var(--panel-w) + 88px);
    grid-template-rows: 1fr auto;
    min-height: 100svh;
  }
  .art {
    position: sticky;
    top: 0;
    grid-row: 1 / span 2;
    height: 100vh;
    height: 100svh;
    aspect-ratio: auto;
    container-type: size;
    -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 13cqw), transparent);
            mask-image: linear-gradient(to right, #000 calc(100% - 13cqw), transparent);
  }
  .art::after { display: none; }
  .art__plate img { object-position: 50% 30%; }
  .art__presents { top: 4cqh; width: min(20cqw, 32cqh); }
  .lockup { top: 8.5cqh; width: min(80cqw, 118cqh); }
  .art__date { bottom: 6cqh; width: min(44cqw, 64cqh); }
  .art__rings,
  .art__louder { bottom: 4.5cqh; }
  .art__rings  { left: 3cqw; width: min(4.6cqw, 7cqh); }
  .art__louder { right: 14cqw; width: min(7cqw, 10.5cqh); }
  .signup {
    grid-column: 2;
    grid-row: 1;
    align-self: center;
    max-width: none;
    margin: 0;
    padding: 44px 48px 20px 40px;
  }
  .panel { padding: 30px 30px 28px; }
  .foot {
    grid-column: 2;
    grid-row: 2;
    max-width: none;
    padding: 6px 48px 22px 40px;
    flex-direction: column;
  }
  .panel__title { font-size: clamp(1.9rem, 2.4vw, 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: 470px; }
}

/* --- landscape phones are a first-class layout ---
   844x390, 932x430, 667x375: wide but almost no height. Compact
   side-by-side, art 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: 340px; }
  .page {
    display: grid;
    grid-template-columns: minmax(0, 1fr) calc(var(--panel-w) + 28px);
    grid-template-rows: 1fr auto;
    min-height: 0;
  }
  .art {
    position: sticky;
    top: 0;
    grid-row: 1 / span 2;
    height: 100vh;
    height: 100svh;
    aspect-ratio: auto;
    container-type: size;
    -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 10cqw), transparent);
            mask-image: linear-gradient(to right, #000 calc(100% - 10cqw), transparent);
  }
  .art::after { display: none; }
  .art__plate img { object-position: 50% 25%; }
  .art__presents { top: 4cqh; width: min(22cqw, 30cqh); }
  .lockup { top: 10cqh; width: min(84cqw, 150cqh); }
  .art__date { bottom: 6cqh; width: min(46cqw, 70cqh); }
  .art__rings, .art__louder { bottom: 5cqh; }
  .art__rings  { left: 3cqw; width: min(5cqw, 9cqh); }
  .art__louder { right: 11cqw; width: min(8cqw, 13cqh); }
  .signup {
    grid-column: 2;
    grid-row: 1;
    max-width: none;
    margin: 0;
    padding: 12px 14px 8px 14px;
  }
  .panel { padding: 18px 18px 18px; }
  .foot { grid-column: 2; grid-row: 2; max-width: none; padding: 4px 14px 14px; flex-direction: column; gap: 8px; }
  .foot__left { flex-direction: row; }
  .spine { margin-bottom: 12px; }
  .panel__title { font-size: 1.4rem; margin-bottom: 8px; }
  .panel__lede { font-size: 14px; margin-bottom: 12px; }
  .form__input { padding: 11px 18px; }
  .btn { padding: 13px 18px; }
  .form__row--check { margin: 10px 0 14px; }
  .form__check { font-size: 12.5px; }
}

/* small phones */
@media (max-width: 360px) {
  .signup { padding: 0 10px 24px; }
  .panel { padding: 22px 18px; }
}

/* ============================================================
   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(--ink); outline-offset: 3px; }
.foot :focus-visible { outline-color: var(--on-red); }
.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;
  }
  .lockup__badge { animation: none !important; }
}
