/* Isogram's site. One ground from the top of the page to the foot, the night the app opens on. A
   section never paints a ground of its own: a stage or canvas that fills the screen paints --ground
   itself, and only an object standing on the ground (a card, the app's window, an island, a printed
   sheet) is allowed one step up, to --raise or --raise-2. The drawings keep the app's own layer
   inks, walls near-white, openings violet, planting green, dimensions blue, since a page of grey
   plans was tried and read as lifeless; colour on the page's own chrome is kept for what it means
   in the app: blue for a dimension and for what you are about to affect, violet for the
   assistant's proposal. */
:root {
  --ground: #0a0b0d;
  --raise: #121316;
  --raise-2: #17181b;
  --snow: #f3f4f6;
  --snow-dim: #9a9fa8;
  /* The third grey, the faintest the page letters in: 5.2:1 on the ground and 4.7:1 on a raised
     card, where #62666e was 3.4:1 and failed small text. */
  --snow-faint: #7e838c;
  --paper: #f4f3ef;
  --ink: #0e0f11;
  --ink-dim: #51555c;
  --blue: #3b9eff;
  --violet: #a371f7;
  /* The ink the app draws its own mark in, on its icon and on the assistant's card (the app's
     --ai-violet): the pale one, which is the one that reads on a dark sheet. The page's marks, the
     nav's, the foot's and the finished icon at the end, wear it too, so there is one flower. */
  --mark: #b3a1ef;
  /* The app's own drawing canvas, for a replica of the app: the hero's window and the assistant's
     card are both the app, so both stand on this one grey rather than each on its own. */
  --model: #1c1d1f;
  --display: "Inter Tight", "Inter", system-ui, -apple-system, sans-serif;
  --sans: "Inter", system-ui, -apple-system, "Segoe UI", sans-serif;
  --mono: "IBM Plex Mono", ui-monospace, Menlo, monospace;
  --ease: cubic-bezier(0.2, 0.7, 0.1, 1);
  --ease-io: cubic-bezier(0.65, 0, 0.35, 1);
  --page: 1320px;
  --gutter: clamp(20px, 4vw, 56px);
  /* Every section reads these; there is no second ground to switch them for. */
  --bg: var(--ground); --fg: var(--snow); --fg-2: var(--snow-dim); --fg-3: var(--snow-faint);
  --hair: rgba(255, 255, 255, 0.08); --hair-2: rgba(255, 255, 255, 0.14);
  --card: var(--raise); --card-2: var(--raise-2); --accent: var(--blue); --assist: var(--violet);
  --btn: var(--snow); --on-btn: var(--ground);
  color-scheme: dark;
}

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-padding-top: 72px; }
html, body { overflow-x: clip; }
body {
  margin: 0; background: var(--ground); color: var(--snow);
  font: 400 17px/1.55 var(--sans); -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}
img, svg, canvas { display: block; max-width: 100%; }
a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; background: none; border: 0; padding: 0; cursor: pointer; }
h1, h2, h3, p { margin: 0; }
h1, h2 { font-family: var(--display); font-weight: 600; letter-spacing: -0.045em; line-height: 0.96; text-wrap: balance; }
/* Headlines follow the window's height as well as its width, so a short window still fits a scene. */
h2 { font-size: clamp(40px, min(6.2vw, 11vh), 96px); }
h3 { font: 600 clamp(22px, 2vw, 28px)/1.15 var(--display); letter-spacing: -0.025em; }
::selection { background: color-mix(in oklab, var(--blue) 45%, transparent); }
:focus-visible { outline: 2px solid var(--blue); outline-offset: 3px; border-radius: 6px; }
/* The email fields drop the outline for a blue rim, which is too faint a mark on its own; the
   keyboard's ring comes back round them like everything else. */
.signup input:focus-visible { outline: 2px solid var(--blue); outline-offset: 2px; }

