/* phaneron.co
   The Handspan app's own system, so the company and the product read as one house:
   - tokens: packages/shell/src/styles/tokens.css, both modes, value for value. The page itself is the
     app's frame (--frame, its deepest black in dark), and what sits on it is the app's card (--canvas).
   - faces: fonts.css. IBM Plex Sans semibold for display (the weight the app ships), the system face
     for reading, JetBrains Mono for labels and figures.
   - colour: ink, drawn in graphite; colour means you (2026-10-04). The page carries no decorative
     colour: the mark, the diagram and the rules are ink and greys, and colour is kept for a state (a
     field in error, a message sent).
   - surface: the page's own colour and nothing behind it. (2026-10-04, Alex: the drafting grid behind
     everything read as a checkerboard, and it is gone, with the light that followed the pointer.)
   - icons: the app's hairline set (site/partials/icons.svg), at the app's stroke weights.
   - motion: the app's timings (--m-fast, --m-base, --m-slow) and its ease (--e-out), and only on
     arrival: the headline, the sections and the diagram come in once; after that only the diagram
     moves, one quiet signal through its stages every twelve seconds.
   - the scroll bar is the app's quiet bar, and the header edge is its fade, never a blur. */

@font-face { font-family: "IBM Plex Sans"; font-style: normal; font-weight: 600; font-display: swap; src: url("/fonts/ibm-plex-sans-latin-600-normal.woff2") format("woff2"); }
@font-face { font-family: "JetBrains Mono"; font-style: normal; font-weight: 400; font-display: swap; src: url("/fonts/jetbrains-mono-latin-400-normal.woff2") format("woff2"); }
@font-face { font-family: "JetBrains Mono"; font-style: normal; font-weight: 500; font-display: swap; src: url("/fonts/jetbrains-mono-latin-500-normal.woff2") format("woff2"); }

:root {
  color-scheme: light dark;
  /* tokens.css, light */
  --frame: #EBEBEE; --canvas: #FBFBFC; --surface: #FFFFFF; --raised: #F0F0F2; --sink: #F7F7F8;
  --line: rgba(13, 13, 15, .09); --line2: rgba(13, 13, 15, .16);
  --ink: #0D0D0F; --dim: #6E6E77; --faint: #9B9BA3;
  --accent: #2A6BDE; --accent-ink: #1F62C9; --attn: #E5561E; --green: #1E9A55; --red: #C8233A; --pearl: #8D959F;
  --ring: var(--ink);
  --shadow: 0 1px 2px rgba(13, 13, 15, .05), 0 30px 70px -20px rgba(13, 13, 15, .16);

  /* the page and what sits on it: in light the app's canvas is the page and its surface the card */
  --page: var(--canvas);
  --card: var(--surface);

  --font-display: "IBM Plex Sans", system-ui, sans-serif;
  --font-body: -apple-system, BlinkMacSystemFont, "SF Pro Text", "Segoe UI", system-ui, sans-serif;
  --font-mono: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace;

  --m-fast: 180ms; --m-base: 280ms; --m-slow: 440ms;
  --e-out: cubic-bezier(.22, .61, .36, 1);

  --wrap: min(1120px, 100% - 48px);
  --gutter: clamp(24px, 4vw, 56px);
  --section: clamp(64px, 7vw, 96px);
  --header: 64px;
}

@media (prefers-color-scheme: dark) {
  :root {
    /* tokens.css, dark */
    --frame: #060607; --canvas: #0D0D0F; --surface: #161618; --raised: #202024; --sink: #0A0A0B;
    --line: rgba(255, 255, 255, .09); --line2: rgba(255, 255, 255, .16);
    --ink: #FAFAFB; --dim: #A0A0AA; --faint: #6E6E77;
    --accent: #5B9DF5; --accent-ink: #5B9DF5; --attn: #FF7442; --green: #5FD98A; --red: #FF5A65; --pearl: #E6E9EE;
    --shadow: 0 1px 2px rgba(0, 0, 0, .5), 0 40px 90px -24px rgba(0, 0, 0, .7);
    /* in dark the page is the app's frame, its black, and a card is the app's canvas */
    --page: var(--frame);
    --card: var(--canvas);
  }
}

