﻿/* ─────────────────────────────────────────
   Trakelix landing page — layout and components.

   Rules carried over from docs/design/trakelix-handoff.md:
     · No raw hex here. Tokens only (tokens.css).
     · No shadows anywhere. Depth = 1px border + surface colour.
     · Spacing is the 8px scale (4px for micro).
     · The amber CTA is identical in both themes — never theme it.
───────────────────────────────────────── */

/* ── Self-hosted fonts — OFF until the files are here ────────────
   The design system specifies Inter and JetBrains Mono, self-hosted
   via Fontsource: "no Google CDN, GDPR-safe". A CDN request would
   send every visitor's IP to a third party, so it is not an option.

   The files are not in this repo, so the rules below stay commented
   out — live @font-face rules pointing at missing files produce a
   404 per weight in the console on every page load. Until then the
   page uses the same fallback the Blazor app already falls back to.

   To switch it on:
     npm pack @fontsource/inter @fontsource/jetbrains-mono
     copy the .woff2 files into landing/assets/fonts/ with these
     names, uncomment this block, and add the SIL OFL license text
     alongside them (both fonts are OFL — the license must ship).
──────────────────────────────────────────────────────────────── */
/*
@font-face { font-family: 'Inter'; font-style: normal; font-weight: 400; font-display: swap;
             src: url('../assets/fonts/inter-400.woff2') format('woff2'); }
@font-face { font-family: 'Inter'; font-style: normal; font-weight: 500; font-display: swap;
             src: url('../assets/fonts/inter-500.woff2') format('woff2'); }
@font-face { font-family: 'Inter'; font-style: normal; font-weight: 600; font-display: swap;
             src: url('../assets/fonts/inter-600.woff2') format('woff2'); }
@font-face { font-family: 'Inter'; font-style: normal; font-weight: 700; font-display: swap;
             src: url('../assets/fonts/inter-700.woff2') format('woff2'); }
@font-face { font-family: 'JetBrains Mono'; font-style: normal; font-weight: 400; font-display: swap;
             src: url('../assets/fonts/jetbrains-mono-400.woff2') format('woff2'); }
*/

/* ── Landing-only type extension ──────────────────────────────
   The app's scale tops out at 32px (--text-4xl) because it is a
   dense tool. A marketing page needs display sizes above that, so
   these three are added here rather than in tokens.css — the app
   has no use for them and should not inherit them.
──────────────────────────────────────────────────────────────── */
:root {
    --display-1: clamp(36px, 6vw, 64px);
    --display-2: clamp(28px, 4vw, 40px);
    --display-3: clamp(20px, 2.4vw, 26px);
    --lede: clamp(16px, 1.6vw, 19px);
    --wrap: 1140px;
    --nav-h: 64px;

    /* Amber, made legible on a light background.
       --amber-400 (#E5A800) is a fill colour, not a text colour: on white it
       is 2.1:1, well under the 4.5:1 small text needs and under the 3:1 a
       meaningful icon needs. The handoff already names the replacements —
       amber-800 is "amber text, warnings, labels" (7.1:1) and amber-600 is
       "amber dark text on light bg" (3.8:1). On the dark ground amber-400 is
       9.2:1 and stays. The CTA button is exempt: it is dark text on an amber
       fill, which is 6.6:1 in both themes. */
    --accent-text: var(--amber-800);
    --accent-mark: var(--amber-600);
}

[data-theme="dark"] {
    --accent-text: var(--amber-400);
    --accent-mark: var(--amber-400);
}

@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) {
        --accent-text: var(--amber-400);
        --accent-mark: var(--amber-400);
    }
}

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

html {
    scroll-behavior: smooth;
    scroll-padding-top: calc(var(--nav-h) + var(--space-6));
    -webkit-text-size-adjust: 100%;
}

body {
    margin: 0;
    font-family: var(--font-body);
    font-size: var(--lede);
    line-height: 1.7;
    background: var(--bg-app);
    color: var(--text-primary);
    overflow-x: hidden;
    -webkit-font-smoothing: antialiased;
}

