/* Aleph Developments — company site
 *
 * Hand-written CSS, no build step, no framework, no third-party request of any
 * kind. That last part is a load-bearing decision rather than a preference: the
 * privacy page claims this site loads nothing from anyone else, and a webfont
 * from Google's CDN would make that claim false. Inter is named first in the
 * stack so it is used when the visitor already has it locally, and the fallback
 * chain is native the rest of the way down.
 *
 * Tokens are copied from aleph-studios/src/styles.css @theme so the two sites
 * are the same brand. Where the hub resolves a value through Tailwind, the
 * literal is written out here.
 */

:root {
  --shell-950: #0b0b0f;
  --shell-900: #101015;
  --shell-850: #16161d;
  --shell-800: #1c1c25;
  --shell-700: #262631;

  --line-strong: #35353f;
  --line-soft: #24242c;

  --ink-100: #f4f4f8;
  --ink-200: #d7d7e0;
  --ink-300: #b0b0bd;
  --ink-400: #85858f;
  --ink-500: #62626c;

  --accent-300: #b9b3ff;
  --accent-400: #9a8dff;
  --accent-500: #7d73ff;
  --accent-600: #675dfa;
  --accent-700: #5148d6;

  --ok: #4fc98c;

  --bg: #07070a;
  --glass: rgba(22, 22, 29, 0.55);
  --glass-border: rgba(255, 255, 255, 0.08);
  --card: linear-gradient(180deg, rgba(28, 28, 37, 0.72), rgba(16, 16, 21, 0.72));
  --shadow: 0 24px 60px -28px rgba(0, 0, 0, 0.75);
  --spot: rgba(125, 115, 255, 0.16);

  --fg: var(--ink-200);
  --fg-strong: var(--ink-100);
  --fg-mute: var(--ink-400);

  --radius: 14px;
  --measure: 68ch;
  --font: Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
    "Helvetica Neue", Arial, "Noto Sans", sans-serif;
  --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas,
    "Liberation Mono", monospace;
}

:root[data-theme="light"] {
  --shell-950: #f4f5f8;
  --shell-900: #e9ebf1;
  --shell-850: #ffffff;
  --shell-800: #f7f8fb;
  --shell-700: #e4e6ee;

  --line-strong: #c9ccd8;
  --line-soft: #e0e2ea;

  --ink-100: #14141a;
  --ink-200: #2a2a35;
  --ink-300: #4b4b58;
  --ink-400: #6a6a78;
  --ink-500: #8a8a96;

  --accent-300: #6e62ea;
  --accent-400: #5a4ce8;
  --accent-500: #4a3fd4;
  --accent-600: #3e34bd;
  --accent-700: #322a9e;

  --bg: #eef0f5;
  --glass: rgba(255, 255, 255, 0.72);
  --glass-border: rgba(20, 20, 26, 0.1);
  --card: linear-gradient(180deg, rgba(255, 255, 255, 0.92), rgba(247, 248, 251, 0.92));
  --shadow: 0 24px 60px -34px rgba(20, 20, 40, 0.28);
  --spot: rgba(90, 76, 232, 0.1);
}

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  overflow-x: clip;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--fg);
  font-family: var(--font);
  font-size: 16px;
  line-height: 1.7;
  overflow-x: clip;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* One ambient plate, fixed, behind everything. Pure gradient — no image, no
 * canvas, nothing that moves. */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -2;
  pointer-events: none;
  background:
    radial-gradient(58rem 34rem at 18% -8%, var(--spot), transparent 65%),
    radial-gradient(46rem 30rem at 92% 4%, rgba(43, 138, 231, 0.09), transparent 68%);
}

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

a:hover {
  text-decoration: underline;
  text-underline-offset: 3px;
}

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

/* ── Layout ─────────────────────────────────────────────────────────── */

.wrap {
  width: 100%;
  max-width: 1120px;
  margin: 0 auto;
  padding: 0 24px;
}

.skip {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--shell-800);
  color: var(--fg-strong);
  padding: 12px 18px;
  border-radius: 0 0 10px 0;
  z-index: 100;
}

.skip:focus {
  left: 0;
}

/* ── Nav ────────────────────────────────────────────────────────────── */

.nav {
  position: sticky;
  top: 0;
  z-index: 40;
  background: var(--glass);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border-bottom: 1px solid var(--glass-border);
}

.nav-in {
  display: flex;
  align-items: center;
  gap: 22px;
  height: 64px;
}