*, *::before, *::after { box-sizing: border-box; }
* { scrollbar-width: none; }
::-webkit-scrollbar { display: none; }

html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; scroll-padding-top: calc(var(--header) + 24px); background: var(--page); }
@media (prefers-reduced-motion: no-preference) { html { scroll-behavior: smooth; } }
body {
  margin: 0; background: var(--page); color: var(--ink);
  font: 400 16px/1.6 var(--font-body);
  -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-rendering: optimizeLegibility;
  position: relative; isolation: isolate;
}
img, svg { display: block; max-width: 100%; }
a { color: inherit; text-decoration: none; transition: color var(--m-fast) var(--e-out); }
:focus-visible { outline: 2px solid var(--ring); outline-offset: 3px; border-radius: 6px; }
/* (2026-10-04) Ink, drawn in graphite; colour means you: the page carries no decorative colour, as the app now does not. */
::selection { background: color-mix(in srgb, var(--ink) 16%, transparent); }
p { margin: 0; text-wrap: pretty; }

.skip { position: absolute; left: 16px; top: -48px; z-index: 30; padding: 8px 14px; border-radius: 8px; background: var(--ink); color: var(--page); font-weight: 600; transition: top var(--m-fast) var(--e-out); }
.skip:focus { top: 16px; }
.wrap { width: var(--wrap); margin-inline: auto; }

/* ---------- header: the page's colour, and a hairline under it once the page has moved (site.js) ----------
   (2026-10-10) The header's fade and its mirror at the bottom edge are gone. Each was a wash of the page's
   own colour laid over the page, and a browser rounds that a shade off the page it sits on (measured:
   rows of 250, 251 and 252 where the page is 251), which showed as a stripe under the header. A hairline
   is the page's line colour or nothing, so there is nothing to round. */
.site-header { position: sticky; top: 0; z-index: 20; background: var(--page); border-bottom: 1px solid transparent; transition: border-color var(--m-base) var(--e-out); }
.site-header.is-scrolled { border-bottom-color: var(--line); }
.site-header .wrap { display: flex; align-items: center; justify-content: space-between; height: var(--header); }
.brand { display: inline-flex; align-items: center; color: var(--ink); }
.brand svg { height: 22px; width: auto; }
/* once the page moves the header folds to the mark (site.js sets .is-scrolled), and the wordmark comes
   back under the pointer; the units are the lockup's own, so 320 is about six pixels */
.brand .lk-word { transition: opacity var(--m-base) var(--e-out), transform var(--m-slow) var(--e-out); }
.site-header.is-scrolled .brand .lk-word { opacity: 0; transform: translateX(-320px); }
.site-header.is-scrolled .brand:hover .lk-word, .site-header.is-scrolled .brand:focus-visible .lk-word { opacity: 1; transform: none; }
.nav { display: flex; align-items: center; gap: 28px; }
.nav a { font-size: 14px; color: var(--dim); }
.nav a:hover { color: var(--ink); }
.nav .nav-cta { color: var(--ink); padding: 6px 14px; border: 1px solid var(--line2); border-radius: 999px; transition: border-color var(--m-fast) var(--e-out), background-color var(--m-fast) var(--e-out); }
.nav .nav-cta:hover { border-color: var(--ink); }
@media (max-width: 560px) { .nav .nav-hide-sm { display: none; } }

/* ---------- type ---------- */
.eyebrow { display: inline-flex; align-items: center; gap: 10px; margin: 0 0 20px; font: 500 11.5px/1.4 var(--font-mono); letter-spacing: .1em; text-transform: uppercase; color: var(--dim); }
.chroma-dot { width: 18px; height: 2px; border-radius: 2px; background: var(--ink); }
h1, h2, h3 { font-family: var(--font-display); font-weight: 600; color: var(--ink); margin: 0; letter-spacing: -.025em; line-height: 1.1; text-wrap: balance; }
h1 { font-size: clamp(36px, 4.6vw, 56px); line-height: 1.04; letter-spacing: -.032em; }
h2 { font-size: clamp(26px, 2.8vw, 34px); }
h3 { font-size: 15px; letter-spacing: -.01em; line-height: 1.35; }
.lead { font-size: 17px; line-height: 1.6; color: var(--dim); max-width: 34em; }
@media (min-width: 880px) { .lead { font-size: 18px; } }
.body { color: var(--dim); max-width: 32em; margin-top: 16px; }

