/* ---------- Design tokens ---------- */
:root {
  --paper:      #F4F1E9;  /* warm paper base */
  --paper-2:    #ECE7DB;  /* slightly deeper panel */
  --ink:        #1E1D19;  /* near-black text */
  --ink-soft:   #55534B;  /* secondary text */
  --line:       #D8D2C4;  /* hairlines / borders */
  --green:      #1F6B49;  /* resolution only — it worked, it's sorted. never a button. */
  --green-dark: #164F36;
  --ochre:      #C98A2B;  /* take action, tap this — the one action colour */
  --ochre-soft: #F0DFC0;
  --shadow:     0 1px 2px rgba(30,29,25,.06), 0 8px 24px rgba(30,29,25,.06);

  /* Design 1a ("Proof First") brings in two webfonts: Schibsted Grotesk as
     the display/body face, IBM Plex Mono for small uppercase labels and
     counters. This is a deliberate reversal of the earlier system-font-only
     decision (made to avoid a render-blocking font request on cold mobile
     ad traffic) — the tradeoff is accepted here because it's what the
     chosen design direction specifies. */
  --font-body: "Schibsted Grotesk", system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --font-mono: "IBM Plex Mono", ui-monospace, Menlo, monospace;

  --wrap: 640px;
}

/* ----------------------------------------------------------------------
   PRE-LAUNCH CHECKLIST
   --ink-soft (#55534B) on --paper (#F4F1E9) — computed contrast ratio is
   ~6.83:1 (checked 2026-07-31). Passes WCAG AA (4.5:1) for normal text at
   every size this token is used at, including the 13px microcopy/eyebrow
   sizes where the margin is closest. Does not reach AAA (7:1) but AAA was
   never the target. Re-check this if either --ink-soft or --paper changes.
   ---------------------------------------------------------------------- */

/* ---------- Reset-ish ---------- */
* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; overflow-x: clip; }
body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: 17px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: clip;
}
img, svg { display: block; max-width: 100%; }

/* ---------- Layout helpers ---------- */
.wrap { width: 100%; max-width: var(--wrap); margin: 0 auto; padding: 0 22px; }

/* ---------- Type ---------- */
h1, h2 { margin: 0; font-weight: 800; letter-spacing: -0.02em; line-height: 1.1; }
h3 { margin: 0; font-weight: 700; letter-spacing: -0.01em; line-height: 1.1; }
p { margin: 0 0 1em; }
.eyebrow {
  font: 600 11px var(--font-mono);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--green);
  margin: 0 0 14px;
}

/* ---------- Header bar ---------- */
.topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 26px 22px 0;
  max-width: var(--wrap);
  margin: 0 auto;
}
.topbar .brand { display: flex; align-items: center; gap: 7px; font-weight: 700; font-size: 15px; letter-spacing: -0.01em; }
.topbar .brand .logo-mark { width: 30px; height: 30px; color: var(--ink); flex: none; }
.topbar .badge {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-soft);
  border: 1px solid var(--line);
  border-radius: 99px;
  padding: 4px 9px;
}

/* ---------- Hero ---------- */
.hero { padding-top: 26px; padding-bottom: 0; }
.hero h1 {
  font-size: clamp(30px, 8.5vw, 36px);
  line-height: 1.05;
  overflow-wrap: anywhere;
  min-width: 0;
  text-wrap: balance;
}
.hero .lede {
  margin-top: 14px;
  font-size: 17px;
  line-height: 1.45;
  color: var(--ink-soft);
  max-width: 32ch;
}