img,
svg {
    display: block;
    max-width: 100%;
}

h1,
h2,
h3,
h4 {
    margin: 0;
    line-height: 1.2;
    letter-spacing: -0.02em;
    font-weight: 700;
}

p {
    margin: 0;
}

ul {
    margin: 0;
    padding: 0;
    list-style: none;
}

a {
    color: inherit;
}

code,
.mono {
    font-family: var(--font-mono);
    font-size: var(--text-mono);
    color: var(--code-text);
}

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

.skip {
    position: absolute;
    left: -9999px;
    top: 0;
    z-index: 100;
    padding: var(--space-3) var(--space-4);
    background: var(--amber-400);
    color: var(--amber-900);
    font-weight: 600;
    border-radius: 0 0 var(--radius-md) 0;
}

.skip:focus {
    left: 0;
}

/* Available to a screen reader, absent from the page. */
.sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

/* ── Layout primitives ───────────────────────────────────────── */
.wrap {
    width: 100%;
    max-width: var(--wrap);
    margin-inline: auto;
    padding-inline: var(--space-6);
}

section {
    padding-block: clamp(var(--space-12), 8vw, 96px);
}

.section--tight {
    padding-block: clamp(var(--space-8), 5vw, var(--space-16));
}

.section--alt {
    background: var(--bg-surface);
    border-block: 1px solid var(--border);
}

.eyebrow {
    font-size: var(--text-xs);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--accent-text);
    margin-bottom: var(--space-3);
}

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

.h-section {
    font-size: var(--display-2);
    max-width: 22ch;
}

.lede {
    font-size: var(--lede);
    color: var(--text-secondary);
    max-width: 62ch;
    margin-top: var(--space-4);
}

.small {
    font-size: var(--text-base);
    line-height: 1.6;
    color: var(--text-muted);
}

.stack > * + * {
    margin-top: var(--space-4);
}

/* The trademark mark rides on the name without changing its line box, so a
   heading with one in it still sits on the same baseline as one without. */
.tm {
    font-size: 0.62em;
    vertical-align: super;
    line-height: 0;
    letter-spacing: 0;
    font-weight: 600;
}

.link {
    color: var(--accent-text);
    text-decoration: underline;
    text-underline-offset: 3px;
}

/* ── Buttons ─────────────────────────────────────────────────── */
.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    height: 44px;
    padding-inline: var(--space-4);
    border-radius: var(--radius-md);
    font-family: inherit;
    font-size: var(--text-base);
    font-weight: 600;
    text-decoration: none;
    white-space: nowrap;
    cursor: pointer;
    border: 1px solid transparent;
    transition: background-color 120ms ease, border-color 120ms ease, color 120ms ease;
}

.btn--sm {
    height: 36px;
    font-weight: 500;
}

/* The one element that must not change between themes. */
.btn--cta {
    background: var(--amber-400);
    color: var(--amber-900);
    border-color: var(--amber-600);
}

.btn--cta:hover {
    background: var(--amber-200);
}

.btn--ghost {
    background: transparent;
    color: var(--text-primary);
    border-color: var(--border-strong);
}

.btn--ghost:hover {
    background: var(--bg-elevated);
}

.btn--secondary {
    background: var(--primary-600);
    color: var(--primary-50);
}

.btn--secondary:hover {
    background: var(--primary-400);
}

.btn-row {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-3);
    margin-top: var(--space-8);
}

/* ── Nav ─────────────────────────────────────────────────────── */
.nav {
    position: sticky;
    top: 0;
    z-index: 50;
    height: var(--nav-h);
    display: flex;
    align-items: center;
    /* Opaque fallback first — a browser without color-mix() would otherwise
       parse the declaration away and leave the bar transparent. */
    background: var(--bg-app);
    background: color-mix(in srgb, var(--bg-app) 88%, transparent);
    backdrop-filter: blur(10px);
    border-bottom: 1px solid var(--border);
}

