/* ==========================================================================
   Inkdesk site
   An editorial system: paper stock, hairline rules, sharp corners.
   No shadows, no gradients, no rounded blobs. Motion is reserved for
   entrances and progress, never for hover.
   ========================================================================== */

@font-face {
  font-family: 'Finger Paint';
  src: url('../fonts/fingerpaint.woff2') format('woff2');
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Plex Sans';
  src: url('../fonts/plexsans.woff2') format('woff2');
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Plex Sans';
  src: url('../fonts/plexsans-600.woff2') format('woff2');
  font-weight: 600; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Plex Mono';
  src: url('../fonts/plexmono.woff2') format('woff2');
  font-weight: 500; font-style: normal; font-display: swap;
}

:root {
  --paper:      #111114;
  --paper-0:    #09090b;
  --red:        #ff416a;
  --red-2:      #d9506f;
  --red-3:      #b06a86;
  --mark:       #ff416a;
  --paper-2:    #18181c;
  --paper-3:    #222228;
  --ink:        #f4f4f6;
  --ink-2:      #d1d0db;
  --muted:      #9896a4;
  --faint:      #636173;
  --rule:       #2b2b34;
  --rule-soft:  #202028;
  --accent:     #ff416a;
  --accent-ink: #ffffff;
  --warn:       #e08c7c;
  --ok:         #8fb894;

  --display: 'Finger Paint', 'Comic Sans MS', 'Bradley Hand', cursive;
  --sans:  'Plex Sans', -apple-system, 'Segoe UI', Roboto, system-ui, sans-serif;
  --mono:  'Plex Mono', ui-monospace, Consolas, monospace;

  --measure: 66ch;
  --page: 1180px;
  --gutter: 32px;
  --rail: 148px;
}

[data-theme="dark"] {
  --paper:      #111114;
  --paper-0:    #09090b;
  --red:        #ff416a;
  --red-2:      #d9506f;
  --red-3:      #b06a86;
  --mark:       #ff416a;
  --paper-2:    #18181c;
  --paper-3:    #222228;
  --ink:        #f4f4f6;
  --ink-2:      #d1d0db;
  --muted:      #948e85;
  --faint:      #6e6961;
  --rule:       #34343a;
  --rule-soft:  #2a2a2f;
  --accent:     #ff6f8e;
  --accent-ink: #111114;
  --warn:       #d08a7c;
  --ok:         #8fb894;
}

[data-theme="light"] {
  --paper:      #f3f0e8;
  --paper-0:    #faf8f2;
  --red:        #ff204e;
  --red-2:      #a0153e;
  --red-3:      #5d0e41;
  --mark:       #ff204e;
  --paper-2:    #eae6da;
  --paper-3:    #e2ddce;
  --ink:        #1b1a16;
  --ink-2:      #46433b;
  --muted:      #77726a;
  --faint:      #9c968b;
  --rule:       #cec8b8;
  --rule-soft:  #dfd9c9;
  --accent:     #a0153e;
  --accent-ink: #f3f0e8;
  --warn:       #8a3a2c;
  --ok:         #3c5f3f;
}

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

html {
  scroll-behavior: smooth;
  /* The sticky header must not cover an anchor target. */
  scroll-padding-top: 96px;
  -webkit-text-size-adjust: 100%;
}
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation-duration: 0.001ms !important; animation-iteration-count: 1 !important; }
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 16.5px;
  line-height: 1.62;
  font-feature-settings: 'kern' 1, 'liga' 1;
  -webkit-font-smoothing: antialiased;
}

img { max-width: 100%; display: block; }
a { color: inherit; }

::selection { background: var(--ink); color: var(--paper); }

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

/* ─────────────────────────── type ─────────────────────────── */

h1, h2, h3, h4 { margin: 0; font-weight: 400; letter-spacing: -0.012em; }
/* Finger Paint is a wide marker face. It wants room to breathe, so the sizes
   are smaller and the leading looser than a serif would need at the same rank. */
h1 { font-family: var(--display); font-size: clamp(31px, 4.5vw, 57px); line-height: 1.16; letter-spacing: 0; }
h2 { font-family: var(--display); font-size: clamp(22px, 2.5vw, 32px); line-height: 1.24; letter-spacing: 0; }
h3 { font-family: var(--sans); font-weight: 600; font-size: 18px; line-height: 1.35; letter-spacing: 0; }
p { margin: 0 0 1.1em; }
p:last-child { margin-bottom: 0; }

.lede { font-size: clamp(18px, 1.8vw, 21px); line-height: 1.55; color: var(--ink-2); max-width: 54ch; }
.prose { max-width: var(--measure); }
.prose h2 { margin: 2.4em 0 0.5em; }
.prose h3 { margin: 2em 0 0.4em; }
.prose ol, .prose ul { padding-left: 1.3em; margin: 0 0 1.1em; }
.prose li { margin-bottom: 0.35em; }
.prose a { text-decoration: underline; text-underline-offset: 3px; text-decoration-thickness: 1px; }

.eyebrow {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted);
  font-weight: 500;
}

.num {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.1em;
  color: var(--faint);
}

/* ─────────────────────────── layout ─────────────────────────── */

.wrap {
  max-width: var(--page);
  margin: 0 auto;
  padding: 0 var(--gutter);
}

.band { border-top: 1px solid var(--rule); }
.band-inner { padding-block: clamp(56px, 7vw, 104px); }

/* An asymmetric two-column rhythm: a narrow rail of metadata beside the
   substance. Deliberately not a row of equal cards. */
.split {
  display: grid;
  grid-template-columns: var(--rail) minmax(0, 1fr);
  gap: 0 48px;
  align-items: start;
}
.split > .rail { padding-top: 0.5em; }
/* A grid item is min-width: auto by default, so a wide code block or table
   would push the whole column past the edge of a phone. */
.split > * { min-width: 0; }
@media (max-width: 860px) {
  .split { grid-template-columns: minmax(0, 1fr); gap: 10px; }
}

/* ─────────────────────────── skip link ─────────────────────────── */

