/* ══════════════════════════════════════════════════════════════════════
   Inter, self-hosted.

   Served from our own origin rather than a font CDN: no third-party request
   on any page, nothing to block, and no dependency on a service we do not
   control. It is also the only way the design actually gets the typeface —
   linking a CDN would have failed silently and fallen back to a system font,
   which is what was happening before.

   One variable file per subset covers every weight, so the whole family
   costs a single 47KB request for Latin text. `font-display: swap` means
   text is readable immediately and reflows when the font lands, rather than
   the page sitting blank.

   Inter is SIL Open Font License 1.1 — self-hosting and redistribution are
   expressly permitted.
   ══════════════════════════════════════════════════════════════════════ */

@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 100 900;          /* variable: one file, all weights */
  font-display: swap;
  src: url("/static/fonts/inter-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6,
                 U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F,
                 U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF,
                 U+FFFD;
}

@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("/static/fonts/inter-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7,
                 U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF,
                 U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0,
                 U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* ══════════════════════════════════════════════════════════════════════
   Design system.

   Palette and type follow the brand book: warm white ground, near-black
   type, deep cobalt accent, restrained grotesk. The site commits to a
   single light visual world — that is the specified identity, not an
   omission — so every colour is painted explicitly and `color-scheme`
   keeps form controls in the same world.

   Anti-patterns held to deliberately: no gradients, no glass, no blobs,
   no oversized animated figures, no decorative rounding.
   ══════════════════════════════════════════════════════════════════════ */

:root {
  color-scheme: light;

  /* Ground and ink */
  --paper:      #FAFAF7;
  --paper-2:    #F3F3ED;   /* warm recessed surface */
  --paper-3:    #ECECE4;
  --ink:        #111111;
  --ink-2:      #3B3B37;   /* secondary prose */
  --muted:      #6E6E67;   /* labels, captions */
  --rule:       #E4E4DB;
  --rule-2:     #D3D3C8;

  /* Accent */
  --accent:     #2457FF;
  --accent-dark:#1740CC;
  --accent-wash:#EDF1FF;
  /* The cobalt is tuned for the warm-white ground; on near-black it drops to
     ~3.5:1 and reads dim. This lifted tint is the same hue for use on the
     dark bars (console header, preview chrome). */
  --accent-lt:  #6B8FFF;

  /* Semantic — used only for status, never as decoration */
  --ok:         #0F7A4A;
  --warn:       #9A6200;
  --err:        #B3261E;

  /* Type */
  --sans: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI Variable Text",
          "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --mono: ui-monospace, "Cascadia Mono", Consolas, "SF Mono", Menlo, monospace;

  /* Measure */
  --container: 68rem;
  --measure: 34rem;

  /* Rhythm */
  --sp-section: clamp(4.5rem, 10vw, 8.5rem);
}

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 1.0625rem;
  line-height: 1.65;
  font-feature-settings: "cv05" 1, "ss01" 1;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

.container {
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: clamp(1.25rem, 5vw, 2.5rem);
}

/* ── Type ────────────────────────────────────────────────────────────── */

h1, h2, h3, h4 {
  margin: 0;
  font-weight: 600;
  letter-spacing: -0.028em;
  line-height: 1.08;
  text-wrap: balance;
}

h1 {
  font-size: clamp(2.75rem, 7.5vw, 5rem);
  letter-spacing: -0.042em;
  line-height: 0.98;
}

h2 {
  font-size: clamp(1.875rem, 4vw, 2.75rem);
  letter-spacing: -0.034em;
}

h3 { font-size: 1.0625rem; letter-spacing: -0.012em; line-height: 1.4; }

p { margin: 0; }

.lede {
  font-size: clamp(1.0625rem, 1.9vw, 1.25rem);
  line-height: 1.55;
  color: var(--ink-2);
  max-width: var(--measure);
  text-wrap: pretty;
}

.label {
  font-size: 0.75rem;
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
}

.prose p + p { margin-top: 1.15em; }
.prose { max-width: var(--measure); color: var(--ink-2); }
.prose strong { color: var(--ink); font-weight: 600; }

a { color: inherit; }

/* ── The mark ────────────────────────────────────────────────────────── */

.mark {
  display: inline-block;
  color: var(--accent);
  font-size: 0.72em;
  vertical-align: 0.14em;
  line-height: 1;
}

/* ── Buttons ─────────────────────────────────────────────────────────── */

.btn {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.8rem 1.35rem;
  border: 1px solid transparent;
  border-radius: 3px;
  font: inherit;
  font-size: 0.9375rem;
  font-weight: 500;
  line-height: 1;
  text-decoration: none;
  cursor: pointer;
  transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}

.btn-primary {
  background: var(--ink);
  color: var(--paper);
}
.btn-primary:hover { background: var(--accent); }

.btn-secondary {
  background: transparent;
  color: var(--ink);
  border-color: var(--rule-2);
}
.btn-secondary:hover { border-color: var(--ink); }

.btn-link {
  padding: 0;
  color: var(--accent);
  text-decoration: none;
  font-weight: 500;
  border-bottom: 1px solid transparent;
  border-radius: 0;
}
.btn-link:hover { border-bottom-color: currentColor; }

:where(a, button, summary, input, textarea):focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 2px;
}