.brand {
  display: flex;
  align-items: center;
  gap: 11px;
  color: var(--fg-strong);
  font-weight: 700;
  letter-spacing: -0.01em;
  flex: none;
}

.brand:hover {
  text-decoration: none;
}

.brand img {
  width: 26px;
  height: 26px;
  display: block;
}

.brand span {
  font-size: 15px;
}

.brand small {
  display: block;
  font-size: 10.5px;
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--fg-mute);
  line-height: 1.2;
}

.nav-links {
  display: flex;
  align-items: center;
  gap: 20px;
  margin-left: auto;
  font-size: 14px;
}

.nav-links a {
  color: var(--ink-300);
}

.nav-links a:hover,
.nav-links a[aria-current="page"] {
  color: var(--fg-strong);
  text-decoration: none;
}

.nav-links a[aria-current="page"] {
  font-weight: 600;
}

.tbtn {
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  flex: none;
  border-radius: 9px;
  border: 1px solid var(--line-soft);
  background: var(--shell-800);
  color: var(--ink-300);
  cursor: pointer;
  padding: 0;
  transition: color 0.18s, border-color 0.18s, background 0.18s;
}

.tbtn:hover {
  color: var(--fg-strong);
  border-color: var(--line-strong);
}

.tbtn svg {
  width: 17px;
  height: 17px;
}

/* ── Hero ───────────────────────────────────────────────────────────────
 *
 * Two columns, and the right one is DELIBERATELY wider than the space it is
 * given: `.hero-shot` has a `min-width` above the column's share, so the
 * screenshot runs off the right edge of the viewport and is clipped by the
 * `overflow-x: clip` on `html`/`body`. That bleed is the whole composition.
 * An earlier version of this page set one `max-width: 1120px` column and left
 * the right 60% of a 1440px viewport empty, which reads as unfinished rather
 * than as restraint.
 *
 * `clip` and not `hidden` on the two roots, for the reason recorded in the
 * hub's notes: `hidden` would re-parent every sticky descendant's scrollport
 * and un-stick the nav. Nothing here is sticky except the nav, which is
 * exactly the thing that would break.
 */

.hero {
  padding: 76px 0 40px;
  position: relative;
}

/* The left padding is derived from `.wrap` rather than chosen, because the
 * hero copy has to start on the same vertical line as every `h2` below it.
 * `.wrap` is `max-width: 1120px` with `24px` of padding, so its content edge
 * sits at `(100% - 1120px) / 2 + 24px` once the viewport is wider than 1120 —
 * and that expression, not a round number, is what keeps the two aligned at
 * every width. A hand-picked value agreed at 1440px and drifted everywhere
 * else, which is visible as a ~100px stagger between the h1 and the h2.
 *
 * There is no right padding and no `max-width`: the grid runs to the viewport
 * edge so the shot has somewhere to bleed into. */
.hero-in {
  width: 100%;
  padding: 0 0 0 max(24px, calc((100% - 1120px) / 2 + 24px));
  display: grid;
  grid-template-columns: minmax(0, 44fr) minmax(0, 56fr);
  gap: 56px;
  align-items: center;
}

.hero-copy {
  min-width: 0;
}

.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--ink-300);
  padding: 0;
  margin: 0 0 20px;
}

.dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--ok);
  flex: none;
}

h1 {
  font-size: clamp(2.1rem, 4.1vw, 3.3rem);
  line-height: 1.07;
  letter-spacing: -0.03em;
  font-weight: 800;
  color: var(--fg-strong);
  margin: 0 0 22px;
  max-width: 19ch;
  text-wrap: balance;
}

/* Was a two-stop gradient clipped to the text. A gradient headline and a
 * gradient pill button are the two most recognisable machine-generated
 * landing-page signals there are, and this page was wearing both. Solid ink
 * with the accent used once, as a colour rather than as a ramp. */
.grad {
  color: var(--accent-300);
}

.lede {
  font-size: clamp(1.02rem, 1.25vw, 1.13rem);
  color: var(--ink-300);
  max-width: 46ch;
  margin: 0 0 30px;
}

/* ── Window chrome ──────────────────────────────────────────────────────
 * One frame, reused by the hero and by every product tile. The screenshots
 * inside it are real captures of the running apps, not mockups. */

