/* Whaaack! project site — self-contained, no framework.
   Palette is lifted from the game itself (ui/theme/Theme.kt), so the site and the app
   are visibly the same product. Dark-first, one warm accent, system font stack. */

:root {
  --cream: #fff3e6;
  --cream-dim: rgba(255, 243, 230, .70);
  --cream-faint: rgba(255, 243, 230, .48);
  --night: #2a1633;
  --bg: #140a1a;
  --bg-2: #1b1024;
  --panel: rgba(9, 20, 40, .55);
  --panel-solid: #12233d;
  --line: rgba(255, 243, 230, .14);
  --line-strong: rgba(255, 243, 230, .28);
  --accent: #ffc97a;
  --accent-2: #f2704f;
  --accent-ink: #43162f;
  --gold: #f3c33c;
  --danger: #ff8a7a;
  --sky: #4c82d0;
  --radius: 18px;
  --radius-lg: 28px;
  --maxw: 1080px;
  --shadow: 0 18px 50px rgba(0, 0, 0, .45);
}

* { box-sizing: border-box; }

html { scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  margin: 0;
  /* clip, not hidden: hidden would make body a scroll container and break the sticky header. */
  overflow-x: clip;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Inter, Roboto, Helvetica, Arial, sans-serif;
  color: var(--cream);
  background:
    radial-gradient(1000px 560px at 78% -8%, rgba(255, 201, 122, .13), transparent 62%),
    radial-gradient(760px 420px at -8% 8%, rgba(242, 112, 79, .10), transparent 58%),
    var(--bg);
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
}

.wrap { width: min(var(--maxw), calc(100% - 40px)); margin-inline: auto; }

a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }

h1, h2, h3 { line-height: 1.15; margin: 0 0 .5em; font-weight: 900; letter-spacing: -.02em; }
h1 { font-size: clamp(2.6rem, 7vw, 4.6rem); }
h2 { font-size: clamp(1.7rem, 3.6vw, 2.5rem); }
h3 { font-size: 1.12rem; }
p { margin: 0 0 1em; }

.eyebrow {
  display: inline-block;
  font-size: .72rem;
  font-weight: 800;
  letter-spacing: .22em;
  text-transform: uppercase;
  color: var(--cream-dim);
  background: rgba(9, 20, 40, .6);
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 7px 15px;
  margin-bottom: 18px;
}

.lead { font-size: clamp(1.02rem, 2vw, 1.2rem); color: var(--cream-dim); max-width: 60ch; }

/* ---- parallax orchard ------------------------------------------------------------- */