/* ── Masthead ────────────────────────────────────────────────────────── */

.masthead {
  border-bottom: 1px solid var(--rule);
  background: var(--paper);
  position: sticky;
  top: 0;
  z-index: 20;
}

.masthead-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 2rem;
  min-height: 4.25rem;
}

.wordmark {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  font-size: 1rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-decoration: none;
  color: var(--ink);
}

.nav {
  display: flex;
  align-items: center;
  gap: 1.75rem;
  font-size: 0.9375rem;
}
.nav a { text-decoration: none; color: var(--ink-2); }
.nav a:hover { color: var(--ink); }
@media (max-width: 52rem) { .nav .nav-hide { display: none; } }

/* Sign in. A control, not another marketing link — as plain text beside
   four of them it read as a fifth and was missed.

   Outlined rather than filled: "Build me one" is this page's call to
   action and has to stay the only solid thing in the bar, or the nav reads
   as two competing asks. Present at every width, including the one that
   hides the marketing links, because a customer who cannot find their own
   account is the only person here with a real problem. */
/* Lives here, not in admin.css: the console loads both sheets and the
   marketing site loads only this one, so a second definition over there
   was a rule that could drift from the one everything else uses. Values
   are admin's originals, so the console is unchanged. */
.btn-sm { padding: .5rem 1rem; font-size: .875rem; }
.nav .nav-in { margin-left: 0.25rem; }
@media (max-width: 52rem) {
  .nav .nav-in { margin-left: 0; }
}

/* ── Sections ────────────────────────────────────────────────────────── */

section { padding-block: var(--sp-section); }
.section-bordered { border-top: 1px solid var(--rule); }
.section-inset { background: var(--paper-2); }

.section-head { max-width: var(--measure); margin-bottom: 3rem; }
.section-head h2 { margin-bottom: 1rem; }

/* ── Hero ────────────────────────────────────────────────────────────── */

.hero { padding-block: clamp(4rem, 11vw, 8.5rem) clamp(3.5rem, 8vw, 6rem); }
.hero h1 { margin-bottom: 1.75rem; }
.hero .lede { margin-bottom: 2.5rem; max-width: 33rem; }

.hero-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1rem 1.5rem;
}

.hero-aside {
  margin-top: 3.5rem;
  padding-top: 1.5rem;
  border-top: 1px solid var(--rule);
  font-size: 0.9375rem;
  color: var(--muted);
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 0.75rem;
  align-items: baseline;
}

/* ── Handled list: the brand device, resolving once ──────────────────── */

.handled-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 0;
  border-top: 1px solid var(--rule);
  max-width: 44rem;
}
@media (min-width: 40rem) {
  .handled-grid { grid-template-columns: 1fr 1fr; column-gap: 3rem; }
}

.handled-item {
  display: flex;
  align-items: center;
  gap: 0.85rem;
  padding: 0.95rem 0;
  border-bottom: 1px solid var(--rule);
  font-size: 1rem;
}

.handled-item .state {
  width: 0.9rem;
  font-family: var(--mono);
  font-size: 0.8rem;
  line-height: 1;
  color: var(--rule-2);
  transition: color 0.3s ease;
}
.handled-item.is-handled .state { color: var(--accent); }

.handled-close {
  margin-top: 2.5rem;
  font-size: clamp(1.5rem, 3.4vw, 2rem);
  font-weight: 600;
  letter-spacing: -0.03em;
}

/* ── Steps: a real sequence, so genuinely ordered ────────────────────── */

.steps { display: grid; gap: 0; max-width: 46rem; }
.step {
  display: grid;
  grid-template-columns: 2.25rem 1fr;
  gap: 1.25rem;
  padding: 1.6rem 0;
  border-top: 1px solid var(--rule);
}
.step:last-child { border-bottom: 1px solid var(--rule); }
.step-n {
  font-family: var(--mono);
  font-size: 0.8125rem;
  color: var(--muted);
  padding-top: 0.2rem;
  font-variant-numeric: tabular-nums;
}
.step h3 { margin-bottom: 0.35rem; }
.step p { color: var(--ink-2); font-size: 0.9688rem; }

/* ── Pricing ─────────────────────────────────────────────────────────── */

.price-card {
  border: 1px solid var(--rule-2);
  background: var(--paper);
  padding: clamp(1.75rem, 4vw, 2.75rem);
  max-width: 34rem;
}

.price-rows { display: grid; gap: 1.5rem; }
.price-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1.5rem;
}
.price-figure {
  font-size: clamp(2.25rem, 5.5vw, 3rem);
  font-weight: 600;
  letter-spacing: -0.04em;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}
.price-figure .per {
  font-size: 0.9375rem;
  font-weight: 500;
  letter-spacing: -0.01em;
  color: var(--muted);
}
.price-what { font-size: 0.9375rem; color: var(--muted); text-align: right; }

.price-included {
  margin-top: 2rem;
  padding-top: 1.75rem;
  border-top: 1px solid var(--rule);
}
.price-included ul {
  margin: 1rem 0 0;
  padding: 0;
  list-style: none;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
  gap: 0.6rem 1.5rem;
  font-size: 0.9375rem;
  color: var(--ink-2);
}
.price-included li { display: flex; gap: 0.6rem; align-items: baseline; }
.price-included li::before {
  content: "■";
  color: var(--accent);
  font-size: 0.6rem;
  line-height: 1.6;
}