.shot {
  border: 1px solid var(--line-soft);
  border-radius: 12px;
  overflow: hidden;
  background: var(--shell-900);
  box-shadow:
    0 30px 70px -24px rgba(0, 0, 0, 0.7),
    0 10px 30px -14px rgba(0, 0, 0, 0.5),
    0 0 140px -30px rgba(22, 130, 215, 0.4),
    inset 0 1px 0 rgba(255, 255, 255, 0.08);
}

.shot-bar {
  display: flex;
  align-items: center;
  gap: 8px;
  height: 34px;
  padding: 0 13px;
  background: linear-gradient(180deg, color-mix(in srgb, var(--shell-850) 100%, white 4%), var(--shell-850));
  border-bottom: 1px solid var(--line-soft);
  font-size: 12px;
  color: var(--fg-mute);
}

.shot-bar i {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--line-strong);
  flex: none;
}

.shot-bar b {
  font-weight: 500;
  color: var(--ink-300);
  margin-left: 6px;
}

.shot-bar span {
  margin-left: auto;
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.04em;
}

.shot img {
  display: block;
  width: 100%;
  height: auto;
}

/* Wider than the column it is in, on purpose — this is the bleed. */
.hero-shot {
  min-width: 820px;
}

@media (min-width: 1600px) {
  .hero-shot { min-width: 900px; }
}

.cta-row {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  align-items: center;
}

.btn {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding: 12px 20px;
  border-radius: 11px;
  font-size: 14.5px;
  font-weight: 600;
  border: 1px solid transparent;
  cursor: pointer;
  transition: transform 0.16s, background 0.18s, border-color 0.18s, color 0.18s;
}

.btn:hover {
  text-decoration: none;
  transform: translateY(-1px);
}

/* Flat, one colour. The gradient-plus-coloured-glow version of this button is
 * the single most copied element on the generated-landing-page internet. */
.btn-primary {
  background: var(--accent-600);
  color: #fff;
}

.btn-primary:hover {
  background: var(--accent-500);
}

:root[data-theme="light"] .btn-primary {
  background: var(--accent-500);
}

:root[data-theme="light"] .btn-primary:hover {
  background: var(--accent-400);
}

.btn-ghost {
  background: var(--shell-800);
  border-color: var(--line-soft);
  color: var(--fg-strong);
}

.btn-ghost:hover {
  border-color: var(--line-strong);
}

/* ── Free-window banner ─────────────────────────────────────────────────
 * Lifted out of the hero and made a full-width rule between the hero and the
 * products. In the hero it was the fifth stacked element in one column and
 * read as another card; as a band it separates two sections and earns its
 * own beat. */

.freebar {
  border-top: 1px solid var(--line-soft);
  border-bottom: 1px solid var(--line-soft);
  background: var(--shell-900);
  padding: 15px 0;
  font-size: 14px;
}

.freebar-in {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 6px 16px;
}

.freebar strong {
  color: var(--fg-strong);
}

.freebar .count {
  font-family: var(--mono);
  font-size: 12px;
  color: var(--accent-300);
  border: 1px solid var(--glass-border);
  border-radius: 999px;
  padding: 3px 11px;
  flex: none;
}

/* ── Sections ───────────────────────────────────────────────────────────
 * Four sections that all ran `h2 → grey lede → thing` at identical spacing
 * gave the page no crescendo — nothing was louder than anything else and the
 * gaps read as unconsidered. Three rhythms now: `.sec-hero` for the products
 * (largest heading, own background, most air), the default for the middle,
 * and `.sec-close` for the quiet last word. */

section {
  padding: 64px 0;
}

/* `--shell-950` against the `--bg` behind it is a 4-value difference in dark
 * and reads as nothing at all — the band has to be visible to do its job of
 * separating two rhythms, so this one colour is stated per theme rather than
 * borrowed from a token that happens to be adjacent to the page background. */
.sec-alt {
  background: #101016;
  border-top: 1px solid var(--line-soft);
  border-bottom: 1px solid var(--line-soft);
  padding: 84px 0;
}

:root[data-theme="light"] .sec-alt {
  background: #e7e9f0;
}

.sec-close {
  padding: 40px 0 72px;
}

h2 {
  font-size: clamp(1.4rem, 2.6vw, 1.85rem);
  line-height: 1.2;
  letter-spacing: -0.02em;
  font-weight: 750;
  color: var(--fg-strong);
  margin: 0 0 14px;
}

.sec-alt h2 {
  font-size: clamp(1.75rem, 3.2vw, 2.5rem);
  letter-spacing: -0.028em;
  font-weight: 800;
}

