/* ==========================================================================
   Beyond Boundaries 2027 - first-access sign-up (/signup2027.html)

   STRUCTURE: a full-height split, not a card on a photograph. The photograph
   owns one half, a solid navy rail owns the other, with a hard mint seam
   between them. A floating panel always reads as incidental because nothing
   anchors it to the frame; a full-height column is structural, and it also
   removes the dead space a small box leaves around itself.

   PALETTE + TYPE are the festival's own, not invented here: the dusk system
   sampled from the client artwork in the 2026-09-03 rebrand, and the site's
   Space Grotesk 700 / Barlow pairing used on index, lineup and faqs.

   THE SCARF is a layer of its own at full opacity. It is never composited
   into a scrimmed plate and never given a CSS opacity - client instruction,
   restated 2026-09-05.

   Class names are the signup engine's and MUST NOT be renamed: app.js keys
   off `.panel`, `.form__error[data-error-for]`, `.btn__text`, `.hp-row` and
   the `data-form-state` machine.
   ========================================================================== */

:root {
  --navy-deep: #05134e;
  --navy-rail: #061a58;   /* the rail, a shade off the page base so the seam reads */
  --navy-lift: #306090;
  --mint:      #7fff98;
  --mint-deep: #5fe07a;
  --wheat:     #e8b33d;
  --cream:     #faf5ed;
  --muted:     rgba(250, 245, 237, 0.60);

  --display: 'Space Grotesk', 'Barlow', -apple-system, BlinkMacSystemFont, 'Helvetica Neue', Helvetica, Arial, sans-serif;
  --body:    'Barlow', -apple-system, BlinkMacSystemFont, 'Helvetica Neue', Helvetica, Arial, sans-serif;

  --field-bg:   rgba(250, 245, 237, 0.055);
  --field-edge: rgba(250, 245, 237, 0.20);
  /* The field stack flattened to one opaque value. Chrome's :-webkit-autofill
     ignores `background` outright, so this is what the inset shadow paints -
     the field's own rgba would sit visibly lighter than an empty field. */
  --field-flat: #131f57;

  --rail-w: 30rem;
}

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

html {
  /* Base colour lives here, never on body: an opaque body paints over the
     scene layers beneath it. */
  background: var(--navy-deep);
  -webkit-text-size-adjust: 100%;
}

body {
  font-family: var(--body);
  color: var(--cream);
  font-size: 16px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}

.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* Honeypot - display:none ONLY. Off-screen positioning gets autofilled by
   Chrome and Edge, which silently blocks real signups. */
.hp-row { display: none !important; }

/* ==========================================================================
   Split
   ========================================================================== */
.split {
  display: flex;
  flex-direction: column;
  min-height: 100svh;
}

/* --- The photographic half ---------------------------------------------- */
.scene {
  position: relative;
  isolation: isolate;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: clamp(2.4rem, 7vw, 4rem) clamp(1.2rem, 5vw, 3rem);
  min-height: 56svh;
  overflow: hidden;
}

.scene__bg {
  position: absolute;
  inset: 0;
  z-index: -2;
  background-image: url("/assets/signup/bg-mobile-sm.webp?v=20260905-11");
  background-size: cover;
  background-position: 50% 55%;
  background-color: var(--navy-deep);
}
@media (min-width: 501px) and (max-aspect-ratio: 7/10) {
  .scene__bg { background-image: url("/assets/signup/bg-mobile.webp?v=20260905-11"); }
}

/* The scarf. Sits behind the lockup, at full colour, bleeding past the top
   edge so it reads as a fragment of something larger rather than a sticker. */