.orchard {
  position: fixed;
  inset: 0;
  z-index: -1;
  overflow: hidden;
  background: linear-gradient(180deg, var(--sky) 0%, #3a5f9e 42%, var(--night) 100%);
}
.orchard span {
  position: absolute;
  left: 0;
  width: 100%;
  background-repeat: repeat-x;
  background-position: 0 bottom;
  image-rendering: pixelated;
  will-change: transform;
}
.orchard .sky   { inset: 0; background-image: url("../img/bg/bg-sky.png");   background-size: auto 100%; opacity: .85; }
.orchard .trees { bottom: 0; height: 63%; background-image: url("../img/bg/bg-trees.png"); background-size: auto 100%; }
.orchard .hills { bottom: 0; height: 63%; background-image: url("../img/bg/bg-hills.png"); background-size: auto 100%; }
.orchard .scrim {
  inset: 0;
  background: linear-gradient(180deg, rgba(20, 10, 26, .58) 0%, rgba(20, 10, 26, .74) 45%, rgba(20, 10, 26, .93) 100%);
}

/* ---- header ----------------------------------------------------------------------- */

.site-header {
  position: sticky;
  top: 0;
  z-index: 50;
  backdrop-filter: blur(14px);
  background: rgba(20, 10, 26, .72);
  border-bottom: 1px solid var(--line);
}
.site-header .wrap {
  display: flex;
  align-items: center;
  gap: 10px 14px;
  min-height: 62px;
  /* Wraps rather than overlapping the brand once the links no longer fit. */
  flex-wrap: wrap;
  padding-block: 8px;
}
.brand { display: flex; align-items: center; gap: 10px; font-weight: 900; font-size: 1.06rem; color: var(--cream); }
.brand:hover { text-decoration: none; }
.brand img { width: 30px; height: 30px; border-radius: 8px; image-rendering: pixelated; }
.nav { margin-left: auto; display: flex; gap: 18px; flex-wrap: wrap; }
.nav a { color: var(--cream-dim); font-size: .9rem; font-weight: 700; }
.nav a:hover, .nav a[aria-current="page"] { color: var(--accent); text-decoration: none; }

/* ---- buttons ---------------------------------------------------------------------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  font-weight: 900;
  font-size: 1rem;
  padding: 15px 26px;
  border-radius: 20px;
  border: 0;
  cursor: pointer;
  transition: transform .16s ease, box-shadow .16s ease, filter .16s ease;
}
.btn:hover { text-decoration: none; transform: translateY(-2px); }
.btn-primary {
  color: var(--accent-ink);
  background: linear-gradient(135deg, var(--accent), var(--accent-2));
  box-shadow: 0 6px 0 #a83c50, var(--shadow);
}
.btn-primary:hover { box-shadow: 0 8px 0 #a83c50, var(--shadow); }
.btn-primary:active { transform: translateY(3px); box-shadow: 0 3px 0 #a83c50; }
.btn-ghost { color: var(--cream); background: rgba(255, 243, 230, .12); border: 1px solid var(--line-strong); }
.btn-block { width: 100%; }

/* ---- hero ------------------------------------------------------------------------- */

/* overflow-hidden because .fruit-field deliberately bleeds past the content column; without
   it that bleed widens the document and every page scrolls sideways on a phone. */
.hero { padding: clamp(52px, 8vw, 96px) 0 clamp(36px, 5vw, 64px); overflow: hidden; }
/* The scattered fruit are positioned against this, so it has to be a containing block. */
.hero .wrap { position: relative; }
.hero-grid { display: grid; grid-template-columns: 1.05fr .95fr; gap: clamp(28px, 5vw, 64px); align-items: center; }
@media (max-width: 860px) { .hero-grid { grid-template-columns: 1fr; } }

.hero h1 { margin-bottom: .28em; }
.hero h1 .shout {
  background: linear-gradient(135deg, var(--accent) 15%, var(--accent-2) 85%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.hero-actions { display: flex; gap: 14px; flex-wrap: wrap; margin-top: 28px; }

.hero-stats { display: flex; gap: 26px; flex-wrap: wrap; margin-top: 34px; }
.hero-stats div { min-width: 84px; }
.hero-stats b { display: block; font-size: 1.55rem; font-weight: 900; color: var(--accent); }
.hero-stats span { font-size: .68rem; font-weight: 800; letter-spacing: .16em; text-transform: uppercase; color: var(--cream-faint); }

/* ---- phone frame ------------------------------------------------------------------ */

.phone {
  position: relative;
  width: min(300px, 78vw);
  margin-inline: auto;
  aspect-ratio: 1080 / 2340;
  border-radius: 34px;
  padding: 9px;
  background: linear-gradient(160deg, #4a3550, #1a1020);
  box-shadow: var(--shadow), 0 0 0 1px rgba(255, 243, 230, .12);
}
.phone img { width: 100%; height: 100%; object-fit: cover; border-radius: 26px; display: block; }
.phone::after {
  content: "";
  position: absolute;
  top: 20px; left: 50%;
  translate: -50% 0;
  width: 78px; height: 5px;
  border-radius: 999px;
  background: rgba(0, 0, 0, .55);
}
.phone.tilt { rotate: -3deg; }
.phone.tilt-r { rotate: 3deg; }

/* ---- floating fruit --------------------------------------------------------------- */

/* Decorative only: sits behind the hero copy, never intercepts a click. */
/* Bleeds well past the content column so the fruit can sit outside the copy rather than
   on top of it. Clipped by the viewport, not by this. */
.fruit-field { position: absolute; inset: -8% -14%; pointer-events: none; z-index: 0; }
.hero-grid { position: relative; z-index: 1; }
.fruit-field img {
  position: absolute;
  width: 46px;
  image-rendering: pixelated;
  opacity: .9;
  filter: drop-shadow(0 8px 14px rgba(0, 0, 0, .5));
  animation: bob 6s ease-in-out infinite;
}
@keyframes bob {
  0%, 100% { transform: translateY(0) rotate(-6deg); }
  50%      { transform: translateY(-18px) rotate(6deg); }
}
@media (prefers-reduced-motion: reduce) { .fruit-field img { animation: none; } }

/* ---- sections --------------------------------------------------------------------- */

.section { padding: clamp(52px, 8vw, 96px) 0; position: relative; }
.section-head { max-width: 62ch; margin-bottom: 40px; }

.cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 18px; }
.card {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: 24px;
  backdrop-filter: blur(6px);
  transition: transform .2s ease, border-color .2s ease;
}
.card:hover { transform: translateY(-4px); border-color: var(--line-strong); }
.card .ico { font-size: 1.7rem; display: block; margin-bottom: 10px; }

/* A watch screenshot inside a card.

   Sized against the card rather than pinned at its own 360px, so a narrow column shrinks
   it instead of letting it overflow; `auto` height keeps the circle a circle at every
   width. Centred because a round image flush to one edge of a rectangular card reads as a
   mistake rather than as a decision. The `width`/`height` attributes stay on the tag so
   the space is reserved before it loads and the card does not jump. */
.watch-shot {
  display: block;
  width: 100%;
  max-width: 200px;
  height: auto;
  margin: 0 auto 16px;
}
.card .ico img { width: 38px; height: 38px; image-rendering: pixelated; }
.card p { color: var(--cream-dim); font-size: .95rem; margin: 0; }

.shots { display: flex; gap: 22px; overflow-x: auto; padding: 8px 4px 22px; scroll-snap-type: x mandatory; }
.shots figure { margin: 0; flex: 0 0 auto; scroll-snap-align: center; text-align: center; }
.shots figcaption { margin-top: 12px; font-size: .8rem; color: var(--cream-faint); font-weight: 700; letter-spacing: .08em; text-transform: uppercase; }

/* ---- ad-free strip ---------------------------------------------------------------- */

.gold-strip {
  background: rgba(243, 195, 60, .12);
  border: 1px solid rgba(243, 195, 60, .45);
  border-radius: var(--radius-lg);
  padding: 26px;
  display: flex;
  gap: 20px;
  align-items: center;
  flex-wrap: wrap;
}
.gold-badge {
  width: 54px; height: 54px;
  flex: 0 0 auto;
  display: grid; place-items: center;
  border-radius: 16px;
  background: rgba(243, 195, 60, .16);
  border: 1px solid rgba(243, 195, 60, .55);
}
.gold-strip h3 { color: var(--gold); margin-bottom: 4px; }
.gold-strip p { margin: 0; color: var(--cream-dim); font-size: .95rem; }

/* ---- prose (legal pages) ---------------------------------------------------------- */

.prose { max-width: 76ch; }
.prose h2 { margin-top: 2.1em; font-size: 1.45rem; }
.prose h3 { margin-top: 1.6em; color: var(--accent); font-size: 1.02rem; }
.prose ul, .prose ol { padding-left: 1.25em; color: var(--cream-dim); }
.prose li { margin-bottom: .5em; }
.prose p { color: var(--cream-dim); }
.prose strong { color: var(--cream); }
.prose table { width: 100%; border-collapse: collapse; margin: 1.2em 0; font-size: .92rem; }
.prose th, .prose td { text-align: left; padding: 11px 13px; border-bottom: 1px solid var(--line); vertical-align: top; }
.prose th { color: var(--cream); font-weight: 800; }
.prose td { color: var(--cream-dim); }
.prose .table-scroll { overflow-x: auto; }

.callout {
  border-left: 3px solid var(--accent);
  background: rgba(255, 201, 122, .09);
  border-radius: 0 14px 14px 0;
  padding: 16px 20px;
  margin: 1.6em 0;
}
.callout p:last-child { margin-bottom: 0; }
.callout.danger { border-left-color: var(--danger); background: rgba(226, 87, 76, .12); }

.updated { font-size: .85rem; color: var(--cream-faint); }

/* ---- contact form ----------------------------------------------------------------- */

.contact-form { max-width: 560px; }
.field { margin-bottom: 16px; }
.field label { display: block; font-size: .74rem; font-weight: 900; letter-spacing: .14em; text-transform: uppercase; color: var(--cream-dim); margin-bottom: 7px; }
.field input, .field textarea {
  width: 100%;
  padding: 13px 15px;
  border-radius: 14px;
  border: 1.5px solid var(--line-strong);
  background: rgba(9, 20, 40, .6);
  color: var(--cream);
  font: inherit;
  font-size: .96rem;
}
/*
  Keyboard focus.

  The rule below used to be `outline: 0` with the ring replaced by a 1px border tint, and it
  was the only focus styling on the site apart from the skip link — so every nav link, footer
  link, button and the submit control had no visible focus indicator at all. That is a WCAG
  2.4.7 failure outright, and the 1px swap on the inputs additionally failed 2.4.11, which
  wants the indicator to be distinguishable from the unfocused state by more than a hairline.

  :focus-visible rather than :focus, so a mouse click on a button does not leave a ring behind
  it — the indicator appears for keyboard and switch navigation, which is who needs it.
*/
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: 4px;
}

.field input:focus-visible, .field textarea:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}

.field input:focus, .field textarea:focus { border-color: var(--accent); }
.field textarea { resize: vertical; }
.h-captcha { margin-bottom: 18px; }

/* ---- password reset (/whaaack/auth/) -----------------------------------------------

   One field and a way to read it back. There is no confirm-it-twice field, because that
   field exists to catch a typo in text you cannot see — and the toggle beside this one
   lets you see it. The watch's settings page makes the same trade for the same reason.

   The toggle is sized off the input rather than given a height of its own, so the two
   stay level whatever the font does. */
.pw-row { display: flex; gap: 8px; align-items: stretch; }
.pw-row input { flex: 1 1 auto; min-width: 0; }
.pw-toggle {
  flex: 0 0 auto;
  padding: 0 16px;
  border-radius: 14px;
  border: 1.5px solid var(--line-strong);
  background: rgba(255, 243, 230, .10);
  color: var(--cream-dim);
  font: inherit;
  font-size: .86rem;
  font-weight: 800;
  cursor: pointer;
}
.pw-toggle:hover { color: var(--cream); border-color: var(--accent); }
.pw-hint { margin: 8px 0 0; font-size: .82rem; color: var(--cream-faint); }

/* ---- footer ----------------------------------------------------------------------- */

.footer { border-top: 1px solid var(--line); padding: 34px 0; margin-top: 40px; background: rgba(20, 10, 26, .72); }
.footer .wrap { display: flex; gap: 16px; justify-content: space-between; flex-wrap: wrap; font-size: .86rem; color: var(--cream-faint); }
.footer a { color: var(--cream-dim); }
.footer nav { display: flex; gap: 14px; flex-wrap: wrap; }

/* ---- scroll reveal (progressive enhancement; visible without JS) ------------------- */

.reveal { opacity: 1; }
.js .reveal { opacity: 0; transform: translateY(20px); transition: opacity .65s ease, transform .65s ease; }
.js .reveal.in { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
  .js .reveal { opacity: 1; transform: none; transition: none; }
}

.skip-link {
  position: absolute; left: -9999px;
  background: var(--accent); color: var(--accent-ink);
  padding: 10px 16px; border-radius: 0 0 12px 0; font-weight: 800; z-index: 100;
}
.skip-link:focus { left: 0; top: 0; }

/* Contact form: the captcha's own label, and where a rejected submit reports itself. */
.captcha-label {
  display: block;
  margin-bottom: 8px;
  font-size: .82rem;
  font-weight: 700;
  color: var(--cream-dim);
}

.form-error {
  margin: 0 0 14px;
  padding: 12px 14px;
  border: 1px solid rgba(242, 112, 79, .55);
  border-radius: 12px;
  background: rgba(242, 112, 79, .12);
  color: var(--cream);
  font-size: .9rem;
}

/* ====================================================================================
   Motion, and the two pieces that are more than decoration: a real recorded run in the
   hero, and a board you can actually whack.

   Everything below degrades. With JS off the fan is a plain row, the demo board stays
   empty and collapses, the video shows its poster and the counters show their final
   numbers. With prefers-reduced-motion nothing moves on its own.
   ==================================================================================== */

/* ---- scroll progress -------------------------------------------------------------- */

.scroll-progress {
  position: fixed;
  inset: 0 0 auto;
  height: 3px;
  z-index: 60;
  pointer-events: none;
}
.scroll-progress span {
  display: block;
  height: 100%;
  width: 100%;
  transform: scaleX(var(--p, 0));
  transform-origin: 0 50%;
  background: linear-gradient(90deg, var(--accent), var(--accent-2));
}

/* ---- store badge ------------------------------------------------------------------ */

.store-badge {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  padding: 10px 20px 10px 16px;
  border-radius: 14px;
  background: #0b0b0d;
  border: 1px solid rgba(255, 243, 230, .3);
  color: #fff;
  min-height: 58px;
  position: relative;
  overflow: hidden;
  transition: transform .16s ease, border-color .16s ease;
}
a.store-badge:hover {
  transform: translateY(-2px);
  border-color: rgba(255, 243, 230, .6);
  text-decoration: none;
}
.store-glyph { width: 26px; height: 26px; flex: 0 0 auto; }
.store-text { display: flex; flex-direction: column; line-height: 1.12; }
.store-text small {
  font-size: .62rem;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, .78);
}
.store-text b { font-size: 1.18rem; font-weight: 700; letter-spacing: .01em; }