.skip {
  position: fixed;
  top: 0; left: 0;
  z-index: 200;
  padding: 12px 18px;
  background: var(--ink);
  color: var(--paper);
  font-size: 14px;
  transform: translateY(-110%);
}
.skip:focus { transform: translateY(0); }

/* ─────────────────────────── scroll progress ─────────────────────────── */

.progress {
  position: fixed;
  top: 0; left: 0;
  height: 2px;
  width: 100%;
  transform-origin: 0 50%;
  transform: scaleX(0);
  background: var(--red);
  z-index: 120;
}

/* ─────────────────────────── header ─────────────────────────── */

.masthead {
  position: sticky;
  top: 0;
  z-index: 110;
  background: var(--paper);
  border-bottom: 1px solid var(--rule);
}
.masthead-in {
  max-width: var(--page);
  margin: 0 auto;
  padding: 0 var(--gutter);
  height: 62px;
  display: flex;
  align-items: center;
  gap: 26px;
}

.wordmark {
  display: inline-flex;
  align-items: baseline;
  gap: 9px;
  text-decoration: none;
  font-family: var(--display);
  font-size: 20px;
  line-height: 1;
  letter-spacing: -0.015em;
}
.wordmark .rule-dot { width: 7px; height: 7px; background: var(--ink); display: inline-block; }

.nav { display: flex; align-items: center; gap: 22px; margin-left: auto; }
.nav a {
  text-decoration: none;
  font-size: 14.5px;
  color: var(--ink-2);
  padding: 3px 0;
  border-bottom: 1px solid transparent;
}
.nav a:hover { color: var(--ink); border-bottom-color: var(--ink); }
.nav a[aria-current="page"] { color: var(--ink); border-bottom-color: var(--rule); }

.head-tools { display: flex; align-items: center; gap: 6px; }

.iconbtn {
  appearance: none;
  border: 1px solid var(--rule);
  background: transparent;
  color: var(--ink-2);
  width: 34px; height: 34px;
  display: grid; place-items: center;
  cursor: pointer;
  padding: 0;
  font: inherit;
}
.iconbtn:hover { background: var(--paper-2); color: var(--ink); }
.iconbtn svg { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 1.5; }
.iconbtn[aria-pressed="true"] { background: var(--ink); color: var(--paper); border-color: var(--ink); }

.searchbtn {
  display: inline-flex; align-items: center; gap: 10px;
  height: 34px; padding: 0 10px 0 11px;
  border: 1px solid var(--rule);
  background: transparent;
  color: var(--muted);
  font: inherit; font-size: 13.5px;
  cursor: pointer;
}
.searchbtn:hover { background: var(--paper-2); color: var(--ink); }
.searchbtn kbd {
  font-family: var(--mono);
  font-size: 10.5px;
  border: 1px solid var(--rule);
  padding: 1px 5px;
  color: var(--faint);
}
@media (max-width: 720px) { .searchbtn kbd { display: none; } }

.menubtn { display: none; }
@media (max-width: 900px) {
  .nav { display: none; }
  .menubtn { display: grid; }
}

/* mobile drawer */
.drawer {
  position: fixed;
  inset: 0;
  z-index: 130;
  background: var(--paper);
  display: flex;
  flex-direction: column;
  padding: 0 var(--gutter) 32px;
}
.drawer[hidden] { display: none; }
.drawer-top { height: 62px; display: flex; align-items: center; border-bottom: 1px solid var(--rule); }
.drawer-top .iconbtn { margin-left: auto; }
.drawer nav { display: flex; flex-direction: column; padding-top: 8px; }
.drawer nav a {
  text-decoration: none;
  font-family: var(--display);
  font-size: 25px;
  padding: 16px 0;
  border-bottom: 1px solid var(--rule-soft);
}
.drawer nav a:hover { color: var(--accent); }

/* ─────────────────────────── buttons ─────────────────────────── */

.btn {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 13px 22px;
  border: 1px solid var(--ink);
  background: transparent;
  color: var(--ink);
  font: inherit;
  font-size: 15px;
  text-decoration: none;
  cursor: pointer;
}
.btn:hover { background: var(--ink); color: var(--paper); }
.btn-solid { background: var(--ink); color: var(--paper); }
.btn-solid:hover { background: var(--ink-2); border-color: var(--ink-2); }
.btn-quiet { border-color: var(--rule); color: var(--ink-2); }
.btn-quiet:hover { background: var(--paper-2); color: var(--ink); border-color: var(--rule); }
.btn:disabled { opacity: 0.45; cursor: not-allowed; }
.btn:disabled:hover { background: transparent; color: var(--ink); }

.btnrow { display: flex; flex-wrap: wrap; gap: 12px; }

/* ─────────────────────────── hero ─────────────────────────── */

.hero { padding-top: clamp(38px, 5.4vw, 68px); padding-bottom: clamp(32px, 4vw, 50px); }
.hero-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 420px);
  gap: 0 56px;
  align-items: end;
}
/* A strip across the foot of the landing rather than a column beside it:
   the pictures need the height more than the list does. */
.hero-index {
  border-top: 1px solid var(--rule);
  padding-top: 14px;
  margin-top: clamp(28px, 3.2vw, 42px);
}
.hero-index ol {
  display: flex; flex-wrap: wrap;
  list-style: none; margin: 10px 0 0; padding: 0; counter-reset: hi;
}
.hero-index li {
  counter-increment: hi;
  flex: 1 1 180px;
  border-left: 1px solid var(--rule-soft);
}
.hero-index li:first-child { border-left: 0; }
.hero-index a {
  display: flex; gap: 12px; align-items: baseline;
  padding: 7px 18px; text-decoration: none; font-size: 14.5px; color: var(--ink-2);
}
.hero-index li:first-child a { padding-left: 0; }
.hero-index a::before {
  content: counter(hi, decimal-leading-zero);
  font-family: var(--mono); font-size: 10.5px; color: var(--faint);
}
.hero-index a:hover { color: var(--ink); }
@media (max-width: 640px) {
  .hero-index li { flex-basis: 100%; border-left: 0; border-bottom: 1px solid var(--rule-soft); }
  .hero-index a, .hero-index li:first-child a { padding: 8px 0; }
}
@media (max-width: 1000px) {
  .hero-grid { grid-template-columns: 1fr; gap: 40px 0; }
  .hero-side { max-width: 560px; }
}
.hero h1 { max-width: 15ch; }
.hero .lede { margin-top: 26px; }
.hero .btnrow { margin-top: 34px; }
.hero-meta {
  margin-top: 30px;
  display: flex;
  flex-wrap: wrap;
  gap: 8px 28px;
  font-family: var(--mono);
  font-size: 11.5px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
}