.nav__inner {
    display: flex;
    align-items: center;
    gap: var(--space-6);
    width: 100%;
    max-width: var(--wrap);
    margin-inline: auto;
    padding-inline: var(--space-6);
}

.nav__brand {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    text-decoration: none;
    font-weight: 700;
    font-size: var(--text-2xl);
    letter-spacing: -0.02em;
    color: var(--text-primary);
    margin-right: auto;
}

.nav__links {
    display: flex;
    gap: var(--space-6);
    font-size: var(--text-xl);
    font-weight: 500;
}

.nav__links a {
    color: var(--text-secondary);
    text-decoration: none;
    padding-block: var(--space-2);
}

.nav__links a:hover {
    color: var(--text-primary);
}

.nav__actions {
    display: flex;
    align-items: center;
    gap: var(--space-2);
}

.icon-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    padding: 0;
    border-radius: var(--radius-md);
    border: 1px solid var(--border-strong);
    background: transparent;
    color: var(--text-secondary);
    cursor: pointer;
}

.icon-btn:hover {
    background: var(--bg-elevated);
    color: var(--text-primary);
}

/* One icon is shown per theme; the other is hidden. */
.icon-sun {
    display: none;
}

[data-theme="dark"] .icon-sun {
    display: block;
}

[data-theme="dark"] .icon-moon {
    display: none;
}

@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) .icon-sun {
        display: block;
    }

    :root:not([data-theme="light"]) .icon-moon {
        display: none;
    }
}

/* ── Hero ────────────────────────────────────────────────────── */
.hero {
    padding-block: clamp(var(--space-12), 7vw, 88px) clamp(var(--space-12), 6vw, 72px);
}

.hero__grid {
    display: grid;
    gap: clamp(var(--space-8), 5vw, var(--space-16));
    align-items: center;
}

.hero h1 {
    font-size: var(--display-1);
    letter-spacing: -0.03em;
    max-width: 16ch;
}

.hero .lede {
    font-size: clamp(17px, 1.8vw, 21px);
    max-width: 52ch;
}

.hero__note {
    margin-top: var(--space-4);
    font-size: var(--text-base);
    color: var(--text-muted);
}

/* ── Proof strip ─────────────────────────────────────────────── */
.proof {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2) var(--space-6);
    padding-block: var(--space-6);
    border-block: 1px solid var(--border);
    font-size: var(--text-base);
    color: var(--text-secondary);
}

.proof span {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
}

.proof svg {
    color: var(--text-muted);
    flex: none;
}

/* ── Feature rows ────────────────────────────────────────────── */
.feature {
    display: grid;
    gap: clamp(var(--space-8), 5vw, var(--space-16));
    align-items: center;
}

.feature__visual {
    min-width: 0;
}

.feature__list {
    margin-top: var(--space-6);
    display: grid;
    gap: var(--space-4);
}

.feature__list li {
    display: grid;
    grid-template-columns: 20px 1fr;
    gap: var(--space-3);
    font-size: var(--text-base);
    line-height: 1.6;
    color: var(--text-secondary);
}

.feature__list svg {
    margin-top: 3px;
    color: var(--accent-mark);
    flex: none;
}

.feature__list strong {
    color: var(--text-primary);
    font-weight: 600;
}

/* ── Cards and grids ─────────────────────────────────────────── */
.grid {
    display: grid;
    gap: var(--space-6);
}

.card {
    background: var(--bg-surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    padding: 20px;
}

.card h3 {
    font-size: var(--text-2xl);
    font-weight: 600;
    letter-spacing: -0.01em;
    margin-bottom: var(--space-2);
}

.card p {
    font-size: var(--text-base);
    line-height: 1.6;
    color: var(--text-secondary);
}

.card__icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    border-radius: var(--radius-md);
    background: var(--bg-elevated);
    color: var(--text-secondary);
    margin-bottom: var(--space-4);
}

.card--amber {
    background: var(--warning-bg);
    border-color: var(--amber-200);
}

.card--amber h3,
.card--amber p {
    color: var(--warning-text);
}

/* ── Chips ───────────────────────────────────────────────────── */
.chips {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
}