.scene__scarf {
  position: absolute;
  z-index: -1;
  top: -14%;
  left: 50%;
  transform: translateX(-46%);
  width: min(78%, 24rem);
  height: auto;
  pointer-events: none;

  /* Suspended silk moves, so this is the one element where motion describes
     the subject instead of decorating the page. It pivots from the top edge,
     where the fabric leaves frame and would actually be held, rather than
     sliding as a whole.

     The animated properties are the INDEPENDENT `translate` and `rotate`, not
     `transform`: `transform` already carries this element's horizontal
     positioning, which differs at two breakpoints, and animating it would
     clobber that. The independent properties compose on top and leave it
     alone. Both are compositor-only, so this costs no layout or paint.

     prefers-reduced-motion is honoured by the global block at the end of this
     file, which sets animation: none on everything. */
  transform-origin: 30% 0%;
  --sway: 1.55;   /* stacked: smaller element, so it needs a bigger multiplier */
  animation: scarf-drift 19s ease-in-out infinite;
}

/* Five stops rather than a there-and-back, so the path is a lazy figure-eight
   instead of a metronome: fabric does not sway on a single axis. The slight
   scale reads as the silk moving toward and away from the viewer, which keeps
   it from looking like a flat sticker being slid around.

   Amplitude is multiplied by --sway so the smaller mobile scarf can be pushed
   harder: `translate` percentages resolve against the element's own size, so
   the same figures move a 304px-wide scarf about half as far as a 528px one. */
@keyframes scarf-drift {
  0%   { translate: 0 0;
         rotate: 0deg;                             scale: 1; }
  22%  { translate: calc(2.6% * var(--sway)) calc(-2.4% * var(--sway));
         rotate: calc(2.1deg * var(--sway));       scale: 1.018; }
  45%  { translate: calc(0.7% * var(--sway)) calc(-4.6% * var(--sway));
         rotate: calc(-1deg * var(--sway));        scale: 1.006; }
  68%  { translate: calc(-2.4% * var(--sway)) calc(-2.6% * var(--sway));
         rotate: calc(-2.3deg * var(--sway));      scale: 1.022; }
  86%  { translate: calc(-0.9% * var(--sway)) calc(-1% * var(--sway));
         rotate: calc(0.8deg * var(--sway));       scale: 1.009; }
  100% { translate: 0 0;
         rotate: 0deg;                             scale: 1; }
}

/* --- The lockup ---------------------------------------------------------- */
.lockup { position: relative; text-align: center; width: 100%; max-width: 34rem; }

.lockup__mark {
  display: block;
  width: min(100%, 24rem);
  height: auto;
  margin: 0 auto;
  /* The wordmark sits over the scarf; this keeps its edge crisp against the
     silk without dulling the silk itself. */
  filter: drop-shadow(0 3px 14px rgba(2, 8, 32, 0.55));
}

.lockup__say { margin-top: clamp(1.2rem, 4vw, 1.9rem); }

.lockup__thanks {
  font-family: var(--display);
  font-size: clamp(2rem, 8.4vw, 3.1rem);
  font-weight: 700;
  line-height: 0.94;
  letter-spacing: -0.018em;
  text-transform: uppercase;
  color: var(--cream);
  text-shadow: 0 2px 18px rgba(2, 8, 32, 0.6);
}

.lockup__rule {
  display: block;
  width: min(70%, 15rem);
  height: 1px;
  margin: clamp(0.9rem, 3vw, 1.3rem) auto;
  background: var(--wheat);
  opacity: 0.85;
}

.lockup__next {
  font-family: var(--display);
  font-size: clamp(0.95rem, 3.6vw, 1.25rem);
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--wheat);
  text-shadow: 0 2px 14px rgba(2, 8, 32, 0.6);
}

.lockup__place {
  margin-top: clamp(1.1rem, 3.6vw, 1.7rem);
  font-size: 0.76rem;
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--muted);
}

/* Replaces the whole lockup on success. app.js mirrors the panel state onto
   <body> so this reads across the split. */
.lockup__thankyou { display: none; width: min(100%, 30rem); height: auto; margin: 0 auto; }
body[data-form-state="success"] .lockup__mark,
body[data-form-state="success"] .lockup__say,
body[data-form-state="success"] .lockup__place { display: none; }
body[data-form-state="success"] .lockup__thankyou { display: block; }

