/* ==========================================================================
   GigSpares — visual system, overhaul of 2026-08-30
   Direction: "the night out", not "the terminal". Warm plum-charcoal plane,
   cream ink, serif display headings, amber warmth in washes; green is kept
   but demoted to what it means — a ticket is live — plus the single CTA.
   Dark-first: dark values live in :root, light mode is a *selected* override
   (not an inversion). Every colour pairing is measured — the ratios are
   recorded in SITE-OVERHAUL.md under this pass.
   Zero external requests: no webfonts, no images, no scripts.
   ========================================================================== */

:root {
  color-scheme: dark light;

  /* surfaces — warm near-black with a plum undertone */
  --plane:      #181114;
  --surface:    #211a1e;
  --raised:     #2a2127;
  --hairline:   #3b3038;

  /* ink — all clear WCAG AA 4.5:1 on every surface they sit on */
  --ink:        #f7f2f0;   /* 16.8:1 on plane */
  --ink-2:      #c6bac0;   /*  9.9:1 */
  --ink-3:      #9a8e94;   /*  5.9:1 on plane, 4.96:1 on raised */

  /* accents: mark step (fills, borders) + text step (type, icons) */
  --green:      #1fa866;   /* mark  · 5.56:1 on --surface */
  --green-txt:  #47dd95;   /* text  · 9.78:1 on --surface */
  --amber:      #c07f16;   /* mark  · 5.11:1 */
  --amber-txt:  #f4c064;   /* text  · 10.21:1 */
  --coral:      #e0563f;   /* mark  · 4.53:1 */
  --coral-txt:  #ff9d8a;   /* text  · 8.48:1 */

  --on-accent:  #181114;   /* label on a bright accent fill · 10.7:1 on green-txt */
  --tint:       rgba(71, 221, 149, 0.08);
  --tint-warm:  rgba(244, 192, 100, 0.08);
  --tint-cold:  rgba(255, 157, 138, 0.07);

  /* hero + final washes: colour with the lights down, never behind body text
     at full strength — alphas are low enough that measured ink ratios hold */
  --glow-a:     rgba(244, 192, 100, 0.13);
  --glow-b:     rgba(224, 86, 63, 0.09);

  /* the phone speaks Telegram's dialect, so it carries its own tokens */
  --tg-bezel:   #0d090b;
  --tg-wall-a:  #251b21;
  --tg-wall-b:  #170f13;
  --tg-bubble:  #2b2229;
  --tg-ink:     #f5f0f2;
  --tg-ink-2:   #c3b7bd;
  --tg-ink-3:   #978b91;
  --tg-btn:     rgba(255, 255, 255, 0.13);
  --tg-btn-ink: #f5f0f2;

  --radius: 14px;
  --radius-sm: 9px;
  --measure: 62ch;

  /* Two lifts only: the phone (the page's centrepiece) and the anchored plan.
     Everything else stays flat on hairlines, which keeps the lifts legible. */
  --shadow-lift: 0 18px 50px rgba(0, 0, 0, .45), 0 4px 12px rgba(0, 0, 0, .30);
  --shadow-soft: 0 10px 30px rgba(0, 0, 0, .30);

  --sans: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  /* Display serif: warmth without a webfont. Falls back to Liberation Serif
     on Linux, Georgia/Palatino elsewhere — all fine at display sizes. */
  --display: "Iowan Old Style", "Palatino Linotype", Palatino, Georgia, "Times New Roman", serif;
  --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;
}

@media (prefers-color-scheme: light) {
  :root {
    --plane:      #faf7f4;   /* warm paper, not clinic white */
    --surface:    #ffffff;
    --raised:     #f3eeea;
    --hairline:   #e3dcd6;

    --ink:        #1c1418;   /* 16.9:1 on plane */
    --ink-2:      #554b50;   /*  7.8:1 */
    --ink-3:      #655a60;   /*  5.7:1 on raised */

    --green:      #0e8f57;   /* mark · 4.13:1 on white */
    --green-txt:  #0b6e43;   /* text · 6.31:1 */
    --amber:      #a56a00;   /* mark · 4.51:1 */
    --amber-txt:  #8a5900;   /* text · 5.98:1 */
    --coral:      #c0402c;   /* mark + text · 5.24:1 */
    --coral-txt:  #c0402c;

    --on-accent:  #ffffff;   /* white on --green-txt fill · 6.31:1 */
    --tint:       rgba(14, 143, 87, 0.06);
    --tint-warm:  rgba(165, 106, 0, 0.07);
    --tint-cold:  rgba(192, 64, 44, 0.06);

    --glow-a:     rgba(224, 160, 60, 0.16);
    --glow-b:     rgba(224, 86, 63, 0.10);

    --tg-bezel:   #241c20;
    --tg-wall-a:  #efe6ea;
    --tg-wall-b:  #e4d8de;
    --tg-bubble:  #ffffff;
    --tg-ink:     #1c1418;
    --tg-ink-2:   #554b50;
    --tg-ink-3:   #5d535a;   /* 5.1:1 on the light wallpaper — audit.py */
    --tg-btn:     rgba(255, 255, 255, 0.92);
    --tg-btn-ink: #085a36;   /* 5.6:1 on the near-white button fill */

    --shadow-lift: 0 18px 44px rgba(28, 20, 24, .13), 0 4px 12px rgba(28, 20, 24, .07);
    --shadow-soft: 0 10px 26px rgba(28, 20, 24, .09);
  }
}