section { position: relative; background: var(--bg); color: var(--fg); }
.wrap { width: min(var(--page), 100% - var(--gutter) * 2); margin-inline: auto; }
.block { padding-block: clamp(96px, 13vw, 180px); }
/* A figure's label, lettered the way a drawing letters its views: small, mono, under or beside the
   thing it names. It replaces the coloured tag that used to sit over every headline. */
.fig { font: 500 12px/1.4 var(--mono); letter-spacing: 0.02em; color: var(--fg-3); }
.fig b { font-weight: 500; color: var(--fg-2); }
/* A sentence in two tones: the claim in full ink, the rest of it in grey, so the eye can stop at
   the claim and lose nothing. */
.say { font: 500 clamp(22px, min(2.3vw, 4.4vh), 34px)/1.22 var(--display); letter-spacing: -0.022em; color: var(--fg-2); text-wrap: balance; }
.say b { font-weight: 500; color: var(--fg); }
.say.center { text-align: center; max-width: 900px; }
.lede { font-size: clamp(18px, 1.55vw, 22px); line-height: 1.45; color: var(--fg-2); letter-spacing: -0.01em; text-wrap: balance; }
.sub { font-size: 17px; line-height: 1.55; color: var(--fg-2); text-wrap: pretty; }
.cap { font: 12.5px/1.5 var(--mono); color: var(--fg-3); }
.head { max-width: 900px; }
.head .lede { margin-top: 24px; max-width: 640px; }
.head.center { margin-inline: auto; text-align: center; }
.head.center .lede { margin-inline: auto; }

/* ── nav: glass over whichever ground is under it ── */
.nav {
  position: fixed; inset: 0 0 auto; z-index: 50; height: 64px;
  display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; padding: 0 var(--gutter);
  color: var(--snow); transition: background 0.3s, color 0.3s, box-shadow 0.3s, transform 0.35s var(--ease);
}
.nav.tucked { transform: translateY(-100%); }
.nav.scrolled {
  background: color-mix(in oklab, var(--ground) 72%, transparent);
  -webkit-backdrop-filter: saturate(1.6) blur(18px); backdrop-filter: saturate(1.6) blur(18px);
  box-shadow: 0 1px 0 rgba(255, 255, 255, 0.07);
}
.brand { display: inline-flex; align-items: center; gap: 10px; font: 600 19px/1 var(--display); letter-spacing: -0.03em; justify-self: start; }
.brand .bloom { color: var(--mark); }
.links { display: flex; gap: 4px; }
.links a { padding: 8px 14px; border-radius: 999px; font-size: 14.5px; color: color-mix(in oklab, currentColor 70%, transparent); transition: color 0.2s, background 0.2s; }
.links a:hover { color: inherit; background: color-mix(in oklab, currentColor 8%, transparent); }
.nav .btn { justify-self: end; }

/* ── buttons: a solid pill, and a quiet one beside it ── */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 10px; height: 52px; padding: 0 26px;
  border-radius: 999px; background: var(--btn); color: var(--on-btn); font: 500 16px/1 var(--sans); letter-spacing: -0.01em;
  box-shadow: 0 1px 0 rgba(255, 255, 255, 0.25) inset, 0 10px 30px -12px rgba(0, 0, 0, 0.6);
  transition: transform 0.2s var(--ease), box-shadow 0.2s, background 0.2s;
}
.btn:hover { transform: translateY(-1px); }
.btn:active { transform: translateY(1px); }
.btn.small { height: 38px; padding: 0 18px; font-size: 14px; }
/* A download that is not out yet (js/download.js): faded, and it does nothing, so nobody goes
   looking for a file that is not there; the line beside it says when. */