.chip {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    height: 28px;
    padding-inline: var(--space-3);
    border-radius: var(--radius-full);
    border: 1px solid var(--border);
    background: var(--bg-surface);
    font-size: var(--text-sm);
    font-weight: 500;
    color: var(--text-secondary);
}

.chip .dot {
    display: inline-block;
    width: 8px;
    height: 8px;
    border-radius: var(--radius-full);
    background: var(--c, var(--text-muted));
    flex: none;
}

/* Small uppercase label inside a card, where an h3 would be too loud. */
.card__label {
    font-size: var(--text-xs);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--text-muted);
    margin: 0 0 var(--space-4);
}

.chip .key {
    font-family: var(--font-mono);
    font-size: var(--text-sm);
    color: var(--text-muted);
}

/* ── Vertical switcher ───────────────────────────────────────
   Pick a trade and the flow and the board below it change words.
   The claim "nothing here ships with a process" is much easier to
   believe when you can watch the vocabulary swap. */
.switch {
    margin-top: var(--space-6);
}

.switch__tabs {
    display: flex;
    gap: var(--space-2);
    overflow-x: auto;
    overscroll-behavior-x: contain;
    padding-bottom: var(--space-2);
}

.switch__tab {
    flex: none;
    height: 36px;
    padding-inline: var(--space-4);
    border-radius: var(--radius-full);
    border: 1px solid var(--border);
    background: transparent;
    color: var(--text-secondary);
    font-family: inherit;
    font-size: var(--text-base);
    font-weight: 500;
    white-space: nowrap;
    cursor: pointer;
    transition: background-color 120ms ease, color 120ms ease, border-color 120ms ease;
}

.switch__tab:hover {
    background: var(--bg-elevated);
    color: var(--text-primary);
}

.switch__tab[aria-selected="true"] {
    background: var(--bg-elevated);
    border-color: var(--border-strong);
    color: var(--text-primary);
    font-weight: 600;
}

.switch__panel {
    margin-top: var(--space-4);
    padding: var(--space-6);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    background: var(--bg-surface);
}

.switch__panel[hidden] {
    display: none;
}

.switch__note {
    margin-top: var(--space-4);
    font-size: var(--text-base);
    line-height: 1.6;
    color: var(--text-muted);
}

/* ── Mini board inside a switcher panel ──────────────────────
   HTML rather than SVG precisely because it has to be swapped:
   five of these in the markup cost less than one data-driven SVG. */
.mini {
    display: grid;
    gap: var(--space-3);
    margin-top: var(--space-6);
}

.mini__col {
    background: var(--bg-app);
    border-radius: var(--radius-md);
    padding: var(--space-3);
}

.mini__head {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    font-size: var(--text-base);
    font-weight: 600;
    color: var(--text-primary);
    margin-bottom: var(--space-3);
}

.mini__head i {
    display: inline-block;
    width: 8px;
    height: 8px;
    border-radius: var(--radius-full);
    background: var(--c, var(--text-muted));
    flex: none;
}

.mini__head span {
    margin-left: auto;
    font-family: var(--font-mono);
    font-size: var(--text-sm);
    font-weight: 400;
    color: var(--text-muted);
}

.mini__card {
    display: grid;
    gap: 2px;
    padding: var(--space-3);
    border-radius: var(--radius-sm);
    border: 1px solid var(--border);
    border-left: 3px solid var(--c, var(--border-strong));
    background: var(--bg-surface);
}

.mini__card + .mini__card {
    margin-top: var(--space-2);
}

.mini__code {
    font-family: var(--font-mono);
    font-size: var(--text-sm);
    color: var(--text-muted);
}

.mini__name {
    font-size: var(--text-base);
    color: var(--text-primary);
}

.flow__steps {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-2);
}

.flow__steps li {
    display: flex;
    align-items: center;
    gap: var(--space-2);
}

/* The separator sits between two pills, so it hangs on the list item
   rather than inside the pill's own background. */