/* --- The navy rail ------------------------------------------------------- */
.rail {
  position: relative;
  display: flex;
  flex-direction: column;
  background: var(--navy-rail);
  border-top: 2px solid var(--mint);   /* the seam */
}

.rail__inner {
  flex: 1 1 auto;
  display: flex;
  align-items: center;
  padding: clamp(1.9rem, 6vw, 3rem) clamp(1.3rem, 5vw, 3rem);
}

.panel { width: 100%; }

.panel__state { display: none; }
.panel[data-form-state="idle"]    .panel__idle    { display: block; }
.panel[data-form-state="otp"]     .panel__otp     { display: block; }
.panel[data-form-state="success"] .panel__success { display: block; }

.panel__eyebrow {
  display: flex;
  align-items: center;
  gap: 0.85rem;
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--wheat);
}
.panel__eyebrow-hair { flex: 1 1 auto; height: 1px; background: rgba(232, 179, 61, 0.35); }

.panel__title {
  font-family: var(--display);
  margin-top: 0.95rem;
  font-size: clamp(1.9rem, 5.4vw, 2.5rem);
  font-weight: 700;
  line-height: 0.94;
  letter-spacing: -0.018em;
  text-transform: uppercase;
  color: var(--cream);
}
.panel__title em { font-style: normal; color: var(--mint); }

/* Scoped so state-specific paragraph rules cannot out-specify the eyebrow. */
.panel__lede,
.panel__state p:not(.panel__eyebrow):not(.form__error):not(.form__resend) {
  margin-top: 1rem;
  font-size: 0.97rem;
  color: var(--muted);
}
.panel__lede strong { color: var(--cream); font-weight: 600; }

.panel__success-note {
  padding: 0.75rem 0.95rem;
  border-left: 2px solid var(--mint);
  background: rgba(127, 255, 152, 0.07);
  color: var(--cream) !important;
  font-size: 0.93rem !important;
}

/* --- Form ---------------------------------------------------------------- */
.form { margin-top: 1.7rem; }
.form__row { margin-bottom: 0.9rem; }

/* sr-only, never display:none - the placeholder carries the meaning visually,
   the label has to stay reachable by a screen reader. */
.form__label {
  position: absolute;
  width: 1px; height: 1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
}

.form__input {
  width: 100%;
  padding: 0.95rem 1rem;
  font-family: inherit;
  font-size: 1rem;
  color: var(--cream);
  background: var(--field-bg);
  border: 1px solid var(--field-edge);
  border-radius: 2px;
  transition: border-color 0.15s ease, background-color 0.15s ease;
}
.form__input::placeholder { color: rgba(250, 245, 237, 0.34); }
.form__input:focus {
  outline: none;
  border-color: var(--mint);
  background: rgba(250, 245, 237, 0.085);
  box-shadow: 0 0 0 3px rgba(127, 255, 152, 0.15);
}
.form__input--otp {
  text-align: center;
  font-size: 1.5rem;
  font-weight: 700;
  letter-spacing: 0.42em;
  text-indent: 0.42em;
}

/* Chrome paints autofilled fields pale lavender and ignores `background`; a
   large inset shadow is the only reliable override, and its colour must be
   the flattened opaque stack, not the field's own rgba. */
.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-flat) inset !important;
          box-shadow: 0 0 0 1000px var(--field-flat) inset !important;
  -webkit-text-fill-color: var(--cream) !important;
  caret-color: var(--cream);
  /* without this Chrome flashes the lavender in before the shadow paints */
  transition: background-color 9999s ease-in-out 0s;
}

