/* ==========================================================================
   Hookproof — styles
   Design system per ../07-sales-page-plan.md. Every value here traces to that
   spec; don't change tokens ad hoc, change them there first.

   Carried over from TechSplit's site.css, deliberately, per the founder's direction not to
   look like the dark-SaaS-console competitors researched (Linear/Vercel/Hookdeck/Svix) but to
   share TechSplit's Apple-derived craft instead:
     - the sans is the -apple-system/SF Pro stack, not a loaded webfont (see index.html's <head>)
     - the sticky frosted nav (.site-nav) — same backdrop-filter recipe, same adaptive-on-scroll
       idea, applied to alternating --bg/--surface tone sections instead of TechSplit's light/dark
     - the scroll-reveal system below (.reveal / .reveal-on) — same easing curve, same stagger,
       same bidirectional/reduced-motion/failsafe behaviour, ported near-verbatim from
       techsplit.net's script.js because the technique itself is what was asked for, not a
       reskinned copy of it
   What deliberately did NOT carry over: TechSplit's literal palette (white/green) and its pill
   corner-to-corner card radius — Hookproof stays dark with its own blue accent so the two
   unrelated products don't read as siblings. See 07-sales-page-plan.md for the full reasoning.
   ========================================================================== */

/* Self-hosted JetBrains Mono (latin subset only — this is an English-only site). One variable
   file backs both weights below; that's not a mistake, it's how Google itself serves it
   (font-weight: 400 and 500 @font-face blocks pointing at the same .woff2, confirmed against
   Google Fonts' own css2 API output before downloading). */
@font-face {
  font-family: 'JetBrains Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('fonts/jetbrains-mono.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: 'JetBrains Mono';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('fonts/jetbrains-mono.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;
}

:root {
  --bg:      #0A0B0D;
  --surface: #141518;
  --border:  #24262B;
  --text:    #F2F3F4;
  --muted:   #8A8F98;
  --accent:  #4C8DFF;
  --pass:    #3FB950;
  --fail:    #F85149;

  /* Apple system-font stack — TechSplit's exact choice. No webfont request for body/headline
     text; it renders as SF Pro on Apple devices, Segoe UI on Windows, Roboto on Android. */
  --sans: -apple-system, BlinkMacSystemFont, "SF Pro Display", "SF Pro Text", "Segoe UI", Roboto,
          Helvetica, Arial, sans-serif;
  --mono: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, Monaco, monospace;

  --content: 1100px;
  --prose:   720px;
  --radius:       6px;
  --radius-card:  16px;   /* more generous than the original 8px — Apple's own cards run 16-28px */
  --radius-pill:  980px;  /* TechSplit's exact pill value, for buttons only — never cards */

  --nav-height: 60px;     /* TechSplit's exact header height */
}

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

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

body {
  margin: 0;
  /* The single tone for the whole page — see "section tone: deliberately uniform" below for why
     there is no per-section alternation. --bg is still used by the nav and by inset surfaces
     (the console's inner panels, code blocks) that need to read as recessed against this. */
  background: var(--surface);
  color: var(--text);
  font-family: var(--sans);
  font-size: 16px;
  line-height: 1.6;
  /* Apple's global tightening — applied everywhere, the same as TechSplit does. */
  letter-spacing: -0.011em;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  /* General guard against anything wide causing horizontal scroll — `clip`, not `hidden`, so it
     doesn't create a scroll container that could interfere with the sticky nav. */
  overflow-x: clip;
}

/* ---------- type scale ---------- */
/* Fluid clamp() sizing and a ch-based max-width (control line length, not just wrapping) are
   TechSplit's headline discipline, carried over — see its .headline/.subhead rules. */

h2 {
  font-size: clamp(28px, 4vw, 36px);
  font-weight: 600;
  letter-spacing: -0.022em;
  line-height: 1.15;
  max-width: 18ch;
  margin: 0 0 20px;
}

h3 {
  font-size: 20px;
  font-weight: 500;
  letter-spacing: -0.01em;
  line-height: 1.3;
  margin: 0 0 8px;
}

p { margin: 0 0 16px; max-width: var(--prose); }
p:last-child { margin-bottom: 0; }

.lede { font-size: 19px; line-height: 1.55; color: var(--text); }

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

code {
  font-family: var(--mono);
  font-size: 0.89em;
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 1px 5px;
}

.label {
  display: block;
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 8px;
}

.note { font-size: 14px; line-height: 1.5; color: var(--muted); margin: 10px 0 0; }

/* ---------- accessibility ---------- */

.skip {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--accent);
  color: #fff;
  padding: 10px 16px;
  z-index: 10;
}
.skip:focus { left: 0; }

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: 3px;
}