.flow__steps li + li::before {
    content: "›";
    color: var(--text-muted);
    font-size: var(--text-2xl);
    line-height: 1;
}

.pill {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    padding: 4px var(--space-3);
    border-radius: var(--radius-full);
    border: 1px solid var(--border);
    background: var(--bg-app);
    font-size: var(--text-base);
    color: var(--text-primary);
    white-space: nowrap;
}

.pill i {
    display: inline-block;
    width: 8px;
    height: 8px;
    border-radius: var(--radius-full);
    background: var(--c, var(--text-muted));
    flex: none;
}

.pill--loop {
    background: var(--warning-bg);
    border-color: var(--amber-200);
    color: var(--warning-text);
    font-weight: 600;
}

/* ── Two screens side by side ────────────────────────────────
   Below 1025 they stack: half of a tablet width is not enough for
   either of them to be readable. */
.duo {
    display: grid;
    gap: var(--space-6);
    align-items: start;
}

/* ── Mockup frame ────────────────────────────────────────────── */
.mock {
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    background: var(--bg-surface);
    overflow: hidden;
}

.mock__bar {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    height: 32px;
    padding-inline: var(--space-3);
    background: var(--table-head-bg);
    border-bottom: 1px solid var(--border);
    font-size: var(--text-xs);
    letter-spacing: 0.08em;
    text-transform: uppercase;
    font-weight: 600;
    color: var(--table-head-text);
}

.mock__bar .lamp {
    width: 8px;
    height: 8px;
    border-radius: var(--radius-full);
    background: var(--border-strong);
    flex: none;
}

.mock svg {
    width: 100%;
    height: auto;
}

/* Below 640 the densest diagrams are unreadable shrunk; a simplified
   variant is swapped in instead of squeezing the full one. */
.only-wide {
    display: block;
}

.only-narrow {
    display: none;
}

/* Everything else scales to its column on desktop, and below 1024 keeps
   its drawn size and scrolls inside its own box instead of shrinking to
   unreadable. The page body never scrolls sideways — only this box does. */
.mock__scroll {
    overflow-x: auto;
    overscroll-behavior-x: contain;
}

/* Diagrams whose smallest text is ~11px cannot survive being scaled to a
   phone, so below 1024 they hold their drawn size and scroll. Add
   --fit to opt a diagram out: the wall display's smallest type is 15px,
   so it scales down cleanly and a clipped tile would just look broken. */
@media (max-width: 1024px) {
    .mock__scroll:not(.mock__scroll--fit) > svg {
        min-width: 600px;
    }
}

/* ── SVG mockup palette ──────────────────────────────────────────
   Presentation attributes cannot reliably carry var(), so the
   mockups paint through classes instead. Everything here is a
   token, so the diagrams re-theme with the page.
──────────────────────────────────────────────────────────────── */
/* Font-family only. A font-size here would beat every font-size="…"
   presentation attribute in the diagrams — CSS outranks them. */
.mock text {
    font-family: var(--font-body);
}

.mock .t-mono {
    font-family: var(--font-mono);
}

.mock .t-ink {
    fill: var(--text-primary);
}

.mock .t-2 {
    fill: var(--text-secondary);
}

.mock .t-mut {
    fill: var(--text-muted);
}

.mock .t-bold {
    font-weight: 600;
}

.mock .t-label {
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 0.08em;
    fill: var(--text-muted);
}

.mock .s-surface {
    fill: var(--bg-surface);
}

.mock .s-app {
    fill: var(--bg-app);
}

.mock .s-elev {
    fill: var(--bg-elevated);
}

.mock .ln {
    fill: none;
    stroke: var(--border);
    stroke-width: 1;
}

.mock .ln-strong {
    fill: none;
    stroke: var(--border-strong);
    stroke-width: 1.5;
}

.mock .edge {
    fill: none;
    stroke: var(--border-strong);
    stroke-width: 2;
    stroke-linecap: round;
}

.mock .b-card {
    fill: var(--bg-surface);
    stroke: var(--border);
    stroke-width: 1;
}

.mock .t-err {
    fill: var(--error);
}