/* ─────────────────────────── figures ─────────────────────────── */

.figure { border: 1px solid var(--rule); background: var(--paper-2); }
.figure-media { position: relative; background: var(--paper-2); }
.figure-media img { width: 100%; height: auto; }
.figure figcaption {
  border-top: 1px solid var(--rule);
  padding: 12px 16px;
  font-size: 13.5px;
  color: var(--muted);
  display: flex;
  gap: 14px;
  align-items: baseline;
}
.figure figcaption b { font-weight: 600; color: var(--ink-2); }

/* skeleton, shown until the real capture has decoded */
.skeleton {
  position: absolute;
  inset: 0;
  background: var(--paper-3);
  overflow: hidden;
}
.skeleton::after {
  content: '';
  position: absolute;
  inset: 0;
  transform: translateX(-100%);
  background: linear-gradient(90deg, transparent, rgba(255,255,255,0.22), transparent);
  animation: sweep 1.25s infinite;
}
[data-theme="dark"] .skeleton::after {
  background: linear-gradient(90deg, transparent, rgba(255,255,255,0.06), transparent);
}
@keyframes sweep { to { transform: translateX(100%); } }
.is-loaded .skeleton { display: none; }
.figure-media img { opacity: 0; }
.is-loaded .figure-media img { opacity: 1; }
.no-js .figure-media img { opacity: 1; }
.no-js .skeleton { display: none; }

/* ─────────────────────────── feature rows ─────────────────────────── */

/* Alternating full-width rows, not a grid of equal cards. */
.rows { border-top: 1px solid var(--rule); }
.rows .row:first-child { padding-top: clamp(30px, 3.4vw, 48px); }
.row {
  display: grid;
  grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
  gap: 0 56px;
  align-items: center;
  padding: clamp(40px, 5vw, 72px) 0;
  border-bottom: 1px solid var(--rule-soft);
}
.row:nth-child(even) .row-text { order: 2; }
.row:nth-child(even) .row-media { order: 1; }
@media (max-width: 900px) {
  .row { grid-template-columns: 1fr; gap: 26px; }
  .row:nth-child(even) .row-text,
  .row:nth-child(even) .row-media { order: initial; }
}
.row-text h2 { margin: 10px 0 14px; }
.row-text p { color: var(--ink-2); max-width: 46ch; }

/* A plain definition list reads better than a wall of ticks. */
.deflist { margin: 18px 0 0; border-top: 1px solid var(--rule-soft); }
.deflist div {
  display: grid;
  grid-template-columns: 132px minmax(0, 1fr);
  gap: 18px;
  padding: 11px 0;
  border-bottom: 1px solid var(--rule-soft);
}
.deflist dt { font-family: var(--mono); font-size: 11px; letter-spacing: 0.08em; text-transform: uppercase; color: var(--muted); padding-top: 3px; }
.deflist dd { margin: 0; font-size: 15px; color: var(--ink-2); }
@media (max-width: 560px) {
  .deflist div { grid-template-columns: 1fr; gap: 2px; }
}

/* ─────────────────────────── tables ─────────────────────────── */

.table { width: 100%; border-collapse: collapse; font-size: 14.5px; }
.table th, .table td { text-align: left; padding: 11px 14px 11px 0; border-bottom: 1px solid var(--rule-soft); vertical-align: top; }
.table th {
  font-family: var(--mono); font-weight: 500; font-size: 11px;
  letter-spacing: 0.09em; text-transform: uppercase; color: var(--muted);
  border-bottom-color: var(--rule);
}
.table td b { font-weight: 600; }
.table-scroll { overflow-x: auto; }

/* ─────────────────────────── steps ─────────────────────────── */

.steps { counter-reset: step; border-top: 1px solid var(--rule); }
.steps > li {
  list-style: none;
  counter-increment: step;
  display: grid;
  grid-template-columns: var(--rail) minmax(0, 1fr);
  gap: 0 48px;
  padding: 30px 0;
  border-bottom: 1px solid var(--rule-soft);
}
.steps > li::before {
  content: counter(step, decimal-leading-zero);
  font-family: var(--mono);
  font-size: 12px;
  color: var(--faint);
  letter-spacing: 0.08em;
  padding-top: 4px;
}
.steps h3 { margin-bottom: 6px; }
.steps p { color: var(--ink-2); max-width: 52ch; margin: 0; }
.steps { padding-left: 0; margin: 0; }
@media (max-width: 860px) {
  .steps > li { grid-template-columns: 1fr; gap: 8px; }
}

/* ─────────────────────────── FAQ ─────────────────────────── */