.form__row--check { margin: 1.2rem 0 1.3rem; }
.form__check {
  display: flex;
  gap: 0.7rem;
  align-items: flex-start;
  font-size: 0.82rem;
  line-height: 1.55;
  color: var(--muted);
  cursor: pointer;
}
.form__check input[type="checkbox"] {
  flex: 0 0 auto;
  width: 1.05rem; height: 1.05rem;
  margin-top: 0.18rem;
  accent-color: var(--mint);
  cursor: pointer;
}
.form__check a { color: var(--cream); text-underline-offset: 2px; }
.form__check a:hover { color: var(--mint); }

.form__error {
  margin-top: 0.4rem;
  font-size: 0.8rem;
  color: #ff9d94;   /* the silk, lifted until it clears AA on the rail */
}
.form__error--global { margin-top: 0.8rem; }

.form__resend { margin-top: 1rem; font-size: 0.83rem; color: var(--muted); }
.form__resend-btn {
  font: inherit;
  color: var(--mint);
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 2px;
}
.form__resend-btn:disabled { color: var(--muted); cursor: default; }

/* --- Buttons ------------------------------------------------------------- */
.btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.6rem;
  width: 100%;
  padding: 1.05rem 1rem;
  font-family: var(--display);
  font-size: 0.9rem;
  font-weight: 700;
  letter-spacing: clamp(0.06em, 0.4vw, 0.12em);
  text-transform: uppercase;
  text-decoration: none;
  text-align: center;
  white-space: nowrap;
  border: 0;
  border-radius: 2px;
  cursor: pointer;
  transition: background-color 0.15s ease, color 0.15s ease, transform 0.12s ease;
}
.btn--primary { background: var(--mint); color: var(--navy-deep); }
.btn--primary:hover:not(:disabled) { background: var(--mint-deep); }
.btn--primary:active:not(:disabled) { transform: translateY(1px); }
.btn--primary:disabled { opacity: 0.6; cursor: default; }

.btn--whatsapp {
  margin-top: 1.25rem;
  background: transparent;
  color: var(--mint);
  border: 1px solid var(--mint);
}
.btn--whatsapp:hover { background: var(--mint); color: var(--navy-deep); }
.btn__icon { width: 1.05rem; height: 1.05rem; flex: 0 0 auto; }

/* --- intl-tel-input v25 -------------------------------------------------- */
.iti { width: 100%; }
/* Starting value only - repadPhone() re-measures the real trigger width.
   Keep this under ~63px or 320px-wide phones lose the first digits. */
.iti input.form__input { padding-left: calc(52px + 0.7rem); }
.iti__selected-country { background: transparent; color: var(--cream); }
.iti__selected-dial-code { color: var(--muted); font-size: 15px; }
.iti__arrow { border-top-color: var(--wheat); }
.iti__arrow--up { border-bottom-color: var(--wheat); }
.iti__dropdown-content {
  background: #08215c;
  border: 1px solid rgba(48, 96, 144, 0.6);
  border-radius: 2px;
  color: var(--cream);
}
.iti__search-input {
  /* Vertical padding only - a shorthand wipes the vendor's reserved horizontal
     space and the magnifier lands on top of the word "Search". */
  padding: 9px 30px 9px 32px;
  font-family: inherit;
  color: var(--cream);
  background: transparent;
  border: 0;
  border-bottom: 1px solid rgba(48, 96, 144, 0.6);
}
.iti__search-input::placeholder { color: rgba(250, 245, 237, 0.34); }
.iti__search-input:focus { outline: none; border-bottom-color: var(--mint); }
.iti__country-list { background: transparent; }
.iti__country { padding: 9px 13px; font-size: 14.5px; }
.iti__country.iti__highlight { background: rgba(127, 255, 152, 0.16); }
.iti__country:hover { background: rgba(127, 255, 152, 0.10); }
.iti__dial-code { color: var(--muted); }
.iti--inline-dropdown .iti__dropdown-content { z-index: 50; }
/* The hidden state lives in the vendor stylesheet; until that loads the whole
   country list flashes open on first paint. */
.iti__dropdown-content.iti__hide { display: none !important; }