.mock .s-err-bg {
    fill: var(--error-bg);
    stroke: var(--error);
    stroke-width: 1;
}

.mock .s-amber-bg {
    fill: var(--warning-bg);
    stroke: var(--amber-200);
    stroke-width: 1;
}

.mock .t-amber {
    fill: var(--warning-text);
}

.mock .drag {
    fill: none;
    stroke: var(--amber-400);
    stroke-width: 2;
    stroke-dasharray: 6 4;
}

/* The wall/station mock is deliberately NOT theme-aware — it is a
   picture of a screen hanging in a workshop, which is always light. */
.wallmock text {
    font-family: var(--font-body);
}

/* ── Data table ──────────────────────────────────────────────
   Mirrors the app's table spec: 11px uppercase header on
   --table-head-bg, 1px row rules, monospace for anything that is
   an id or a measurement. */
.tbl-wrap {
    overflow-x: auto;
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    background: var(--bg-surface);
}

.tbl {
    width: 100%;
    min-width: 480px;
    border-collapse: collapse;
    font-size: var(--text-base);
}

.tbl th {
    background: var(--table-head-bg);
    color: var(--table-head-text);
    font-size: var(--text-xs);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    text-align: left;
    padding: var(--space-3);
    white-space: nowrap;
    border-bottom: 1px solid var(--border);
}

.tbl th + th {
    text-align: right;
}

.tbl td {
    padding: var(--space-3);
    border-bottom: 1px solid var(--border);
    color: var(--text-secondary);
    white-space: nowrap;
}

.tbl th:first-child,
.tbl td:first-child {
    padding-left: var(--space-4);
}

.tbl th:last-child,
.tbl td:last-child {
    padding-right: var(--space-4);
}

.tbl tr:last-child td {
    border-bottom: 0;
}

.tbl .num {
    font-family: var(--font-mono);
    font-size: var(--text-mono);
    text-align: right;
}

/* The median is the column the app tells you to trust, so it is the
   only one set in the primary ink. */
.tbl .lead {
    color: var(--text-primary);
    font-weight: 600;
}

.tbl .status {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    color: var(--text-primary);
}

.tbl .status i {
    display: inline-block;
    width: 8px;
    height: 8px;
    border-radius: var(--radius-full);
    background: var(--c, var(--text-muted));
    flex: none;
}

/* ── Rule sentence ───────────────────────────────────────────
   A rule reads as one sentence with the configurable parts set in
   relief — which is the point the section is making. */
.sentence {
    font-size: var(--lede);
    line-height: 2.1;
    color: var(--text-secondary);
}

.tok {
    display: inline-block;
    padding: 2px var(--space-2);
    margin: 0 2px;
    border-radius: var(--radius-sm);
    background: var(--bg-elevated);
    border: 1px solid var(--border-strong);
    color: var(--text-primary);
    font-size: var(--text-base);
    font-weight: 600;
    white-space: nowrap;
}

.tok--amber {
    background: var(--warning-bg);
    border-color: var(--amber-200);
    color: var(--warning-text);
}

/* ── Compact block list (screen widgets) ─────────────────────── */
.blocks {
    display: grid;
    gap: var(--space-4);
}

.block {
    display: grid;
    grid-template-columns: auto 1fr;
    gap: var(--space-3) var(--space-4);
    align-items: start;
    padding: var(--space-4);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    background: var(--bg-surface);
}

.block__key {
    grid-column: 1 / -1;
    font-family: var(--font-mono);
    font-size: var(--text-sm);
    color: var(--text-muted);
}

.block h4 {
    font-size: var(--text-2xl);
    font-weight: 600;
    letter-spacing: -0.01em;
    margin: 0;
    grid-column: 1 / -1;
}

.block p {
    grid-column: 1 / -1;
    font-size: var(--text-base);
    line-height: 1.6;
    color: var(--text-secondary);
}

/* ── Worked-example timeline ─────────────────────────────────── */
.steps {
    display: grid;
    gap: var(--space-4);
    counter-reset: step;
}