.faq { border-top: 1px solid var(--rule); }
.faq details { border-bottom: 1px solid var(--rule-soft); }
.faq summary {
  cursor: pointer;
  list-style: none;
  padding: 20px 40px 20px 0;
  position: relative;
  font-size: 17px;
  color: var(--ink);
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary:hover { color: var(--accent); }
.faq summary::after {
  content: '';
  position: absolute;
  right: 6px; top: 50%;
  width: 11px; height: 11px;
  border-right: 1px solid currentColor;
  border-bottom: 1px solid currentColor;
  transform: translateY(-70%) rotate(45deg);
}
.faq details[open] summary::after { transform: translateY(-30%) rotate(-135deg); }
.faq .answer { padding: 0 0 22px; color: var(--ink-2); max-width: 60ch; }

/* ─────────────────────────── code + copy ─────────────────────────── */

.codeblock { border: 1px solid var(--rule); background: var(--paper-2); }
.codeblock-top {
  display: flex; align-items: center; justify-content: space-between;
  padding: 8px 10px 8px 14px;
  border-bottom: 1px solid var(--rule);
  font-family: var(--mono); font-size: 11px;
  letter-spacing: 0.08em; text-transform: uppercase; color: var(--muted);
}
.codeblock pre {
  margin: 0;
  padding: 16px;
  overflow-x: auto;
  font-family: var(--mono);
  font-size: 13px;
  line-height: 1.65;
  color: var(--ink-2);
}
.copybtn {
  appearance: none; border: 1px solid var(--rule); background: transparent;
  color: var(--ink-2); font: inherit; font-family: var(--mono);
  font-size: 11px; letter-spacing: 0.08em; text-transform: uppercase;
  padding: 5px 10px; cursor: pointer;
}
.copybtn:hover { background: var(--ink); color: var(--paper); border-color: var(--ink); }
.copybtn[data-state="done"] { color: var(--ok); border-color: var(--ok); }
.copybtn[data-state="done"]:hover { background: var(--ok); color: var(--paper); }

/* ─────────────────────────── forms ─────────────────────────── */

.field { margin-bottom: 18px; }
.field label {
  display: block;
  font-family: var(--mono); font-size: 11px; letter-spacing: 0.09em;
  text-transform: uppercase; color: var(--muted); margin-bottom: 6px;
}
.field input, .field textarea, .field select {
  width: 100%;
  font: inherit;
  font-size: 15px;
  color: var(--ink);
  background: var(--paper);
  border: 1px solid var(--rule);
  padding: 11px 12px;
}
.field textarea { min-height: 132px; resize: vertical; }
.field input:focus, .field textarea:focus { border-color: var(--ink); outline: none; }
.field[data-invalid] input, .field[data-invalid] textarea { border-color: var(--warn); }
.field .hint { font-size: 13px; color: var(--muted); margin-top: 6px; }
.field .err { font-size: 13px; color: var(--warn); margin-top: 6px; display: none; }
.field[data-invalid] .err { display: block; }

.pw-wrap { position: relative; display: flex; }
.pw-wrap input { padding-right: 84px; }
.pw-toggle {
  position: absolute; right: 1px; top: 1px; bottom: 1px;
  border: 0; border-left: 1px solid var(--rule);
  background: transparent; color: var(--muted);
  font: inherit; font-family: var(--mono); font-size: 10.5px;
  letter-spacing: 0.08em; text-transform: uppercase;
  padding: 0 12px; cursor: pointer;
}
.pw-toggle:hover { background: var(--paper-2); color: var(--ink); }

.formnote {
  border: 1px solid var(--rule);
  padding: 14px 16px;
  font-size: 14.5px;
  margin-bottom: 20px;
  display: none;
}
.formnote[data-show] { display: block; }
.formnote[data-kind="ok"] { border-color: var(--ok); color: var(--ok); }
.formnote[data-kind="error"] { border-color: var(--warn); color: var(--warn); }

/* ─────────────────────────── modal ─────────────────────────── */

.modal-back {
  position: fixed; inset: 0; z-index: 140;
  background: rgba(20, 19, 15, 0.42);
  display: grid; place-items: center;
  padding: 24px;
}
[data-theme="dark"] .modal-back { background: rgba(0, 0, 0, 0.6); }
.modal-back[hidden] { display: none; }
.modal {
  background: var(--paper);
  border: 1px solid var(--ink);
  max-width: 460px;
  width: 100%;
  padding: 26px;
}
.modal h3 { font-size: 20px; margin-bottom: 10px; }
.modal p { color: var(--ink-2); font-size: 15px; }
.modal .btnrow { margin-top: 22px; justify-content: flex-end; }

/* search panel */
.search-back { align-items: start; padding-top: 12vh; }
.search-panel {
  background: var(--paper);
  border: 1px solid var(--ink);
  width: 100%;
  max-width: 620px;
}
.search-panel input {
  width: 100%; border: 0; border-bottom: 1px solid var(--rule);
  background: transparent; color: var(--ink);
  font: inherit; font-size: 18px; padding: 18px 20px;
}
.search-panel input:focus { outline: none; }
.search-results { max-height: 54vh; overflow-y: auto; }
.search-results a {
  display: block; text-decoration: none;
  padding: 13px 20px; border-bottom: 1px solid var(--rule-soft);
}
.search-results a:hover, .search-results a[data-active] { background: var(--paper-2); }
.search-results .r-title { display: block; font-size: 15.5px; line-height: 1.35; }
.search-results .r-page {
  display: block;
  font-family: var(--mono); font-size: 10.5px; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--faint); margin-bottom: 4px;
}
.search-results .r-text {
  display: block; font-size: 13.5px; line-height: 1.5;
  color: var(--muted); margin-top: 4px;
  overflow: hidden; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
}
.search-empty { padding: 22px 20px; color: var(--muted); font-size: 14.5px; }
.search-foot {
  border-top: 1px solid var(--rule);
  padding: 9px 20px;
  font-family: var(--mono); font-size: 10.5px;
  letter-spacing: 0.08em; text-transform: uppercase; color: var(--faint);
  display: flex; gap: 18px;
}

/* ─────────────────────────── floating controls ─────────────────────────── */

.floats {
  position: fixed;
  right: 20px; bottom: 20px;
  z-index: 100;
  display: flex; flex-direction: column; gap: 8px; align-items: flex-end;
}
.float {
  border: 1px solid var(--ink);
  background: var(--paper);
  color: var(--ink);
  font: inherit; font-size: 13.5px;
  padding: 10px 15px;
  cursor: pointer;
  display: inline-flex; align-items: center; gap: 9px;
}
.float:hover { background: var(--ink); color: var(--paper); }
.float svg { width: 14px; height: 14px; fill: none; stroke: currentColor; stroke-width: 1.6; }
.float[hidden] { display: none; }
.float-top { padding: 10px 12px; }

/* ─────────────────────────── cookie notice ─────────────────────────── */