.btn[aria-disabled="true"] { opacity: 0.32; box-shadow: none; pointer-events: none; }
/* Beside every email form: where the privacy note is, before the address is given. */
.signup .privacy { margin: 8px 0 0; font: 12px/1.5 var(--mono); color: var(--fg-3); }
.signup .privacy a { text-decoration: underline; text-underline-offset: 3px; text-decoration-color: var(--hair-2); }
.signup .privacy a:hover { color: var(--fg-2); text-decoration-color: var(--fg-3); }
.nav .btn { background: var(--snow); color: var(--ground); }
.btn.ghost { background: transparent; color: var(--fg); box-shadow: inset 0 0 0 1px var(--hair-2); }
.btn.ghost:hover { box-shadow: inset 0 0 0 1px color-mix(in oklab, var(--fg) 40%, transparent); }
.btn .arr { transition: transform 0.25s var(--ease); }
.btn:hover .arr { transform: translateY(2px); }
.btn small { font: 12px var(--mono); opacity: 0.55; }

/* ── the bloom: open at rest; it breathes while it thinks ── */
.bloom { fill: currentColor; overflow: visible; }
.bloom.thinking .turn { animation: turn 2.3s linear infinite; transform-origin: 8px 8px; }
.bloom.thinking .open { animation: breathe 2.3s ease-in-out infinite; transform-origin: 8px 4.9px; }
@keyframes turn { to { transform: rotate(72deg); } }
@keyframes breathe { 0%, 100% { transform: scale(1); } 50% { transform: scale(0.72); } }

/* ── things arrive a little late, in order, as they come into view ── */
.rv { opacity: 0; transform: translateY(18px); transition: opacity 0.9s var(--ease), transform 1s var(--ease); transition-delay: calc(var(--i, 0) * 90ms); }
.rv.in { opacity: 1; transform: none; }
/* The first screen's arrivals keep their own layer after they land. When a fade ended, the browser
   folded the headline, the line under it and the form back into the page's layer and drew them
   again, and on a phone each was gone for a frame as it did (filmed frame by frame, 27 September
   2026): the "flash" on entering. Three layers held for good cost less than that. */
.hero-copy .rv { will-change: opacity, transform; }

/* ── a chapter: after the first screen the page is four books, Architecture, Engineering, Agentic
   and Team, each opened by its name set large, so the reader knows which one they are in and the
   others' examples never cut in. The rule above it is the only line the page draws across itself.
   The opener is the numeral and the name and nothing else, about a third of a screen: four of them
   at the old height, sentence and all, cost the page nearly three screens of reading nothing. Its
   top was kept short on the thought that the scene before ends on empty ground, but most end on
   their drawing, and the rule came in about 100 px under it; the owner found the gaps uneven and
   tight (27 September 2026), so the top is a clear breath: about a sixth of the screen. ── */
.chapter { padding: clamp(64px, 16vh, 180px) 0 clamp(20px, 4vh, 56px); }
/* The nav's chapters are followed downward, so the bar tucks away and most of the 72 px kept for it
   would show the tail of the scene before. Taking 24 back still leaves the rule clear of the bar
   when a chapter is reached going up and the bar comes back over it, down to a 500 px window,
   where the opener's top is at its shortest. */
.chapter { scroll-margin-top: -24px; }
.chapter-in { border-top: 1px solid var(--hair); padding-top: clamp(20px, 4vh, 40px); }
.chapter-n { margin-bottom: clamp(10px, 2vh, 20px); }
.chapter h2 { font-size: clamp(64px, min(12vw, 20vh), 190px); letter-spacing: -0.058em; line-height: 0.9; }
/* The chapter the reader is in is the nav link that stays lit. */
.links a.here { color: inherit; background: color-mix(in oklab, currentColor 8%, transparent); }

/* ── a pinned scene: a tall section whose stage holds still while the scroll plays it ── */
.scene { height: var(--len, 300vh); }
.scene .stage { position: sticky; top: 0; height: 100vh; height: 100svh; overflow: hidden; }

/* ── a card that floats over a drawing, as the app floats its islands ── */
/* It is --raise-2 all but see-through, and blurred without saturating: a saturated blur picked up the
   drawing's blues under it and every island came out a different, bluish grey. */