/* Not a link while there is no listing. Reads as a badge rather than as a button that
   ignores you. */
.store-badge.is-soon { cursor: default; opacity: .92; }
.store-badge.is-soon .store-glyph { filter: saturate(.85); }

/* A slow sheen, so a badge that cannot be clicked yet still looks alive. */
.store-badge::after {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: -60%;
  width: 40%;
  background: linear-gradient(100deg, transparent, rgba(255, 255, 255, .16), transparent);
  animation: sheen 5.5s ease-in-out infinite;
}
@keyframes sheen {
  0%, 65% { left: -60%; }
  100%    { left: 130%; }
}

.pkg { margin-top: 14px; font-size: .82rem; color: var(--cream-faint); }
.pkg code {
  background: rgba(9, 20, 40, .6);
  border: 1px solid var(--line);
  border-radius: 7px;
  padding: 2px 7px;
}

/* ---- the hero's floating screens ---------------------------------------------------- */

/* Two real captures stacked and tilted, the front one drifting. Modelled on the Helena
   site's hero, which does the same thing with two app windows. */

.hero-box {
  position: relative;
  /* Sized by height, not width. Helena floats two landscape app windows, where a width
     percentage works; these are 9:20 phone screens, and at 74% of the column they were a
     thousand pixels tall and got cut off by the hero's own overflow clip. */
  aspect-ratio: 1 / 1.02;
  max-width: 520px;
  margin-inline: auto;
  perspective: 1200px;
  /* Pointer tilt writes --rx/--ry; the whole stack leans together. */
  transform: perspective(1200px) rotateX(var(--rx, 0deg)) rotateY(var(--ry, 0deg));
  transition: transform .3s ease;
  will-change: transform;
}
.hero-box .glow {
  position: absolute;
  inset: -4% -6% -8% -6%;
  z-index: 0;
  pointer-events: none;
  background: radial-gradient(58% 58% at 55% 45%, rgba(255, 201, 122, .32), transparent 70%);
  filter: blur(14px);
}
.hero-box .win {
  position: absolute;
  margin: 0;
  border-radius: 20px;
  overflow: hidden;
  background: #12233d;
  box-shadow: var(--shadow), 0 0 0 1px rgba(255, 243, 230, .14);
}
.hero-box .win img { height: 100%; width: auto; display: block; }
.hero-box .win-back {
  top: 0;
  right: 2%;
  height: 80%;
  z-index: 1;
  opacity: .82;
  rotate: 4deg;
}
.hero-box .win-front {
  bottom: 0;
  left: 2%;
  height: 94%;
  z-index: 2;
  rotate: -2.5deg;
  --drift: -14px;
  animation: drift 7s ease-in-out infinite;
}
@keyframes drift { 50% { translate: 0 var(--drift, -12px); } }