.step {
    display: grid;
    grid-template-columns: 32px 1fr;
    gap: var(--space-4);
    align-items: start;
}

.step__num {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    border-radius: var(--radius-full);
    background: var(--bg-elevated);
    border: 1px solid var(--border);
    font-family: var(--font-mono);
    font-size: var(--text-sm);
    color: var(--text-secondary);
}

.step p {
    font-size: var(--text-base);
    line-height: 1.6;
    color: var(--text-secondary);
}

.step strong {
    color: var(--text-primary);
}

/* ── CTA band ────────────────────────────────────────────────── */
.band {
    background: var(--amber-400);
    color: var(--amber-900);
    border-block: 1px solid var(--amber-600);
    text-align: center;
}

.band h2 {
    font-size: var(--display-2);
    max-width: 20ch;
    margin-inline: auto;
}

.band p {
    margin-top: var(--space-4);
    max-width: 54ch;
    margin-inline: auto;
    font-size: var(--text-base);
    line-height: 1.6;
    color: var(--amber-900);
    opacity: 0.85;
}

.band .btn-row {
    justify-content: center;
}

.band .btn--onamber {
    background: var(--primary-900);
    color: var(--primary-50);
    border-color: var(--primary-900);
}

.band .btn--onamber:hover {
    background: var(--primary-600);
}

.band .btn--onamber-ghost {
    background: transparent;
    color: var(--amber-900);
    border-color: var(--amber-800);
}

.band .btn--onamber-ghost:hover {
    background: var(--amber-200);
}

/* ── Contact ─────────────────────────────────────────────────── */
.contact {
    display: grid;
    gap: var(--space-12);
    align-items: start;
}

.contact__copy .feature__list {
    margin-top: var(--space-8);
}

/* The form is a .card, so it picks up the surface and the 1px border the rest
   of the page uses. Everything below only describes the fields. */
.contact-form {
    display: grid;
    gap: var(--space-4);
    padding: var(--space-6);
}

.field-row {
    display: grid;
    gap: var(--space-4);
}

.field label {
    display: block;
    font-size: var(--text-xs);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--text-muted);
    margin-bottom: var(--space-2);
}

.field input,
.field textarea {
    width: 100%;
    background: var(--bg-app);
    color: var(--text-primary);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    padding: var(--space-3);
    font-family: inherit;
    font-size: var(--text-base);
    line-height: 1.5;
    transition: border-color 120ms ease;
}

.field textarea {
    min-height: 132px;
    resize: vertical;
}

.field input::placeholder,
.field textarea::placeholder {
    color: var(--text-muted);
}

.field input:hover,
.field textarea:hover {
    border-color: var(--border-strong);
}

.field input:focus,
.field textarea:focus {
    outline: none;
    border-color: var(--amber-400);
}

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

.contact-form__actions {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--space-4);
    margin-top: var(--space-2);
}

.contact-form__privacy a {
    color: var(--text-secondary);
    text-decoration: underline;
    text-underline-offset: 3px;
}

/* Honeypot. Hidden from people, still a real field in the DOM for the bots
   that fill in everything they find. Not display:none — some skip those. */
.hp {
    position: absolute;
    left: -9999px;
    width: 1px;
    height: 1px;
    overflow: hidden;
}

/* Result banner, shown only once the form has something to say. */
.form-result {
    display: none;
    padding: var(--space-3) var(--space-4);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    font-size: var(--text-base);
    line-height: 1.5;
    color: var(--text-secondary);
}

.form-result.show {
    display: block;
}

.form-result.ok {
    background: var(--success-bg);
    border-color: var(--success);
    color: var(--success-text);
}

.form-result.bad {
    background: var(--error-bg);
    border-color: var(--error);
    color: var(--error-text);
}

.contact-form.sending button[type="submit"] {
    opacity: 0.6;
    pointer-events: none;
}

/* ── Footer ──────────────────────────────────────────────────── */
.footer {
    background: var(--bg-surface);
    border-top: 1px solid var(--border);
    padding-block: var(--space-12) var(--space-8);
    font-size: var(--text-base);
    color: var(--text-secondary);
}