/* The last section is a note, not an announcement: no h2 weight, a rule down
 * the left instead, and a narrower measure than anything above it. */
.closing {
  max-width: 62ch;
  border-left: 2px solid var(--accent-500);
  padding-left: 26px;
}

.closing h2 {
  font-size: 1.12rem;
  font-weight: 650;
  letter-spacing: -0.005em;
  margin-bottom: 12px;
}

/* `flex-end` stranded the count in mid-air beside a three-line lede — baseline
 * with the BOTTOM of a tall block is not alignment to anything the eye can
 * see. It sits on the heading's line instead. */
.sec-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 4px 32px;
  margin-bottom: 34px;
}

.sec-head > div {
  min-width: 0;
  flex: 1 1 30ch;
}

.sec-head .sec-lede {
  margin: 0;
  max-width: 54ch;
}

.sec-count {
  font-family: var(--mono);
  font-size: 12px;
  color: var(--fg-mute);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  white-space: nowrap;
  margin: 0;
  flex: none;
}

h3 {
  font-size: 1.06rem;
  font-weight: 650;
  color: var(--fg-strong);
  letter-spacing: -0.01em;
  margin: 32px 0 10px;
}

h4 {
  font-size: 0.95rem;
  font-weight: 650;
  color: var(--fg-strong);
  margin: 24px 0 8px;
}

p {
  margin: 0 0 16px;
}

.sec-lede {
  color: var(--ink-300);
  max-width: var(--measure);
  margin: 0 0 30px;
}

/* ── Product grid ───────────────────────────────────────────────────── */

/* Two big tiles over four small ones. Six identical cards in a 3×2 block is the
 * default feature grid; making some of them bigger is what turns it into a
 * composition.
 *
 * The column count is 4 and not 3 for an arithmetic reason worth writing down:
 * with two tiles spanning 2 columns each, the six tiles occupy EIGHT cells,
 * and 8 divides by 4 but not by 3. A 3-column version of this same idea leaves
 * a one-tile orphan on the last row, which is what the first attempt shipped
 * and it read as a layout bug rather than as emphasis. Count the cells, not
 * the tiles. */
.grid {
  display: grid;
  gap: 18px;
  grid-template-columns: minmax(0, 1fr);
}

@media (min-width: 700px) {
  .grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .tile-wide { grid-column: span 2; }
  .tile-wide .tile-shot { aspect-ratio: 2.3 / 1; }
}

@media (min-width: 1180px) {
  .grid { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .tile-wide .tile-shot { aspect-ratio: 2 / 1; }
}

.tile {
  position: relative;
  display: flex;
  flex-direction: column;
  border: 1px solid var(--glass-border);
  background: var(--card);
  border-radius: var(--radius);
  overflow: hidden;
  transition: transform 0.25s cubic-bezier(0.2, 0.8, 0.2, 1), border-color 0.25s,
    box-shadow 0.25s;
  box-shadow: 0 16px 40px -22px rgba(0, 0, 0, 0.6);
}

.tile:hover {
  text-decoration: none;
  transform: translateY(-4px);
  border-color: var(--line-strong);
  box-shadow:
    0 24px 50px -20px rgba(0, 0, 0, 0.65),
    0 0 60px -16px color-mix(in srgb, var(--hue, var(--accent-500)) 55%, transparent);
}

.tile::before {
  content: "";
  position: absolute;
  inset: 0 0 auto;
  height: 2px;
  background: var(--hue, var(--accent-500));
  z-index: 2;
}

/* A real capture of the running app, cropped to the top-left of the frame so
 * the toolbars and the document are both legible at tile size. `object-position`
 * rather than a centre crop: the middle of an editor screenshot is empty
 * canvas, which photographs as a grey rectangle. */
.tile-shot {
  position: relative;
  aspect-ratio: 16 / 9;
  overflow: hidden;
  background: var(--shell-950);
  border-bottom: 1px solid var(--line-soft);
  box-shadow:
    inset 0 0 0 1px rgba(255, 255, 255, 0.04),
    inset 0 -30px 40px -30px rgba(0, 0, 0, 0.5);
}

.tile-shot img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: left top;
  transition: transform 0.5s cubic-bezier(0.2, 0.8, 0.2, 1);
}

.tile:hover .tile-shot img {
  transform: scale(1.035);
}

