/* ============================================================
   WELCOME GATES — five variants. 36C Forge, GB pack.

   THESIS: a welcome gate is something HANDED OVER at the door, not
   a box thrown in the way. It refuses the category default: centred
   grey rectangle, headline, email field, and a "no thanks, I hate
   saving money" dismiss.
   OWN-WORLD: the GB pack, nothing else. #1A1A1A and #FCFCFC grounds,
   one #E2211C that is never decoration, AdihausDIN Condensed for
   anything shouted. Each gate is a physical object — a pass, a foil
   card, a clock, two doors, a posted letter — and reads as that
   object with all the copy removed.
   STORY: the visitor is given £50 off the 4- or 6-week challenge
   without asking, is told exactly when it dies, and books or leaves
   clean. Nothing is withheld to extract anything.
   FIRST VIEWPORT: the object fills the panel; the amount is the
   biggest thing in it; the deadline sits directly beneath the
   amount; the red CTA is the only red on a dark gate.
   FORM: five objects, one shell. A local extension of section 33's
   sheet and modal shell — no concept tournament, no new world.
   ============================================================ */


/* ============================================================
   THE SHARED SHELL
   Native <dialog> throughout: the focus trap, Escape, the inert
   background and ::backdrop are all more robust than anything
   hand-rolled. Close controls are <form method="dialog"> so they
   still work if the script dies.
   ============================================================ */

