/* ============ Fonts ============ */
@font-face {
  font-family: "Aethon";
  src: url("../fonts-web/Aethon-Bold.woff2") format("woff2"),
       url("../fonts-web/Aethon-Bold.woff") format("woff");
  font-weight: 700;
  font-style: normal;
  font-display: block;
}
@font-face {
  font-family: "Aethon Shattered";
  src: url("../fonts-web/AethonShattered-Bold.woff2") format("woff2"),
       url("../fonts-web/AethonShattered-Bold.woff") format("woff");
  font-weight: 700;
  font-style: normal;
  font-display: block;
}

@font-face {
  font-family: "Basic";
  src: url("../fonts-web/Basic-Regular.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: block;
}
@font-face {
  font-family: "Anybody";
  src: url("../fonts-web/Anybody-SemiBold.woff2") format("woff2");
  font-weight: 600;
  font-style: normal;
  font-display: block;
}

/* ============ Tokens ============ */
:root {
  --cream: #e9dcbe;
  --black: #000000;
  --field-bg: rgba(233, 220, 190, 0.2);
  --field-strip: rgba(0, 0, 0, 0.25);
  --placeholder: rgba(255, 255, 255, 0.4);
  --input-text: #ffffff;
  --error: #ff5c5c;
  --error-bg: rgba(255, 155, 155, 0.2);
  --glow: #ffd16f;
  --shattered: "Aethon Shattered", "Aethon", serif;
  --aethon: "Aethon", serif;

  /* Final zoom: 78.89 * max(vw/1440, vh/800), expressed as layout width.
     78.89 * 60.3371 / 1440 * 100vw = 330.55vw ; 78.89 * 60.3371 / 800 * 100vh = 594.99vh */
  --logo-w: max(330.55vw, 594.99vh);
  /* set by JS: 1 / (78.89 * max(vw/1440, vh/800)) */
  --invS: 0.012676;
}

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

html, body { background: var(--black); }
body {
  overflow-x: hidden;
  font-family: var(--aethon);
  -webkit-font-smoothing: antialiased;
}

/* ============ Background stage (the logo IS the screen-2 background) ============ */
.bg {
  position: fixed;
  inset: 0;
  overflow: hidden;
  background: var(--black);
}
.logo {
  position: absolute;
  left: 50%;
  top: 50%;
  /* independent translate composes with the animated transform: scale() and
     keeps the element centre pinned to the viewport centre at every scale */
  translate: -50% -50%;
  width: var(--logo-w);
  aspect-ratio: 60.3371 / 60.0014;
  transform-origin: 50% 50%;
}
.logo svg { display: block; width: 100%; height: 100%; }

/* Final state is the CSS default: shards dimmed, everything visible. */
.logo .cream { fill-opacity: 0.25; }

/* ---- Intro (only when JS is running) ---- */
html.js .logo {
  opacity: 0;
  transform: scale(calc(var(--invS) * 0.85));
}
html.js.enter .logo {
  opacity: 1;
  transform: scale(var(--invS));
  transition: opacity 0.8s cubic-bezier(0.22, 1, 0.36, 1),
              transform 0.8s cubic-bezier(0.22, 1, 0.36, 1);
}
html.js .logo .cream { fill-opacity: 1; }
html.js.zoom .logo {
  transform: scale(1);
  transition: transform 1.4s cubic-bezier(0.65, 0, 0.35, 1);
}
html.js.zoom .logo .cream {
  fill-opacity: 0.25;
  transition: fill-opacity 1.4s cubic-bezier(0.65, 0, 0.35, 1);
}
html.js.settled .logo { transform: none; transition: none; }

@media (prefers-reduced-motion: reduce) {
  html.js .logo { opacity: 1; transform: none; transition: none; }
  html.js .logo .cream { fill-opacity: 0.25; transition: none; }
}

/* ============ Content ============ */
.content {
  position: relative;
  z-index: 1;
  min-height: 100vh;
  min-height: 100dvh;
  display: grid;
  place-items: center;
  padding: 40px 0;
}
.column {
  width: 792px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 30px;
  translate: 0 0.5px;
}

/* Staggered reveal. Scoped to :not(.settled): once the intro is done these
   rules must stop declaring opacity, or they override the error dim. */
html.js:not(.settled) .reveal { opacity: 0; transform: translateY(26px); }
html.js.content-in:not(.settled) .reveal {
  opacity: 1;
  transform: translateY(0);
  transition: opacity 0.6s cubic-bezier(0.22, 1, 0.36, 1),
              transform 0.6s cubic-bezier(0.22, 1, 0.36, 1);
}
html.js.content-in:not(.settled) .reveal:nth-child(2) { transition-delay: 0.12s; }
html.js.content-in:not(.settled) .reveal:nth-child(3) { transition-delay: 0.24s; }
html.js.content-in:not(.settled) .reveal:nth-child(4) { transition-delay: 0.36s; }
@media (prefers-reduced-motion: reduce) {
  html.js:not(.settled) .reveal { opacity: 1; transform: none; transition: none; }
}

/* ============ 1. Wordmark lockup ============ */
.lockup { display: flex; justify-content: center; }
.lockup-box {
  width: 210.482px;
  background: var(--black);
  padding: 0 3.508px 3.508px;
  display: flex;
  flex-direction: column;
}
.lockup-wraith { position: relative; height: 49.012px; width: 100%; }
.lockup-wraith span {
  position: absolute;
  top: 4.04px;
  left: 50%;
  transform: translateX(-50%);
  width: 203.466px;
  font-family: var(--shattered);
  font-weight: 700;
  font-size: 53.222px;
  line-height: normal;
  color: var(--cream);
  text-transform: uppercase;
  letter-spacing: 0.12em;
  text-indent: 0.12em;
  text-align: center;
  white-space: nowrap;
}
.lockup-bar { position: relative; height: 27.48px; width: 100%; background: var(--cream); }
.lockup-bar span {
  position: absolute;
  top: calc(50% - 10.3px);
  left: 50%;
  transform: translateX(-50%);
  width: 203.466px;
  font-family: var(--shattered);
  font-weight: 700;
  font-size: 24.356px;
  line-height: normal;
  color: var(--black);
  text-transform: uppercase;
  letter-spacing: 0.12em;
  text-indent: 0.12em;
  text-align: center;
  white-space: nowrap;
}

/* ============ 2. Headline ============ */
.headline {
  display: flex;
  flex-direction: column;
  gap: 10px;
  align-items: center;
  text-align: center;
}
.headline h1 {
  width: 716px;
  font-family: var(--shattered);
  font-weight: 700;
  font-size: 60px;
  line-height: 60px;
  color: var(--cream);
  text-transform: uppercase;
  letter-spacing: 0;
}
.headline .sub {
  font-family: var(--aethon);
  font-weight: 700;
  font-size: 20px;
  line-height: 20px; /* pinned: font arrival must not move the column */
  color: #ffffff;
  letter-spacing: 0.1em;
  text-indent: 0.1em;
  white-space: nowrap;
}

/* ============ 3. Form ============ */
.waitlist {
  width: 400px;
  display: flex;
  flex-direction: column;
  gap: 20px;
}
.field {
  position: relative;
  width: 100%;
  height: 55px;
  background: var(--field-bg);
  padding: 4px;
  display: flex;
  flex-direction: column;
  gap: 5px;
}
.field input {
  height: 26px;
  width: 100%;
  background: transparent;
  border: 0;
  outline: 0;
  text-align: center;
  font-family: var(--aethon);
  font-weight: 700;
  font-size: 20px;
  line-height: 26px;
  letter-spacing: 0.1em;
  text-indent: 0.1em;
  color: var(--input-text);
  caret-color: #ffffff;
  border-radius: 0;
}
.field input::placeholder { color: var(--placeholder); opacity: 1; }
.field .strip { height: 16px; width: 100%; background: var(--field-strip); }
.field .chip {
  position: absolute;
  left: 380px;
  top: -20.5px;
  background: #ffffff;
  padding: 5px;
  font-family: var(--aethon);
  font-weight: 700;
  font-size: 29.089px;
  line-height: normal;
  color: var(--black);
  white-space: nowrap;
  z-index: 1;
}
.form-error {
  display: none;
  font-family: var(--aethon);
  font-weight: 700;
  font-size: 13px;
  letter-spacing: 0.1em;
  text-indent: 0.1em;
  text-transform: uppercase;
  text-align: center;
  color: var(--error);
}
.form-error.show { display: block; }

/* Honeypot — off-screen, never shown */
.hp {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* ============ Error state (Figma 176:1755) ============ */
/* The page recedes; the problem stays lit. Wordmark, errored field,
   tooltip and arrow keep full opacity. */
.headline, .social, .submit, .field { transition: opacity 0.25s ease; }
/* once the intro is done, the reveal transition (0.6s + stagger delays)
   must not delay the dim */
html.js.settled .reveal { transition: opacity 0.25s ease; }
.column.error-mode .headline,
.column.error-mode .social,
.column.error-mode .submit,
.column.error-mode .field:not(.error) { opacity: 0.35; }

.field.error {
  background: var(--error-bg);
  /* 2px #FF5C5C border drawn inward (outline, not border) so the 55px
     geometry never shifts */
  outline: 2px solid var(--error);
  outline-offset: -2px;
}

/* Tooltip: 86x50 anchored to the errored field, resting at -10deg.
   Offsets derived from the rotated bounding box in 176:1755 (column x 97,
   y 300.5) so the rendered position matches Figma exactly. */
.field .tip {
  position: absolute;
  left: -95.3px;
  top: -57.4px;
  min-width: 86px;
  min-height: 50px;
  padding: 5px;
  background: var(--error);
  display: flex;
  align-items: center;
  justify-content: center;
  rotate: -10deg;
  transform-origin: 50% 50%;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.25s ease, visibility 0s linear 0.25s;
  pointer-events: none;
  z-index: 2;
}
.field .tip-text {
  width: 76px;
  font-family: var(--aethon);
  font-weight: 700;
  font-size: 20px;
  line-height: normal;
  letter-spacing: 0.1em;
  text-align: center;
  color: #ffffff;
}
/* longer copy (the @ callout) hugs wider instead of shrinking the type */
.field .tip.wide { min-width: 0; width: max-content; max-width: 160px; }
.field .tip.wide .tip-text { width: 96px; }
.field .tip-arrow {
  position: absolute;
  left: -49.5px;
  top: -10px;
  width: 49px;
  height: 35px;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.25s ease, visibility 0s linear 0.25s;
  pointer-events: none;
  z-index: 2;
}
.field.error.show-tip .tip,
.field.error.show-tip .tip-arrow {
  opacity: 1;
  visibility: visible;
  transition: opacity 0.25s ease;
}

/* ============ Shakes ============ */
/* Tooltip: rest -10deg, +/-5deg both ways, 3 decaying oscillations */
@keyframes tip-shake {
  0%   { rotate: -10deg; }
  15%  { rotate: -15deg; }
  32%  { rotate: -5deg; }
  50%  { rotate: -14deg; }
  67%  { rotate: -6.5deg; }
  84%  { rotate: -12deg; }
  100% { rotate: -10deg; }
}
.field.error.shake .tip { animation: tip-shake 0.6s ease both; }

/* Submit button: horizontal, decaying */
@keyframes btn-shake {
  0%    { translate: 0 0; }
  12%   { translate: -8px 0; }
  25%   { translate: 8px 0; }
  37%   { translate: -6px 0; }
  50%   { translate: 6px 0; }
  62%   { translate: -4px 0; }
  75%   { translate: 4px 0; }
  87%   { translate: -2px 0; }
  100%  { translate: 0 0; }
}
.submit.shake { animation: btn-shake 0.45s ease-out both; }

/* Hover shakes: chips oscillate +/-5 around 0; the tooltip reuses tip-shake
   (rest -10, -5 to -15). Fired once per pointerenter by JS, re-armed on
   leave with a cooldown. */
@keyframes chip-shake {
  0%   { rotate: 0deg; }
  15%  { rotate: -5deg; }
  32%  { rotate: 5deg; }
  50%  { rotate: -4deg; }
  67%  { rotate: 3.5deg; }
  84%  { rotate: -2deg; }
  100% { rotate: 0deg; }
}
.chip.hover-shake { animation: chip-shake 0.6s ease both; }
.tip.hover-shake { animation: tip-shake 0.6s ease both; }
.field.error.show-tip .tip { pointer-events: auto; }

@media (prefers-reduced-motion: reduce) {
  .field.error.shake .tip,
  .submit.shake,
  .chip.hover-shake,
  .tip.hover-shake { animation: none; }
}

/* ============ Hover: glow + shard slide ============ */
/* The buttons clip their own content now, so the glow needs no wrapper —
   it lives as a ::before at z-index -1 inside each button's stacking
   context: above the button fill, below the label text and shards. */
.submit { z-index: 0; }
.social a { z-index: 0; }
.submit::before,
.social a::before {
  content: "";
  position: absolute;
  background: var(--glow);
  border-radius: 50%;
  /* Figma layer blur 64 — tuned against the hover screenshots; CSS blur(28)
     matches the rendered spread, blur(64) does not */
  filter: blur(28px);
  opacity: 0;
  transition: opacity 0.2s ease;
  pointer-events: none;
  z-index: -1;
}
/* --gx/--gy are the glow centre, driven by JS cursor tracking; with the
   vars unset (touch, reduced motion, no JS) they fall back to the centred
   static ellipse. */
.submit::before {
  width: 305px;
  height: 51px;
  left: calc(var(--gx, 50%) - 152.5px);
  top: calc(var(--gy, 50%) - 25.5px);
}
.social a::before {
  width: 127px;
  height: 21px;
  left: calc(var(--gx, 50%) - 63.5px);
  top: calc(var(--gy, 50%) - 10.5px);
}
/* smooth press-dim reverse on touch devices */
.social a { transition: opacity 0.2s ease; }
/* keep horizontal finger-slides on the buttons ours (glow tracking);
   vertical pans still scroll and fire pointercancel, which resets cleanly */
.submit, .social a { touch-action: pan-y; }

.submit .shard-l,
.submit .shard-r,
.social .shard {
  transition: translate 0.3s cubic-bezier(0.22, 1, 0.36, 1);
}

@media (hover: hover) and (pointer: fine) {
  .submit:hover::before,
  .social a:hover::before { opacity: 1; }
  /* hovering one social recedes the other three; error dim wins */
  .social a { transition: opacity 0.2s ease; }
  .column:not(.error-mode) .social:hover a:not(:hover) { opacity: 0.45; }
  @media (prefers-reduced-motion: no-preference) {
    .submit:hover .shard-l { translate: -20px -30px; }
    .submit:hover .shard-r { translate: 29px -38px; }
    .social a:hover .shard { translate: -20px -24px; }
  }
}

.submit {
  position: relative;
  width: 400px;
  height: 60px;
  background: var(--cream);
  border: 0;
  border-radius: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--shattered);
  font-weight: 700;
  font-size: 30px;
  letter-spacing: 0.1em;
  text-indent: 0.1em;
  color: var(--black);
  cursor: pointer;
  overflow: hidden; /* 167:1610 now clips — shards cut at the button edge */
}
.submit[disabled] { cursor: progress; opacity: 0.75; }
.submit .shard-l,
.submit .shard-r {
  position: absolute;
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
  color: var(--black);
}
.submit .shard-l { left: -54.44px; top: -36.06px; width: 90.44px; height: 97.113px; }
.submit .shard-l svg { flex: none; width: 94.318px; height: 87.417px; transform: rotate(91.87deg); }
.submit .shard-r { right: -73.24px; top: -44px; width: 135.238px; height: 100.116px; }
.submit .shard-r svg { flex: none; width: 121.393px; height: 61.478px; transform: rotate(-20.51deg); }

/* Success confirmation (not in Figma — built from existing tokens only) */
.success {
  position: relative;
  width: 400px;
  background: var(--black);
  border: 2.5px solid var(--cream);
  border-radius: 0;
  overflow: hidden; /* shard bleeds in from the left, like the social buttons */
  padding: 26px 24px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  align-items: center;
  text-align: center;
}
.success .shard {
  position: absolute;
  left: -56.94px;
  top: -38.56px;
  width: 90.44px;
  height: 97.113px;
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
  color: var(--cream);
}
.success .shard svg { flex: none; width: 94.318px; height: 87.417px; transform: rotate(91.87deg); }
.success h2 {
  font-family: var(--shattered);
  font-weight: 700;
  font-size: 30px;
  line-height: normal;
  letter-spacing: 0.1em;
  text-indent: 0.1em;
  text-transform: uppercase;
  color: var(--cream);
}
.success p {
  font-family: var(--aethon);
  font-weight: 700;
  font-size: 16px;
  letter-spacing: 0.1em;
  text-indent: 0.1em;
  color: #ffffff;
}

/* ============ 4. Social row ============ */
.social {
  width: 100%;
  display: flex;
  gap: 30px;
  align-items: center;
  justify-content: center;
}
.social a {
  position: relative;
  height: 60px;
  padding: 4px 0;
  background: var(--black);
  border: 2.5px solid var(--cream);
  border-radius: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden; /* shard is clipped — clipsContent: true */
  font-family: var(--shattered);
  font-weight: 700;
  font-size: 30px;
  letter-spacing: 0;
  color: var(--cream);
  text-decoration: none;
  white-space: nowrap;
}
.social .shard {
  position: absolute;
  left: -56.94px;
  top: -38.56px;
  width: 90.44px;
  height: 97.113px;
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
  color: var(--cream);
}
.social .shard svg { flex: none; width: 94.318px; height: 87.417px; transform: rotate(91.87deg); }
/* Figma hug widths, pinned exactly */
.social a:nth-child(1) { width: 100px; }
.social a:nth-child(2) { width: 186px; }
.social a:nth-child(3) { width: 222px; }
.social a:nth-child(4) { width: 194px; }

/* ============ Focus ============ */
.submit:focus-visible,
.social a:focus-visible {
  outline: 2px solid var(--cream);
  outline-offset: 3px;
}

/* ============ FIX 3: tooltip clamp (JS adds .tip-clamped when the tooltip
   would rise above the form block; the arrow re-aims beside the field) ==== */
.field.tip-clamped .tip-arrow {
  left: -46px;
  top: 30px;
  rotate: -35deg;
}

/* ============ Feature: parallax wrapper (inert without JS) ============ */
.plx { position: absolute; inset: 0; }

/* ============ Feature: success zoom (html.szoom set by JS when enabled) ==
   With the flag on, the SVG is laid out at S x 1.45 and Screen 2 rests at
   scale(1/1.45) = 0.68966. Success releases to scale(1), so the page never
   scales past layout size and the end state stays vector-crisp everywhere,
   Safari included. */
html.szoom .logo {
  width: max(479.3vw, 862.73vh); /* the base max() formula x 1.45 */
  transform: scale(0.68966);
}
html.szoom.js .logo {
  opacity: 0;
  transform: scale(calc(var(--invS) * 0.85));
}
html.szoom.js.enter .logo { opacity: 1; transform: scale(var(--invS)); }
html.szoom.js.zoom .logo { transform: scale(0.68966); }
html.szoom.js.settled .logo { transform: scale(0.68966); transition: none; }

html.szoom.landed .logo,
html.szoom.js.settled.landed .logo {
  transform: scale(1);
  transition: transform 1.4s cubic-bezier(0.16, 1, 0.3, 1);
}
/* shard warming: starts 350ms after the success class (t=150), i.e. t=500 */
html.szoom.landed .logo .cream {
  fill: #ffd16f;
  fill-opacity: 0.4;
  transition: fill 1.2s cubic-bezier(0.16, 1, 0.3, 1) 0.35s,
              fill-opacity 1.2s cubic-bezier(0.16, 1, 0.3, 1) 0.35s;
}
/* state restored from localStorage, or intro skipped: no transitions */
html.instant .logo,
html.instant .logo .cream,
html.instant .reveal { transition: none !important; }

/* the form un-forms: reverse of the entry stagger, let go, not wiped */
form.unform .submit,
form.unform .field {
  opacity: 0;
  translate: 0 12px;
  transition: opacity 0.5s cubic-bezier(0.4, 0, 1, 1),
              translate 0.5s cubic-bezier(0.4, 0, 1, 1);
  pointer-events: none;
}
form.unform #field-email { transition-delay: 0.08s; }
form.unform #field-name { transition-delay: 0.16s; }

/* success block entrance */
.success.fixed210 {
  height: 210px;
  padding: 22px 24px 34px;
  gap: 8px;
  justify-content: center;
}
.success.pre { opacity: 0; translate: 0 -20px; }
.success.in {
  opacity: 1;
  translate: 0 0;
  transition: opacity 0.7s cubic-bezier(0.16, 1, 0.3, 1),
              translate 0.7s cubic-bezier(0.16, 1, 0.3, 1);
}

/* one slow breath on the social row after success settles */
@keyframes border-breathe {
  0% { border-color: var(--cream); }
  50% { border-color: rgba(233, 220, 190, 0.6); }
  100% { border-color: var(--cream); }
}
.social.pulse a { animation: border-breathe 1.2s ease-in-out 1; }

/* vessel count — pinned to the bottom of the 210px box so a late or absent
   count never reflows the content */
.success .vessel-count {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 12px;
  font-family: var(--aethon);
  font-weight: 700;
  font-size: 20px;
  letter-spacing: 0.1em;
  text-indent: 0.1em;
  text-align: center;
  color: #ffffff;
  opacity: 0;
  transition: opacity 0.4s ease;
}
.success .vessel-count.show { opacity: 1; }

/* share step */
.success .share-copy {
  font-family: var(--aethon);
  font-weight: 700;
  font-size: 13px;
  letter-spacing: 0.1em;
  text-indent: 0.1em;
  color: #ffffff;
}
.success .copy-link {
  height: 40px;
  padding: 0 22px;
  background: transparent;
  border: 2.5px solid var(--cream);
  border-radius: 0;
  font-family: var(--shattered);
  font-weight: 700;
  font-size: 20px;
  letter-spacing: 0.1em;
  text-indent: 0.1em;
  color: var(--cream);
  cursor: pointer;
}
.success .copy-link:focus-visible { outline: 2px solid var(--cream); outline-offset: 3px; }
.success .share-fallback {
  width: 100%;
  height: 32px;
  background: transparent;
  border: 1px solid var(--cream);
  border-radius: 0;
  text-align: center;
  font-family: var(--aethon);
  font-weight: 700;
  font-size: 13px;
  color: #ffffff;
}

/* sound toggle (plumbing; flag currently off) */
.sound-toggle.snd-failed {
  border-color: var(--error);
  color: var(--error);
  cursor: not-allowed;
}
.sound-toggle.snd-failed::after {
  content: "";
  position: absolute;
  left: 6px;
  right: 6px;
  top: 50%;
  height: 2px;
  background: var(--error);
  rotate: -30deg;
}
.sound-toggle {
  position: relative;
  position: fixed;
  right: 24px;
  bottom: 20px;
  width: 40px;
  height: 40px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: 2.5px solid var(--cream);
  border-radius: 0;
  color: var(--cream);
  cursor: pointer;
}

@media (prefers-reduced-motion: reduce) {
  /* no success zoom, no stagger, no pulse; shards jump to warm */
  html.szoom.js .logo { opacity: 1; transform: scale(0.68966); transition: none; }
  html.szoom.landed .logo,
  html.szoom.js.settled.landed .logo { transform: scale(0.68966); transition: none; }
  html.szoom.landed .logo .cream { transition: none; }
  form.unform .submit,
  form.unform .field { translate: 0 0; transition: opacity 0.2s ease; transition-delay: 0s; }
  .success.pre { translate: 0 0; }
  .success.in { translate: 0 0; transition: opacity 0.2s ease; }
  .social.pulse a { animation: none; }
}

/* ============ Feature: depth travel (html.dt) ============
   Success now travels to the 404's depth: 145.39 / 78.89 = 1.84295. The
   layout carries 78.89 x 1.84295 = the same max() as the 404 page, Screen 2
   rests at scale(1/1.84295) = 0.54261, success releases to scale(1). The
   entry/exit z moves themselves are JS-driven inline (one z, two layers,
   same frame); these rules define the REST states. */
html.dt.szoom .logo {
  width: max(609.2vw, 1096.55vh);
  transform: scale(0.54261);
}
html.dt.szoom.js.zoom .logo,
html.dt.szoom.js.settled .logo { transform: scale(0.54261); }
/* success still wins over the dt rest rule: the world moves, you stay still */
html.dt.szoom.landed .logo,
html.dt.szoom.js.settled.landed .logo {
  transform: scale(1);
  transition: transform 1.4s cubic-bezier(0.16, 1, 0.3, 1);
}

/* the column arrives as one rigid object: no stagger, no per-child motion.
   Content visibility during travel is driven by JS opacity on .content. */
html.dt.js .column .reveal {
  opacity: 1;
  transform: none;
  transition: none;
}
html.dt.js.settled .column .reveal { transition: opacity 0.25s ease; }
.content { transform-origin: 50% 50%; }

/* cream fade rides the travel curve under dt */
html.dt.js.zoom .logo .cream {
  transition: fill-opacity 1s cubic-bezier(0.16, 1, 0.3, 1); /* = INTRO_TRAVEL_MS */
}

@media (prefers-reduced-motion: reduce) {
  html.dt.szoom.js .logo,
  html.dt.szoom.landed .logo,
  html.dt.szoom.js.settled.landed .logo { transform: scale(0.54261); transition: none; }
}

/* ============ Feature: glitch — waitlist screen 189:2128 ============
   Character panels at both edges, orange accents, white strokes, tracked
   callout frames. No shard layer on this screen. Resting geometry is kept;
   only surface treatments change (a mid-glitch reflow would read as a bug). */
.gl-wash, .gl-panel { display: none; }
html.glitched .plx { display: none; } /* the shard layer is absent here */
html.glitched .gl-wash {
  display: block;
  position: absolute;
  left: 50%;
  translate: -50% 0;
  bottom: 3.25%;
  width: 516px;
  height: 539px;
  background: rgba(251, 124, 42, 0.3);
  filter: blur(177px);
  pointer-events: none;
}
html.glitched .gl-panel {
  display: block;
  position: absolute;
  top: 0;
  bottom: 0;
  width: 372px;
  overflow: hidden;
  pointer-events: none;
}
.gl-left { left: 0; }
.gl-right { right: 0; }
.gl-orange {
  position: absolute;
  width: 296px;
  height: 437px;
  background: #fb7c2a;
  filter: blur(147px);
}
.gl-left .gl-orange { left: 0; bottom: 0; }
.gl-right .gl-orange { left: 60px; bottom: -90px; }
.gl-char { position: absolute; }
.gl-left .gl-char { left: 0; top: 0; width: 335px; }
.gl-right .gl-char { left: 0; top: 40px; width: 372px; height: 760px; }
.gl-right .gl-v8 { position: absolute; left: -202.38px; top: 39.89px; width: 391.98px; height: 424.72px; }
.gl-fade {
  position: absolute;
  inset: 0;
  /* the visible band of the 1796px transparent-to-black wash */
  background: linear-gradient(to bottom, rgba(0, 0, 0, 0.55), #000000);
}
.gl-line { position: absolute; inset: 0; width: 100%; height: 100%; }
.gl-line line { stroke: rgba(255, 255, 255, 0.7); stroke-width: 1; }
.gl-callout {
  position: absolute;
  width: 158px;
  height: 163px;
  border: 1px solid rgba(255, 255, 255, 0.4);
}
.gl-face { left: 195px; top: 154px; }
.gl-skull { left: 6px; top: 84px; }
.gl-grad {
  position: absolute;
  left: -1px;
  bottom: -1px;
  width: 158px;
  height: 125px;
  background: linear-gradient(to bottom, #000000 0.9%, #fb8327);
  opacity: 0.27;
}
.gl-ellipse {
  position: absolute;
  width: 75px;
  height: 75px;
  border-radius: 50%;
  background: #000000;
  filter: blur(28px);
}
.gl-face .gl-ellipse { left: calc(50% + 1.5px); bottom: -30px; translate: -50% 0; }
.gl-skull .gl-ellipse { left: calc(50% + 0.5px); top: 50%; translate: -50% -50%; }
.gl-callout > img { position: absolute; left: 3px; top: 3px; width: 150px; height: 155px; }
.gl-tick {
  position: absolute;
  width: 8px;
  height: 8px;
  background: #ffffff;
}
.gl-tick.tl { left: -5px; top: -5px; }
.gl-tick.tr { right: -5px; top: -5px; }
.gl-tick.bl { left: -5px; bottom: -5px; }
.gl-tick.br { right: -5px; bottom: -5px; }

/* content treatments (geometry untouched — the Figma's 767px rebuild of the
   column is treated as a duplication artifact, not a deliberate reflow) */
html.glitched .lockup-wraith span { color: #ffffff; }
html.glitched .lockup-bar { background: #ffffff; }
html.glitched .lockup-box { position: relative; overflow: visible; }
html.glitched .lockup-box::before,
html.glitched .lockup-box::after {
  content: "";
  position: absolute;
  width: 8px;
  height: 8px;
  background: #ffffff;
  bottom: -4px;
}
html.glitched .lockup-box::before { left: -3.76px; }
html.glitched .lockup-box::after { left: 206.24px; }
html.glitched .headline h1,
html.glitched .headline .sub { color: #ffffff; }
html.glitched .headline h1 {
  font-family: "Basic", var(--aethon);
  font-weight: 400;
  text-transform: none; /* sentence case */
  line-height: 60px;
}
html.glitched .headline .sub,
html.glitched .field input,
html.glitched .chip {
  font-family: "Basic", var(--aethon);
  font-weight: 400;
}
/* Basic's natural leading is 5px taller at 20px; pin it or the centred
   column shifts 2.5px on the cut */
html.glitched .headline .sub { line-height: 20px; }
html.glitched .submit,
html.glitched .social a {
  font-family: "Anybody", var(--shattered);
  font-weight: 600;
  font-size: 25px;
  letter-spacing: 0;
  text-indent: 0;
}
/* two-line container pinned so rest and glitch occupy identical geometry */
.headline h1 { height: 120px; }
html.glitched .field {
  background: rgba(255, 255, 255, 0.15);
  outline: 1px solid rgba(255, 255, 255, 0.2);
  outline-offset: -1px;
}
html.glitched .field:focus-within { outline-color: #ffffff; }
html.glitched .chip {
  background: #262626;
  border: 1px solid #ffffff;
  padding: 4px; /* 5px - 1px border: same outer box, no layout shift */
  color: #ffffff;
}
html.glitched .submit .shard-l,
html.glitched .submit .shard-r { display: none; }

/* ---- Torn banner submit (Figma 236:1489) ----
   Replaces the gold gradient on the glitch screen. html.torn-rest would
   extend it to the resting screen — not set anywhere; pending the call on
   whether #16171B reads against resting black.
   Layout slot stays 60px: the Figma body ("Rectangle 103") is 61.3px tall
   and the remaining 16px of the 77.32px node is shard overflow
   (clipsContent: false), so it overflows instead of growing the column —
   the wordmark and headline cannot move. */
.submit .torn { display: none; }
:is(html.glitched, html.torn-rest) .submit {
  background: transparent;
  overflow: visible;
  font-family: var(--shattered);
  font-weight: 700;
  font-size: 23px;
  letter-spacing: 0.1em;
  text-indent: 0.1em;
  color: #ffffff;
}
:is(html.glitched, html.torn-rest) .submit::before { display: none; }
:is(html.glitched, html.torn-rest) .submit .shard-l,
:is(html.glitched, html.torn-rest) .submit .shard-r { display: none; }
:is(html.glitched, html.torn-rest) .submit .torn {
  display: block;
  position: absolute;
  z-index: -1;
  left: 0;
  width: 100%;
  aspect-ratio: 400 / 77.3193;
  /* body centre (y 38.09 of 77.32) sits on the slot centre at any width */
  top: 50%;
  translate: 0 -49.26%;
  pointer-events: none;
}
.submit .torn svg { display: block; width: 100%; height: 100%; overflow: visible; }
.submit .torn-pale { opacity: 0; } /* as in Figma */
/* the label centres on the body, not the node: Figma x 209.76 of 400 */
:is(html.glitched, html.torn-rest) .submit-label {
  position: relative;
  left: 2.44%;
  white-space: nowrap;
}
/* glow: the same cursor-tracked ellipse, clipped to the torn body */
.submit .torn-glow {
  position: absolute;
  inset: 0;
  overflow: hidden; /* a mask hides the ellipse but doesn't clip layout */
  -webkit-mask: var(--torn-mask) center / 100% 100% no-repeat;
  mask: var(--torn-mask) center / 100% 100% no-repeat;
  opacity: 0;
  transition: opacity 0.2s ease;
}
.submit .torn-glow i {
  position: absolute;
  width: 305px;
  height: 51px;
  border-radius: 50%;
  background: var(--glow);
  filter: blur(28px);
  /* --gx/--gy are in button coordinates; the torn box starts above it */
  left: calc(var(--gx, 50%) - 152.5px);
  /* torn box top = slot centre (30px) - 49.26% of its own height */
  top: calc(var(--gy, 30px) - 25.5px - 30px + 49.26%);
}
.submit {
  --torn-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 400 77.3193'%3E%3Cpath d='M145.686 11.4854L145.588 11.875L399.098 7.42773L400 13.7402L386.924 29.0713H386.923L376.102 36.7373L387.513 29.8076L392.334 35.835L370.69 56.126L267.317 60.249L259.796 55.7549L264.842 60.3477L206.305 62.6826L204.755 67.8496L199.846 62.9404L181.511 63.6709L180.856 66.9482L172.147 64.0449L169.212 64.1621L156.057 77.3193L148.842 65.5947V71.9082L136.521 66.5176L136.667 66.4971L139.823 53.4209L134.158 65.5596L85.2812 67.5098L82.5576 73.2607L80.7539 69.2021L80.6348 69.2305L99.6914 23.6602L77.8574 69.8965L69.4814 71.9082V68.1396L54.1504 68.752L86.8447 18.7002H86.6162L94.2812 5.62402L152.449 3.82031L145.686 11.4854Z M172.739 37.1885C171.743 37.1891 170.937 38.3998 170.937 39.8936C170.937 41.3872 171.744 42.598 172.739 42.5986C173.735 42.5986 174.543 41.3876 174.543 39.8936C174.543 38.3994 173.735 37.1885 172.739 37.1885Z M119.081 36.2861V33.1299L113.67 29.9736L119.081 36.2861Z M130.354 29.9736L133.06 32.6787L138.02 22.7588L130.354 29.9736Z'/%3E%3C/svg%3E");
}
.submit .torn-shards { transition: translate 0.3s cubic-bezier(0.22, 1, 0.36, 1); }
@media (hover: hover) and (pointer: fine) {
  .submit:hover .torn-glow { opacity: 1; }
  @media (prefers-reduced-motion: no-preference) {
    .submit:hover .torn-shards { translate: -14px -6px; }
  }
}
.submit.glow-on .torn-glow { opacity: 1; transition: opacity 0.12s ease; }
@media (prefers-reduced-motion: no-preference) {
  .submit.press .torn-shards { translate: -14px -6px; }
}
/* the ring clears the overflowing shards */
:is(html.glitched, html.torn-rest) .submit:focus-visible { outline-color: #ffffff; outline-offset: 12px; }
html.glitched .social a {
  background: #000000;
  border: 1px solid #ffffff;
  color: #ffffff;
}
html.glitched .social .shard { display: none; }

/* Transition fx: discrete stepped slice displacement on the background
   field (feDisplacementMap driven by generated band maps), channel split on
   type only, wordmark anchored — sharp and unmoved so the shearing around
   it stays legible. Hard steps, no tweening. */
html.fx-pre .bg, html.fx-pre .nf-bg { filter: url(#wotv-fx-pre); }
html.fx-s1 .bg, html.fx-s1 .nf-bg { filter: url(#wotv-fx-1); }
html.fx-s2 .bg, html.fx-s2 .nf-bg { filter: url(#wotv-fx-2); }
html.fx-s3 .bg, html.fx-s3 .nf-bg { filter: url(#wotv-fx-3); }

/* Lite tear (html.fx-lite — phones, Safari, or any device that stalled):
   WebKit runs SVG filters on HTML in software, and the background layer is
   ~9000px on a portrait phone, so the displacement step froze iOS outright.
   Same stepped, unweighted shear, done with compositor-only transforms. */
html.fx-lite.fx-pre .bg, html.fx-lite.fx-pre .nf-bg,
html.fx-lite.fx-s1 .bg, html.fx-lite.fx-s1 .nf-bg,
html.fx-lite.fx-s2 .bg, html.fx-lite.fx-s2 .nf-bg,
html.fx-lite.fx-s3 .bg, html.fx-lite.fx-s3 .nf-bg,
html.fx-lite.fx-cyc .nf-bg, html.fx-lite.fx-cyc .nf-wrap { filter: none; }
html.fx-lite.fx-pre .bg, html.fx-lite.fx-pre .nf-bg { translate: 14px 0; }
html.fx-lite.fx-s1 .bg, html.fx-lite.fx-s1 .nf-bg { translate: -34px 0; }
html.fx-lite.fx-s2 .bg, html.fx-lite.fx-s2 .nf-bg { translate: 46px 0; }
html.fx-lite.fx-s3 .bg, html.fx-lite.fx-s3 .nf-bg { translate: -18px 0; }
html.fx-lite.fx-cyc .nf-bg { translate: -24px 0; }

/* static scanlines through the step window — constant across steps, kept
   faint so the onset stays well under the 10% luminance band */
html.fx-split::after {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 90;
  pointer-events: none;
  background: repeating-linear-gradient(0deg, rgba(0, 0, 0, 0.1) 0 2px, transparent 2px 5px);
}

/* channel split: type only, never the wordmark (the anchor) */
html.fx-split .headline h1,
html.fx-split .headline .sub,
html.fx-split .field input,
html.fx-split .chip,
html.fx-split .submit-label,
html.fx-split .social a,
html.fx-split .success h2,
html.fx-split .success p,
html.fx-split .nf-404,
html.fx-split .nf-btn {
  text-shadow: var(--gsplit, 10px) 0 rgba(255, 60, 60, 0.55),
               calc(-1 * var(--gsplit, 10px)) 0 rgba(60, 200, 255, 0.55);
}

/* one frame of impact on the cut step: 1.5%, whole composition */
html.fx-punch .bg,
html.fx-punch .content,
html.fx-punch .nf-bg,
html.fx-punch .nf-wrap { scale: 1.015; }

/* the way out lingers: shards ease back to cream over 350ms while
   everything else snaps */
html.glitch-out .plx .logo .cream { transition: fill 0.35s ease; }

/* the glitch escape hatch is the Escape key (persisted), not a button */

@media (prefers-reduced-motion: reduce) {
  /* the engine never starts under reduced motion; belt-and-braces */
  html.fx-pre .bg, html.fx-s1 .bg, html.fx-s2 .bg, html.fx-s3 .bg { filter: none; }
}

/* ============ Touch parity ============ */
/* glow shown while the finger is down; 120ms in (touch feedback must feel
   instant), 200ms out from wherever it was */
.submit.glow-on::before,
.social a.glow-on::before {
  opacity: 1;
  transition: opacity 0.12s ease;
}
/* press = anticipation: shards slide while the finger is down */
@media (prefers-reduced-motion: no-preference) {
  .submit.press .shard-l { translate: -20px -30px; }
  .submit.press .shard-r { translate: 29px -38px; }
  .social a.press .shard { translate: -20px -24px; }
}
.column:not(.error-mode) .social.press-dim a:not(.press) {
  opacity: 0.45;
  transition: opacity 0.2s ease;
}


/* ============ Feature: thank-you sequence (195:2854) ============
   The card field is the whole celebration; 195:2936 (the cream card) is no
   longer on screen — it only renders into the SAVE YOUR VESSEL PNG. */
.ty-layer { position: fixed; inset: 0; z-index: 2; pointer-events: none; }
.ty-canvas { position: absolute; inset: 0; width: 100%; height: 100%; }
.ty-canvas.fade { opacity: 0; transition: opacity 0.3s ease; }
/* the persistent confirmation: they outlive the pops */
.ty-tag {
  position: absolute;
  z-index: 1;
  /* corners, lifted clear of the fixed sound toggle (bottom 20 + 40px) */
  bottom: 76px;
  width: 86px;
  height: 50px;
  padding: 5px;
  background: #4db04f;
  rotate: -10deg;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  font-family: var(--aethon);
  font-weight: 700;
  font-size: 20px;
  line-height: normal;
  color: #ffffff;
  border: 0;
  border-radius: 0;
  appearance: none;
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation; /* no double-tap zoom delay on the pop */
  pointer-events: none;
}
.ty-tag-l { left: 24px; }
.ty-tag-r { right: 24px; }
/* poppable once the page has landed (never during the field) */
.ty-landed .ty-tag { pointer-events: auto; cursor: pointer; transition: scale 0.15s ease; }
@media (hover: hover) and (pointer: fine) {
  .ty-landed .ty-tag:hover { scale: 1.06; }
}
.ty-tag:focus-visible { outline: 2px solid #ffffff; outline-offset: 3px; }
/* the field's tell: snap to 1.18 over 60ms, then it's gone */
.ty-landed .ty-tag.tell { scale: 1.18; transition: scale 0.06s ease-out; }
.ty-tag.gone { visibility: hidden; transition: none; }
.ty-tag.gone-soft { opacity: 0; transition: opacity 0.25s ease; }
/* and it comes back: dropped in, slight overshoot */
@keyframes ty-tag-back {
  0%   { opacity: 0; scale: 0.6; translate: 0 -18px; }
  65%  { opacity: 1; scale: 1.06; translate: 0 0; }
  100% { opacity: 1; scale: 1; translate: 0 0; }
}
.ty-tag.back { animation: ty-tag-back 0.42s cubic-bezier(0.34, 1.4, 0.64, 1) both; }
.ty-confetti {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 3;
  pointer-events: none;
}
.ty-logo-pop {
  position: absolute;
  left: 50%;
  top: 50%;
  translate: -50% -50%;
  width: 220px;
  aspect-ratio: 60.3371 / 60.0014;
  opacity: 0;
}
.ty-logo-pop svg { display: block; width: 100%; height: 100%; }
.ty-logo-pop .cream { fill-opacity: 1; }
.ty-logo-pop.burst {
  opacity: 0 !important;
  scale: 6;
  transition: opacity 0.32s ease-in, scale 0.32s ease-in;
}
/* the landed page: one centred stack; the bottom padding keeps it clear of
   the corner tags (76 + 50px, rotated) and it scrolls if a phone is short */
.ty-page {
  position: absolute;
  inset: 0;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: safe center;
  gap: 40px;
  padding: 40px 16px 150px;
  pointer-events: auto; /* so a short phone can scroll it */
}
.ty-extras {
  width: min(560px, 100%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  pointer-events: auto;
  opacity: 0;
  transition: opacity 0.5s ease;
}
.ty-extras.show { opacity: 1; }
.ty-extras .ty-title {
  font-family: var(--shattered);
  font-weight: 700;
  font-size: 30px;
  line-height: normal;
  letter-spacing: 0.1em;
  text-indent: 0.1em;
  text-transform: uppercase;
  color: var(--cream);
}
.ty-extras .ty-msg {
  margin-bottom: 8px;
  font-family: var(--aethon);
  font-weight: 700;
  font-size: 22px;
  line-height: 1.35;
  letter-spacing: 0.1em;
  text-indent: 0.1em;
  text-align: center;
  color: #ffffff;
}
.ty-extras .share-copy,
.ty-extras .vessel-count {
  font-family: var(--aethon);
  font-weight: 700;
  letter-spacing: 0.1em;
  text-indent: 0.1em;
  text-align: center;
  color: #ffffff;
}
.ty-extras .share-copy { font-size: 13px; }
.ty-extras .ty-position {
  font-family: var(--aethon);
  font-weight: 700;
  font-size: 15px;
  line-height: 1.7;
  letter-spacing: 0.1em;
  text-indent: 0.1em;
  text-align: center;
  color: var(--cream);
}
.ty-extras .vessel-count { font-size: 24px; }
.ty-extras .ty-actions {
  display: flex;
  gap: 12px;
  flex-wrap: wrap;
  justify-content: center;
}
.ty-extras .copy-link {
  height: 40px;
  padding: 0 22px;
  background: transparent;
  border: 2.5px solid var(--cream);
  border-radius: 0;
  font-family: var(--shattered);
  font-weight: 700;
  font-size: 20px;
  letter-spacing: 0.1em;
  text-indent: 0.1em;
  color: var(--cream);
  cursor: pointer;
}
.ty-extras .copy-link:focus-visible { outline: 2px solid var(--cream); outline-offset: 3px; }

/* the social row returns under the card, receded; hover brings one back */
.ty-socials {
  width: min(792px, 100%);
  pointer-events: auto;
  opacity: 0;
  transition: opacity 0.6s ease;
}
.ty-socials.show { opacity: 1; }
.ty-socials .social a { opacity: 0.45; }
@media (hover: hover) and (pointer: fine) {
  .ty-socials .social a:hover { opacity: 1; }
}

/* ============ Responsive ============ */
/* 1024–1439: scale the whole column proportionally, no reflow */
@media (min-width: 1024px) and (max-width: 1439.98px) {
  .column { transform: scale(calc(100vw / 1440)); }
}

/* Below 1024: reflow */
@media (max-width: 1023.98px) {
  .column { width: min(792px, calc(100vw - 48px)); }
  .headline h1 {
    width: 100%;
    height: auto;
    font-size: clamp(32px, 7.4vw, 56px);
    line-height: 1;
  }
  .headline .sub {
    white-space: normal;
    font-size: 16px;
    max-width: 34em;
  }
  .waitlist, .submit, .success { width: min(400px, 100%); }
  .field .chip { left: auto; right: 0; font-size: 22px; }
  .social {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 20px;
    width: min(460px, 100%);
  }
  .social a { padding: 4px 10px; font-size: 24px; }
  .social a:nth-child(n) { width: 100%; }
  /* no room to hang the tooltip off the left edge on small screens */
  .field .tip { left: 4px; top: -60px; }
  .field .tip-arrow { display: none; }
  /* glitch screen: the 372px character panels don't fit a phone */
  html.glitched .gl-panel { display: none; }
  .ty-page { gap: 28px; }
  .ty-extras .ty-title { font-size: 26px; }
  .ty-extras .ty-msg { font-size: 17px; }
  .ty-extras .vessel-count { font-size: 19px; }
}