.stage-note {
  margin: 20px 0 0;
  text-align: center;
  font-size: .76rem;
  letter-spacing: .1em;
  text-transform: uppercase;
  font-weight: 800;
  color: var(--cream-faint);
}

@media (max-width: 860px) {
  /* Overlapping a stack inside a single column just makes both unreadable. */
  .hero-box { aspect-ratio: auto; max-width: 260px; }
  .hero-box .win { position: relative; rotate: none; animation: none; height: auto; }
  .hero-box .win img { width: 100%; height: auto; }
  .hero-box .win-back { display: none; }
  .hero-box .win-front { inset: auto; }
}

/* ---- the screenshot fan ----------------------------------------------------------- */

/* Full bleed, so the fan can spread past the content column. */
.fan-rail { width: 100%; overflow: hidden; padding: 10px 0 30px; }
.fan {
  display: flex;
  justify-content: center;
  align-items: flex-start;
  /* --fan runs 0 to 1 as the section crosses the viewport; site.js writes it. Default 1
     so that without JS the fan is simply open. */
  --fan: 1;
}
.fan figure {
  margin: 0;
  flex: 0 0 auto;
  width: min(210px, 42vw);
  text-align: center;
  /* Shut, the four overlap into a deck; open, they spread out and straighten up. */
  --spread: calc(var(--i) - 1.5);
  margin-inline: calc(-34px + var(--fan) * 34px);
  rotate: calc(var(--spread) * (7deg - var(--fan) * 4deg));
  translate: 0 calc(abs(var(--spread)) * (26px - var(--fan) * 18px));
  transform-origin: 50% 120%;
  transition: rotate .4s ease, translate .4s ease, margin-inline .4s ease;
  z-index: 1;
}
.fan figure:hover { z-index: 3; }
.fan figure:hover .phone { transform: translateY(-14px) scale(1.04); }
.fan .phone {
  width: 100%;
  aspect-ratio: 540 / 1205;
  transition: transform .28s ease;
}
.fan figcaption {
  margin-top: 14px;
  font-size: .74rem;
  color: var(--cream-faint);
  font-weight: 800;
  letter-spacing: .1em;
  text-transform: uppercase;
}
@media (max-width: 720px) {
  /* A fan of four is a hand of playing cards on a phone. Two rows read better. */
  .fan { flex-wrap: wrap; gap: 18px 10px; }
  .fan figure { width: min(150px, 40vw); margin-inline: 0; rotate: none; translate: none; }
}

/* ---- the closing strip ------------------------------------------------------------ */

.get-strip {
  display: flex;
  gap: 26px;
  align-items: center;
  flex-wrap: wrap;
  justify-content: space-between;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: clamp(22px, 4vw, 34px);
  backdrop-filter: blur(6px);
}
.get-actions { display: flex; gap: 14px; align-items: center; flex-wrap: wrap; }

/* ---- staggered reveal ------------------------------------------------------------- */

.js .reveal { transition-delay: calc(var(--i, 0) * 70ms); }

@media (prefers-reduced-motion: reduce) {
  .store-badge::after { animation: none; }
  .hero-box { transform: none; }
  .hero-box .win-front { animation: none; }
  .fan figure { rotate: none; translate: none; transition: none; }
  .scroll-progress { display: none; }
}