/* ── reset ───────────────────────────────────────────────────────────────── */

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  * { transition: none !important; animation: none !important; }
}

body {
  margin: 0;
  background: var(--plane);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 1.0625rem;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
}

h1, h2 {
  font-family: var(--display);
  font-weight: 700;
  line-height: 1.08; letter-spacing: -0.015em; margin: 0 0 .5em;
  text-wrap: balance;
}
h3 {
  font-weight: 700; font-size: 1.1rem; letter-spacing: -0.01em;
  line-height: 1.25; margin: 0 0 .45em; text-wrap: balance;
}
h1 { font-size: clamp(2.4rem, 6.5vw, 4rem); }
h2 { font-size: clamp(1.7rem, 3.6vw, 2.5rem); }
p  { margin: 0 0 1em; max-width: var(--measure); text-wrap: pretty; }
b, strong { font-weight: 700; color: var(--ink); }
em { font-style: italic; }
ul, ol { margin: 0 0 1em; padding: 0; }

a { color: var(--green-txt); text-decoration-thickness: 1px; text-underline-offset: 3px; }
a:hover { text-decoration-thickness: 2px; }

::selection { background: var(--green); color: var(--on-accent); }

:focus-visible {
  outline: 3px solid var(--green-txt);
  outline-offset: 3px;
  border-radius: 4px;
}

.skip {
  position: absolute; left: -9999px; top: 0; z-index: 99;
  background: var(--green-txt); color: var(--on-accent);
  padding: .7rem 1.1rem; font-weight: 700; border-radius: 0 0 var(--radius-sm) 0;
}
.skip:focus { left: 0; }

.wrap { width: min(1120px, 100% - 2.5rem); margin-inline: auto; }
section { padding: clamp(3rem, 7vw, 5.75rem) 0; }

.section-title { max-width: 22ch; }
.section-lede { color: var(--ink-2); font-size: 1.125rem; margin-bottom: 2.25rem; }

/* the live dot — the brand mark and the status light are the same object */
.dot {
  display: inline-block; width: .5em; height: .5em; border-radius: 50%;
  background: var(--green-txt); flex: none;
}

/* ── header ──────────────────────────────────────────────────────────────── */

.site-head {
  position: sticky; top: 0; z-index: 20;
  background: var(--plane);
  border-bottom: 1px solid var(--hairline);
}
@supports (backdrop-filter: blur(10px)) {
  .site-head {
    background: color-mix(in srgb, var(--plane) 92%, transparent);
    backdrop-filter: blur(12px);
  }
}
/* Anchored sections must not land underneath that header (see the 680px block
   for why the phone-width case differs). */
[id] { scroll-margin-top: 74px; }
.head-inner {
  display: flex; align-items: center; justify-content: space-between;
  gap: 1rem; min-height: 62px; flex-wrap: wrap;
}
.wordmark {
  display: inline-flex; align-items: baseline; gap: .3em;
  font-family: var(--display); font-weight: 700;
  font-size: 1.25rem; letter-spacing: -0.02em;
  color: var(--ink); text-decoration: none;
}
.wordmark .dot { width: .3em; height: .3em; }
.site-head nav {
  display: flex; gap: .3rem; flex-wrap: wrap; align-items: center;
}
/* Quiet but navigable (David, 2026-08-31 18:49: the pill group "sticks out
   too much"). Plain links: hover and the :has(:target)-lit current section
   speak in ink weight and an underline, no fills or borders — the one
   emphasised element up here is the Get-alerts button. Browsers without
   :has() just lose the lit state. */