.cookie {
  position: fixed;
  left: 20px; bottom: 20px;
  z-index: 105;
  max-width: 420px;
  background: var(--paper);
  border: 1px solid var(--ink);
  padding: 18px 20px;
}
.cookie[hidden] { display: none; }
.cookie p { font-size: 14px; color: var(--ink-2); margin-bottom: 14px; }
.cookie .btnrow .btn { padding: 8px 14px; font-size: 13.5px; }
@media (max-width: 620px) {
  .cookie { left: 12px; right: 12px; bottom: 12px; max-width: none; }
  .floats { right: 12px; bottom: 12px; }
}

/* ─────────────────────────── footer ─────────────────────────── */

.foot { border-top: 1px solid var(--rule); margin-top: 0; }
.foot-in {
  max-width: var(--page); margin: 0 auto; padding: 54px var(--gutter) 40px;
  display: grid; grid-template-columns: minmax(0, 2fr) repeat(2, minmax(0, 1fr));
  gap: 40px;
}
@media (max-width: 760px) { .foot-in { grid-template-columns: 1fr 1fr; } .foot-brand { grid-column: 1 / -1; } }
.foot h4 {
  font-family: var(--mono); font-size: 11px; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--muted); margin-bottom: 12px; font-weight: 500;
}
.foot ul { list-style: none; margin: 0; padding: 0; }
.foot li { margin-bottom: 8px; }
.foot a { text-decoration: none; font-size: 14.5px; color: var(--ink-2); border-bottom: 1px solid transparent; }
.foot a:hover { color: var(--ink); border-bottom-color: var(--ink); }
.foot-brand p { font-size: 14px; color: var(--muted); max-width: 34ch; margin-top: 12px; }
.foot-base {
  border-top: 1px solid var(--rule-soft);
  max-width: var(--page); margin: 0 auto;
  padding: 16px var(--gutter) 34px;
  display: flex; flex-wrap: wrap; gap: 8px 22px;
  font-size: 13px; color: var(--faint);
}

/* ─────────────────────────── reveal ─────────────────────────── */

/* Entrance only. Nothing here fires on hover. */
[data-reveal] { opacity: 0; }
.no-js [data-reveal], .revealed { opacity: 1; }

/* ─────────────────────────── legal pages ─────────────────────────── */

.legal-head { padding-top: clamp(44px, 6vw, 76px); padding-bottom: 30px; }
.updated {
  font-family: var(--mono); font-size: 11px; letter-spacing: 0.09em;
  text-transform: uppercase; color: var(--muted); margin-top: 14px;
}
.toc { border: 1px solid var(--rule); padding: 18px 20px; margin-bottom: 34px; }
.toc h4 { font-family: var(--mono); font-size: 11px; letter-spacing: 0.1em; text-transform: uppercase; color: var(--muted); margin: 0 0 10px; font-weight: 500; }
.toc ol { margin: 0; padding-left: 1.2em; }
.toc li { margin-bottom: 5px; font-size: 14.5px; }
.toc a { text-decoration: none; }
.toc a:hover { text-decoration: underline; }

/* ─────────────────────────── motion ───────────────────────────

   Everything below is entrance, scroll or ambient motion. Nothing in this
   file fires on hover: pointing at the page never makes it move. All of it
   is switched off by the reduced-motion rule near the top of the file.
   ============================================================== */

@keyframes drift      { from { transform: translateX(0); }      to { transform: translateX(-50%); } }
@keyframes drift-rev  { from { transform: translateX(-50%); }   to { transform: translateX(0); } }
@keyframes run        { from { transform: translateX(-100%); }   to { transform: translateX(calc(100vw + 100%)); } }
@keyframes draw-x     { from { transform: scaleX(0); }          to { transform: scaleX(1); } }
@keyframes draw-y     { from { transform: scaleY(0); }          to { transform: scaleY(1); } }
@keyframes swipe      { from { transform: scaleX(0); }          to { transform: scaleX(1); } }
@keyframes drop-in    { from { transform: translateY(-100%); }  to { transform: translateY(0); } }
@keyframes blink      { 0%, 62% { opacity: 1; } 63%, 100% { opacity: 0.18; } }

/* ── announcement banner ───────────────────────────────────────
   A thin strip above the masthead. Dismissed once and it stays dismissed. */

.announce {
  position: relative;
  background: var(--ink);
  color: var(--paper);
  border-bottom: 1px solid var(--ink);
  animation: drop-in 620ms cubic-bezier(.22,.68,.28,1) both;
}
.announce-in {
  display: flex; align-items: center; gap: 14px;
  padding: 9px var(--gutter);
  font-size: 13.5px;
}
.announce-in p { margin: 0; color: var(--paper); }
.announce-tag {
  font-family: var(--mono); font-size: 10px; letter-spacing: 0.12em;
  text-transform: uppercase;
  background: var(--red); color: #fff; border: 1px solid var(--red); padding: 2px 7px;
  flex: none;
  animation: blink 2.6s steps(1, end) infinite;
}
.announce-in a { color: var(--paper); text-underline-offset: 3px; }
.announce-in a:hover { color: var(--paper); text-decoration-thickness: 2px; }
.announce-x {
  margin-left: auto; flex: none;
  color: var(--paper); border-color: transparent; background: none;
}
.announce-x:hover { border-color: var(--paper); }
/* A tick that keeps travelling under the strip, so it reads as live rather
   than static. One short bar, no gradient. */
.announce { overflow: hidden; }
.announce::after {
  content: ''; position: absolute; left: 0; bottom: 0; height: 2px; width: 88px;
  background: var(--red); opacity: 0.9;
  animation: run 4.2s cubic-bezier(.55,0,.45,1) infinite;
}
@media (max-width: 720px) {
  .announce-in { font-size: 12.5px; gap: 10px; }
  .announce-in a { display: none; }
}

/* ── ticker ────────────────────────────────────────────────────
   A band of words that keeps moving. The track is duplicated in script, so
   the loop is seamless and the markup only lists each word once. */