.tile-body {
  padding: 18px 20px 20px;
  display: flex;
  flex-direction: column;
  flex: 1;
}

/* Product hues, copied from aleph-studios/src/data.ts. These are classes and
 * not `style="--hue:…"` attributes for one specific reason: an inline style
 * attribute cannot be allow-listed by hash, so keeping them here is what lets
 * the Content-Security-Policy in vercel.json stay at a clean
 * `style-src 'self'` with no 'unsafe-inline'. */
.t-vector { --hue: #6C67C4; }
.t-photo  { --hue: #1682D7; }
.t-lumen  { --hue: #16B3A6; }
.t-motion { --hue: #317CC8; }
.t-pages  { --hue: #E8873A; }
.t-draft  { --hue: #0D4894; }

.tile-top {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 12px;
}

.mono {
  display: grid;
  place-items: center;
  width: 38px;
  height: 38px;
  flex: none;
  border-radius: 10px;
  font-size: 14px;
  font-weight: 700;
  letter-spacing: -0.02em;
  color: #fff;
  background: linear-gradient(
    145deg,
    color-mix(in srgb, var(--hue, var(--accent-500)) 100%, white 14%),
    var(--hue, var(--accent-500))
  );
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.25),
    0 4px 12px -4px color-mix(in srgb, var(--hue, var(--accent-500)) 70%, transparent);
}

/* The name and the class label are two stacked lines, not a sentence. Left
 * inline they run together and wrap mid-label ("Illustrator-class · / Vector"),
 * which is what the first browser pass caught. min-width:0 lets the column
 * shrink inside the flex row so the Live pill keeps its place instead of being
 * pushed out. */
.tile-id {
  flex: 1;
  min-width: 0;
}

.tile-name {
  display: block;
  font-weight: 650;
  color: var(--fg-strong);
  font-size: 15px;
  line-height: 1.3;
}

.tile-klass {
  display: block;
  font-size: 11.5px;
  color: var(--fg-mute);
  letter-spacing: 0.02em;
}

.tile-desc {
  font-size: 13.6px;
  color: var(--ink-300);
  line-height: 1.62;
  margin: 0;
}

.pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ok);
  margin-left: auto;
  flex: none;
}

.pill.soon {
  color: var(--fg-mute);
}

.pill .dot {
  width: 6px;
  height: 6px;
  background: currentColor;
}

/* ── Fact strip ─────────────────────────────────────────────────────────
 * Four entries that are the SAME KIND of thing. The previous version ran
 * `0` / `None` / `Zero` / `Modest hardware`, so the fourth broke the pattern
 * the first three had spent the row establishing — and three different words
 * for zero read as thesaurus rather than emphasis. All four are numerals now,
 * which makes the repetition deliberate and lets the last one land. */

.facts {
  display: grid;
  gap: 1px;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  background: var(--line-soft);
  border: 1px solid var(--glass-border);
  border-radius: var(--radius);
  overflow: hidden;
}

.fact {
  background: var(--shell-900);
  padding: 26px 22px;
}

.fact dt {
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--fg-mute);
  margin: 0 0 14px;
}

.fact dd {
  margin: 0;
  font-size: 13.6px;
  color: var(--ink-300);
  line-height: 1.6;
}

.fact dd b {
  display: block;
  font-size: clamp(2.1rem, 3.6vw, 2.9rem);
  font-weight: 800;
  letter-spacing: -0.04em;
  color: var(--fg-strong);
  line-height: 1;
  margin-bottom: 9px;
  font-variant-numeric: tabular-nums;
}

/* ── Prose (legal pages) ────────────────────────────────────────────── */

.doc {
  padding: 52px 0 24px;
}

.doc-head {
  border-bottom: 1px solid var(--line-soft);
  padding-bottom: 26px;
  margin-bottom: 8px;
}

.doc-head h1 {
  max-width: none;
  font-size: clamp(1.8rem, 4vw, 2.5rem);
  margin-bottom: 12px;
}

.meta {
  font-size: 13px;
  color: var(--fg-mute);
  font-family: var(--mono);
}

.prose {
  max-width: var(--measure);
}

.prose > p,
.prose > ul,
.prose > ol {
  color: var(--ink-200);
}

.prose ul,
.prose ol {
  padding-left: 22px;
  margin: 0 0 16px;
}

.prose li {
  margin-bottom: 9px;
}

.prose h2 {
  font-size: 1.22rem;
  margin: 40px 0 12px;
  padding-top: 6px;
}

.prose h2:first-of-type {
  margin-top: 30px;
}

.prose code {
  font-family: var(--mono);
  font-size: 0.855em;
  background: var(--shell-800);
  border: 1px solid var(--line-soft);
  border-radius: 5px;
  padding: 1.5px 5px;
  color: var(--accent-300);
  white-space: nowrap;
}

.callout {
  border: 1px solid var(--glass-border);
  border-left: 3px solid var(--accent-500);
  background: var(--glass);
  border-radius: 0 var(--radius) var(--radius) 0;
  padding: 18px 20px;
  margin: 0 0 28px;
  font-size: 14.4px;
  color: var(--ink-200);
}

.callout p:last-child {
  margin-bottom: 0;
}

.callout.warn {
  border-left-color: #f2a03d;
}

.tbl-scroll {
  overflow-x: auto;
  border: 1px solid var(--glass-border);
  border-radius: var(--radius);
  margin: 0 0 26px;
}

table {
  width: 100%;
  border-collapse: collapse;
  font-size: 13.6px;
  min-width: 520px;
}

th,
td {
  text-align: left;
  padding: 11px 15px;
  border-bottom: 1px solid var(--line-soft);
  vertical-align: top;
}

th {
  background: var(--shell-850);
  color: var(--fg-strong);
  font-weight: 650;
  font-size: 12.5px;
  letter-spacing: 0.03em;
  white-space: nowrap;
}

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

td code {
  white-space: nowrap;
}

/* Table of contents on the long documents */
.toc {
  border: 1px solid var(--glass-border);
  background: var(--glass);
  border-radius: var(--radius);
  padding: 18px 22px;
  margin: 26px 0 34px;
  max-width: var(--measure);
}

.toc p {
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--fg-mute);
  margin: 0 0 10px;
}

.toc ol {
  margin: 0;
  padding-left: 20px;
  columns: 2;
  column-gap: 28px;
  font-size: 13.6px;
}

.toc li {
  margin-bottom: 5px;
  break-inside: avoid;
}

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

footer {
  border-top: 1px solid var(--line-soft);
  margin-top: 56px;
  padding: 44px 0 40px;
  background: var(--shell-950);
}

.foot-grid {
  display: grid;
  gap: 30px;
  grid-template-columns: 1.6fr 1fr 1fr 1fr;
}

.foot-col h5 {
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--fg-mute);
  margin: 0 0 12px;
}