.island {
  position: absolute; z-index: 3; border-radius: 16px;
  background: color-mix(in oklab, var(--raise-2) 92%, transparent); color: var(--snow);
  -webkit-backdrop-filter: blur(14px); backdrop-filter: blur(14px);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.09), 0 18px 40px -16px rgba(0, 0, 0, 0.7);
}
/* ── a plate: the dark rounded object a drawing or a study stands on, one step up from the ground,
   in the app's night inks. Study plates were white cards once and read as prints pasted onto the
   night. Its corners follow its size, as a window's do: a script that sizes a plate sets --r. ── */
.plate { background: var(--raise-2); border-radius: var(--r, 14px); box-shadow: inset 0 0 0 1px var(--hair); }

.caret { display: inline-block; width: 1.5px; height: 1.1em; background: currentColor; vertical-align: -0.18em; animation: blink 1.05s steps(1) infinite; }
@keyframes blink { 50% { opacity: 0; } }

/* A value that is not decided yet, so it is never mistaken for the figure. */
.placeholder { padding: 0 8px; border-radius: 6px; border: 1px dashed currentColor; opacity: 0.6; }

kbd {
  display: inline-grid; place-items: center; min-width: 30px; height: 28px; padding: 0 8px; border-radius: 7px;
  font: 500 12.5px/1 var(--mono); color: var(--fg); background: var(--card-2);
  box-shadow: inset 0 0 0 1px var(--hair-2), 0 2px 0 var(--hair-2);
}

/* ── footer ── */
/* Two rows on the page's own gutters: the mark left and the links right, then a hairline and the
   company's fine print. On a phone the links wrap under the mark, left-aligned with it. */
.foot {
  padding: 40px var(--gutter) 44px; border-top: 1px solid rgba(255, 255, 255, 0.07);
  font: 13px var(--mono); color: var(--snow-faint); background: var(--ground);
}
.foot-top { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 18px 32px; }
.foot-brand { display: inline-flex; align-items: center; gap: 8px; color: var(--snow); }
.foot-brand .bloom { color: var(--mark); }
.foot-links { display: flex; flex-wrap: wrap; gap: 12px 26px; }
.foot-links a:hover { color: var(--snow); }
/* The translated pages keep the one-line footer until they are written again from this page. */
.foot:not(:has(.foot-top)) { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 18px; }
.foot:not(:has(.foot-top)) .foot-company { flex-basis: 100%; margin: 4px 0 0; padding: 0; border: 0; }
.foot-company { margin: 28px 0 0; padding-top: 22px; border-top: 1px solid rgba(255, 255, 255, 0.05); font: 12px/1.7 var(--mono); color: var(--fg-3); }
.foot-company i { font-style: normal; margin: 0 0.5em; opacity: 0.6; }
@media (max-width: 600px) {
  .foot-top { flex-direction: column; align-items: flex-start; }
  /* One fact a line: the dots between them would start a line as often as not. */
  .foot-company span { display: block; }
  .foot-company i { display: none; }
}

@media (max-width: 900px) {
  .links { display: none; }
  .nav { grid-template-columns: 1fr auto; }
}
@media (prefers-reduced-motion: reduce) {
  .rv { opacity: 1; transform: none; transition: none; }
  .bloom.thinking .turn, .bloom.thinking .open, .caret { animation: none; }
}

/* Cloudflare's human check (js/signup.js, js/support.js). Its inside is Cloudflare's own frame and
   is left as it draws it; the box around it takes the fields' corners and fades once it has said
   "Success!", so it reads as part of the form rather than a panel pasted under it. */
.check, .contact-check { border-radius: 14px; overflow: hidden; transition: opacity .5s ease, max-height .5s ease, margin .5s ease; max-height: 120px; }
.check iframe, .contact-check iframe { display: block; }
.check-gone { opacity: 0; max-height: 0; margin-top: 0 !important; margin-bottom: 0 !important; pointer-events: none; }
@media (prefers-reduced-motion: reduce) { .check, .contact-check { transition: none; } }