.ticker {
  border-block: 1px solid var(--rule);
  background: var(--paper-2);
  overflow: hidden;
  padding: 11px 0;
}
.ticker-track {
  display: flex; width: max-content;
  animation: drift 42s linear infinite;
  will-change: transform;
}
.ticker--rev .ticker-track { animation-name: drift-rev; }
.ticker--slow .ticker-track { animation-duration: 66s; }
.ticker-track span {
  font-family: var(--mono); font-size: 11.5px; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--muted);
  padding: 0 20px;
  display: inline-flex; align-items: center; gap: 20px;
  white-space: nowrap;
}
.ticker-track span::after {
  content: ''; width: 5px; height: 5px; background: var(--rule); flex: none;
}

/* ── statistics band ───────────────────────────────────────────
   Numbers that count up the first time they come into view. */

.statband { border-block: 1px solid var(--rule); background: var(--paper-2); }
.statband-in {
  max-width: var(--page); margin: 0 auto;
  padding: clamp(30px, 4vw, 46px) var(--gutter);
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
}
.stat { padding: 4px 26px 4px 0; }
.stat + .stat { border-left: 1px solid var(--rule); padding-left: 26px; }
/* The number sits in a b, the caption in a direct span. Keeping the caption
   rule to a direct child stops it from restyling the number inside the b. */
.stat b {
  display: block;
  font-family: var(--display);
  font-size: clamp(30px, 3.6vw, 44px);
  line-height: 1.1; font-weight: 400;
}
.stat > span {
  display: block; margin-top: 10px;
  font-family: var(--mono); font-size: 11px; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--muted);
}
.stat-line {
  display: block; height: 2px; width: 100%; margin-top: 16px;
  background: var(--red); transform: scaleX(0); transform-origin: left;
}
.revealed .stat-line, .stat.drawn .stat-line { animation: draw-x 780ms cubic-bezier(.22,.68,.28,1) forwards; }

/* ── pull quote ────────────────────────────────────────────────*/

.quote {
  max-width: 30ch;
  font-family: var(--display);
  font-size: clamp(21px, 2.5vw, 31px);
  line-height: 1.32;
}
.quote-rule {
  height: 3px; background: var(--red); margin-top: 22px;
  transform: scaleX(0); transform-origin: left;
}
.revealed .quote-rule { animation: draw-x 900ms 120ms cubic-bezier(.22,.68,.28,1) forwards; }
.quote-by {
  font-family: var(--mono); font-size: 11px; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--muted); margin-top: 14px;
}

/* ── marker highlight ──────────────────────────────────────────
   A highlighter pass behind a few words, drawn in when the line arrives. */

/* The highlighter rides on each split word, so a phrase that breaks over two
   lines gets two strokes rather than one box behind the lot. */
.mark .word { position: relative; z-index: 0; }
.mark .word::before {
  content: ''; position: absolute; z-index: -1;
  left: -0.2em; right: -0.2em; top: 0.17em; bottom: 0.05em;
  background: var(--mark); opacity: 0.26;
  transform: scaleX(0); transform-origin: left;
}
.revealed .mark .word::before {
  animation: swipe 460ms cubic-bezier(.22,.68,.28,1) forwards;
  animation-delay: calc(var(--n, 0) * 42ms + 300ms);
}
[data-theme="dark"] .mark .word::before { opacity: 0.32; }

/* ── rules that draw themselves ────────────────────────────────*/

[data-draw] { transform: scaleX(0); transform-origin: left; }
[data-draw].drawn { animation: draw-x 760ms cubic-bezier(.22,.68,.28,1) forwards; }
.no-js [data-draw] { transform: none; }

.band-rule { height: 1px; background: var(--rule); margin-bottom: clamp(26px, 3vw, 40px); }

/* ── the spine beside a run of rows ────────────────────────────
   A hairline down the left of the section that fills as you scroll it. */

.rows { position: relative; }
@media (min-width: 1000px) {
  .rows::before, .rows::after {
    content: ''; position: absolute; left: -26px; top: 4px; bottom: 4px; width: 1px;
  }
  .rows::before { background: var(--rule-soft); }
  .rows::after {
    background: var(--red);
    transform: scaleY(var(--spine, 0)); transform-origin: top;
  }
}

/* ── figure parallax ───────────────────────────────────────────
   A few pixels of drift, enough to feel alive and not enough to distract. */

[data-parallax] img { transform: translate3d(0, var(--par, 0px), 0); }

/* ── reveal variants ───────────────────────────────────────────*/

[data-reveal="wipe"] .figure-media,
[data-reveal="wipe"] > img { clip-path: inset(0 100% 0 0); }
[data-reveal="wipe"].revealed .figure-media,
[data-reveal="wipe"].revealed > img { clip-path: inset(0 0 0 0); transition: clip-path 820ms cubic-bezier(.22,.68,.28,1); }
.no-js [data-reveal="wipe"] .figure-media { clip-path: none; }

/* Word by word, in the spirit of an anime.js stagger. The words are wrapped
   in script, so the copy in the markup stays a plain sentence. */
.word { display: inline-block; will-change: transform; }
[data-reveal="words"] .word { opacity: 0; }
.no-js [data-reveal="words"] .word, [data-reveal="words"].done .word { opacity: 1; }

/* ── scroll spy ────────────────────────────────────────────────*/

.hero-index a, .toc a { position: relative; }
.hero-index li.is-active a, .toc li.is-active a { color: var(--accent); }
.hero-index li.is-active::marker { color: var(--accent); }
.hero-index li a::after, .toc li a::after {
  content: ''; position: absolute; left: 0; right: 0; bottom: -3px; height: 1px;
  background: var(--accent); transform: scaleX(0); transform-origin: left;
}
.hero-index li.is-active a::after, .toc li.is-active a::after {
  animation: draw-x 420ms cubic-bezier(.22,.68,.28,1) forwards;
}

/* ── section numbers ───────────────────────────────────────────
   The 01, 02, 03 beside each row get a box that draws itself. */