.price-terms {
  margin-top: 2rem;
  padding-top: 1.5rem;
  border-top: 1px solid var(--rule);
  display: grid;
  gap: 0.45rem;
  font-size: 0.9375rem;
  color: var(--ink-2);
}
.price-terms strong { color: var(--ink); font-weight: 600; }

/* ── Footer ──────────────────────────────────────────────────────────── */

.site-footer {
  border-top: 1px solid var(--rule);
  padding-block: 3.5rem 4rem;
  font-size: 0.9375rem;
  color: var(--muted);
}
.footer-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 2.5rem;
}
@media (min-width: 46rem) {
  .footer-grid { grid-template-columns: 1.4fr 1fr 1fr; gap: 3rem; }
}
.footer-col h4 {
  font-size: 0.75rem;
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 1rem;
}
.footer-col ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.55rem; }
.footer-col a { color: var(--ink-2); text-decoration: none; }
.footer-col a:hover { color: var(--ink); }
.footer-legal {
  margin-top: 3rem;
  padding-top: 1.5rem;
  border-top: 1px solid var(--rule);
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1.5rem;
  justify-content: space-between;
  font-size: 0.875rem;
}

/* ── Build-time gate: refuses to let unverifiable claims ship ─────────── */

.launch-gate {
  background: #2B1A00;
  color: #FFD9A0;
  font-size: 0.875rem;
  line-height: 1.5;
  padding: 0.85rem 0;
}
.launch-gate strong { color: #FFF; font-weight: 600; }
.launch-gate code {
  font-family: var(--mono);
  font-size: 0.9em;
  background: rgba(255, 255, 255, 0.1);
  padding: 0.1em 0.35em;
  border-radius: 2px;
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    transition-duration: 0.001ms !important;
  }
}

/* ══════════════════════════════════════════════════════════════════════
   Status vocabulary — ○ pending, ◐ setting up, ■ handled.

   One place, so "Handled" looks and reads identically wherever it appears.
   The mark carries the state as shape as well as colour, so it survives
   greyscale, colour-blindness and a bad phone screen in sunlight.
   ══════════════════════════════════════════════════════════════════════ */

.st-list { display: grid; gap: 1px; background: var(--rule);
           border: 1px solid var(--rule); }
.st-item { display: flex; gap: .85rem; align-items: flex-start;
           background: var(--paper); padding: 1rem 1.15rem; }
.st-mark { font-family: var(--mono); font-size: .95rem; line-height: 1.5;
           flex: none; width: 1rem; text-align: center; }
.st-body { display: grid; gap: .1rem; min-width: 0; }
.st-label { font-weight: 600; font-size: .9688rem; }
.st-state { font-size: .8125rem; letter-spacing: .04em; text-transform: uppercase; }
.st-detail { font-size: .875rem; color: var(--muted); margin-top: .15rem; }

.st-handled   .st-mark  { color: var(--ok); }
.st-handled   .st-state { color: var(--ok); }
.st-working   .st-mark  { color: var(--accent); }
.st-working   .st-state { color: var(--accent-dark); }
.st-pending   .st-mark  { color: var(--rule-2); }
.st-pending   .st-state { color: var(--muted); }
.st-attention .st-mark  { color: var(--warn); font-weight: 700; }
.st-attention .st-state { color: var(--warn); }

/* The one piece of motion in the system: work actually in progress. */
@media (prefers-reduced-motion: no-preference) {
  .st-working .st-mark { animation: st-pulse 1.8s ease-in-out infinite; }
}
@keyframes st-pulse { 0%, 100% { opacity: 1 } 50% { opacity: .45 } }


/* ══════════════════════════════════════════════════════════════════════
   The purchase flow
   ══════════════════════════════════════════════════════════════════════
   Its own chrome, because a checkout is not a marketing page. No exits, a
   visible position in the sequence, and the business's own name in the bar
   so the page never stops being about them. */

.checkout-bar .masthead-inner { gap: 1rem 1.5rem; flex-wrap: wrap; }
.checkout-bar .wordmark { cursor: default; }
.checkout-for { color: var(--muted); font-size: .9375rem; }
.checkout-for strong { color: var(--ink); font-weight: 600; }

/* Scoped to the checkout bar, and it must stay that way. Unscoped, this
   sits 200 lines below the corporate `.steps` at identical specificity and
   silently wins — turning the "Four steps" section on how-it-works from a
   vertical list into four flex columns, each about one word wide, with the
   whole page scrolling sideways on a phone. */