.footer__grid {
    display: grid;
    gap: var(--space-8);
}

.footer h4 {
    font-size: var(--text-xs);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--text-muted);
    margin-bottom: var(--space-3);
}

.footer li + li {
    margin-top: var(--space-2);
}

.footer a {
    text-decoration: none;
    color: var(--text-secondary);
}

.footer a:hover {
    color: var(--text-primary);
    text-decoration: underline;
}

.footer__bottom {
    margin-top: var(--space-12);
    padding-top: var(--space-6);
    border-top: 1px solid var(--border);
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-4);
    justify-content: space-between;
    font-size: var(--text-sm);
    color: var(--text-muted);
}

.foot-id {
    margin: 0;
    line-height: 1.8;
}

.foot-id a {
    color: var(--text-muted);
    text-decoration: underline;
    text-underline-offset: 3px;
}

.foot-id a:hover {
    color: var(--text-primary);
}

/* ── Breakpoints ─────────────────────────────────────────────── */
@media (max-width: 1024px) {
    .nav__links {
        display: none;
    }
}

@media (min-width: 1025px) {
    .hero__grid {
        grid-template-columns: 1fr 1.05fr;
    }

    .feature {
        grid-template-columns: 1fr 1.2fr;
    }

    /* Odd feature rows put the visual on the right, even ones on the left.
       Source order stays text-then-visual so a screen reader gets the
       explanation before the picture.

       The track sizes have to swap with it. Reordering alone would drop the
       visual into the 1fr track and hand the wider one to the prose — which
       is backwards, and is what was clipping the widest diagrams. */
    .feature--flip {
        grid-template-columns: 1.2fr 1fr;
    }

    .feature--flip .feature__copy {
        order: 2;
    }

    .grid--3,
    .blocks {
        grid-template-columns: repeat(3, 1fr);
    }

    .grid--4 {
        grid-template-columns: repeat(4, 1fr);
    }

    .grid--2 {
        grid-template-columns: repeat(2, 1fr);
    }

    .mini {
        grid-template-columns: repeat(3, 1fr);
    }

    .duo {
        grid-template-columns: 1fr 1fr;
    }

    /* The prose column stays narrower than the form: the form has fields to
       fit, the prose only has to stay under a comfortable measure. */
    .contact {
        grid-template-columns: 1fr 1.05fr;
    }

    /* The brand column takes the extra room; every link column is equal,
       and the count varies by page. */
    .footer__grid {
        grid-template-columns: 1.6fr repeat(auto-fit, minmax(0, 1fr));
        grid-auto-columns: minmax(0, 1fr);
        grid-auto-flow: column;
    }
}

@media (min-width: 641px) and (max-width: 1024px) {
    .grid--3,
    .grid--4,
    .grid--2,
    .blocks {
        grid-template-columns: repeat(2, 1fr);
    }

    /* The mini board keeps three columns — two would stop looking like a
       board, which is the only thing it is there to look like. */
    .mini {
        grid-template-columns: repeat(3, 1fr);
    }

    .footer__grid {
        grid-template-columns: repeat(2, 1fr);
    }
}

/* Name and email sit side by side as soon as there is room for two of them. */
@media (min-width: 561px) {
    .field-row {
        grid-template-columns: 1fr 1fr;
    }
}

@media (max-width: 640px) {
    .wrap,
    .nav__inner {
        padding-inline: var(--space-4);
    }

    .only-wide {
        display: none;
    }

    .only-narrow {
        display: block;
    }

    .btn-row .btn {
        flex: 1 1 auto;
    }

    .nav__brand span {
        display: none;
    }
}

/* ── Motion ──────────────────────────────────────────────────── */
@media (prefers-reduced-motion: reduce) {
    html {
        scroll-behavior: auto;
    }

    *,
    *::before,
    *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
    }
}

/* ── Print ───────────────────────────────────────────────────── */
@media print {
    .nav,
    .band,
    .btn-row {
        display: none;
    }
}