/* ---------- icons (the app's hairlines) ---------- */
/* the app's solid icons (build.mjs): a shape filled with the text's colour and its light over it */
.ico { width: 18px; height: 18px; flex: none; }

/* ---------- buttons ---------- */
.actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 32px; }
.button {
  display: inline-flex; align-items: center; gap: 8px; height: 42px; padding: 0 18px; border-radius: 999px;
  font: 600 14px/1 var(--font-body); cursor: pointer; border: 1px solid transparent;
  transition: background-color var(--m-fast) var(--e-out), border-color var(--m-fast) var(--e-out), color var(--m-fast) var(--e-out), transform var(--m-fast) var(--e-out);
}
.button .ico { width: 16px; height: 16px; transition: transform var(--m-base) var(--e-out); }
.button:hover .ico { transform: translateX(3px); }
.button-primary { background: var(--ink); color: var(--page); }
.button-primary:hover { background: color-mix(in srgb, var(--ink) 86%, var(--page)); }
.button-ghost { border-color: var(--line2); color: var(--ink); background: color-mix(in srgb, var(--page) 60%, transparent); }
.button-ghost:hover { border-color: var(--ink); }
.button:active { transform: translateY(1px); }
.button[disabled] { opacity: .55; cursor: progress; }

/* ---------- the opening: the thesis, and the organization it argues for ---------- */
.hero-thesis { padding-block: clamp(48px, 8vw, 104px) var(--section); }
.hero-thesis .hero { max-width: 50rem; }
.hero-thesis h1 { font-size: clamp(40px, 5.4vw, 70px); }
.hero h1 em { font-style: normal; color: var(--dim); }
.hero h1 + .lead { margin-top: 24px; }
/* the coming-soon page (2026-10-10): the opening is the first screen, the words beside the mark's own
   construction drawing (lib/construction.mjs), and a line under the buttons saying it is not out yet */
.hero-thesis.is-soon { display: flex; align-items: center; min-height: calc(100svh - var(--header) - 1px); padding-block: clamp(48px, 6vw, 80px); }
.hero-grid { display: grid; grid-template-columns: minmax(0, 11fr) minmax(0, 9fr); gap: clamp(24px, 4vw, 56px); align-items: center; }
.hero-thesis.is-soon h1 { font-size: clamp(40px, 4.6vw, 58px); }
.soon { display: flex; align-items: center; gap: 10px; margin-top: 24px; font: 400 12px/1.4 var(--font-mono); letter-spacing: .06em; color: var(--dim); }
/* the dot of a working session in the app's session list, value for value (packages/shell/src/styles/onboarding.css,
   the working .row-mark and bs-breathe): 8px, the ink shaded toward the surface top left to bottom right, and breathing
   (below, with motion allowed). Alex, 2026-10-20: "in development, blinking in the same dot from our application session sidebar" */
.soon-dot { flex: none; width: 8px; height: 8px; border-radius: 50%; background-image: linear-gradient(135deg, var(--ink) 10%, color-mix(in srgb, var(--ink) 70%, var(--surface)) 95%); }
.mark-figure { margin: 0; padding: 0; justify-self: center; width: 100%; max-width: 460px; }
.cd { display: block; width: 100%; height: auto; overflow: visible; }
.cd path { vector-effect: non-scaling-stroke; }
.cd-con { fill: none; stroke: var(--ink); stroke-width: 1; opacity: .15; }
.cd-center { fill: none; stroke: var(--ink); stroke-width: 1; stroke-dasharray: 12 4 2 4; opacity: .2; }
.cd-fill { fill: color-mix(in srgb, var(--ink) 5%, transparent); stroke: none; }
.cd-mark { fill: none; stroke: var(--ink); stroke-width: 1.5; stroke-linejoin: miter; }
.cd-dim { fill: none; stroke: var(--ink); stroke-width: 1; opacity: .5; }
.cd-num { fill: var(--dim); font: 400 12px var(--font-mono); letter-spacing: .04em; }
/* the mark as a solid (lib/mark3d.mjs). (2026-10-14) The finished solid is the company's mark made in the app's icon kit, two images:
   its shape, filled with the page's ink, and its light over it, so it is black in light and white in dark as the app's icons are.
   (2026-10-20) While it is made (site.js) a wireframe is drawn over it, as the app's 3D space draws a part: the sketch, its two
   dimensions, the extruded edges and a small set of axes. None of it is part of the finished picture */