.wg {
  --wg-ink: var(--brand-ink-strong, #1A1A1A);
  --wg-body: var(--brand-ink, #333);
  --wg-quiet: var(--brand-quiet-ink, #333);
  --wg-surface: var(--brand-bg, #FCFCFC);
  --wg-raised: var(--brand-bg-muted, #EDEDED);
  --wg-rule: rgba(26, 26, 26, 0.14);
  --wg-accent: var(--brand-accent-ink, #0074C8);
  --wg-pad: clamp(24px, 4.5vw, 46px);
  --wg-dur: 0.44s;

  width: min(620px, calc(100vw - 28px));
  max-width: none;
  max-height: min(88svh, 920px);
  margin: auto;
  padding: 0;
  border: 0;
  border-radius: 6px;
  background: var(--wg-surface);
  color: var(--wg-body);
  overflow: visible;
}
.wg::backdrop {
  background: rgba(8, 8, 9, 0.66);
  backdrop-filter: blur(2.5px);
}
.wg-panel {
  position: relative;
  max-height: inherit;
  overflow-y: auto;
  overflow-x: hidden;
  overscroll-behavior: contain;
  border-radius: inherit;
}
/* the panel takes focus on open but is not a control, so it never rings */
.wg-panel:focus { outline: none; }
.wg-body { padding: var(--wg-pad); }

/* ---- the dark skin ---- */
.wg-pass, .wg-clock, .wg-dispatch {
  --wg-ink: var(--brand-ink-on-dark, #FCFCFC);
  --wg-body: rgba(255, 255, 255, 0.86);
  --wg-quiet: rgba(255, 255, 255, 0.62);
  --wg-surface: var(--brand-surface-dark, #1A1A1A);
  --wg-raised: var(--brand-surface-muted, #333);
  --wg-rule: rgba(255, 255, 255, 0.16);
  --wg-accent: var(--brand-accent-bright, #27A5FF);
}

/* ---- close ---- */
.wg-dismiss-form { position: absolute; top: 0; right: 0; z-index: 4; margin: 0; }
.wg-x {
  appearance: none;
  display: grid; place-items: center;
  width: 44px; height: 44px;
  margin: 6px 6px 0 0;
  padding: 0; border: 0; border-radius: 50%;
  background: none; color: var(--wg-quiet);
  cursor: pointer;
  transition: color 0.22s var(--f-ease), background-color 0.22s var(--f-ease);
}
.wg-x svg { width: 17px; height: 17px; }
.wg-x:hover, .wg-x:focus-visible {
  color: var(--wg-ink);
  background: color-mix(in oklab, var(--wg-surface), var(--wg-ink) 12%);
}

/* ---- the message. ONE left edge. ---- */
.wg-eyebrow {
  margin: 0 0 var(--f-space-s);
  font-size: var(--f-text-caption);
  letter-spacing: var(--f-track-eyebrow);
  text-transform: uppercase;
  color: var(--wg-accent);
  max-width: none;
}
.wg-turn {
  margin: 0 0 var(--f-space-s);
  font-family: var(--brand-font-display, inherit);
  font-weight: 700;
  text-transform: var(--brand-display-transform, none);
  font-size: var(--f-h2);
  line-height: var(--f-lh-h2);
  letter-spacing: var(--f-track-h2);
  color: var(--wg-ink);
  text-wrap: balance;
  max-width: 17ch;
}
.wg-line {
  margin: 0 0 var(--f-space-m);
  font-size: var(--f-text-small);
  line-height: var(--f-lh-body);
  color: var(--wg-body);
  max-width: 46ch;
}
.wg-line b { color: var(--wg-ink); font-weight: 500; }
.wg-cta { display: block; width: 100%; padding-inline: 24px; }
/* 44px tall, not the 29px this laid out at. A dismiss is the one
   control on a gate that a person is genuinely trying to hit, often
   with a thumb and often in a hurry, and quiet is a visual weight,
   not a size. Width stays fitted so the underline matches the words. */
.wg-quiet {
  appearance: none; display: block;
  width: fit-content;
  margin: var(--f-space-xs) auto 0;
  padding: 12px 14px;
  min-height: 44px;
  border: 0; background: none;
  font-family: var(--brand-font-body, inherit);
  font-size: var(--f-text-caption);
  color: var(--wg-quiet);
  text-decoration: underline; text-underline-offset: 3px;
  cursor: pointer;
}
.wg-quiet:hover, .wg-quiet:focus-visible { color: var(--wg-ink); }

/* ---- the code block, shared by four gates ----
   A discount code is a string to be transcribed character by
   character, so it gets the widest tracking on the page and a
   copy button, and the button says what happened. */
.pass-code {
  display: flex; align-items: stretch; gap: 8px;
  margin: 0 0 var(--f-space-s);
}
.pass-code-box {
  flex: 1 1 auto;
  display: grid; gap: 1px;
  padding: 10px 16px;
  border: 1px dashed var(--wg-rule);
  border-radius: 4px;
  background: color-mix(in oklab, var(--wg-surface), var(--wg-ink) 5%);
}
.pass-code-label {
  font-size: var(--f-text-micro);
  text-transform: uppercase; letter-spacing: 0.14em;
  color: var(--wg-quiet);
}
.pass-code-val {
  font-family: var(--brand-font-display, inherit);
  font-weight: 700;
  font-size: 1.6rem; line-height: 1.15;
  letter-spacing: 0.16em;
  font-variant-numeric: tabular-nums;
  color: var(--wg-ink);
}
.wg-copy {
  flex: none;
  display: inline-flex; align-items: center; gap: 7px;
  padding: 0 16px;
  border: 1px solid var(--wg-rule);
  border-radius: 4px;
  background: none;
  color: var(--wg-body);
  font: 500 var(--f-text-caption)/1 var(--brand-font-body, inherit);
  text-transform: uppercase; letter-spacing: 0.08em;
  cursor: pointer;
  transition: border-color 0.2s var(--f-ease), color 0.2s var(--f-ease), background-color 0.2s var(--f-ease);
}
.wg-copy svg { width: 16px; height: 16px; flex: none; }
.wg-copy:hover, .wg-copy:focus-visible {
  color: var(--wg-ink);
  border-color: var(--wg-ink);
  background: color-mix(in oklab, var(--wg-surface), var(--wg-ink) 8%);
}
.wg-copy[data-copied] { color: var(--wg-accent); border-color: var(--wg-accent); }

/* ---- entrance. One authored move per gate, from an already
   visible default; the backdrop fades on its own so the page
   behind never appears to shift. ---- */
@media (prefers-reduced-motion: no-preference) {
  .wg[open] { animation: wg-in var(--wg-dur) var(--f-ease); }
  .wg[open]::backdrop { animation: wg-fade 0.32s linear; }
}
@keyframes wg-in { from { opacity: 0; translate: 0 16px; scale: 0.986; } }
@keyframes wg-fade { from { opacity: 0; } }


/* ============================================================
   1 · THE PASS
   A pass torn off and handed across the counter: a red stub with
   the amount on it, a dashed seam, and the terms on the body.
   Given, not won and not traded for anything, so there is no
   action between arriving and having it.

   The seam is a split ground plus a dashed rule, never CSS
   half-circle perforations: those render as arrowheads at this
   size (learned on section 33's cut `ticket` treatment).
   ============================================================ */

.wg-pass { width: min(660px, calc(100vw - 28px)); }
.pass-card {
  display: grid;
  grid-template-columns: 104px 1fr;
  min-height: 100%;
  border-radius: inherit;
  overflow: hidden;
}
.pass-stub {
  display: grid; place-content: center; gap: 2px;
  padding: 20px 0;
  background: var(--brand-cta-bg, #E2211C);
  color: #FFFFFF;
  text-align: center;
  writing-mode: vertical-rl;
  rotate: 180deg;
  border-right: 2px dashed rgba(255, 255, 255, 0.42);
}
.pass-stub-amt {
  font-family: var(--brand-font-display, inherit);
  font-weight: 700; font-size: 3.1rem; line-height: 1;
  letter-spacing: 0.01em;
}
.pass-stub-word {
  font-size: var(--f-text-caption);
  text-transform: uppercase; letter-spacing: 0.32em;
  opacity: 0.9;
}
.pass-body { padding: var(--wg-pad); }
.pass-valid {
  margin: 0 0 var(--f-space-m);
  font-size: var(--f-text-caption);
  text-transform: uppercase; letter-spacing: 0.1em;
  color: var(--wg-quiet);
}
.pass-valid b { color: var(--wg-ink); font-weight: 500; letter-spacing: 0.06em; }

/* The pass is dealt across a surface rather than fading in: it comes
   up and straightens. Exponential ease-out, not the chassis spring —
   a card slid across a counter decelerates into place, it does not
   overshoot and come back, and the spring read as a wobble at this
   size. The rotate carries the character instead. */
@media (prefers-reduced-motion: no-preference) {
  .wg-pass[open] { animation: wg-deal 0.5s var(--f-ease); }
}
@keyframes wg-deal {
  from { opacity: 0; translate: 0 30px; rotate: -1.4deg; }
}

@media (max-width: 560px) {
  .pass-card { grid-template-columns: 1fr; }
  .pass-stub {
    writing-mode: horizontal-tb; rotate: none;
    grid-auto-flow: column; align-items: baseline; justify-content: center; gap: 10px;
    padding: 14px 56px 14px 0;
    border-right: 0;
    border-bottom: 2px dashed rgba(255, 255, 255, 0.42);
  }
  .pass-stub-amt { font-size: 2.3rem; }
  /* Stacked, the stub becomes a band ACROSS THE TOP and the close
     button lands on it. The panel's quiet ink is white at 62%, which
     over #E2211C measures 2.45:1 — under the 3:1 an icon needs. Pure
     white on that red is 4.70:1, so the one gate where the X sits on
     a saturated ground gets a pure-white X and a dark press state
     instead of the light one. */
  .wg-pass .wg-x { color: #FFFFFF; }
  .wg-pass .wg-x:hover, .wg-pass .wg-x:focus-visible {
    color: #FFFFFF;
    background: rgba(0, 0, 0, 0.22);
  }
}


/* ============================================================
   2 · THE SCRATCH CARD
   A foil panel over a fixed prize. It is NOT a prize draw and the
   copy says so out loud: every card is the same £50, and the
   scratching is the pleasure, not the lottery. A gate that implies
   chance while the outcome is fixed is a small lie, and a school
   selling to parents cannot afford one.

   The canvas is the mechanism, not an imitation of it: real
   destination-out erasing, real cleared-area sampling. The button
   underneath is not only an accessibility fallback — it is the
   route for anyone who does not want to play.
   ============================================================ */

/* 3/1, not the 5/2 this started on. The revealed state adds a code
   block, an expiry line and a CTA below the card, and at 5/2 that
   pushed the primary action below the fold on a 900px-tall window —
   measured, not guessed. A scratch panel wants to be wide and low
   anyway; it is the shape of the thing it imitates. */
.scr-stage {
  position: relative;
  aspect-ratio: 3 / 1;
  margin: 0 0 var(--f-space-s);
  border-radius: 5px;
  overflow: hidden;
  background: var(--wg-raised);
  border: 1px solid var(--wg-rule);
  touch-action: none;
  user-select: none;
}
.scr-prize {
  position: absolute; inset: 0;
  display: grid; place-content: center; justify-items: center; gap: 2px;
  text-align: center;
  padding: 12px;
}
.scr-prize-amt {
  font-family: var(--brand-font-display, inherit);
  font-weight: 700;
  font-size: clamp(3.2rem, 12vw, 4.6rem);
  line-height: 0.92;
  letter-spacing: -0.01em;
  color: var(--brand-cta-bg, #E2211C);
}
.scr-prize-word {
  font-size: var(--f-text-caption);
  text-transform: uppercase; letter-spacing: 0.22em;
  color: var(--wg-body);
}
.scr-foil {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  cursor: grab;
  transition: opacity 0.5s var(--f-ease);
}
.scr-foil:active { cursor: grabbing; }
.scr-stage[data-revealed] .scr-foil { opacity: 0; pointer-events: none; }
.scr-hint {
  position: absolute; inset-inline: 0; bottom: 12px;
  margin: 0; text-align: center; pointer-events: none;
  transition: opacity 0.35s var(--f-ease);
}
.scr-hint span {
  display: inline-block;
  padding: 5px 13px;
  border-radius: 100px;
  background: rgba(0, 0, 0, 0.34);
  color: #FFFFFF;
  font-size: var(--f-text-caption);
  text-transform: uppercase; letter-spacing: 0.16em;
}
.scr-stage[data-touched] .scr-hint { opacity: 0; }

/* the prize sits still and the foil leaves; a stamp-press on the
   amount is the one flourish, and it fires once. A stamp lands and
   stops, so this decelerates and holds — no overshoot. */
@media (prefers-reduced-motion: no-preference) {
  .scr-stage[data-revealed] .scr-prize-amt { animation: scr-press 0.45s var(--f-ease); }
}
@keyframes scr-press {
  0%   { scale: 1.14; opacity: 0.35; }
  100% { scale: 1; opacity: 1; }
}

/* Two quiet underlined links stacked would compete: this one is
   part of the card (an alternative way through it) and the dismiss
   below is a way out of the gate, so they must not look alike.
   This sits tight under the foil, right-aligned to it, and only
   underlines on hover. */
.scr-reveal {
  display: block;
  width: fit-content;
  margin: 0 -10px var(--f-space-s) auto;
  padding: 12px 10px; min-height: 44px;
  border: 0; background: none;
  font-family: var(--brand-font-body, inherit);
  font-size: var(--f-text-micro);
  text-transform: uppercase; letter-spacing: 0.08em;
  color: var(--wg-quiet);
  text-decoration: none;
  cursor: pointer;
}
.scr-reveal:hover, .scr-reveal:focus-visible {
  color: var(--wg-ink);
  text-decoration: underline; text-underline-offset: 3px;
}
.scr-stage[data-revealed] ~ .scr-reveal { display: none; }

.scr-after { animation: wg-step 0.42s var(--f-ease); }
.scr-days {
  margin: 0 0 var(--f-space-s);
  font-size: var(--f-text-caption);
  color: var(--wg-quiet);
}
.scr-days b { color: var(--wg-ink); font-weight: 500; }

/* ONCE THE CARD IS SCRATCHED IT IS THE MESSAGE, so the paragraph
   explaining that this is not a prize draw has done its job and
   goes, and the panel settles smaller. This is not tidiness: at
   1280x700 the revealed state put "Claim it & book" 77px below the
   fold, measured. Losing the explainer and taking the card down to
   3.4:1 brings the primary action back on screen. */
.wg-scratch:has(.scr-stage[data-revealed]) .wg-line { display: none; }
.scr-stage[data-revealed] { aspect-ratio: 3.4 / 1; }


/* ============================================================
   3 · THE CLOCK
   A side sheet, full height, in from the right — the shape section
   33 settled on, because it reads as something handed over rather
   than thrown in the way, and the page stays visible beside it.

   The countdown is the composition, not a badge stuck on one. The
   rule beneath it is the month draining, which is real information
   and the reason this variant exists at all. The plain sentence
   under the clock is not a fallback: a ticking region is unusable
   to a screen reader, so the date is stated in words and the
   digits are hidden from the accessibility tree.
   ============================================================ */

.wg-clock {
  border-radius: 0;
  width: min(520px, 100vw);
  height: 100svh;
  max-height: 100svh;
  margin: 0 0 0 auto;
}
.wg-clock .wg-panel { display: grid; align-content: center; min-height: 100%; }
.wg-clock .wg-body { padding: clamp(26px, 4vw, 52px); }

.clk {
  display: flex; align-items: flex-start; gap: clamp(4px, 1.6vw, 10px);
  margin: 0 0 var(--f-space-s);
}
.clk-unit { display: grid; justify-items: center; gap: 3px; min-width: 0; flex: 1 1 0; }
.clk-n {
  font-family: var(--brand-font-display, inherit);
  font-weight: 700;
  font-size: clamp(2.6rem, 11vw, 3.6rem);
  line-height: 1;
  letter-spacing: -0.01em;
  font-variant-numeric: tabular-nums;
  color: var(--wg-ink);
}
.clk-unit-s .clk-n { color: var(--brand-cta-bg, #E2211C); }
.clk-l {
  font-size: var(--f-text-micro);
  text-transform: uppercase; letter-spacing: 0.18em;
  color: var(--wg-quiet);
}
.clk-sep {
  font-family: var(--brand-font-display, inherit);
  font-size: clamp(2rem, 8vw, 2.6rem);
  line-height: 1.16;
  color: var(--wg-rule);
}
/* the month draining. Real measurement, so it gets a real rule. */
.clk-drain {
  position: relative;
  height: 3px;
  margin: 0 0 var(--f-space-s);
  background: var(--wg-rule);
  border-radius: 2px;
  overflow: hidden;
}
/* scaled, not width-animated: this updates once a second for as long
   as the sheet is open, and animating width relayouts on every tick.
   scale is composited. Same device as the fork door's base rule. */
.clk-drain span {
  position: absolute; inset: 0;
  transform-origin: left center;
  scale: var(--clk-left, 1) 1;
  background: var(--brand-cta-bg, #E2211C);
  transition: scale 1s linear;
}
.clk-plain {
  margin: 0 0 var(--f-space-m);
  font-size: var(--f-text-caption);
  color: var(--wg-quiet);
}
.clk-plain b { color: var(--wg-ink); font-weight: 500; }
.clk-code { margin-bottom: var(--f-space-m); }

@media (prefers-reduced-motion: no-preference) {
  .wg-clock[open] { animation: wg-slide var(--wg-dur) var(--f-ease); }
}
@keyframes wg-slide { from { translate: 44px 0; opacity: 0; } }

@media (max-width: 700px) {
  /* height: fit-content, NOT auto. A modal <dialog> is fixed with
     inset: 0, so `height: auto` is over-constrained and stretches to
     the full inset box — the sheet then sat at its 90svh cap with
     185px of empty ground under the dismiss link, measured at
     390x844. fit-content is what the UA stylesheet uses and what
     every other gate here is already relying on. */
  .wg-clock {
    margin: auto 0 0;
    width: 100vw;
    height: fit-content;
    max-height: 90svh;
    border-radius: 8px 8px 0 0;
  }
  .wg-clock .wg-panel { align-content: start; min-height: 0; }
  @media (prefers-reduced-motion: no-preference) {
    .wg-clock[open] { animation: wg-slide-up var(--wg-dur) var(--f-ease); }
  }
}
@keyframes wg-slide-up { from { translate: 0 44px; opacity: 0; } }


/* ============================================================
   4 · THE FORK
   Two doors. The discount is identical behind both, so the choice
   is not about money — it is the first small commitment, and it
   tells the school which block to put the person in. That is the
   whole argument for this variant: it captures an answer without
   asking for a field.
   ============================================================ */

.wg-fork { width: min(680px, calc(100vw - 28px)); }
.fork-doors {
  display: grid; gap: 10px;
  grid-template-columns: 1fr 1fr;
  margin: 0 0 var(--f-space-s);
}
.fork-door {
  position: relative;
  display: grid; gap: 2px;
  align-content: start;
  padding: 22px 18px 52px;
  min-height: 244px;
  text-align: left;
  background: var(--wg-raised);
  border: 1px solid transparent;
  border-radius: 5px;
  color: var(--wg-body);
  font-family: var(--brand-font-body, inherit);
  cursor: pointer;
  overflow: hidden;
  transition: background-color 0.24s var(--f-ease), border-color 0.24s var(--f-ease), translate 0.24s var(--f-ease);
}
/* A door swings on a hinge. The base rule sweeping out from the
   left edge is that movement, and it is the only thing on either
   door that moves — so the pair reads as two of one object rather
   than two cards that happen to sit together. */
.fork-door::after {
  content: "";
  position: absolute; inset: auto 0 0 0;
  height: 3px;
  background: var(--brand-cta-bg, #E2211C);
  scale: 0 1;
  transform-origin: left center;
  transition: scale 0.34s var(--f-ease);
}
.fork-door:hover::after, .fork-door:focus-visible::after { scale: 1 1; }

.fork-door-tag {
  position: absolute; top: 0; right: 0;
  padding: 5px 11px 6px;
  border-radius: 0 5px 0 5px;
  background: var(--wg-ink);
  color: var(--wg-surface);
  font-size: var(--f-text-micro);
  text-transform: uppercase; letter-spacing: 0.1em;
}
.fork-door-n {
  font-family: var(--brand-font-display, inherit);
  font-weight: 700;
  font-size: clamp(3.4rem, 12vw, 5rem);
  line-height: 0.86;
  letter-spacing: -0.02em;
  color: var(--wg-ink);
  transition: color 0.24s var(--f-ease);
}
.fork-door-w {
  font-size: var(--f-text-caption);
  text-transform: uppercase; letter-spacing: 0.2em;
  color: var(--wg-quiet);
  margin-bottom: 14px;
}
.fork-door-d {
  font-size: var(--f-text-caption);
  line-height: 1.5;
  color: var(--wg-body);
  max-width: 24ch;
}
/* MEASURED, not chosen by eye: --brand-cta-bg (#E2211C) on the GB
   raised ground (#EDEDED) is 3.93:1, which clears the 3:1 bar for
   the big numeral and FAILS the 4.5:1 bar for this 13px line. The
   pack's own deep red is 8.95:1 on the same ground, so the label
   stays in the brand's red family and stays legible. */
.fork-door-go {
  position: absolute; left: 18px; right: 18px; bottom: 18px;
  padding-top: 13px;
  border-top: 1px solid var(--wg-rule);
  font-size: var(--f-text-caption);
  font-weight: 500;
  color: var(--brand-cta-bg-hover, #7C1313);
  text-transform: uppercase; letter-spacing: 0.06em;
}
.fork-door-go i {
  display: inline-block; font-style: normal;
  transition: translate 0.24s var(--f-ease);
}
.fork-door:hover .fork-door-go i, .fork-door:focus-visible .fork-door-go i { translate: 4px 0; }
.fork-door:hover, .fork-door:focus-visible {
  background: color-mix(in oklab, var(--wg-raised), var(--wg-ink) 6%);
  border-color: color-mix(in oklab, var(--wg-ink), transparent 78%);
  translate: 0 -3px;
}
.fork-door:hover .fork-door-n, .fork-door:focus-visible .fork-door-n {
  color: var(--brand-cta-bg, #E2211C);
}
.fork-door:active { translate: 0 0; }
.fork-note {
  margin: 0;
  font-size: var(--f-text-caption);
  color: var(--wg-quiet);
}
.fork-note b { color: var(--wg-ink); font-weight: 500; }

.fork-step[data-fork-step="2"] { animation: wg-step 0.42s var(--f-ease); }
@keyframes wg-step { from { opacity: 0; translate: 0 12px; } }
.fork-valid {
  margin: 0 0 var(--f-space-m);
  font-size: var(--f-text-caption);
  text-transform: uppercase; letter-spacing: 0.1em;
  color: var(--wg-quiet);
}
.fork-valid b { color: var(--wg-ink); font-weight: 500; letter-spacing: 0.06em; }

@media (max-width: 540px) {
  .fork-doors { grid-template-columns: 1fr; }
  .fork-door { padding: 16px 16px 46px; min-height: 0; }
  .fork-door-n { font-size: 2.9rem; }
  .fork-door-w { margin-bottom: 8px; }
}


/* ============================================================
   5 · THE DISPATCH
   The one gate that asks for something. So it says what it wants,
   what it will send, and what it will not do, above the field
   rather than in grey type below it — and it still shows the code
   on screen afterwards, because holding it hostage in an inbox is
   how a gate turns into a chore.
   ============================================================ */

.dsp-form { margin: 0 0 var(--f-space-s); }
.dsp-field { margin-bottom: var(--f-space-s); }
.dsp-field label {
  display: block;
  margin-bottom: 6px;
  font-size: var(--f-text-micro);
  text-transform: uppercase; letter-spacing: 0.14em;
  color: var(--wg-quiet);
}
.dsp-field input {
  width: 100%;
  padding: 14px 16px;
  border: 1px solid color-mix(in oklab, var(--wg-ink), transparent 76%);
  border-radius: 4px;
  background: color-mix(in oklab, var(--wg-surface), var(--wg-ink) 6%);
  color: var(--wg-ink);
  font: 400 var(--f-text)/1.3 var(--brand-font-body, inherit);
  transition: border-color 0.2s var(--f-ease), background-color 0.2s var(--f-ease);
}
.dsp-field input::placeholder { color: color-mix(in oklab, var(--wg-ink), transparent 44%); }
.dsp-field input:hover { border-color: color-mix(in oklab, var(--wg-ink), transparent 60%); }
.dsp-field input:focus-visible {
  outline: 2px solid var(--wg-accent);
  outline-offset: 1px;
  border-color: var(--wg-accent);
}
.dsp-field[data-invalid] input { border-color: #FF6B66; }
.dsp-err {
  margin: 8px 0 0;
  font-size: var(--f-text-caption);
  color: #FF8A85;
}
.dsp-submit { position: relative; }
.dsp-submit[data-busy] { pointer-events: none; }
.dsp-submit[data-busy] .dsp-submit-t { opacity: 0.35; }
.dsp-spin {
  position: absolute; inset: 0;
  display: none; place-items: center;
}
.dsp-submit[data-busy] .dsp-spin { display: grid; }
.dsp-spin::after {
  content: "";
  width: 18px; height: 18px;
  border: 2px solid rgba(255, 255, 255, 0.34);
  border-top-color: #FFFFFF;
  border-radius: 50%;
  animation: dsp-spin 0.7s linear infinite;
}
@keyframes dsp-spin { to { rotate: 360deg; } }
.dsp-small {
  margin: 0;
  font-size: var(--f-text-micro);
  line-height: 1.5;
  color: var(--wg-quiet);
  max-width: 44ch;
}
.dsp-step[data-dsp-step="2"] { animation: wg-step 0.42s var(--f-ease); }
.dsp-valid {
  margin: 0 0 var(--f-space-m);
  font-size: var(--f-text-caption);
  text-transform: uppercase; letter-spacing: 0.1em;
  color: var(--wg-quiet);
}
.dsp-valid b { color: var(--wg-ink); font-weight: 500; letter-spacing: 0.06em; }


/* ============================================================
   TOAST — the copy button's receipt
   ============================================================ */
.wg-toast {
  position: fixed; left: 50%; bottom: 28px;
  z-index: 100;
  translate: -50% 14px;
  padding: 11px 20px;
  border-radius: 100px;
  background: #1A1A1A;
  color: #FCFCFC;
  border: 1px solid rgba(255, 255, 255, 0.18);
  font-size: var(--f-text-caption);
  letter-spacing: 0.02em;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.24s var(--f-ease), translate 0.24s var(--f-ease);
}
.wg-toast[data-show] { opacity: 1; translate: -50% 0; }


/* ============================================================
   REDUCED MOTION — every authored move comes off, nothing that
   carries meaning goes with it.
   ============================================================ */
@media (prefers-reduced-motion: reduce) {
  .wg[open], .wg[open]::backdrop,
  .scr-stage[data-revealed] .scr-prize-amt,
  .fork-step, .scr-after, .dsp-step { animation: none !important; }
  .wg-x, .wg-copy, .fork-door, .scr-foil, .scr-hint,
  .dsp-field input, .clk-drain span, .wg-toast { transition: none !important; }
  .dsp-spin::after { animation-duration: 2s; }
}