.foot-col ul {
  list-style: none;
  margin: 0;
  padding: 0;
  font-size: 13.6px;
}

.foot-col li {
  margin-bottom: 8px;
}

.foot-col a {
  color: var(--ink-300);
}

.foot-col a:hover {
  color: var(--fg-strong);
}

.foot-about {
  font-size: 13.4px;
  color: var(--fg-mute);
  max-width: 34ch;
  margin: 12px 0 0;
  line-height: 1.65;
}

.foot-base {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 18px;
  align-items: center;
  justify-content: space-between;
  border-top: 1px solid var(--line-soft);
  margin-top: 34px;
  padding-top: 22px;
  font-size: 12.6px;
  color: var(--fg-mute);
}

/* ── Responsive ─────────────────────────────────────────────────────── */

/* Below this the bleed stops paying for itself: the copy column gets too
 * narrow to read and the shot too small to show anything. Stack, and let the
 * screenshot sit full width under the copy at its natural size. */
@media (max-width: 1040px) {
  .hero-in {
    grid-template-columns: minmax(0, 1fr);
    gap: 40px;
    padding: 0 24px;
  }

  .hero {
    padding-bottom: 28px;
  }

  .hero-shot {
    min-width: 0;
  }

  h1 {
    max-width: 18ch;
  }

  .lede {
    max-width: 58ch;
  }
}

@media (max-width: 900px) {
  .foot-grid {
    grid-template-columns: 1fr 1fr;
  }

  .sec-alt {
    padding: 60px 0;
  }
}

@media (max-width: 640px) {
  .wrap {
    padding: 0 18px;
  }

  .hero {
    padding: 52px 0 36px;
  }

  .hero-in {
    padding: 0 18px;
    gap: 32px;
  }

  section {
    padding: 48px 0;
  }

  .sec-close {
    padding: 52px 0 68px;
  }

  .closing {
    padding-left: 18px;
  }

  .shot-bar span {
    display: none;
  }

  .nav-links {
    gap: 15px;
    font-size: 13.4px;
  }

  .nav-links .hide-sm {
    display: none;
  }

  .toc ol {
    columns: 1;
  }

  .foot-grid {
    grid-template-columns: 1fr;
    gap: 26px;
  }
}