.m3 { color: var(--ink); }
.m3-wire { fill: none; stroke: var(--ink); stroke-width: 1.3; stroke-linejoin: round; transition: opacity 600ms var(--e-out); }
.m3-wire.is-back, .m3-wire.is-side { opacity: .35; }
.m3-axis { fill: none; stroke: var(--ink); stroke-width: 1; opacity: .45; }
.m3-axis-name { fill: var(--dim); font: 400 10px var(--font-mono); letter-spacing: .04em; }
/* the working, not the work: shown only while the solid is being made (below), and the finished picture is the solid alone */
.m3-work { opacity: 0; transition: opacity 700ms var(--e-out); }
@media (max-width: 920px) {
  .hero-thesis.is-soon { min-height: 0; }
  .hero-grid { grid-template-columns: 1fr; gap: 48px; }
  .mark-figure { justify-self: start; max-width: 300px; }
  /* drawn smaller, the figures are set larger, so they stay readable */
  .m3 .cd-num { font-size: 16px; }
}

/* the picture of the thesis (lib/network.mjs draws it): requirements in, lead agents that check one
   another, teams of no fixed size, the task agents they summon, and a working machine out. It sits on the
   page with no box; the narrow drawing is the same picture laid out for a phone */
.net { margin: clamp(56px, 7vw, 96px) 0 0; padding: 0; }
.nw { display: block; width: 100%; height: auto; overflow: visible; }
.nw.is-narrow { display: none; }
@media (max-width: 720px) { .nw.is-wide { display: none; } .nw.is-narrow { display: block; } }
.nw-edge { fill: none; stroke: var(--ink); stroke-width: 1; opacity: .16; }
.nw-edge.is-strong { opacity: .34; }
.nw-edge.is-team { opacity: .3; }
.nw-edge.is-task { opacity: .1; }
.nw-edge.is-faint { opacity: .1; }
.nw-edge.is-dashed { stroke-dasharray: 2 5; opacity: .3; }
.nw-sig, .nw-trace { fill: none; stroke: var(--ink); stroke-linecap: round; opacity: 0; }
.nw-sig { stroke-width: 1.6; stroke-dasharray: 6 94; }
.nw-trace { stroke-width: 1.6; stroke-dasharray: 16 84; }
.nw-lead { fill: var(--ink); }
.nw-node, .nw-join { fill: var(--page); stroke: var(--ink); stroke-width: 1.1; }
.nw-task { fill: var(--ink); opacity: .4; }
.nw-tick { stroke: var(--ink); stroke-width: 1; opacity: .35; }
.nw-spec { fill: var(--dim); font: 400 12.5px var(--font-mono); }
.nw.is-narrow .nw-spec { font-size: 17px; }
.nw-tier { fill: var(--faint); font: 400 11px var(--font-mono); letter-spacing: .08em; text-transform: uppercase; }
.nw.is-narrow .nw-tier { font-size: 15px; }
.nw-car { fill: none; stroke: var(--ink); stroke-width: 1.3; stroke-linejoin: round; stroke-linecap: round; }
.nw-car.is-glass { fill: color-mix(in srgb, var(--ink) 5%, transparent); stroke-width: 1; }
.nw-car.is-line { stroke-width: .8; opacity: .55; }
.nw-car.is-tyre { stroke-width: 1.9; }
.nw-ground { fill: none; stroke: var(--ink); stroke-width: 1; opacity: .14; }
.net figcaption { max-width: 40em; margin: 28px auto 0; text-align: center; font: 400 14px/1.55 var(--font-body); color: var(--dim); text-wrap: balance; }