.num { position: relative; display: inline-block; }
.num::after {
  content: ''; position: absolute; left: -8px; right: -8px; bottom: -4px; height: 1px;
  background: var(--red); transform: scaleX(0); transform-origin: left;
}
.revealed .num::after { animation: draw-x 620ms 120ms cubic-bezier(.22,.68,.28,1) forwards; }

/* ─────────────────────────── the feature deck ───────────────────────────

   One feature at a time in an outlined card, with a button at the bottom
   right that walks through the rest. The old page had all six stacked, each
   one small and the whole thing long; this gives every feature the width of
   the page and lets somebody read only the one they came for.

   Without script every slab is simply on the page, stacked, and the control
   bar is hidden. Nothing here is behind a button that cannot be pressed.
   ======================================================================== */

.deck-wrap { padding-bottom: clamp(40px, 5vw, 72px); }

.deck {
  border: 1px solid var(--ink);
  background: var(--paper);
  position: relative;
}

.slab {
  padding: clamp(26px, 3.6vw, 48px);
}
/* Stacked, they need a rule between them. Stepped, only one is ever shown. */
.slab + .slab { border-top: 1px solid var(--rule); }
.deck[data-stepped="yes"] .slab { display: none; border-top: 0; }
.deck[data-stepped="yes"] .slab[data-on] { display: block; }

.slab-num {
  display: flex; align-items: center; gap: 12px;
  margin: 0 0 18px;
  font-family: var(--mono); font-size: 11px; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--muted);
}
.slab-num .n { font-size: 15px; color: var(--red); font-weight: 500; letter-spacing: 0.04em; }
.slab-num .tag {
  margin-left: auto;
  border: 1px solid var(--rule); padding: 3px 10px;
  color: var(--ink-2);
}

.slab h2 { max-width: 20ch; }
.slab-lede {
  margin: 16px 0 0;
  font-size: clamp(16px, 1.5vw, 18.5px);
  line-height: 1.55;
  color: var(--ink-2);
  max-width: 62ch;
}

/* The whole point of the rework: the capture gets the width of the page. */
.slab-shot { margin-top: clamp(22px, 2.6vw, 34px); }
.slab-shot .figure-media { background: var(--paper-2); }
.slab-shot figcaption { font-size: 14px; }

.slab-list { margin-top: clamp(22px, 2.6vw, 32px); }
.slab .table-scroll { margin-top: clamp(22px, 2.6vw, 32px); }

.slab-quote {
  margin: clamp(22px, 2.6vw, 32px) 0 0;
  padding: 0 0 0 20px;
  border-left: 1px solid var(--red);
  font-family: var(--display);
  font-size: clamp(19px, 2vw, 26px);
  line-height: 1.35;
  max-width: 30ch;
}

/* ── the control bar ── */

.deck-bar {
  display: flex; align-items: center; gap: 20px; flex-wrap: wrap;
  border: 1px solid var(--ink); border-top: 0;
  padding: 14px clamp(18px, 2.4vw, 26px);
  background: var(--paper-2);
}
.deck-bar[hidden] { display: none; }

.deck-dots { display: flex; gap: 7px; list-style: none; margin: 0; padding: 0; }
.deck-dots li { display: block; }
.deck-dots button {
  display: block;
  width: 26px; height: 4px; padding: 0;
  border: 0; background: var(--rule);
  cursor: pointer;
}
.deck-dots button[aria-current="true"] { background: var(--red); }

/* The button that walks through them, at the bottom right. */
.deck-nav { margin-left: auto; display: flex; gap: 10px; align-items: center; }
.deck-nav .btn { white-space: nowrap; }
.deck-nav .btn[disabled] { opacity: 0.4; cursor: not-allowed; }

@media (max-width: 620px) {
  .deck-bar { gap: 14px; }
  .deck-nav { margin-left: 0; width: 100%; }
  .deck-nav .btn { flex: 1; }
}

/* ─────────────────────────── the intro ───────────────────────────

   A blank screen with one line on it. Scroll and the line leaves, the next
   one arrives, and at the end the site itself rises into place. The whole
   thing is scrubbed from the scroll position, so it never runs away from you
   and scrolling back plays it backwards.
   ================================================================= */

@keyframes fall {
  from { transform: translateY(-9px); opacity: 0; }
  40%  { opacity: 1; }
  to   { transform: translateY(13px); opacity: 0; }
}

.prologue { position: relative; height: 470vh; }

.prologue-stage {
  position: sticky; top: 0;
  height: 100vh;
  display: grid; place-items: center;
  z-index: 200;
}
/* The backdrop is a layer of its own. Fading the stage itself would take the
   shards with it, and they have to survive over the page coming up behind. */
.prologue-stage::before {
  content: ''; position: absolute; inset: 0; z-index: -1;
  background: var(--paper-0);
  opacity: var(--stage, 1);
}
.intro-over .prologue-stage { pointer-events: none; }

.prologue-lines {
  display: grid;
  width: min(100%, 1040px);
  padding: 0 var(--gutter);
}
.prologue-line {
  grid-area: 1 / 1;
  place-self: center;
  margin: 0;
  max-width: 19ch;
  font-family: var(--display);
  font-size: clamp(27px, 4.3vw, 60px);
  line-height: 1.22;
  text-align: center;
  opacity: 0;
  will-change: transform, opacity;
  /* The one shadow on the site. It belongs to the intro, where the type is
     doing all the work and needs to lift off an otherwise empty screen. */
  text-shadow: 0 16px 38px rgba(27, 26, 22, 0.17), 0 2px 0 rgba(27, 26, 22, 0.07);
}
[data-theme="dark"] .prologue-line {
  text-shadow: 0 18px 44px rgba(0, 0, 0, 0.66), 0 2px 0 rgba(0, 0, 0, 0.45);
}
.prologue-brand {
  max-width: none;
  font-size: clamp(46px, 9.5vw, 124px);
  line-height: 1;
}
/* Without script the lines cannot be scrubbed, so they read as a plain
   opening statement instead of a stack of overlapping type. */