/* ── Reduced motion ─────────────────────────────────────────────────────
 * There is exactly nothing on this site that loops, and only four
 * transitions exist (.tbtn, .btn, .tile, .tile-shot img — the last one
 * added with the screenshot hover-zoom). They are named individually rather
 * than clamped universally, so this block stays a readable census of every
 * moving subject — same convention as the hub's reduce block.
 */
@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  .tbtn,
  .btn,
  .tile,
  .tile-shot img {
    transition: none !important;
  }

  .btn:hover,
  .tile:hover {
    transform: none !important;
  }

  .tile:hover .tile-shot img {
    transform: none !important;
  }
}

@media print {
  .nav,
  footer,
  .cta-row,
  .toc {
    display: none !important;
  }

  body {
    background: #fff;
    color: #000;
  }

  body::before {
    display: none;
  }

  .prose {
    max-width: none;
  }
}

/* ── Bug report widget ─────────────────────────────────────────────────
 * Injected by bug-report.js. Floating trigger + modal, mailto-based, no
 * network calls. Kept in its own block so it is easy to diff against the
 * hand-authored site CSS above it. */

.bugreport-fab {
  position: fixed;
  right: 20px;
  bottom: 20px;
  z-index: 2000;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 11px 16px;
  border-radius: 999px;
  border: 1px solid var(--glass-border);
  background: var(--glass);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  color: var(--fg-strong);
  font: inherit;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  box-shadow: var(--shadow);
  transition: border-color 0.15s ease, transform 0.15s ease;
}

.bugreport-fab:hover {
  border-color: var(--line-strong);
  transform: translateY(-1px);
}

.bugreport-fab svg {
  color: var(--accent-300);
  flex: none;
}

.bugreport-overlay {
  position: fixed;
  inset: 0;
  z-index: 2100;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
  background: rgba(4, 4, 7, 0.6);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
}

.bugreport-overlay[hidden] {
  display: none;
}

.bugreport-modal {
  width: 100%;
  max-width: 460px;
  max-height: calc(100vh - 40px);
  overflow-y: auto;
  background: var(--card);
  background-color: var(--shell-900);
  border: 1px solid var(--glass-border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 28px;
  position: relative;
}

.bugreport-modal h2 {
  margin: 0 0 8px;
  font-size: 19px;
  color: var(--fg-strong);
}

.bugreport-sub {
  margin: 0 0 18px;
  font-size: 13px;
  line-height: 1.55;
  color: var(--fg-mute);
}

.bugreport-sub strong {
  color: var(--fg-strong);
  font-weight: 600;
}

.bugreport-close {
  position: absolute;
  top: 16px;
  right: 16px;
  width: 30px;
  height: 30px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 999px;
  border: 1px solid var(--glass-border);
  background: transparent;
  color: var(--fg-mute);
  cursor: pointer;
}

.bugreport-close:hover {
  color: var(--fg-strong);
  border-color: var(--line-strong);
}

.bugreport-label {
  display: block;
  font-size: 12px;
  font-weight: 600;
  color: var(--fg-mute);
  margin: 14px 0 6px;
}

.bugreport-textarea,
.bugreport-input {
  width: 100%;
  box-sizing: border-box;
  border-radius: 10px;
  border: 1px solid var(--line-soft);
  background: var(--shell-850);
  color: var(--fg-strong);
  font: inherit;
  font-size: 14px;
  padding: 10px 12px;
  resize: vertical;
}

.bugreport-textarea:focus,
.bugreport-input:focus {
  outline: 2px solid var(--accent-500);
  outline-offset: 1px;
}

.bugreport-error {
  margin: 8px 0 0;
  font-size: 12.5px;
  color: #ff8a8a;
}

.bugreport-actions {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  margin-top: 20px;
}

.bugreport-fallback {
  margin: 16px 0 0;
  font-size: 12px;
  color: var(--fg-mute);
  text-align: center;
}

.bugreport-fallback a {
  color: var(--accent-300);
}

body.bugreport-lock {
  overflow: hidden;
}

@media (max-width: 480px) {
  .bugreport-fab span {
    display: none;
  }
  .bugreport-fab {
    padding: 12px;
  }
}