@media (prefers-reduced-motion: no-preference) {
  .soon-dot { animation: breathe 1.8s ease-in-out infinite; }
  @keyframes breathe { 0%, 100% { opacity: .35; transform: scale(.8); } 50% { opacity: 1; transform: scale(1); } }
  /* the headline rises a line at a time (site.js wraps the lines), then the rest */
  .js .hero h1:not(.is-split) { visibility: hidden; animation: unhide 0s 1s forwards; }
  .js .hero h1 .line { display: block; overflow: hidden; padding-bottom: .08em; margin-bottom: -.08em; }
  .js .hero h1 .line > span { display: block; transform: translateY(105%); animation: line-up 850ms var(--e-out) forwards; animation-delay: calc(80ms + var(--i, 0) * 80ms); }
  .js .hero .eyebrow, .js .hero .lead, .js .hero .actions, .js .hero .soon { opacity: 0; transform: translateY(8px); animation: rise var(--m-slow) var(--e-out) forwards; }
  .js .hero .eyebrow { animation-delay: 0ms; }
  .js .hero .lead { animation-delay: 420ms; }
  .js .hero .actions { animation-delay: 520ms; }
  .js .hero .soon { animation-delay: 620ms; }
  /* the mark is made before it stands (site.js): sketched flat with two dimensions, extruded as the
     camera turns, and the solid comes up through the wireframe, which goes. Until the script takes hold
     the picture is held back, and it is shown finished if the script never does */
  .js .m3:not(.is-run) { opacity: 0; animation: fade 0s 3s forwards; }
  .js .m3.is-run:not(.is-done) .m3-work { opacity: 1; }
  .js .m3.is-run:not(.is-sized) .m3-sketch-dims, .js .m3.is-extruding .m3-sketch-dims { opacity: 0; }
  .js .m3.is-run:not(.is-solid) .m3-render { opacity: 0; }
  .js .m3.is-solid .m3-wire { opacity: 0; }
  .m3-render { transition: opacity 700ms var(--e-out); }
  .m3-sketch-dims { transition: opacity 300ms var(--e-out); }

  /* the picture arrives with the headline; then one signal passes through it, a stage at a time, round
     the loop (out to the teams, between them, back to the leads) and on to the machine, and rests */
  .js .net { opacity: 0; transform: translateY(12px); animation: rise 900ms var(--e-out) 600ms forwards; }
  .nw-sig { animation: nw-sig 12s linear infinite; }
  .nw-trace { animation: nw-trace 12s linear infinite; }
  .nw-node, .nw-join { animation: nw-on 12s linear infinite; }
  .nw-task { animation: nw-task 12s linear infinite; }
  .nw .s0 { animation-delay: .4s; }    /* requirements to the leads */
  .nw .s1 { animation-delay: 1.3s; }   /* the leads check one another */
  .nw .s2 { animation-delay: 2.2s; }   /* the leads to the teams */
  .nw .s3 { animation-delay: 3.1s; }   /* the teams take it up */
  .nw .s4 { animation-delay: 3.3s; }   /* the teams work with one another */
  .nw .s5 { animation-delay: 4s; }     /* their task agents */
  .nw .s8 { animation-delay: 4.9s; }   /* the teams report back */
  .nw .s9 { animation-delay: 5.9s; }   /* the leads check again */
  .nw .s6 { animation-delay: 6.8s; }   /* the work comes together */
  .nw .s7 { animation-delay: 7.8s; }   /* into the machine, and the check passes over it */

  /* sections rise in as they arrive, their parts a beat apart */
  .js .reveal { opacity: 0; transform: translateY(10px); transition: opacity 520ms var(--e-out), transform 520ms var(--e-out); transition-delay: var(--d, 0ms); }
  .js .reveal.is-in { opacity: 1; transform: none; }
  /* a section's heading rises a line at a time as the section arrives, as the headline does (site.js) */
  .js .reveal h2.is-split .line { display: block; overflow: hidden; padding-bottom: .08em; margin-bottom: -.08em; }
  .js .reveal h2.is-split .line > span { display: block; transform: translateY(105%); transition: transform 640ms var(--e-out); transition-delay: calc(var(--d, 0ms) + var(--i, 0) * 80ms); }
  .js .reveal.is-in h2.is-split .line > span { transform: none; }
  /* and the rule over a list draws from the left */
  .js .who::before { transform: scaleX(0); transition: transform 1100ms var(--e-out) 120ms; }
  .js .reveal.is-in .who::before { transform: none; }
}
@keyframes nw-sig { 0% { stroke-dashoffset: 100; opacity: 0; } 1% { opacity: .8; } 8.5% { stroke-dashoffset: 6; opacity: .8; } 9.5%, 100% { stroke-dashoffset: 6; opacity: 0; } }
@keyframes nw-trace { 0% { stroke-dashoffset: 100; opacity: 0; } 2% { opacity: .9; } 20% { stroke-dashoffset: 0; opacity: .9; } 22%, 100% { stroke-dashoffset: 0; opacity: 0; } }
@keyframes nw-on { 0%, 8%, 100% { fill: var(--page); } 2%, 5% { fill: var(--ink); } }
@keyframes nw-task { 0%, 10%, 100% { opacity: .4; } 3%, 6% { opacity: 1; } }
@keyframes fade { to { opacity: 1; } }
@keyframes rise { to { opacity: 1; transform: none; } }
@keyframes line-up { to { transform: none; } }
@keyframes unhide { to { visibility: visible; } }