.no-js .prologue { height: auto; }
.no-js .prologue-stage { position: static; height: auto; padding: 11vh 0 7vh; background: var(--paper-0); }
.no-js .prologue-stage::before { display: none; }
.no-js .prologue-lines { display: block; text-align: center; }
.no-js .prologue-line {
  opacity: 1; max-width: 30ch; margin: 0 auto 30px;
  font-size: clamp(21px, 3vw, 33px); text-shadow: none;
}
.no-js .prologue-brand { font-size: clamp(34px, 6vw, 62px); }
.no-js .prologue-foot { position: static; margin-top: 24px; }
.no-js .prologue-dots, .no-js .prologue-hint { display: none; }

.prologue-foot {
  opacity: var(--stage, 1);
  position: absolute; left: 0; right: 0; bottom: 30px;
  display: flex; align-items: center; justify-content: center;
  gap: 22px; flex-wrap: wrap;
  padding: 0 var(--gutter);
}
.prologue-dots { display: flex; gap: 7px; list-style: none; margin: 0; padding: 0; }
.prologue-dots li { width: 20px; height: 2px; background: var(--rule); }
.prologue-dots li.on { background: var(--ink); }
.prologue-hint {
  margin: 0; display: inline-flex; align-items: center; gap: 11px;
  font-family: var(--mono); font-size: 10.5px; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--muted);
}
.prologue-hint-rule {
  display: block; width: 1px; height: 15px; background: var(--muted);
  animation: fall 2s cubic-bezier(.5,0,.5,1) infinite;
}
.prologue-skip {
  font-family: var(--mono); font-size: 10.5px; letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--muted);
  background: none; border: 1px solid var(--rule);
  padding: 7px 13px; cursor: pointer;
}
.prologue-skip:hover { color: var(--ink); border-color: var(--ink); }

/* The closing word breaks into its own pixels and blows apart. The squares
   are built in script from a rasterisation of the word itself, so they are
   the letters rather than a decoration standing in for them. */
.pixels { position: absolute; pointer-events: none; z-index: 2; }
.pixel {
  position: absolute; display: block;
  width: var(--s); height: var(--s);
  background: var(--ink);
  opacity: 0;
  will-change: transform, opacity;
}
.pixel.hot { background: var(--mark); }
.shattered .prologue-brand { opacity: 0 !important; transition: opacity 190ms linear; }

/* While the intro plays the site is held back, then lifted into place. */
.has-intro .masthead,
.has-intro .announce,
.has-intro .floats { opacity: var(--rise, 1); }
.has-intro main { opacity: var(--rise, 1); }
.has-intro:not(.intro-over) main { transform: translateY(calc((1 - var(--rise, 1)) * 52px)); }
.no-js .has-intro main, .no-js .has-intro .masthead { opacity: 1; }

@media (max-width: 720px) {
  .prologue { height: 430vh; }
  /* A phone has the height but not the width, so the line runs shorter and
     larger rather than small and wide. */
  .prologue-line { font-size: clamp(30px, 8.4vw, 42px); max-width: 14ch; }
  .prologue-brand { font-size: clamp(52px, 15vw, 88px); max-width: none; }
  .prologue-foot { gap: 14px; bottom: 22px; }
  .prologue-hint { display: none; }
}

/* Nothing to scrub through if motion is unwelcome: the lines simply read as
   a short opening statement and the site follows. */
@media (prefers-reduced-motion: reduce) {
  .prologue { height: auto; }
  .prologue-stage { position: static; height: auto; padding: 12vh 0 8vh; background: var(--paper-0); }
  .prologue-stage::before, .pixels { display: none; }
  .prologue-lines { display: block; text-align: center; }
  .prologue-line {
    opacity: 1 !important; transform: none !important;
    max-width: 30ch; margin: 0 auto 30px;
    font-size: clamp(21px, 3vw, 33px);
    text-shadow: none;
  }
  .prologue-brand { font-size: clamp(34px, 6vw, 62px); }
  .prologue-foot { position: static; margin-top: 26px; }
  .prologue-dots { display: none; }
  .has-intro main, .has-intro .masthead, .has-intro .announce, .has-intro .floats {
    opacity: 1 !important; transform: none !important;
  }
}

/* ─────────────────────────── the landing ───────────────────────────

   The hero carries the product rather than describing it: one large capture
   and a pair beneath, all of them real pages.
   =================================================================== */

.hero-side { align-self: end; }
.hero-stack { display: grid; gap: 11px; }
.shot-pair { display: grid; grid-template-columns: 1fr 1fr; gap: 11px; }

.figure-tight figcaption {
  padding: 9px 12px;
  gap: 10px;
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}
.figure-tight figcaption b { font-weight: 500; color: var(--ink); }
.figure-tight figcaption span { color: var(--muted); }
.shot-pair .figure-tight figcaption { padding: 7px 9px; font-size: 9px; letter-spacing: 0.07em; }
.shot-pair .figure-tight figcaption span { display: none; }

/* ─────────────────────────── print ─────────────────────────── */

@media print {
  :root { --paper: #fff; --ink: #000; --ink-2: #222; --muted: #444; --rule: #999; --rule-soft: #ccc; }
  .masthead, .floats, .cookie, .progress, .skip, .drawer, .modal-back,
  .search-back, .btnrow, .skeleton, .searchbtn, .head-tools,
  .announce, .ticker, .statband, .prologue { display: none !important; }
  .word, [data-reveal], [data-draw] { opacity: 1 !important; transform: none !important; }
  [data-reveal="wipe"] .figure-media { clip-path: none !important; }
  body { background: #fff; color: #000; font-size: 11pt; }
  .band-inner, .hero { padding: 18pt 0; }
  .row { grid-template-columns: 1fr; padding: 14pt 0; page-break-inside: avoid; }
  .figure { border: 1px solid #999; page-break-inside: avoid; }
  .figure-media img { opacity: 1 !important; }
  h1 { font-size: 26pt; } h2 { font-size: 17pt; }
  .faq details { page-break-inside: avoid; }
  .faq .answer { display: block !important; }
  a[href^="http"]::after { content: ' (' attr(href) ')'; font-size: 9pt; color: #555; }
  .prose { max-width: none; }
}