/* ---------- sticky nav ----------
   TechSplit's exact frosted-glass recipe (backdrop-filter: saturate + blur, a translucent
   background, a hairline border). TechSplit needs the .is-over-dark swap because it alternates
   fully light and dark sections; this page is dark throughout, so the "swap" here is a much
   smaller shift in opacity/border between the --bg and --surface tone sections below — same
   mechanism (see console.js's initAdaptiveNav), scaled to an actual need rather than copied
   for its own sake. */

/* One state, tuned to the single page tone. There used to be a second `.is-over-surface` state
   for scrolling over a lighter section; the page no longer alternates tones (see "section tone:
   deliberately uniform"), so there is nothing to adapt to and a second state would only flicker.
   console.js's initAdaptiveNav still toggles the class — it now matches no rule. */
.site-nav {
  position: sticky;
  top: 0;
  z-index: 50;
  height: var(--nav-height);
  background: rgba(20, 21, 24, 0.78);
  backdrop-filter: saturate(180%) blur(20px);
  -webkit-backdrop-filter: saturate(180%) blur(20px);
  border-bottom: 1px solid rgba(255, 255, 255, 0.09);
  transition: background-color .35s ease, border-color .35s ease;
}

.site-nav__inner {
  height: 100%;
  max-width: var(--content);
  margin: 0 auto;
  padding: 0 24px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
}

.site-nav__logo {
  font-family: var(--mono);
  font-size: 14px;
  font-weight: 500;
  color: var(--text) !important;
  letter-spacing: -0.01em;
}
.site-nav__logo:hover { text-decoration: none; }

.site-nav__links {
  display: flex;
  gap: 28px;
  font-size: 14px;
}
.site-nav__links a { color: var(--muted); }
.site-nav__links a:hover { color: var(--text); text-decoration: none; }

/* ---------- scroll reveal ----------
   Ported near-verbatim from techsplit.net's script.js/site.css — same easing curve, same
   28px rise, same 0.9s duration, same bidirectional/reduced-motion/failsafe behaviour. Default
   is fully visible; JS opts elements in by adding .reveal-on to <html>, so a visitor with JS
   disabled (or a crawler that never scrolls) always sees everything. See console.js's
   initReveals(). */

@media (prefers-reduced-motion: no-preference) {
  .reveal-on .reveal {
    opacity: 0;
    transform: translateY(28px);
    transition: opacity 0.9s cubic-bezier(0.22, 0.61, 0.36, 1),
                transform 0.9s cubic-bezier(0.22, 0.61, 0.36, 1);
    will-change: opacity, transform;
  }
  .reveal-on .reveal.is-visible {
    opacity: 1;
    transform: none;
  }
}