.rail__mark {
  padding: 0 clamp(1.3rem, 5vw, 3rem) clamp(1.1rem, 3vw, 1.6rem);
  text-align: center;
}
.rail__mark img {
  display: block;
  margin: 0 auto;
  height: 26px;
  width: auto;
  opacity: 0.55;
  transition: opacity 0.15s ease;
}
.rail__mark a:hover img,
.rail__mark a:focus-visible img { opacity: 0.9; }

/* --- Footer, inside the rail so it always has a dark ground -------------- */
.foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.6rem 0.9rem;
  /* Narrower gutter than the rest of the rail: at 1440 the rail is 34rem, and
     the full 3rem inset leaves too little room for copyright, credit and
     privacy to sit on one line. */
  margin: 0 clamp(1.1rem, 3vw, 1.6rem);
  padding: clamp(1rem, 3vw, 1.3rem) 0 clamp(1.4rem, 4vw, 1.8rem);
  border-top: 1px solid rgba(48, 96, 144, 0.4);
  font-size: 0.7rem;
  color: var(--muted);
}
.foot__left { display: flex; align-items: center; gap: 0.7rem; flex-wrap: wrap; }
.foot__legal { margin: 0; }
.foot__legal a { color: var(--muted); text-underline-offset: 2px; }
.foot__legal a:hover { color: var(--mint); }


/* The pill, matching the rest of the site's footer treatment. The background
   sits on the <a>, not the <p>: the <p> is a flex item that needs to be able to
   take a full row without the pill stretching to fill it. */
.foot__pill { display: flex; margin: 0; }
.foot__pill a {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: rgba(255, 255, 255, 0.12);
  padding: 6px 11px;
  border-radius: 6px;
  font-size: 0.69rem;
  color: rgba(255, 255, 255, 0.85);
  text-decoration: none;
}
.foot__pill a:hover { background: rgba(255, 255, 255, 0.18); }
.foot__pill img { height: 14px; width: auto; display: block; }



/* ==========================================================================
   Stacked layout (phones, and narrow or portrait windows).

   The exact complement of the split block below, so there is no gap and no
   overlap between them. Everything above this point in the column is centred -
   the lockup, the headline, the place line - so a left-ragged footer under it
   reads as a mistake rather than a choice.
   ========================================================================== */
@media not all and (min-width: 860px) and (min-aspect-ratio: 7/10) {
  /* The scene hugs the lockup rather than centring it in a tall box. At 56svh
     a 390x844 phone left ~110px of empty photo between the venue line and the
     sign-up block; the privacy page already used 40svh, which is the value
     that reads correctly, so both pages now share it. */
  .scene { min-height: 40svh; }

  /* .split is min-height:100svh but neither child grows, so on a short page
     the rail stopped above the fold and the html background showed beneath it
     as a mismatched navy band. */
  .rail { flex: 1 1 auto; }

  /* Push the mark and footer to the bottom of the rail. Without this they sit
     directly under the button and leave a tall empty block beneath them on a
     long phone screen. */
  .rail__mark { margin-top: auto; padding-bottom: 1rem; }

  .foot {
    flex-direction: column;
    align-items: center;
    justify-content: center;
    text-align: center;
    gap: 0.85rem;
    padding-top: 1.15rem;
  }
  .foot__legal { margin: 0; }
  .foot__left { flex-direction: column; align-items: center; gap: 0.85rem; }
}

/* ==========================================================================
   Side-by-side. Gated on aspect ratio as well as width: width alone leaves a
   dead band at squarish window shapes (~570-900px) where neither the stacked
   nor the split treatment applies.
   ========================================================================== */