/* ---------- sections ---------- */
.section { padding-block: var(--section); border-top: 1px solid var(--line); }
.split { display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 6fr); gap: var(--gutter); align-items: start; }
@media (max-width: 920px) { .split { grid-template-columns: 1fr; gap: 40px; } }

/* why now: the statement, then the two halves side by side, ours the one drawn in ink */
.statement { font: 600 clamp(26px, 3.2vw, 40px)/1.15 var(--font-display); letter-spacing: -.028em; color: var(--ink); max-width: 22em; text-wrap: balance; }
.statement em { font-style: normal; color: var(--dim); }
.statement-sub { margin-top: 20px; color: var(--dim); max-width: 36em; }
.halves { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(16px, 2vw, 24px); margin-top: clamp(32px, 4vw, 48px); }
.half { padding: clamp(24px, 2.6vw, 32px); border: 1px solid var(--line); border-radius: 16px; background: var(--card); }
.half-ours { border-color: color-mix(in srgb, var(--ink) 40%, transparent); box-shadow: var(--shadow); }
.half-k { display: flex; align-items: center; gap: 10px; font: 500 11.5px/1.4 var(--font-mono); letter-spacing: .1em; text-transform: uppercase; color: var(--faint); }
.half-k span { color: var(--dim); }
.half-ours .half-k { color: var(--ink); }
.half h3 { margin: 22px 0 10px; font-size: clamp(22px, 2.2vw, 28px); letter-spacing: -.022em; line-height: 1.15; }
.half > p:not(.half-k) { color: var(--dim); max-width: 30em; }
/* the agentic coding tools the proven half means, named as text */
.half-names { display: flex; flex-wrap: wrap; gap: 6px; margin: 18px 0 0; padding: 0; list-style: none; }
.half-names li { padding: 5px 10px; border: 1px solid var(--line2); border-radius: 999px; font: 500 12px/1 var(--font-mono); color: var(--ink); }
.halves-sum { margin-top: clamp(28px, 3vw, 40px); max-width: 40em; font: 600 clamp(18px, 1.6vw, 21px)/1.45 var(--font-display); letter-spacing: -.012em; color: var(--ink); text-wrap: pretty; }
/* who we want to hear from: a card each, and a link that opens the form on its subject */
.half-link { display: inline-flex; align-items: center; gap: 8px; margin-top: 24px; padding-bottom: 2px; font: 600 14px/1.3 var(--font-body); color: var(--ink); border-bottom: 1px solid var(--line2); transition: border-color var(--m-fast) var(--e-out); }
.half-link:hover { border-color: var(--ink); }
.half-link .ico { width: 15px; height: 15px; transition: transform var(--m-base) var(--e-out); }
.half-link:hover .ico { transform: translateX(3px); }
#who .half { display: flex; flex-direction: column; align-items: flex-start; }
#who .half h3 { margin: 16px 0 8px; }
#who .half .half-link { margin-top: auto; }
#who .half > p:not(.half-k) { margin-bottom: 24px; }
.halves.is-three { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.halves.is-three .half h3 { font-size: clamp(20px, 1.9vw, 24px); }
@media (max-width: 960px) { .halves, .halves.is-three { grid-template-columns: 1fr; } }

/* ---------- contact ---------- */
.direct { display: inline-flex; align-items: center; gap: 10px; margin-top: 24px; font-size: 15px; color: var(--ink); padding-bottom: 2px; border-bottom: 1px solid var(--line2); transition: border-color var(--m-fast) var(--e-out); }
.direct:hover { border-color: var(--ink); }
.direct .ico { width: 16px; height: 16px; color: var(--dim); }

/* who we want to hear from: three rows in the spec list's manner; each takes you to the form with its
   subject chosen (site.js), and without scripts it is a plain link to the form */
.who { list-style: none; margin: 28px 0 0; padding: 0; position: relative; max-width: 32em; }
.who a { display: grid; grid-template-columns: 1fr 16px; gap: 4px 16px; align-items: start; padding: 18px 0; border-bottom: 1px solid var(--line); }
.who strong { font: 600 15px/1.35 var(--font-display); letter-spacing: -.01em; color: var(--ink); }
.who span { grid-column: 1; color: var(--dim); font-size: 15px; line-height: 1.55; }
.who .ico { grid-column: 2; grid-row: 1; width: 16px; height: 16px; margin-top: 2px; color: var(--faint); transition: transform var(--m-base) var(--e-out), color var(--m-fast) var(--e-out); }
.who a:hover .ico, .who a:focus-visible .ico { color: var(--ink); transform: translateX(3px); }
.who a:hover strong { text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 3px; text-decoration-color: var(--line2); }
.who + .direct { margin-top: 24px; }

.form { background: var(--card); border: 1px solid var(--line); border-radius: 16px; padding: clamp(24px, 2.6vw, 32px); box-shadow: var(--shadow); }
.form-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
.field { display: flex; flex-direction: column; gap: 7px; min-width: 0; }
.field-full { grid-column: 1 / -1; }
.field label { font-size: 13px; font-weight: 600; color: var(--ink); }
.field label .opt { font-weight: 400; color: var(--faint); margin-left: 6px; }
.field input, .field select, .field textarea {
  width: 100%; font: 400 15px/1.4 var(--font-body); color: var(--ink);
  background: var(--sink); border: 1px solid var(--line2); border-radius: 10px; padding: 11px 13px;
  transition: border-color var(--m-fast) var(--e-out), background-color var(--m-fast) var(--e-out), box-shadow var(--m-fast) var(--e-out);
  -webkit-appearance: none; appearance: none;
}
.field select { padding-right: 38px; }
/* the select's arrow is the app's solid chevron (build.mjs writes its two layers): its shape masks the box, its light lies over
   the colour, as the app paints its icons */
.select { position: relative; display: block; }
.select::after {
  content: ""; position: absolute; right: 12px; top: 50%; width: 14px; height: 14px; translate: 0 -50%; pointer-events: none;
  background: url("/brand/icon-chevron-down-light.png") center / 100% 100% no-repeat; background-color: var(--dim);
  mask: url("/brand/icon-chevron-down-shape.png") center / 100% 100% no-repeat luminance;
}
/* one size, never dragged: what does not fit scrolls inside it, under its own quiet bar (site.js) */
.field-full { position: relative; }
.field textarea { height: 152px; resize: none; line-height: 1.55; overflow-y: auto; overscroll-behavior: contain; padding-right: 20px; }
.field input:hover, .field select:hover, .field textarea:hover { border-color: color-mix(in srgb, var(--ink) 30%, var(--line2)); }
.field input:focus, .field select:focus, .field textarea:focus { outline: none; border-color: color-mix(in srgb, var(--ink) 40%, transparent); background: var(--card); box-shadow: 0 0 0 3px color-mix(in srgb, var(--ink) 8%, transparent); }
.field [aria-invalid="true"] { border-color: var(--red); }
.field-error { font-size: 12.5px; color: var(--red); }
.field-error:empty { display: none; }
.hp { position: absolute !important; left: -10000px; width: 1px; height: 1px; overflow: hidden; }
/* the person check (Cloudflare Turnstile): takes room only when it asks someone to tick its box */
.person-check.is-asking { margin-top: 24px; }
.form-foot { display: flex; align-items: center; justify-content: space-between; gap: 16px; margin-top: 24px; flex-wrap: wrap; }
.form-note { font-size: 12.5px; color: var(--faint); }
.form-note a { color: var(--dim); border-bottom: 1px solid var(--line2); }
.form-status { margin-top: 18px; font-size: 14px; padding: 12px 14px; border-radius: 10px; border: 1px solid var(--line); }
.form-status:empty { display: none; }
.form-status.ok { border-color: color-mix(in srgb, var(--green) 40%, var(--line)); background: color-mix(in srgb, var(--green) 9%, transparent); }
.form-status.err { border-color: color-mix(in srgb, var(--red) 40%, var(--line)); background: color-mix(in srgb, var(--red) 8%, transparent); }
@media (max-width: 560px) { .form-grid { grid-template-columns: 1fr; } }

/* ---------- simple pages ---------- */
.page { padding-block: clamp(56px, 8vw, 104px) var(--section); }
.page .wrap { max-width: 720px; }
.page h1 { font-size: clamp(32px, 4vw, 46px); margin-bottom: 16px; }
.page .meta { font: 400 12.5px/1.5 var(--font-mono); color: var(--faint); margin-bottom: 48px; }
.prose h2 { font-size: 19px; letter-spacing: -.012em; margin: 40px 0 10px; }
.prose p { color: var(--dim); }
.prose p + p { margin-top: 1em; }
.prose p strong { color: var(--ink); font-weight: 600; }
.prose a, .message .lead a { border-bottom: 1px solid var(--line2); }
.message .lead { margin-top: 16px; }

/* ---------- footer: the name, the company, and where else to go, on one line ---------- */
.site-footer { border-top: 1px solid var(--line); padding-block: 32px; color: var(--dim); font-size: 13px; line-height: 1; background: var(--page); }
.foot-row { display: flex; align-items: center; flex-wrap: wrap; gap: 12px 24px; }
.foot-row .brand svg { height: 18px; }
.foot-legal { color: var(--faint); }
.foot-links { display: flex; align-items: center; gap: 24px; margin-left: auto; }
.foot-links a { color: var(--dim); }
.foot-links a:hover { color: var(--ink); }

/* ---------- the quiet scroll bar (the app's .qbar): a thumb and nothing else ---------- */
.qbar { position: fixed; z-index: 25; top: calc(var(--header) + 6px); bottom: 6px; right: 0; width: 14px; }
.qbar.qbar-box { position: absolute; z-index: 2; bottom: auto; }
.qbar[hidden] { display: none; }
.qbar-thumb {
  position: absolute; top: 0; right: 4px; width: 4px; border-radius: 999px;
  background: color-mix(in srgb, var(--ink) 22%, transparent); opacity: 0;
  transition: opacity var(--m-slow) var(--e-out), width var(--m-fast) var(--e-out), right var(--m-fast) var(--e-out), background-color var(--m-fast) var(--e-out);
  will-change: transform;
}
.qbar.is-active .qbar-thumb, .qbar:hover .qbar-thumb, .qbar.is-dragged .qbar-thumb { opacity: 1; transition: opacity 120ms var(--e-out), width var(--m-fast) var(--e-out), right var(--m-fast) var(--e-out), background-color var(--m-fast) var(--e-out); }
.qbar:hover .qbar-thumb { right: 3px; width: 6px; background: color-mix(in srgb, var(--ink) 36%, transparent); }
.qbar.is-dragged .qbar-thumb { right: 3px; width: 6px; background: color-mix(in srgb, var(--ink) 48%, transparent); }

@media print {
  .site-header, .form, .actions, .qbar { display: none !important; }
  body { background: #fff; color: #000; }
}