/* ---------- section tone: deliberately uniform ----------
   There is no light/dark section alternation. Every section sits on the same surface tone, set
   on <body> above; the page reads as one continuous surface, separated only by the 1px
   border-top on each section.

   History, 2026-09-22, so this isn't "fixed" back into a bug later. This started as
   `.tone-surface { box-shadow: 0 0 0 100vmax var(--surface); }` — the standard trick for
   bleeding a background edge-to-edge out of a width-constrained column. It cannot stay inside
   its own section: the spread radiates from the section's box in every direction, so on a
   2000px-wide viewport each of the two .tone-surface sections painted surface colour 2000px
   above and below itself, and between them they flooded the entire document. That flood is why
   the page looked uniform at full screen — the bug succeeding completely. At narrower widths
   100vmax is smaller, the flood only reached partway down, and the uncovered near-black body
   background showed through as a hard tone seam cutting across #problem's cards. (Note for
   anyone reaching for `overflow: clip` on the section to contain it: that does nothing. An
   element's own box-shadow paints with its own background/border layer and is not clipped by
   its own overflow.)

   Given the choice between making the alternation render correctly at every width and dropping
   it, the founder chose to drop it — the uniform look was the intended one. So the tone now
   comes from a single background on <body> and nothing bleeds anywhere.

   `.tone-bg` / `.tone-surface` are left on the sections in index.html as inert markers, and
   console.js's initAdaptiveNav still reads them; with the page uniform there is no longer a
   tone for the nav to adapt to, so the `.site-nav.is-over-surface` rule is gone and that toggle
   is a no-op. Kept rather than deleted so the alternation is straightforward to restore if it's
   ever wanted — restoring it means giving .tone-surface a top/bottom-pinned full-width
   pseudo-element (bounded, so it can't leave its section), NOT the box-shadow spread. */

/* ---------- layout ---------- */

main > section {
  max-width: var(--content);
  margin: 0 auto;
  padding: 96px 24px;
  border-top: 1px solid var(--border);
}

main > section.console-wrap { border-top: 0; }

/* ---------- screen one: the console ---------- */

.console-wrap {
  min-height: calc(100svh - var(--nav-height));
  display: flex;
  align-items: center;
  padding-top: 40px !important;
  padding-bottom: 40px !important;
}

.console {
  width: 100%;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 10px;
  overflow: hidden;
}

.console__bar {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 14px 18px;
  border-bottom: 1px solid var(--border);
  background: rgba(255, 255, 255, 0.015);
}

.console__dots { display: flex; gap: 6px; flex-shrink: 0; }
.console__dots i {
  width: 10px; height: 10px;
  border-radius: 50%;
  background: var(--border);
}

/* The <h1> lives here as interface chrome, not as a marketing headline —
   present for SEO with the category keyword, sized like a title bar. */
.console__bar h1 {
  font-size: 15px;
  font-weight: 500;
  letter-spacing: -0.01em;
  line-height: 1.4;
  margin: 0;
  display: flex;
  align-items: baseline;
  gap: 10px;
  flex-wrap: wrap;
}

.console__sub { color: var(--muted); font-weight: 400; }

.badge {
  margin-left: auto;
  flex-shrink: 0;
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--muted);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 3px 10px;
}

.console__target { padding: 20px 18px; border-bottom: 1px solid var(--border); }

.target-row { display: flex; gap: 10px; align-items: stretch; }

.target-input {
  flex: 1;
  min-width: 0;
  font-family: var(--mono);
  font-size: 14px;
  color: var(--muted);
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 11px 14px;
  cursor: default;
}

.btn {
  font-family: var(--sans);
  font-size: 15px;
  font-weight: 500;
  border-radius: var(--radius);
  padding: 12px 20px;
  border: 1px solid transparent;
  cursor: pointer;
  white-space: nowrap;
  transition: background-color .15s ease, opacity .15s ease;
}