@media (min-width: 860px) and (min-aspect-ratio: 7/10) {
  .split {
    /* The rail track must be DEFINITE. Left as `auto` it would size from its
       own content, the fr track has no basis to distribute from, and the
       scene collapses toward its padding. */
    display: grid;
    grid-template-columns: minmax(0, 1fr) var(--rail-w);
    height: 100svh;
    min-height: 0;
  }

  .scene { min-height: 0; height: 100svh; padding: clamp(2rem, 4vw, 3.5rem); }
  .scene__bg {
    background-image: url("/assets/signup/bg-desktop-sm.webp?v=20260905-11");
    background-position: 46% 50%;
  }

  /* Bleeds off the left edge and past the top, behind the lockup, at full
     colour. Large enough to read as the festival's silk, not a motif. */
  .scene__scarf {
    top: -12%;
    left: 0;
    transform: translateX(-22%);
    width: min(80%, 33rem);
    --sway: 1;
  }

  .rail {
    border-top: 0;
    border-left: 2px solid var(--mint);   /* the seam */
    height: 100svh;
    overflow-y: auto;
  }

  .rail__mark { margin-top: auto; }
}

@media (min-width: 1180px) and (min-aspect-ratio: 7/10) {
  :root { --rail-w: 34rem; }
  .lockup__mark { width: min(100%, 30rem); }
  .lockup { max-width: 38rem; }
}
@media (min-width: 1501px) and (min-aspect-ratio: 7/10) {
  :root { --rail-w: 38rem; }
  .scene__bg { background-image: url("/assets/signup/bg-desktop.webp?v=20260905-11"); }
  .lockup__mark { width: min(100%, 34rem); }
}

/* ==========================================================================
   Landscape phone. A rotated handset (844x390, 932x430, 667x375) satisfies
   the width and aspect conditions above but has almost no height. Placed
   AFTER the split blocks so it wins at equal specificity.
   ========================================================================== */
@media (min-width: 640px) and (min-aspect-ratio: 7/10) and (max-height: 520px) {
  .split {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 21rem;
    height: 100svh;
    min-height: 0;
  }
  .scene {
    height: 100svh;
    min-height: 0;
    padding: 1rem 1.2rem;
  }
  .scene__bg {
    background-image: url("/assets/signup/bg-desktop-sm.webp?v=20260905-11");
    background-position: 46% 50%;
  }
  .rail {
    border-top: 0;
    border-left: 2px solid var(--mint);
    height: 100svh;
    overflow-y: auto;
  }
  .foot { margin-top: auto; }
  .lockup__mark { width: min(100%, 15rem); }
  .lockup__say { margin-top: 0.7rem; }
  .lockup__thanks { font-size: clamp(1.5rem, 3.6vw, 2rem); }
  .lockup__rule { margin: 0.55rem auto; }
  .lockup__next { font-size: 0.8rem; }
  .lockup__place { margin-top: 0.7rem; font-size: 0.68rem; }
  .lockup__thankyou { width: min(100%, 18rem); }
  .scene__scarf { top: -22%; width: min(70%, 18rem); }

  .rail__inner { padding: 1rem 1.2rem; }
  .panel__title { font-size: 1.4rem; margin-top: 0.55rem; }
  .panel__lede,
  .panel__state p:not(.panel__eyebrow):not(.form__error):not(.form__resend) { margin-top: 0.6rem; font-size: 0.85rem; }
  .form { margin-top: 1rem; }
  .form__row { margin-bottom: 0.6rem; }
  .form__input { padding: 0.65rem 0.85rem; }
  .form__row--check { margin: 0.85rem 0 0.9rem; }
  .btn { padding: 0.78rem 1rem; }
  .foot {
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
    text-align: left;
    margin: 0 1.2rem;
    padding: 0.7rem 0 0.8rem;
    gap: 0.5rem 0.9rem;
    font-size: 0.7rem;
  }
  .foot__left { gap: 0.65rem; }
  .rail__mark { margin-top: auto; padding: 0 1.2rem 0.6rem; }
  .rail__mark img { height: 20px; }
}

/* --- Focus + motion ------------------------------------------------------ */
a:focus-visible,
button:focus-visible,
input:focus-visible,
.iti__selected-country:focus-visible {
  outline: 2px solid var(--mint);
  outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation: none !important; transition: none !important; }
}