/* ---------- Camera hook ---------- */
.hook { padding: 22px 22px 0; }
.hook-frame {
  position: relative;
  border-radius: 24px;
  overflow: hidden;
  background: var(--paper-2);
  aspect-ratio: 1 / 1;
}
.hook-frame .stripes {
  position: absolute;
  inset: 0;
  background: repeating-linear-gradient(135deg, #e3ddcd 0 10px, #ece7db 10px 20px);
}
.hook-frame .caption {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  font: 500 10.5px/1.5 var(--font-mono);
  letter-spacing: 0.05em;
  color: #8b8577;
  text-align: center;
  padding: 0 20px;
}
.hook-frame.shot .caption { display: none; }

/* Viewfinder corner brackets — reads as a camera's focus reticle, not a
   re-drawn OS/app chrome. Fades out once the shot is taken, same as a
   real camera UI would once it's done focusing. */
.viewfinder {
  position: absolute;
  inset: 14px;
  width: calc(100% - 28px);
  height: calc(100% - 28px);
  pointer-events: none;
  transition: opacity .3s ease;
}
.viewfinder path {
  fill: none;
  stroke: rgba(30,29,25,.55);
  stroke-width: 2.5;
  stroke-linecap: round;
  vector-effect: non-scaling-stroke;
}
.hook-frame.scanning .viewfinder,
.hook-frame.revealed .viewfinder { opacity: 0; }

/* Flash: a single quick white pulse the instant the shutter is tapped */
.hook-flash {
  position: absolute;
  inset: 0;
  background: #fff;
  pointer-events: none;
  opacity: 0;
}
.hook-frame.scanning .hook-flash { animation: flashPop .5s ease forwards; }

/* Scan: a soft ochre band sweeping down while "grading" */
.hook-scan {
  position: absolute;
  left: 0; right: 0;
  height: 26%;
  background: linear-gradient(180deg, rgba(201,138,43,0), rgba(201,138,43,.4));
  opacity: 0;
  pointer-events: none;
}
.hook-frame.scanning .hook-scan {
  opacity: 1;
  animation: scanSweep 1.1s .25s linear;
}

/* Result: the worked example, revealed once grading finishes */
.hook-result {
  position: absolute;
  left: 12px; right: 12px; bottom: 12px;
  display: none;
}
.hook-frame.revealed .hook-result { display: block; animation: riseIn .4s ease forwards; }
.hook-result-card {
  background: rgba(244,241,233,.96);
  border-radius: 18px;
  padding: 16px 18px;
}
.hook-result-card .lead { font-size: 13px; color: var(--ink-soft); margin-bottom: 10px; }
.hook-result-card .result-body { display: flex; align-items: center; gap: 12px; }
.hook-result-card .result-icon { flex: 0 0 auto; width: 44px; height: 44px; }
.hook-result-card .result-text { flex: 1; min-width: 0; }
/* Named .hook-item-name, not .item — the cascade below defines a global
   .item { opacity: 0 } for its travelling squares, which was silently
   hiding this text when both shared the same class name. */
.hook-result-card .row { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
.hook-result-card .hook-item-name { font-size: 21px; font-weight: 800; letter-spacing: -0.02em; overflow-wrap: anywhere; }
.hook-result-card .price { font-size: 21px; font-weight: 800; letter-spacing: -0.02em; color: var(--green); white-space: nowrap; }
.hook-result-card .chips { margin-top: 8px; display: flex; gap: 6px; flex-wrap: wrap; }
.hook-result-card .chip {
  font-size: 12px;
  font-weight: 600;
  color: var(--green-dark);
  background: #E1EDE5;
  border-radius: 99px;
  padding: 5px 10px;
}

/* Real camera-style shutter: a ring with a filled dot, like an actual
   phone camera app's capture button, rather than a text pill. */
.hook-shutter {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  bottom: 18px;
  width: 62px;
  height: 62px;
  border-radius: 50%;
  background: transparent;
  border: none;
  padding: 0;
  cursor: pointer;
}
.shutter-ring {
  display: grid;
  place-items: center;
  width: 100%;
  height: 100%;
  border-radius: 50%;
  border: 3px solid #fff;
  box-shadow: 0 2px 10px rgba(30,29,25,.25);
}
.shutter-dot {
  width: 48px;
  height: 48px;
  border-radius: 50%;
  background: #fff;
  transition: transform .12s ease, background .18s ease;
}
.hook-shutter:active .shutter-dot { transform: scale(.88); }
.hook-frame.scanning .shutter-dot { background: var(--ochre); }
.hook-frame.scanning .hook-shutter { pointer-events: none; }
.hook-frame.revealed .hook-shutter { display: none; }
.hook-shutter:focus-visible { outline: 3px solid var(--ochre); outline-offset: 4px; }
.hook-note { margin: 12px 2px 0; font-size: 13.5px; color: var(--ink-soft); text-align: center; }

/* ---------- Survey ("soft gate") ----------
   Unlike a hard gate, nothing below this is hidden — all three questions
   show at once, answers are changeable any time, and the CTA just dims
   until all three are answered. Fully visible in the page's normal scroll
   order, no separate "screen". */
.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;
}

/* ---------- Hard gate ----------
   Screen 2 (everything from "How it works" down, including the footer)
   isn't reachable/interactive until the survey is complete, but it's not
   fully hidden either — a dimmed, blurred, non-interactive hint of it
   stays visible through the gate, so scrolling past the survey signals
   "there's more, finish this first" rather than the page just ending.
   .gated is removed from <body> once all 3 are answered; the opacity/
   blur transition below handles the reveal automatically, no JS-driven
   animation needed. */
.screen-two {
  transition: opacity .5s ease, filter .5s ease;
}
body.gated .screen-two {
  opacity: .16;
  filter: blur(3px) saturate(70%);
  pointer-events: none;
  user-select: none;
}
body.gated .sticky { display: none; }

.survey { padding: 26px 22px 30px; }
.survey-progress-row { display: flex; align-items: center; gap: 10px; margin-bottom: 4px; }
.survey-bar { flex: 1; height: 3px; border-radius: 2px; background: var(--line); overflow: hidden; }
.survey-bar-fill { height: 100%; background: var(--ochre); border-radius: 2px; transition: width .3s ease; }
.survey-count { font: 600 10.5px var(--font-mono); color: #8b8577; letter-spacing: 0.06em; }
.survey-intro { margin: 12px 0 18px; font-size: 14.5px; color: var(--ink-soft); }

.q-block { margin-bottom: 22px; }
.q-block .q-text {
  margin: 0 0 10px;
  font-size: 16.5px;
  font-weight: 700;
  letter-spacing: -0.01em;
  line-height: 1.3;
  max-width: 30ch;
}
.q-opts { display: flex; flex-wrap: wrap; gap: 8px; }
.q-opt {
  font: 600 14.5px var(--font-body);
  text-align: left;
  cursor: pointer;
  padding: 11px 15px;
  min-height: 44px;
  border-radius: 99px;
  border: 1.5px solid var(--line);
  background: #fff;
  color: var(--ink);
  transition: border-color .16s ease, background .16s ease, color .16s ease;
}
.q-opt:hover { border-color: var(--ink); }
.q-opt:focus-visible { outline: 3px solid var(--ochre); outline-offset: 2px; }
.q-opt.picked { border-color: var(--ink); background: var(--ink); color: var(--paper); }

.survey-cta-wrap { margin-top: 6px; transition: opacity .3s ease; }
.survey-cta-wrap[data-locked="true"] { opacity: .35; pointer-events: none; }

/* ---------- How it works ---------- */
.how { background: var(--paper-2); padding: 32px 22px; border-top: 1px solid var(--line); }
.how .wrap { padding: 0; }
.how h2 { font-size: 25px; line-height: 1.15; margin-bottom: 20px; }

.steps { display: flex; flex-direction: column; gap: 10px; }
.step {
  display: flex;
  gap: 14px;
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: 16px;
  padding: 18px;
}
.step .num {
  flex: 0 0 auto;
  width: 30px; height: 30px;
  border-radius: 50%;
  display: grid; place-items: center;
  font-weight: 700; font-size: 14px;
  color: var(--green-dark);
  background: #fff;
  border: 1.5px solid var(--line);
}
.step h3 { font-size: 17px; margin-bottom: 3px; }
.step p { margin: 0; color: var(--ink-soft); font-size: 15px; line-height: 1.45; }

/* Proof card — a single worked example (item, grade, route), leading into
   the cascade below it as one worked example before the fuller animation.
   Same inline-SVG language as the cascade — kept from the earlier build
   per explicit instruction, alongside the cascade itself. */
.proof-card { margin: 14px 0 6px; max-width: 280px; }
.proof-bridge { margin: 14px 0 0; font-size: 15px; color: var(--ink-soft); }
.proof-card .proof-label { font: 600 10px var(--font-mono); fill: var(--ink-soft); letter-spacing: .04em; }
.proof-card .proof-grade { font: 800 13px var(--font-body); fill: var(--ink); }
.proof-card .proof-route { font: 600 11px var(--font-mono); fill: var(--green); }

/* The signature: routing cascade — the page's payoff visual for step 2,
   kept from the earlier build per explicit instruction (design 1a's own
   bar-chart alternative is not used). A stillness beat before it starts
   animating is timed in script.js, not here. */
.cascade-wrap { margin-top: 22px; margin-bottom: 4px; }
.cascade { width: 100%; height: auto; }
.bin-label { font: 600 10px var(--font-mono); fill: var(--ink-soft); letter-spacing: .04em; }

/* ---------- Why bother ---------- */
.why { padding: 32px 22px; }
.why h2 { font-size: 25px; line-height: 1.15; margin-bottom: 18px; }
.answer-echo {
  display: none;
  margin: -6px 0 18px;
  font-size: 16.5px;
  font-weight: 600;
  color: var(--ink-soft);
  line-height: 1.4;
}
.answer-echo.show { display: block; }

.grind { display: flex; flex-direction: column; border-top: 1px solid var(--line); }
.grind li {
  display: flex;
  gap: 12px;
  padding: 13px 0;
  border-bottom: 1px solid var(--line);
  list-style: none;
}
.grind li::before {
  content: "";
  flex: 0 0 6px;
  width: 6px; height: 6px;
  margin-top: 8px;
  border-radius: 3px;
  background: var(--ochre);
}
.grind li span { font-size: 15px; color: var(--ink-soft); line-height: 1.45; }
.grind { margin: 0; padding: 0; }

.relief {
  margin-top: 20px;
  border: 1.5px solid var(--green);
  background: #fff;
  border-radius: 16px;
  padding: 20px;
}
.relief .head { font-weight: 700; color: var(--green-dark); margin-bottom: 8px; font-size: 15px; }
.relief p { margin: 0; font-size: 15.5px; line-height: 1.45; }

/* ---------- Final capture ---------- */
.final { padding: 0 22px 34px; }
.final .card {
  background: var(--green);
  color: #fff;
  border-radius: 22px;
  padding: 28px 22px;
}
.final .card.done { display: none; }
.final h2 { font-size: 27px; line-height: 1.12; color: #fff; margin-bottom: 10px; }
/* :not(.microcopy) — without this, every property here (font-size
   included) leaks onto the "No spam..." line too, since this rule's
   specificity beats a bare .microcopy class selector. The previous fix
   only overrode margin and missed that font-size was leaking the same
   way, making the line render at 15.5px instead of its own 12.5px. */
.final .card p:not(.microcopy) { margin: 0 0 18px; font-size: 15.5px; line-height: 1.45; color: rgba(255,255,255,.86); max-width: 40ch; }

.field {
  width: 100%;
  font: 400 16px var(--font-body);
  padding: 15px 16px;
  border: none;
  border-radius: 12px;
  background: #fff;
  color: var(--ink);
  margin-bottom: 10px;
  transition: box-shadow .18s ease;
}
.field::placeholder { color: #9d988a; }
.field:focus {
  outline: none;
  box-shadow: 0 0 0 3px rgba(255,255,255,.5);
}

.btn {
  width: 100%;
  font: 700 16.5px var(--font-body);
  border: none;
  border-radius: 12px;
  padding: 16px 20px;
  background: var(--ochre);
  color: #241a08;
  cursor: pointer;
  box-shadow: 0 2px 0 #9c6a1e;
  transition: transform .12s ease, background .18s ease, box-shadow .12s ease;
}
.btn:hover { background: #b87d26; }
.btn:active { transform: translateY(2px); box-shadow: 0 0 0 #9c6a1e; }
.btn:focus-visible { outline: 3px solid var(--ink); outline-offset: 2px; }
.btn:disabled { cursor: default; opacity: .7; }

.microcopy { margin: 10px 0 0; font-size: 12.5px; color: rgba(255,255,255,.72); text-align: center; }

.form-note { margin-top: 12px; font-size: 15px; display: none; text-align: center; }
.form-note.show { display: block; }
.form-note.err { color: #ffd9d0; }

/* Success state — swaps in for the card once the form is submitted.
   Needs the same green "card" treatment as .final .card: without its own
   background, the white heading/text here is invisible against the
   page's paper background. */
.done-state {
  display: none;
  background: var(--green);
  border-radius: 22px;
  padding: 28px 22px;
}
.done-state.show { display: block; animation: riseIn .35s ease; }
.done-icon {
  width: 46px; height: 46px;
  border-radius: 50%;
  background: rgba(255,255,255,.16);
  display: grid; place-items: center;
  margin-bottom: 14px;
}
.done-state h2 { font-size: 25px; line-height: 1.14; color: #fff; margin-bottom: 8px; }
.done-state p { margin: 0 0 16px; font-size: 15.5px; line-height: 1.45; color: rgba(255,255,255,.86); }
.done-footnote {
  border-top: 1px solid rgba(255,255,255,.22);
  padding-top: 14px;
  font: 600 11px var(--font-mono);
  letter-spacing: .08em;
  color: rgba(255,255,255,.7);
}

/* ---------- Sticky bar (scroll-triggered) ---------- */
.sticky {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 40;
  background: rgba(244,241,233,.94);
  backdrop-filter: saturate(140%) blur(8px);
  border-top: 1px solid var(--line);
  padding: 12px 0 calc(12px + env(safe-area-inset-bottom, 0px));
  transform: translateY(120%);
  transition: transform .28s ease;
  box-shadow: 0 -6px 20px rgba(30,29,25,.08);
}
.sticky.show { transform: translateY(0); }
.sticky .wrap { display: flex; align-items: center; gap: 12px; }
.sticky .line { flex: 1; font-size: 14.5px; font-weight: 600; }
.sticky .line span { color: var(--ink-soft); font-weight: 500; display: block; font-size: 12.5px; }
.sticky .btn { width: auto; padding: 12px 18px; font-size: 15px; }

/* ---------- Footer ---------- */
footer {
  padding: 32px 22px 64px;
  border-top: 1px solid var(--line);
  color: var(--ink-soft);
  font-size: 13px;
}
footer .wrap { padding: 0; display: flex; flex-wrap: wrap; gap: 6px 16px; align-items: baseline; }
footer .name { font-weight: 700; color: var(--ink); }
footer a { color: var(--ink-soft); text-decoration: underline; text-underline-offset: 2px; }

/* ---------- Scroll reveal ---------- */
.reveal {
  opacity: 0;
  transform: translateY(16px);
  transition: opacity .6s ease, transform .6s ease;
  will-change: opacity, transform;
}
.reveal.in { opacity: 1; transform: none; }

/* ---------- Cascade animation (plays when step 2 is in view) ---------- */
.item { opacity: 0; }
.cascade.run .item { animation: drop 2.6s ease-in-out infinite; }
.cascade.run .i1 { animation-delay: 0s;    }
.cascade.run .i2 { animation-delay: .45s;  }
.cascade.run .i3 { animation-delay: .9s;   }
.cascade.run .i4 { animation-delay: 1.35s; }
@keyframes drop {
  0%   { opacity: 0; transform: translate(0,0) scale(.9); }
  12%  { opacity: 1; }
  70%  { opacity: 1; }
  100% { opacity: 0; transform: var(--to) scale(1); }
}
.flash { transform-origin: center; }
.cascade.run .flash { animation: flash 2.6s ease-in-out infinite; }
@keyframes flash {
  0%, 8%   { opacity: 0; transform: scale(.6); }
  3%       { opacity: .9; }
  16%,100% { opacity: 0; transform: scale(1.3); }
}

/* ---------- Camera-hook animations ---------- */
@keyframes flashPop { 0% { opacity: 0; } 20% { opacity: .9; } 100% { opacity: 0; } }
@keyframes scanSweep { from { transform: translateY(-100%); } to { transform: translateY(320%); } }
@keyframes riseIn { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: none; } }

/* Respect people who ask for less motion */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .reveal { opacity: 1; transform: none; transition: none; }
  .cascade.run .item { animation: none; opacity: 1; }
  .cascade.run .flash { animation: none; opacity: .8; }
  .btn { transition: none; }
  .q-opt { transition: none; }
  .hook-frame.scanning .hook-flash,
  .hook-frame.scanning .hook-scan,
  .hook-frame.revealed .hook-result { animation: none; }
  .hook-frame.revealed .hook-result { opacity: 1; transform: none; }
  .screen-two { transition: none; }
  .sticky { transition: none; }
  .viewfinder { transition: none; }
  .shutter-dot { transition: none; }
}