.btn--primary { background: var(--accent); color: #fff; }
.btn--primary:hover:not(:disabled) { background: #5F9AFF; }
.btn--primary:disabled { opacity: .55; cursor: default; }

/* Pill shape — TechSplit's exact --radius-pill value, reserved for buttons only (never cards;
   see the :root comment). The nav CTA is the only pill on the page; the console's own Run button
   stays --radius so it still reads as part of the terminal chrome, not a marketing CTA. */
.btn--pill { border-radius: var(--radius-pill); }
.btn--small { padding: 8px 18px; font-size: 14px; }
.btn--small:hover { text-decoration: none; }

/* ---------- results pane ---------- */

.console__results {
  padding: 18px;
  font-family: var(--mono);
  font-size: 14px;
  line-height: 1.7;
  min-height: 180px;
}

.empty { color: var(--muted); margin: 0; max-width: none; }
.empty strong { color: var(--text); font-weight: 500; }

.act { margin-bottom: 22px; }
.act:last-child { margin-bottom: 0; }

.act__head {
  color: var(--muted);
  font-size: 12px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  margin-bottom: 10px;
  padding-bottom: 8px;
  border-bottom: 1px solid var(--border);
  max-width: none;
}

.row {
  display: grid;
  grid-template-columns: 62px 190px 1fr;
  gap: 14px;
  align-items: baseline;
  padding: 3px 0;
  animation: rowIn .22s ease both;
}

@keyframes rowIn {
  from { opacity: 0; transform: translateY(-2px); }
  to   { opacity: 1; transform: none; }
}

.row__verdict { font-weight: 500; }
.row--pass .row__verdict { color: var(--pass); }
.row--fail .row__verdict { color: var(--fail); }
.row--run  .row__verdict { color: var(--muted); }

.row__mode { color: var(--text); }
.row__detail { color: var(--muted); }

.summary {
  margin-top: 14px;
  padding-top: 12px;
  border-top: 1px solid var(--border);
  color: var(--muted);
  max-width: none;
}
.summary strong { color: var(--text); font-weight: 500; }

.console__foot {
  padding: 14px 18px;
  border-top: 1px solid var(--border);
  background: rgba(255, 255, 255, 0.015);
  font-size: 13px;
  line-height: 1.55;
  color: var(--muted);
}
.console__foot strong { color: var(--text); font-weight: 500; }

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

.checks {
  max-width: var(--prose);
  padding-left: 20px;
  margin: 16px 0 0;
}
.checks li { margin-bottom: 10px; color: var(--muted); }
.checks code { color: var(--text); }

.grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 16px;
  margin-top: 32px;
}

.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  padding: 20px;
}
.card p { color: var(--muted); font-size: 15px; margin: 0; max-width: none; }

.steps {
  counter-reset: step;
  list-style: none;
  padding: 0;
  margin: 32px 0 0;
  display: grid;
  gap: 28px;
  max-width: var(--prose);
}
.steps li { counter-increment: step; padding-left: 46px; position: relative; }
.steps li::before {
  content: counter(step);
  position: absolute;
  left: 0; top: 0;
  width: 30px; height: 30px;
  display: grid;
  place-items: center;
  font-family: var(--mono);
  font-size: 13px;
  color: var(--muted);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 50%;
}
.steps p { color: var(--muted); margin: 0; }

/* ---------- FAQ ---------- */

details {
  max-width: var(--prose);
  border-bottom: 1px solid var(--border);
}
details summary {
  cursor: pointer;
  padding: 18px 32px 18px 0;
  font-size: 17px;
  font-weight: 500;
  letter-spacing: -0.01em;
  position: relative;
  list-style: none;
}
details summary::-webkit-details-marker { display: none; }
details summary::after {
  content: "+";
  position: absolute;
  right: 4px; top: 50%;
  transform: translateY(-50%);
  font-family: var(--mono);
  font-size: 18px;
  color: var(--muted);
}
details[open] summary::after { content: "−"; }
details p { color: var(--muted); padding-bottom: 20px; margin: 0; }

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

.form { max-width: 520px; margin-top: 32px; }
.field { margin-bottom: 20px; }