.checkout-bar .steps {
  list-style: none; display: flex; align-items: center; gap: .35rem;
  margin: 0 0 0 auto; padding: 0; font-size: .8125rem;
}
.checkout-bar .steps li {
  display: flex; align-items: center; gap: .45rem;
  color: var(--muted); white-space: nowrap;
}
.checkout-bar .steps li + li::before {
  content: ""; width: 1.25rem; height: 1px; background: var(--rule-2);
  margin-right: .35rem;
}
.checkout-bar .steps .n {
  width: 1.4rem; height: 1.4rem; border-radius: 50%; flex: none;
  display: grid; place-items: center; font-weight: 700; font-size: .6875rem;
  background: var(--paper-3); color: var(--muted);
}
.checkout-bar .steps [aria-current="step"] { color: var(--ink); font-weight: 700; }
.checkout-bar .steps [aria-current="step"] .n { background: var(--accent); color: #fff; }
.checkout-bar .steps .done { color: var(--ink-2); }
.checkout-bar .steps .done .n { background: var(--accent-wash); color: var(--accent-dark); }

/* On a phone the labels are noise — the numbers still say where you are. */
@media (max-width: 46rem) {
  .checkout-bar .steps .l { display: none; }
  .checkout-bar .steps li + li::before { width: .75rem; }
  .checkout-for { width: 100%; order: 3; }
}

/* A quiet, permanent reminder of what is being bought. A checkout that
   hides the price until the last screen reads as a trap. */
.price-rail {
  border: 1px solid var(--rule); border-radius: 6px; background: var(--paper-2);
  padding: 1rem 1.25rem; display: flex; gap: .6rem 1.5rem; flex-wrap: wrap;
  align-items: baseline; margin-top: 2.5rem;
}
.price-rail .amt { font-weight: 700; color: var(--ink); }
.price-rail .note { color: var(--muted); font-size: .9375rem; }


/* One measure for the whole purchase flow.
   ──────────────────────────────────────────────────────────────────────
   The question and the answers were in different containers: the heading
   ran the full 68rem and the options sat in a centred 38rem block, so the
   choices began 105px to the right of the thing they answered. Two
   left edges on a page with one job.

   Everything in a checkout step now hangs off the same edge, at a width
   that is actually readable rather than the width that happens to be
   available. */
.flow { width: 100%; max-width: 40rem; margin-inline: 0; }
.flow h1 { max-width: 18ch; }
.flow .lede { max-width: 34rem; }

/* The steps carry the vertical rhythm, so the sections between them do not
   need to shout. A checkout that scrolls twice before the first choice
   feels longer than it is. */
.flow-head { padding-block: clamp(2rem, 5vw, 3.25rem) clamp(1.25rem, 3vw, 2rem); }
.flow-body { padding-block: 0 clamp(3rem, 7vw, 5rem); }


/* The preview — the arrival.
   ══════════════════════════════════════════════════════════════════════
   Someone who never asked for this has clicked a link from a stranger.
   The order of the page is the whole argument: someone made this for me →
   here it is, real and finished → this is what it costs → and if not, no
   hard feelings.

   Two brands share the page and must never blur. The chrome is ours — ink
   ground, cobalt accent, the same on every preview we ever send. The site
   inside the frame is theirs, in its own trade colour. Anyone should be
   able to tell at a glance which part is the company selling and which is
   the thing being sold. */

.pv { background: var(--paper); }

/* The demonstration's own declaration. Deliberately not styled as a warning
   — it is a statement of what the page is, and looking anxious about it
   would undercut the confidence the rest of the page is built on. */
.pv-demo-bar { background: var(--accent); color: #fff; padding-block: .85rem; }
.pv-demo-bar .container { font-size: .9375rem; line-height: 1.5; max-width: 62rem; }
.pv-demo-bar strong { font-weight: 700; }

/* A control that shows where the decision sits without being one. Not a
   <button disabled>, because there is no action here to disable — it is a
   span, so it is not focusable and screen readers are told plainly. */
.btn.is-disabled { background: var(--rule-2); color: var(--muted);
                   cursor: not-allowed; pointer-events: none; box-shadow: none; }
.pv-offer .btn.is-disabled { background: #3A3D42; color: #8B8983; }
.pv-demo-note { font-size: .875rem; color: #8B8983; }

.pv-open { background: var(--ink); color: var(--paper);
           padding-block: 1.25rem clamp(2.5rem, 6vw, 4rem); }
.pv-open-bar { display: flex; align-items: center; justify-content: space-between;
               gap: 1rem; margin-bottom: clamp(2.5rem, 7vw, 4.5rem); }
.pv-open .wordmark, .pv-open .wordmark .mark { color: var(--paper); }
.pv-private { display: inline-flex; align-items: center; gap: .45rem;
              font-size: .75rem; letter-spacing: .1em; text-transform: uppercase;
              font-weight: 700; color: #8B8983; }

.pv-eyebrow { font-size: .8125rem; letter-spacing: .14em; text-transform: uppercase;
              font-weight: 700; color: #8B8983; margin: 0 0 1.1rem; }
.pv-title { font-size: clamp(2.4rem, 8vw, 5rem); font-weight: 800;
            letter-spacing: -.045em; line-height: 1; margin: 0 0 1.5rem;
            color: var(--paper); text-wrap: balance; }
/* Their name is the largest thing on our page. The page is about them; we
   are only the frame around it. */
.pv-name { color: var(--accent-lt); }
.pv-sub { font-size: clamp(1.0625rem, 2.4vw, 1.375rem); line-height: 1.5;
          color: #C9C7C1; max-width: 42ch; margin: 0; }

/* The site, shown as an object rather than embedded. A bare full-bleed
   iframe reads as part of our page; inset on its own ground, with the
   address it could live at above it, it reads as their website. */
.pv-stage { background: var(--ink); padding-bottom: clamp(3rem, 8vw, 5rem); }
.pv-window { border-radius: 10px; overflow: hidden; background: #fff;
             box-shadow: 0 2rem 5rem rgba(0,0,0,.45),
                         0 0 0 1px rgba(255,255,255,.08); }
.pv-chrome { display: flex; align-items: center; gap: .85rem;
             background: var(--paper-2); border-bottom: 1px solid var(--rule);
             padding: .6rem .9rem; }
.pv-dots { display: inline-flex; gap: .32rem; flex: none; }
.pv-dots i { width: .55rem; height: .55rem; border-radius: 50%;
             background: var(--rule-2); display: block; }
.pv-url { font-family: var(--mono); font-size: .8125rem; color: var(--muted);
          background: var(--paper); border: 1px solid var(--rule);
          border-radius: 4px; padding: .25rem .7rem; flex: 1 1 auto;
          min-width: 0; overflow: hidden; text-overflow: ellipsis;
          white-space: nowrap; }
.pv-frame { display: block; width: 100%; height: min(78vh, 44rem); border: 0;
            background: #fff; }
.pv-scrollnote { margin: 1.15rem 0 0; font-size: .9375rem; color: #8B8983;
                 text-align: center; }

/* Specs: facts we can point at on the page above, not adjectives. */
.pv-facts-band { border-bottom: 1px solid var(--rule);
                 padding-block: clamp(2.5rem, 6vw, 4rem); }
.pv-specs { list-style: none; margin: 0; padding: 0; display: grid; gap: 2rem; }
@media (min-width: 44rem) {
  .pv-specs { grid-template-columns: repeat(4, 1fr); gap: 2.5rem; }
}
.pv-specs li { display: grid; gap: .35rem; }
.pv-specs b { font-size: 1.0625rem; letter-spacing: -.015em; }
.pv-specs span { font-size: .9375rem; color: var(--ink-2); line-height: 1.5; }

/* The offer: said once, plainly, with the walk-away in the same breath. */
.pv-offer { background: var(--ink); color: var(--paper);
            padding-block: clamp(3rem, 8vw, 5rem); }
.pv-offer-in { display: grid; gap: 2.5rem; align-items: start; }
@media (min-width: 52rem) {
  .pv-offer-in { grid-template-columns: 1.2fr auto; gap: 4rem; }
}
.pv-offer .pv-eyebrow { color: var(--accent-lt); }
.pv-figure { font-size: clamp(1.5rem, 4vw, 2.25rem); font-weight: 700;
             letter-spacing: -.03em; line-height: 1.25; margin: 0 0 1rem;
             color: var(--paper); }
.pv-figure b { font-weight: 800; color: var(--accent-lt);
               font-variant-numeric: tabular-nums; }
.pv-offer-note { font-size: 1rem; color: #C9C7C1; max-width: 46ch; margin: 0;
                 line-height: 1.6; }
.pv-actions { display: flex; flex-direction: column; align-items: flex-start;
              gap: 1rem; }
.btn-lg { font-size: 1.0625rem; padding: 1rem 2rem; }
/* The primary button is ink on paper everywhere else, which on the ink band
   is a button you cannot see. Inverted here, so the one control that closes
   the sale is the brightest thing in the section. */
.pv-offer .btn-primary { background: var(--paper); color: var(--ink); }
.pv-offer .btn-primary:hover { background: var(--accent-lt); color: var(--ink); }
.pv-quiet { font-size: .9375rem; color: #C9C7C1; text-decoration: none;
            border-bottom: 1px solid #3A3D42; }
.pv-quiet:hover { color: var(--paper); border-bottom-color: #8B8983; }

/* A page that pressures here undoes everything above it. */
.pv-either-way { margin: clamp(2.5rem, 6vw, 3.5rem) 0 0; padding-top: 2rem;
                 border-top: 1px solid #2A2C30; font-size: 1rem;
                 line-height: 1.6; color: #C9C7C1; max-width: 56ch; }
.pv-either-way a { color: #8B8983; text-decoration: underline;
                   text-underline-offset: .2em; margin-left: .35rem; }
.pv-either-way a:hover { color: var(--paper); }

/* Make it yours. Below the offer on purpose: someone who wants to improve
   it before deciding is already most of the way to buying. */
.pv-yours { padding-block: clamp(3rem, 8vw, 5rem); }
.pv-h2 { font-size: clamp(1.6rem, 4vw, 2.25rem); font-weight: 800;
         letter-spacing: -.03em; margin: 0 0 .75rem; }
.pv-yours .pv-sub { color: var(--ink-2); }
.pv-yours-grid { display: grid; gap: 1.5rem; }
@media (min-width: 52rem) { .pv-yours-grid { grid-template-columns: 1fr 1fr; } }
.pv-card { border: 1px solid var(--rule); border-radius: 8px; padding: 1.75rem;
           background: var(--paper); }
.pv-card h3 { font-size: 1.125rem; letter-spacing: -.02em; margin: 0 0 .5rem; }
.pv-card > p { font-size: .9375rem; color: var(--ink-2); margin: 0 0 1.25rem; }
.pv-card label.btn { cursor: pointer; }
.pv-ok  { color: var(--ok);  font-weight: 600; font-size: .9375rem; margin: 0 0 1rem; }
.pv-bad { color: var(--err); font-weight: 600; font-size: .9375rem; margin: 0 0 1rem; }
.pv-note { font-size: .875rem; color: var(--muted); margin: 1rem 0 0; }

.pv-thumbs { list-style: none; margin: 1.25rem 0 0; padding: 0; display: grid;
             grid-template-columns: repeat(auto-fill, minmax(6rem, 1fr));
             gap: .6rem; }
.pv-thumbs li { position: relative; aspect-ratio: 1; border-radius: 4px;
                overflow: hidden; background: var(--paper-2); }
.pv-thumbs img { width: 100%; height: 100%; object-fit: cover; display: block; }
.pv-thumbs form { position: absolute; inset: auto 0 0 0; margin: 0; }
.pv-thumbs button { width: 100%; border: 0; cursor: pointer; font: inherit;
                    font-size: .6875rem; font-weight: 600; padding: .3rem;
                    background: rgba(0,0,0,.62); color: #fff; }
.pv-thumbs button:hover { background: var(--err); }

.pv-form fieldset { border: 1px solid var(--rule); border-radius: 5px;
                    padding: 1rem 1.15rem; margin: 0 0 1rem; }
.pv-form legend { font-size: .6875rem; letter-spacing: .12em;
                  text-transform: uppercase; color: var(--muted);
                  font-weight: 700; padding-inline: .4rem; }
.pv-days { display: grid; gap: .5rem; }
.pv-fields { display: grid; gap: .6rem;
             grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr)); }
.pv-form label { display: grid; gap: .25rem; }
.pv-days label { grid-template-columns: 5.5rem 1fr; gap: .6rem;
                 align-items: center; }
.pv-form span { font-size: .75rem; font-weight: 600; color: var(--ink-2); }
/* 16px minimum, or iOS zooms the page the instant a field is focused. */
.pv-form input { font: inherit; font-size: 16px; padding: .55rem .7rem;
                 border: 1px solid var(--rule-2); border-radius: 4px;
                 background: var(--paper); color: var(--ink); width: 100%;
                 min-height: 44px; }

/* The purchase flow's own footer: what someone about to pay has a right to
   read, and nothing that leads back out of the funnel. */
.flow-footer { border-top: 1px solid var(--rule); padding-block: 2.5rem 4rem;
               background: var(--paper-2); }
.flow-footer .container { display: grid; gap: .85rem; justify-items: start; }
.flow-footer p { margin: 0; font-size: .9375rem; color: var(--ink-2);
                 max-width: 52ch; }
.flow-links { list-style: none; margin: 0; padding: 0; display: flex;
              flex-wrap: wrap; gap: .5rem 1.5rem; font-size: .9375rem; }
.flow-links a { color: var(--ink-2); text-decoration: none;
                border-bottom: 1px solid var(--rule-2); }
.flow-links a:hover { color: var(--ink); border-bottom-color: var(--ink); }
.flow-legal { font-size: .8125rem; color: var(--muted); }

.pv-close { border-top: 1px solid var(--rule); padding-block: 2.5rem 4rem;
            background: var(--paper-2); }
.pv-close-in { display: grid; gap: .85rem; justify-items: start; }
.pv-close p { margin: 0; font-size: .9375rem; color: var(--ink-2);
              max-width: 52ch; }
.pv-legal { font-size: .8125rem; color: var(--muted); }

@media (max-width: 44rem) {
  .pv-frame { height: min(70vh, 34rem); }
  .pv-actions { width: 100%; }
  .pv-actions .btn { width: 100%; justify-content: center; text-align: center; }
}

/* ── The site, beside whatever is being asked of them ──────────────
   Two pages ask something of a prospect about a website they can no longer
   see: "why" asks them to trust us, and "changes" asks them to describe
   what is wrong with it.
   It sits alongside the reading column in the same frame they met it in, so
   it reads as the same object rather than a second screenshot of one.

   Inert on purpose. A scrollable copy here would compete with the live one
   on the arrival page and give them two places to be lost in; this is for
   looking at while reading, and the way back to the real thing is the
   "Back to the concept" link at the top.

   Everything is namespaced `why-` and the split only exists above 1100px.
   Below that there is no beside, and the arrival page they just came from
   already gave the site the full width of the screen.
   ─────────────────────────────────────────────────────────────────────── */

.beside-site { display: none; }

@media (min-width: 1100px) {
  .beside {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(24rem, 34vw);
    gap: clamp(2rem, 4vw, 3.5rem);
    align-items: start;
    max-width: 96rem;
    margin-inline: auto;
    padding-inline: clamp(1.25rem, 4vw, 2.5rem);
  }

  /* The sections keep their own rhythm but stop centring themselves on the
     viewport — the column is the page now. */
  .beside-main .container { max-width: none; padding-inline: 0; }

  .beside-site {
    display: block;
    position: sticky;
    top: 2rem;
    padding-top: clamp(3rem, 7vw, 4.5rem);
  }

  .beside-site .pv-window {
    box-shadow: 0 1rem 2.5rem rgba(0, 0, 0, .13),
                0 0 0 1px var(--rule);
  }

  .beside-frame {
    width: 100%;
    height: min(38rem, calc(100vh - 12rem));
    border: 0;
    display: block;
    background: var(--paper);
    pointer-events: none;
  }

  .beside-note {
    margin: .85rem 0 0;
    font-size: .8125rem;
    color: var(--muted);
    text-align: center;
  }
}


/* ══ The work ═══════════════════════════════════════════════════════════
   Three real renders from the generator, framed. Every website company
   writes a paragraph claiming they make good websites and none of them
   show you one, so this sits directly under the hero — before any claim,
   rather than after it.

   The frames are inert. This is a shopfront window: the whole card is the
   link, and clicking anywhere on it opens the site properly rather than
   dropping you inside a scaled iframe you cannot navigate out of.
   ════════════════════════════════════════════════════════════════════ */

.work {
  padding-block: clamp(3rem, 7vw, 5rem);
  background: var(--paper-2);
  border-top: 1px solid var(--rule);
  border-bottom: 1px solid var(--rule);
}
.work-head { max-width: 42rem; margin-bottom: clamp(2rem, 4vw, 3rem); }
.work-head h2 { margin: .35rem 0 .75rem; }
.work-head .lede { margin: 0; }

.work-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(17rem, 1fr));
  gap: clamp(1rem, 2.5vw, 1.75rem);
}

.work-item {
  display: block;
  text-decoration: none;
  color: inherit;
  border-radius: 12px;
}
.work-frame {
  display: block;
  position: relative;
  overflow: hidden;
  border-radius: 12px;
  border: 1px solid var(--rule-2);
  background: var(--paper);
  aspect-ratio: 4 / 3;
  /* So the render inside can be scaled against this frame's own width. */
  container-type: inline-size;
  box-shadow: 0 1px 2px rgba(17, 17, 17, .04);
  transition: box-shadow .28s ease, transform .28s ease;
}
.work-frame iframe {
  /* Rendered at desktop width and scaled down, so what is on show is the
     layout a visitor would actually get rather than the mobile stack. */
  width: 1280px;
  height: 960px;
  border: 0;
  transform-origin: 0 0;
  pointer-events: none;
  /* Fallback for anything without container queries: close, and cropping a
     little is better than overflowing a lot. */
  transform: scale(.24);
  /* The real answer — the frame's own width divided by the render width. */
  transform: scale(calc(100cqw / 1280px));
}
/* The whole card is the link; the frame must never swallow the click. */
.work-item:hover .work-frame,
.work-item:focus-visible .work-frame {
  box-shadow: 0 1.25rem 2.5rem -1rem rgba(17, 17, 17, .22);
  transform: translateY(-3px);
}
.work-item:focus-visible { outline: 2px solid var(--accent); outline-offset: 4px; }

.work-meta {
  display: block;
  padding: .9rem .15rem 0;
}
.work-meta strong { display: block; font-size: 1rem; letter-spacing: -.01em; }
.work-meta span { display: block; font-size: .875rem; color: var(--muted); margin-top: .15rem; }
.work-note { margin: clamp(1.5rem, 3vw, 2.25rem) 0 0; font-size: .875rem; color: var(--muted); }

/* ══ Motion ═════════════════════════════════════════════════════════════
   One idea, used once: things arrive as you reach them. Enough to make the
   page feel alive without turning reading into a slideshow, and the whole
   effect is a translate and an opacity so nothing reflows.

   Everything is legible with the script blocked — `.reveal` only gets its
   starting state once JavaScript has said it is going to finish the job.
   ════════════════════════════════════════════════════════════════════ */

.js .reveal {
  opacity: 0;
  transform: translateY(14px);
}
.js .reveal.shown {
  opacity: 1;
  transform: none;
  transition: opacity .5s cubic-bezier(.2, .6, .2, 1) calc(var(--i, 0) * 90ms),
              transform .5s cubic-bezier(.2, .6, .2, 1) calc(var(--i, 0) * 90ms);
}

@media (prefers-reduced-motion: reduce) {
  .js .reveal { opacity: 1; transform: none; }
  .work-frame, .work-item:hover .work-frame { transition: none; transform: none; }
}


/* ══ Who this is for ════════════════════════════════════════════════════
   Photographs of the trades we approach. The names sit under the images
   rather than over them: text on a photograph needs a scrim, a scrim needs
   the photograph darkened, and darkening them to caption them would defeat
   the reason for having them at all.
   ════════════════════════════════════════════════════════════════════ */

.trades { padding-block: clamp(3rem, 7vw, 5rem); }
.trade-grid {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(9.5rem, 1fr));
  gap: clamp(.75rem, 1.8vw, 1.25rem);
}
.trade { margin: 0; }
.trade-shot {
  display: block;
  overflow: hidden;
  border-radius: 10px;
  background: var(--paper-3);
  aspect-ratio: 3 / 4;
}
.trade-shot img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  /* Settles as you look at it. The photographs are stock, and stock reads
     as stock partly because it is always at full saturation. */
  filter: saturate(.82);
  transition: filter .6s ease, transform .6s cubic-bezier(.2, .6, .2, 1);
}
.trade:hover .trade-shot img {
  filter: saturate(1);
  transform: scale(1.03);
}
.trade-name {
  display: block;
  margin-top: .6rem;
  font-size: .875rem;
  letter-spacing: .01em;
  color: var(--ink-2);
}
.trade-note {
  margin: clamp(1.5rem, 3vw, 2.25rem) 0 0;
  font-size: .875rem;
  color: var(--muted);
  max-width: 44ch;
}

/* ══ The mark, doing what the brand book says it does ═══════════════════
   Pending, working, handled — the promise of the page performed in three
   characters instead of asserted. Decorative, so it is hidden from screen
   readers, and it renders on the handled state with no script at all.
   ════════════════════════════════════════════════════════════════════ */

.hero-mark {
  margin: 0 0 1.25rem;
  font-size: 1.5rem;
  line-height: 1;
  color: var(--accent);
}

@media (prefers-reduced-motion: reduce) {
  .trade-shot img,
  .trade:hover .trade-shot img { transition: none; transform: none; filter: saturate(.9); }
}


/* ══ The sequence ═══════════════════════════════════════════════════════
   Four steps, and whose each one is is the actual information here — so
   the design carries it rather than setting four identical rows and
   leaving the heading to claim it.

   Three are ours and read as a quiet set. The one that is yours is the
   only thing being asked of anybody on this page, so it is the one that
   looks different: accent rule, its own label, and a lift off the ground.
   ════════════════════════════════════════════════════════════════════ */

.flow-steps {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  gap: clamp(.85rem, 2vw, 1.25rem);
  counter-reset: none;
}

.fstep {
  position: relative;
  padding: 1.5rem 1.35rem 1.6rem;
  border: 1px solid var(--rule);
  border-top: 3px solid var(--rule-2);
  border-radius: 4px;
  background: var(--paper);
}

.fstep-n {
  display: block;
  font-family: var(--mono);
  font-size: .8125rem;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
  margin-bottom: .9rem;
}

.fstep-who {
  display: block;
  font-size: .6875rem;
  font-weight: 600;
  letter-spacing: .11em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: .35rem;
}

.fstep h3 { margin: 0 0 .5rem; }
.fstep p { color: var(--ink-2); font-size: .9688rem; }

/* The one step that is yours. The whole pitch is that there is only one,
   so it is worth being the thing the eye lands on. */
.fstep.is-yours {
  border-top-color: var(--accent);
  background: var(--paper);
  box-shadow: 0 .75rem 1.75rem -1rem rgba(36, 87, 255, .28);
}
.fstep.is-yours .fstep-who { color: var(--accent); }
.fstep.is-yours .fstep-n { color: var(--accent); }

/* ══ Questions ══════════════════════════════════════════════════════════
   Not a sequence, so not numbered. These used the step component with an
   em dash where the number goes, which is what a component being wrong
   looks like.

   Two columns where there is room: five full-width answers stacked is the
   wall this section read as, and the questions are independent so there is
   no order for a single column to preserve.
   ════════════════════════════════════════════════════════════════════ */

.qa {
  margin: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(20rem, 1fr));
  gap: 0 clamp(2rem, 5vw, 4rem);
}

.qa-item {
  padding: 1.35rem 0;
  border-top: 1px solid var(--rule);
  break-inside: avoid;
}

.qa dt {
  font-size: 1.0625rem;
  font-weight: 600;
  letter-spacing: -.012em;
  line-height: 1.35;
  margin-bottom: .4rem;
}

.qa dd {
  margin: 0;
  color: var(--ink-2);
  font-size: .9688rem;
  max-width: 44ch;
}

.qa-note {
  display: block;
  color: var(--muted);
  font-size: .875rem;
  margin-bottom: .25rem;
}


/* ══ Signing in ═════════════════════════════════════════════════════════
   Three ways in on one small page. One email field serves all of them —
   `formaction` sends the same form to a different route, so asking for the
   address twice, or copying it between forms with a script, is a worse
   answer to a question HTML already answers.
   ════════════════════════════════════════════════════════════════════ */

.signin { display: grid; gap: 1rem; }
.signin label {
  display: grid;
  gap: .35rem;
  font-size: .875rem;
  font-weight: 600;
}
.signin input {
  font: inherit;
  font-size: 1rem;
  padding: .65rem .8rem;
  border: 1px solid var(--rule-2);
  border-radius: 3px;
  background: var(--paper);
  color: var(--ink);
}
.signin-note {
  font-size: .9375rem;
  color: var(--muted);
  margin: 0;
  line-height: 1.5;
}
.signin-note a { color: var(--accent); }

/* A submit button that has to read as a sentence, because it is one. */
.linklike {
  font: inherit;
  font-size: inherit;
  color: var(--accent);
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 2px;
}

/* The reply after asking for a preview link back. Deliberately the same
   words whether or not we hold the address. */
.lookup-said {
  margin: 1.5rem 0 0;
  padding: 1rem 1.15rem;
  background: var(--paper-2);
  border-left: 2px solid var(--accent);
  border-radius: 0 6px 6px 0;
  font-size: .9375rem;
  color: var(--ink-2);
  max-width: 34rem;
}