.site-head nav a:not(.btn) {
  padding: .45rem .6rem;
  color: var(--ink-2); font-weight: 500; font-size: .92rem;
  text-decoration: none;
  text-underline-offset: 6px; text-decoration-thickness: 1.5px;
}
.site-head nav a:not(.btn):hover {
  color: var(--ink);
  text-decoration: underline; text-decoration-color: var(--ink-3);
}
.site-head nav a:not(.btn):focus-visible { color: var(--ink); }
body:has(#how:target)      .site-head nav a[href="#how"],
body:has(#faq:target)      .site-head nav a[href="#faq"] {
  color: var(--ink);
  text-decoration: underline; text-decoration-color: var(--green-txt);
}
.site-head nav a.btn { font-size: .88rem; padding: .5rem .95rem; margin-left: .35rem; }
.site-head nav a.btn:hover { text-decoration: none; }

/* ── buttons ─────────────────────────────────────────────────────────────── */

.btn {
  display: inline-flex; align-items: center; justify-content: center;
  gap: .5rem; padding: .78rem 1.35rem;
  border-radius: 999px; border: 1px solid transparent;
  font: inherit; font-weight: 700; font-size: 1rem;
  text-decoration: none; cursor: pointer;
  transition: transform .12s ease, filter .12s ease;
}
.btn:hover { transform: translateY(-1px); }
.btn:active { transform: translateY(0); filter: brightness(.95); }
.btn-primary { background: var(--green-txt); color: var(--on-accent); }
.btn-primary:hover { filter: brightness(1.08); }
/* The quiet sibling: same shape, no fill. Used wherever a second action
   stands beside the primary one — it must read as a button, not a link. */
.btn-ghost {
  background: transparent; color: var(--ink);
  border-color: var(--hairline);
}
.btn-ghost:hover { border-color: var(--ink-3); background: var(--tint); }
.btn-block { display: flex; width: 100%; }
.btn-lg { padding: 1rem 2rem; font-size: 1.075rem; }

/* Screen-reader-only text: plan buttons all read "Start" visually, but each
   accessible name says which plan it starts. */
.vh {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap;
}

.cta-row {
  display: flex; gap: .75rem; flex-wrap: wrap; align-items: center;
  margin: 1.7rem 0 .75rem; max-width: none;
}
.microcopy { color: var(--ink-3); font-size: .9rem; margin: 0; }

/* ── hero ────────────────────────────────────────────────────────────────── */

/* The one full-bleed moment on the page: warm light pooling behind the phone,
   like house lights going down. Decorative only — body ink never sits on the
   glow at full strength. */
.hero {
  position: relative;
  padding-top: clamp(2.75rem, 6vw, 5rem);
  padding-bottom: clamp(3rem, 7vw, 5.5rem);
  overflow: hidden;
}
.hero::before {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background:
    radial-gradient(620px 460px at 82% 12%, var(--glow-a), transparent 68%),
    radial-gradient(560px 420px at 96% 62%, var(--glow-b), transparent 70%);
}
.hero .wrap { position: relative; }
.hero-grid {
  display: grid; grid-template-columns: 1.08fr .92fr;
  gap: clamp(2rem, 5vw, 4.5rem); align-items: center;
}
.eyebrow {
  display: inline-flex; align-items: center; gap: .55rem;
  color: var(--ink-2); font-size: .875rem; font-weight: 600;
  letter-spacing: .01em; margin-bottom: 1.2rem;
  padding: .3rem .8rem .3rem .65rem;
  background: var(--tint); border: 1px solid var(--hairline);
  border-radius: 999px;
}
.lede { font-size: 1.26rem; line-height: 1.5; margin-bottom: 1rem; }
.lede strong { font-weight: 700; }
.sub { color: var(--ink-2); }
/* With the hero cut to one paragraph, that paragraph carries the pitch —
   give it lede weight without lede bulk. */
.hero .sub { font-size: 1.14rem; line-height: 1.55; }

/* ── the phone ───────────────────────────────────────────────────────────── */

/* The alert is a message arriving on a phone, so it is drawn as one: device
   frame, chat header, bubble, inline button. Pure CSS — no images. */
.hero-phone { justify-self: center; width: min(340px, 100%); }
.phone-label {
  font-size: .8rem; font-weight: 700; letter-spacing: .08em;
  text-transform: uppercase; color: var(--ink-3);
  margin-bottom: .8rem; text-align: center;
}
.phone { margin: 0; }
.phone-frame {
  background: var(--tg-bezel);
  border: 1px solid var(--hairline);
  border-radius: 44px;
  padding: 10px;
  box-shadow: var(--shadow-lift);
}
.phone-screen {
  border-radius: 35px; overflow: hidden;
  /* Solid colour UNDER the gradient: it is what contrast tooling (audit.py)
     measures against, and it is the truth — the gradient's two stops
     bracket it. Without it the auditor falls through to the bezel and
     reports fictional 1.1:1 ratios for text that really sits on the
     wallpaper. */
  background-color: var(--tg-wall-a);
  background-image: linear-gradient(178deg, var(--tg-wall-a), var(--tg-wall-b));
  color: var(--tg-ink);
  display: flex; flex-direction: column;
}
.phone-notch {
  width: 92px; height: 22px; margin: 8px auto 2px;
  background: var(--tg-bezel); border-radius: 999px;
}
.chat-head {
  display: flex; align-items: center; gap: .65rem;
  padding: .55rem .95rem .6rem;
  border-bottom: 1px solid rgba(128, 118, 124, .25);
}
.chat-avatar {
  display: flex; align-items: center; justify-content: center;
  width: 2.1rem; height: 2.1rem; border-radius: 50%; flex: none;
  background-color: var(--green-txt);   /* solid under the gradient — audit */
  background-image: linear-gradient(150deg, var(--green-txt), var(--green));
  color: var(--on-accent);
  font-family: var(--display); font-weight: 700; font-size: 1.05rem;
}
.chat-name { display: block; font-weight: 700; font-size: .95rem; line-height: 1.2; }
.chat-status { display: block; font-size: .74rem; color: var(--tg-ink-3); }
.chat-scroll { padding: .8rem .8rem 1rem; }
.chat-day {
  width: fit-content; margin: 0 auto .7rem;
  padding: .1rem .7rem; border-radius: 999px;
  background: rgba(128, 118, 124, .18);
  font-size: .72rem; font-weight: 600; color: var(--tg-ink-2);
}
.msg {
  position: relative;
  background: var(--tg-bubble);
  border-radius: 16px 16px 16px 5px;
  padding: .7rem .8rem .95rem;
  font-size: .82rem; line-height: 1.5;
  box-shadow: 0 1px 3px rgba(0, 0, 0, .18);
}
.msg p { margin: 0 0 .45rem; max-width: none; }
.msg b, .msg strong { color: var(--tg-ink); }
.msg-title { font-weight: 700; color: var(--tg-ink); }
.msg-when { color: var(--tg-ink-2); }
.msg-headline { color: var(--tg-ink); }
.msg-rows {
  list-style: none; margin: 0 0 .55rem;
  font-variant-numeric: tabular-nums;
}
.msg-rows li {
  display: flex; justify-content: space-between; gap: .8rem;
  padding: .16rem 0; color: var(--tg-ink-2);
  border-bottom: 1px solid rgba(128, 118, 124, .18);
}
.msg-rows li:last-child { border-bottom: 0; }
.msg-rows span { color: var(--tg-ink); font-weight: 700; }
.msg-rows .more { color: var(--tg-ink-3); }
.msg-tip { color: var(--tg-ink-2); font-size: .78rem; }
.msg-tip b { font-weight: 700; }
.msg-time {
  position: absolute; right: .7rem; bottom: .38rem;
  font-size: .68rem; color: var(--tg-ink-3);
  font-variant-numeric: tabular-nums;
}
/* Telegram draws inline buttons as translucent bars under the bubble */
.msg-btn {
  margin-top: .45rem; padding: .55rem;
  border-radius: 10px; text-align: center;
  background: var(--tg-btn); color: var(--tg-btn-ink);
  font-size: .84rem; font-weight: 700;
}
.phone-home {
  width: 110px; height: 4px; margin: .65rem auto .5rem;
  border-radius: 999px; background: rgba(128, 118, 124, .45);
}
.phone-caption {
  margin-top: 1rem; color: var(--ink-3); font-size: .875rem; line-height: 1.55;
  text-align: center;
}

/* ── the flow diagram ────────────────────────────────────────────────────── */

/* Four nodes, directed left to right, drawn instead of written — the
   answer to "it's a lot of words". Nodes are cards, connectors are amber
   chevrons in the gaps, icons are inline SVG on currentColor so both
   colour schemes get them for free. On narrow screens the flow turns
   vertical and the chevrons point down. */
.flow {
  list-style: none; margin: 0 0 2.25rem; padding: 0;
  display: grid; grid-template-columns: repeat(4, 1fr);
  gap: 2.4rem; counter-reset: flow;
}
.flow li {
  position: relative; counter-increment: flow;
  background: var(--surface); border: 1px solid var(--hairline);
  border-radius: var(--radius); padding: 1.35rem 1.25rem 1.2rem;
}
.flow li::before {
  content: counter(flow); position: absolute; top: 1.1rem; right: 1.1rem;
  font-family: var(--display); font-weight: 700; font-size: 1.15rem;
  line-height: 1; color: var(--ink-3);
}
/* The connector: a chevron centred in the grid gap, pointing at the next
   node. Amber — it is emphasis, not a warning. */
.flow li:not(:last-child)::after {
  content: ""; position: absolute; top: 50%; right: -1.62rem;
  width: .72rem; height: .72rem;
  border-top: 3px solid var(--amber); border-right: 3px solid var(--amber);
  transform: translateY(-50%) rotate(45deg);
}
.flow-icon {
  display: inline-flex; align-items: center; justify-content: center;
  width: 44px; height: 44px; border-radius: 12px;
  background: var(--tint); color: var(--green-txt);
  margin-bottom: .8rem;
}
.flow-icon svg { width: 26px; height: 26px; }
.flow h3 { font-size: 1.02rem; margin-bottom: .3rem; }
.flow p { color: var(--ink-2); font-size: .92rem; margin: 0; max-width: none; }
.how-note {
  max-width: 62rem; color: var(--ink-2); margin: 0;
  padding: 1.2rem 1.5rem; border-radius: var(--radius);
  background: var(--tint-warm); border-left: 3px solid var(--amber);
}

/* ── pricing ─────────────────────────────────────────────────────────────── */

/* Three lengths of the SAME service, but not three equals: the three-month
   plan is the shape of the actual job (a gig is usually announced about that
   far out), so it is the visual default — bigger, lifted, warm. Hierarchy
   and per-month arithmetic, not a "best value" sticker: the €15/€13/€10
   line under each price is what makes the choice legible. */
.plans {
  list-style: none; margin: 0 0 1.1rem; padding: 0;
  display: grid; grid-template-columns: 1fr 1.18fr 1fr;
  gap: 1rem; align-items: stretch;
  max-width: 52rem;
}
.plan {
  padding: 1.35rem 1.2rem; background: var(--surface);
  border: 1px solid var(--hairline); border-radius: var(--radius);
  text-align: center;
  display: flex; flex-direction: column; gap: .1rem;
}
.plan-period {
  margin: 0 0 .4rem; font-size: .8rem; font-weight: 700;
  letter-spacing: .09em; text-transform: uppercase; color: var(--ink-3);
}
.plan-price { margin: 0; font-variant-numeric: tabular-nums; letter-spacing: -0.03em; }
.plan-price b {
  font-family: var(--display); font-size: 2.3rem; font-weight: 700; line-height: 1;
}
.plan-permo { margin: .35rem 0 .5rem; color: var(--ink-2); font-size: .92rem; font-weight: 600; }

/* THE CHECKOUT LIVES ON THE CARDS. Every plan carries its own real /buy
   button; margin-top:auto pins the three to a shared baseline so the row
   reads as one system whatever the note-length. Only the anchored plan's
   button is filled — one green fill per viewport keeps the primary action
   unambiguous, and the quiet ones are still unmistakably buttons. */
.btn-plan { margin-top: 1.1rem; width: 100%; font-size: .95rem; }
.plan .btn-plan:not(.btn-primary) {
  background: transparent; color: var(--green-txt);
  border-color: var(--hairline);
}
.plan .btn-plan:not(.btn-primary):hover {
  border-color: var(--green); background: var(--tint);
}

.plan-anchor {
  border-color: var(--amber);
  background:
    linear-gradient(170deg, var(--tint-warm), transparent 70%),
    var(--surface);
  box-shadow: var(--shadow-soft);
  padding-block: 1.9rem;
}
.plan-anchor .plan-price b { font-size: 3rem; }
.plan-anchor .plan-period { color: var(--amber-txt); }

.plan-detail {
  max-width: 52rem; padding: 1.6rem;
  background: var(--surface);
  border: 1px solid var(--hairline); border-radius: var(--radius);
}
.tier-name {
  font-size: .8rem; letter-spacing: .09em; text-transform: uppercase;
  color: var(--ink-3); margin-bottom: .5rem;
}
.tier-line { color: var(--ink-2); margin-bottom: 1rem; }
.ticks { list-style: none; margin: 0 0 1.4rem; }
.ticks li {
  position: relative; padding-left: 1.6rem; margin-bottom: .5rem;
  color: var(--ink-2); font-size: .96rem;
}
.ticks li::before {
  content: ""; position: absolute; left: .15rem; top: .62em;
  width: .48rem; height: .48rem; border-radius: 50%; background: var(--green);
}
/* The tick list splits into two columns where there is room, so the feature
   card stays a card and not a queue. */
@media (min-width: 720px) {
  .ticks { display: grid; grid-template-columns: 1fr 1fr; column-gap: 2rem; }
}
.tier-why { margin: .9rem 0 0; color: var(--ink-3); font-size: .875rem; }

/* The three facts a buyer wants before the tap (2026-09-01): who takes the
   card, what renews, what happens after. Icons on currentColor like the
   flow diagram; three columns on desktop, a stack on a phone. Plain ink,
   no tint, no border-glow -- terms, not a pitch. */
.pay-facts {
  list-style: none; margin: 1rem 0 0; padding: 0; max-width: 52rem;
  display: grid; grid-template-columns: repeat(3, 1fr); gap: .8rem;
}
.pay-facts li {
  display: flex; gap: .8rem; align-items: flex-start;
  padding: .95rem 1rem;
  border: 1px solid var(--hairline); border-radius: var(--radius-sm);
}
.pay-facts p { margin: 0; max-width: none; color: var(--ink-3); font-size: .875rem; line-height: 1.5; }
.pay-facts p b { color: var(--ink-2); }
.pay-facts a { color: var(--ink-2); }
.pay-icon {
  display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 32px; border-radius: 9px; flex: none;
  background: var(--tint); color: var(--green-txt);
}
.pay-icon svg { width: 18px; height: 18px; }
@media (max-width: 980px) {
  .pay-facts { grid-template-columns: 1fr; }
}

/* ── faq ─────────────────────────────────────────────────────────────────── */

/* Centred as a block, the same fix §13.3 made for #why and for the same
   reason: at 1280 the 74ch accordion column sat on the left rail against
   ~500px of dead plane. It was the last flat stretch on the page. Centring
   it also gives the close a shape — pricing is the last section on the rail,
   then Questions and the CTA band both sit in the middle. min() means narrow
   viewports keep the ordinary .wrap gutter and nothing changes on mobile. */
#faq .wrap { width: min(74ch, 100% - 2.5rem); }

.faq { display: grid; gap: .6rem; max-width: 74ch; }
.faq details {
  background: var(--surface); border: 1px solid var(--hairline);
  border-radius: var(--radius); overflow: hidden;
}
.faq details[open] { border-color: var(--amber); }
.faq summary {
  padding: 1rem 1.3rem; cursor: pointer;
  font-weight: 700; font-size: 1.02rem; color: var(--ink);
  list-style: none; display: flex; align-items: center; gap: .8rem;
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::before {
  content: "+"; color: var(--amber-txt); font-weight: 800;
  font-size: 1.15rem; line-height: 1; flex: none; width: 1ch;
}
.faq details[open] summary::before { content: "\2212"; }
.faq summary:hover { background: var(--tint-warm); }
.faq details > div { padding: 0 1.3rem 1.1rem 3.1rem; }
.faq details p { color: var(--ink-2); margin-bottom: .8rem; }
.faq details p:last-child { margin-bottom: 0; }

/* ── final + footer ──────────────────────────────────────────────────────── */

/* The lights come back up: the hero's warmth returns for the close. */
.final {
  position: relative; text-align: center; overflow: hidden;
  border-top: 1px solid var(--hairline);
  background: var(--surface);
}
.final::before {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background:
    radial-gradient(640px 340px at 50% 115%, var(--glow-a), transparent 70%),
    radial-gradient(480px 300px at 18% 120%, var(--glow-b), transparent 72%);
}
.final .wrap { position: relative; }
.final h2 { max-width: none; }
.final .cta-row { justify-content: center; }

.site-foot {
  border-top: 1px solid var(--hairline);
  padding: 2.5rem 0 3.5rem; background: var(--plane);
}
.foot-mark {
  display: inline-flex; align-items: baseline; gap: .3em;
  font-family: var(--display); font-weight: 700;
  letter-spacing: -0.02em; color: var(--ink);
  margin-bottom: .8rem;
}
.foot-mark .dot { width: .3em; height: .3em; }
.site-foot p { color: var(--ink-2); font-size: .94rem; }
.foot-links { display: flex; flex-wrap: wrap; gap: 1.25rem; }
.foot-links a { color: var(--ink); text-underline-offset: 3px; }
.site-foot .small { color: var(--ink-3); font-size: .84rem; margin-bottom: 0; }

/* ── responsive ──────────────────────────────────────────────────────────── */

@media (max-width: 980px) {
  .hero-grid { grid-template-columns: 1fr; }
  /* The flow goes vertical: one column, chevrons rotate to point down. */
  .flow { grid-template-columns: 1fr; gap: 1.9rem; max-width: 34rem; }
  .flow li:not(:last-child)::after {
    top: auto; right: auto; bottom: -1.32rem; left: 50%;
    transform: translateX(-50%) rotate(135deg);
  }
  [id] { scroll-margin-top: 84px; }
  .phone-caption { max-width: 46ch; margin-inline: auto; }
}

@media (max-width: 680px) {
  body { font-size: 1rem; }
  /* On a phone the header would pin rows over a page you read by
     scrolling, so it scrolls away with the page instead. */
  .site-head { position: static; }
  [id] { scroll-margin-top: 1rem; }
  /* One slim row: wordmark left, Get-alerts right. The section links go —
     a phone reads this page by scrolling, and every extra header row is a
     row of pitch pushed below the fold. Manage stays in the footer. */
  .head-inner { min-height: 0; padding: .6rem 0; flex-wrap: nowrap; }
  .site-head nav a:not(.btn) { display: none; }
  .site-head nav a.btn { margin-left: 0; }

  /* The first screen is the pitch and the way to buy, nothing else.
     Sized so eyebrow, headline, paragraph, button and price all land
     inside 390x844 and 375x812 before any scroll — the alert phone is
     the reward for the first flick. Deliberate mobile sizes, not shrunk
     desktop: the headline steps down to a phone display size and the
     paragraph back to body size. */
  .hero { padding-top: 1.5rem; padding-bottom: 3rem; }
  h1 { font-size: clamp(1.9rem, 8.6vw, 2.3rem); }
  .eyebrow {
    font-size: .78rem; border: 0; background: none; padding: 0;
    margin-bottom: .8rem;
  }
  .hero .sub { font-size: 1.02rem; }
  .cta-row { margin-top: 1.3rem; }
  .cta-row .btn { flex: 1 1 100%; }

  .lede { font-size: 1.125rem; }
  .faq details > div { padding-left: 1.3rem; }
  /* One plan per row, €15 monthly first — document order, unreordered
     (David, 2026-08-31: €15 leads). The anchored three-month plan keeps
     its lift, second in the stack. */
  .plans { grid-template-columns: 1fr; gap: .7rem; }
  .plan { text-align: left; padding: 1.1rem 1.2rem; }
  .plan-anchor { padding-block: 1.4rem; }
  .plan-anchor .plan-price b { font-size: 2.4rem; }
}

/* ── flow pages (/welcome /claim /manage /cancelled, server-rendered) ────────
   The purchase journey's own pages, designed 2026-09-01 after four passes
   on the landing page and none on these. A person lands here having just
   given money to a site they met ten minutes ago, so: same head, same
   tokens, same type -- visibly the same site -- one narrow centred column,
   and the page's single action gets the only green fill, full width on a
   phone and inside the first screen (flow_verify.py measures that at
   390x844 and 375x812). Everything below the action is "what happens now",
   never a second ask. ───────────────────────────────────────────────────── */

.flow-body { min-height: 100svh; display: flex; flex-direction: column; }
.flow-body .site-head { position: static; }
.flow-main {
  flex: 1;
  width: min(58ch, 100% - 2.5rem); margin-inline: auto;
  padding: clamp(2rem, 6vw, 4rem) 0 clamp(3rem, 8vw, 5rem);
}
.flow-main h1 {
  font-size: clamp(2rem, 5.2vw, 2.8rem); margin-bottom: .45em;
}
.flow-main h2 {
  font-size: .8rem; font-family: var(--sans); font-weight: 700;
  letter-spacing: .09em; text-transform: uppercase; color: var(--ink-3);
  margin: 2.6em 0 .9em;
}
.flow-main .lede { font-size: 1.125rem; line-height: 1.5; color: var(--ink-2); }
.flow-main p { color: var(--ink-2); }
.flow-main p b, .flow-main li b { color: var(--ink); }
.flow-main code {
  font-family: var(--mono); font-size: .88em;
  background: var(--raised); padding: .1em .35em; border-radius: 4px;
  color: var(--ink);
}
.flow-main .cta-row { margin: 1.6rem 0 .6rem; }
.flow-main .btn-block { display: flex; width: 100%; }
.flow-main .microcopy { margin-bottom: .25rem; }
.aside { color: var(--ink-3); font-size: .92rem; margin-top: 1.4rem; }
.aside a { color: var(--ink-2); }

/* The page's mark: one icon, above the headline, the colour of the news.
   Green ring = the money landed / the rescue worked; quiet = nothing
   happened here (no charge, not found), which must not look like an
   error -- a coral mark on "nothing was charged" reads as an alarm. */
.mark {
  display: inline-flex; align-items: center; justify-content: center;
  width: 3.1rem; height: 3.1rem; border-radius: 50%;
  margin: 0 0 1.2rem; max-width: none;
}
.mark svg { width: 1.6rem; height: 1.6rem; }
.mark-ok { background: var(--tint); color: var(--green-txt); }
.mark-quiet { background: var(--raised); color: var(--ink-2); }

/* The receipt: what Stripe says was paid, as a strip of label/value pairs.
   Tabular numerals, hairline card, nothing bold but the values -- it is
   there to be checked against a bank app, not to sell anything. */
.receipt {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: .9rem 1.2rem; margin: 1.4rem 0 0;
  padding: 1rem 1.2rem;
  background: var(--surface); border: 1px solid var(--hairline);
  border-radius: var(--radius);
  font-variant-numeric: tabular-nums;
}
.receipt div { min-width: 0; }
.receipt dt {
  font-size: .74rem; font-weight: 700; letter-spacing: .08em;
  text-transform: uppercase; color: var(--ink-3); margin-bottom: .15rem;
}
.receipt dd {
  margin: 0; color: var(--ink); font-weight: 600; font-size: 1.02rem;
  /* break-word, not anywhere: `anywhere` shrinks the cell's min-content to
     one character, so an auto grid track squeezed "you@example.com" into
     "you@example.c / om" (seen 2026-09-02). break-word only splits a value
     that could not fit its track on its own line. */
  overflow-wrap: break-word;
}
/* The email is the one value that can be long; on a phone it takes the
   whole row rather than half of it, and on wider screens the last track
   is the flexible one so the fixed ones (paid, plan, renews) never wrap. */
.receipt .r-email { grid-column: 1 / -1; }
@media (min-width: 520px) {
  .receipt { grid-template-columns: auto auto auto minmax(0, 1fr);
             gap: .5rem 2rem; }
  .receipt .r-email { grid-column: auto; }
}

/* Where the buyer is: pay → connect → watch. The current step is the amber
   one -- same amber, same job as the step numerals on the main page. */
.progress {
  list-style: none; display: flex; flex-wrap: wrap;
  gap: .4rem 0; margin: 1.6rem 0 0; padding: 0;
  font-size: .85rem; font-weight: 600; color: var(--ink-3);
}
.progress li { display: inline-flex; align-items: center; }
.progress li:not(:first-child)::before {
  content: ""; width: 1.3rem; height: 1px; margin-inline: .55rem;
  background: var(--hairline);
}
.progress li.done { color: var(--green-txt); }
.progress li.done::after { content: " ✓"; white-space: pre; }
.progress li.now { color: var(--amber-txt); }

/* "What happens now": three numbered lines, numerals in the margin the
   way the landing page sets its flow, no cards -- it is instruction, not
   decoration, and it sits under the button rather than competing with it. */
.next {
  list-style: none; margin: 0; padding: 0; counter-reset: next;
  display: grid; gap: .9rem;
}
.next li {
  position: relative; counter-increment: next;
  padding-left: 2.4rem; color: var(--ink-2); line-height: 1.55;
}
.next li::before {
  content: counter(next); position: absolute; left: 0; top: .05em;
  width: 1.65rem; height: 1.65rem; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--tint); color: var(--green-txt);
  font-family: var(--display); font-weight: 700; font-size: .95rem;
}

/* Settling: a live dot that breathes while the webhook lands. The page is
   already refreshing itself; the dot is only so the wait looks alive.
   Reduced motion gets a still dot (the global rule kills the animation). */
.settling {
  display: flex; align-items: center; gap: .6rem;
  margin: 1.4rem 0 0; color: var(--ink); font-weight: 600;
}
.pulse {
  width: .7rem; height: .7rem; border-radius: 50%; flex: none;
  background: var(--green-txt);
  animation: breathe 1.6s ease-in-out infinite;
}
@keyframes breathe {
  0%, 100% { opacity: 1; transform: scale(1); }
  50% { opacity: .45; transform: scale(.8); }
}

/* Claim: the form is the rescue, so it is the widest thing on the page
   and its button is the full width of the input above it. */
.claim-form { margin: 1.7rem 0 0; }
.claim-form label {
  display: block; font-size: .875rem; font-weight: 700;
  color: var(--ink-2); margin-bottom: .45rem;
}
.claim-form input {
  display: block; width: 100%; margin-bottom: .8rem;
  padding: .85rem 1rem; font: inherit; font-size: 1.05rem; color: var(--ink);
  background: var(--surface); border: 1px solid var(--hairline);
  border-radius: var(--radius-sm);
}
.claim-form input::placeholder { color: var(--ink-3); }
.claim-form input:focus-visible { outline-offset: 0; }
.claim-form .btn { width: 100%; }

/* Claim result: the HTML is identical whether or not a purchase was found
   (only the link differs -- §23), so the two readings are both present and
   CSS shows the one the button's presence implies. A browser without
   :has() gets the neutral sentence. */
.claim-found, .claim-none, .claim-neutral { display: none; }
.claim-result:has(.btn-primary) .claim-found { display: block; }
.claim-result:not(:has(.btn-primary)) .claim-none { display: block; }
.claim-result:has(.btn-primary) .claim-why,
.claim-result:has(.btn-primary) .cta-row:has(.btn-ghost) { display: none; }
@supports not selector(:has(a)) {
  .claim-neutral { display: block; }
}
.claim-why {
  list-style: none; margin: 1rem 0 0; padding: 0; display: grid; gap: .7rem;
}
.claim-why li {
  padding: .85rem 1rem; color: var(--ink-2); line-height: 1.5;
  background: var(--surface); border: 1px solid var(--hairline);
  border-radius: var(--radius-sm);
}
.claim-why b { display: block; margin-bottom: .1rem; }

/* Manage: the four things a customer came to find, as a 2x2 of quiet
   cards. Label first, the fact under it; no icons -- the sliders mark at
   the top is the page's one picture. */
.facts {
  list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: 1fr 1fr; gap: .7rem;
}
.facts li {
  padding: .9rem 1rem; color: var(--ink-2); font-size: .95rem; line-height: 1.5;
  background: var(--surface); border: 1px solid var(--hairline);
  border-radius: var(--radius-sm);
}
.facts b { display: block; margin-bottom: .15rem; }
.flow-manage h2 + p { margin-bottom: .6rem; }

.flow-foot {
  border-top: 1px solid var(--hairline);
  padding: 1.6rem 0 2rem;
  font-size: .9rem; color: var(--ink-3);
}
.flow-foot a { color: var(--ink-2); }

@media (max-width: 680px) {
  .flow-main { padding-top: 1.6rem; }
  .flow-main h1 { font-size: clamp(1.85rem, 8vw, 2.2rem); }
  .flow-main .lede { font-size: 1.05rem; }
  .flow-main .cta-row { margin-top: 1.3rem; }
  .flow-main .cta-row .btn { flex: 1 1 100%; }
  .facts { grid-template-columns: 1fr; }
  .mark { width: 2.7rem; height: 2.7rem; margin-bottom: .9rem; }
  .mark svg { width: 1.4rem; height: 1.4rem; }
}

/* ── legal pages (terms.html, privacy.html) ──────────────────────────────────
   Generated from TERMS.md and PRIVACY.md by render_legal.py, so this styles
   raw markdown output: bare h1/h2/h3, ul, table, no classes to hook.

   Long-form prose, so the measure matters more here than anywhere else on the
   site. These documents are the ones a suspicious reader actually reads before
   paying a stranger EUR 15, and a 120-character line is how you make somebody
   give up halfway down a privacy policy. Same measure cap as the rest of the
   site, with the page narrowed rather than the paragraphs floated in a wide
   column, so headings and body share a left edge.
   ────────────────────────────────────────────────────────────────────────── */
.legal {
  width: min(72ch, 100% - 2.5rem);
  padding: clamp(2.5rem, 7vw, 4.5rem) 0 clamp(3rem, 8vw, 5rem);
}
.legal h1 { font-size: clamp(1.8rem, 5vw, 2.6rem); margin-bottom: .6em; }
.legal h2 {
  font-size: clamp(1.2rem, 2.8vw, 1.5rem);
  margin-top: 2.2em; padding-top: 1.2em;
  border-top: 1px solid var(--hairline);
}
.legal h2:first-of-type { margin-top: 1.6em; }
.legal p, .legal li { color: var(--ink-2); max-width: none; }
.legal strong { color: var(--ink); }
.legal ul { list-style: disc; padding-left: 1.35rem; margin-bottom: 1.2em; }
.legal li { margin-bottom: .5em; }
.legal li > ul { margin-top: .5em; margin-bottom: .3em; }
.legal code {
  font-family: var(--mono); font-size: .88em;
  background: var(--raised); padding: .1em .35em; border-radius: 4px;
  color: var(--ink);
}

/* The "What we collect" table. It is the most useful thing in either document
   -- a field-by-field list of what the database holds -- so it gets to be a
   real table on desktop and stacked rows on a phone, rather than the usual
   horizontal-scroll shrug. */
.legal table {
  width: 100%; border-collapse: collapse; margin: 0 0 1.6em;
  font-size: .95rem;
}
.legal th, .legal td {
  text-align: left; vertical-align: top; padding: .7rem .8rem;
  border: 1px solid var(--hairline); color: var(--ink-2);
}
.legal th { background: var(--raised); color: var(--ink); font-weight: 700; }

.legal-back { margin-top: 2.5rem; }

@media (max-width: 680px) {
  .legal thead { position: absolute; width: 1px; height: 1px;
                 overflow: hidden; clip-path: inset(50%); }
  .legal table, .legal tbody, .legal tr, .legal td { display: block; width: 100%; }
  .legal tr {
    border: 1px solid var(--hairline); border-radius: var(--radius-sm);
    margin-bottom: .8rem; padding: .3rem 0; background: var(--surface);
  }
  .legal td { border: 0; padding: .45rem .9rem; }
  /* Without the header row the columns lose their meaning, so each cell
     carries its own label. Content, not decoration, hence not ::before-only
     styling that a screen reader would skip. */
  .legal td:first-child { color: var(--ink); font-weight: 600; }
  .legal td:not(:first-child)::before {
    content: attr(data-label); display: block;
    font-size: .72rem; letter-spacing: .08em; text-transform: uppercase;
    color: var(--ink-3); margin-bottom: .15rem;
  }
}

@media print {
  .site-head, .skip { display: none; }
  body { background: #fff; color: #000; }
}