.form input,
.form textarea {
  width: 100%;
  font-family: var(--sans);
  font-size: 15px;
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 11px 14px;
}
.form textarea { resize: vertical; line-height: 1.55; }
.form input::placeholder,
.form textarea::placeholder { color: #5A5F68; }
.form input:focus, .form textarea:focus { border-color: var(--accent); outline: none; }

.form__status { font-size: 14px; margin: 14px 0 0; min-height: 21px; }
.form__status[data-state="error"] { color: var(--fail); }
.form__status[data-state="ok"] { color: var(--pass); }

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

.site-foot {
  max-width: var(--content);
  margin: 0 auto;
  padding: 32px 24px 48px;
  border-top: 1px solid var(--border);
  color: var(--muted);
  font-size: 14px;
}
.site-foot p { margin: 0; }

/* ---------- guides (hub + article) ---------- */
/* Added 2026-09-15 for the distribution/SEO content work (05-distribution.md). Long-form article
   typography didn't exist before this — the rest of the site is card/grid marketing copy, not
   prose. Reuses existing tokens (--prose, --content, --surface, --border, --mono) rather than
   inventing a new palette. */

.article-nav {
  max-width: var(--content);
  margin: 0 auto;
  padding: 20px 24px 0;
  font-size: 14px;
  color: var(--muted);
}
.article-nav a { color: var(--muted); }
.article-nav a:hover { color: var(--text); }

.article {
  max-width: var(--prose);
  margin: 0 auto;
  padding: 40px 24px 96px;
}
.article h1 {
  font-size: clamp(30px, 4.2vw, 42px);
  font-weight: 600;
  letter-spacing: -0.022em;
  line-height: 1.15;
  max-width: none;
  margin: 0 0 16px;
}
.article .article__meta { color: var(--muted); font-size: 14px; margin: 0 0 40px; }
.article h2 { max-width: none; font-size: clamp(22px, 3vw, 28px); margin: 48px 0 16px; }
.article h3 { margin: 28px 0 8px; }
.article p, .article li { max-width: none; color: var(--text); }
.article ul, .article ol { padding-left: 22px; margin: 0 0 16px; }
.article li { margin-bottom: 8px; }
.article strong { font-weight: 500; }
.article a { color: var(--accent); }
.article blockquote {
  margin: 24px 0;
  padding: 4px 0 4px 18px;
  border-left: 2px solid var(--accent);
  color: var(--muted);
}
.article pre {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 16px 18px;
  overflow-x: auto;
  margin: 0 0 20px;
  font-family: var(--mono);
  font-size: 13.5px;
  line-height: 1.6;
}
.article code {
  font-family: var(--mono);
  font-size: 0.9em;
  color: var(--text);
}
.article .article__cta {
  margin-top: 48px;
  padding: 28px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
}
.article .article__cta p { color: var(--muted); }
.article .article__cta .btn { margin-top: 12px; }

.guide-hub__intro { color: var(--muted); }
.guide-hub-list {
  list-style: none;
  padding: 0;
  margin: 32px 0 0;
  display: grid;
  gap: 16px;
}
.guide-hub-list a {
  display: block;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  padding: 20px;
  color: var(--text);
}
.guide-hub-list a:hover { border-color: var(--accent); text-decoration: none; }
.guide-hub-list h3 { margin: 0 0 6px; }
.guide-hub-list p { margin: 0; color: var(--muted); font-size: 15px; max-width: none; }

/* ---------- responsive ---------- */

@media (max-width: 720px) {
  main > section { padding: 56px 18px; }
  .console-wrap { min-height: 0; padding-top: 28px !important; padding-bottom: 28px !important; }
  .lede { font-size: 17px; }

  /* Nav: drop the middle links, keep the logo and the CTA — matches TechSplit's own mobile nav
     (nav-mobile.png in its build history), which does the same simplification rather than a
     hamburger menu, since there are only ever two things worth tapping on a page this short. */
  .site-nav__links { display: none; }
  .site-nav__inner { padding: 0 18px; }

  .console__bar { flex-wrap: wrap; gap: 10px; }
  .badge { margin-left: 0; order: 3; }
  .target-row { flex-direction: column; }
  .console__results { font-size: 12.5px; padding: 14px; }

  /* stack each result row so long detail strings stay readable */
  .row {
    grid-template-columns: 58px 1fr;
    gap: 4px 12px;
    padding: 7px 0;
  }
  .row__detail { grid-column: 2; }
}

/* ---------- reduced motion ---------- */

@media (prefers-reduced-motion: reduce) {
  .row { animation: none; }
  * { transition: none !important; }
}
