@import url("../fonts/fonts.css");

/* ============================================================================
   NexLotus · design system

   THE GROUND IS WARM AND THE INK IS THE MARK'S.

   Rewritten 2026-09-09. The old system was cool: a near-white bone, a navy
   drawn straight from the logo, and a hairline around everything. It read as a
   specification document, which was half right. What it lacked was air.

   The ground is now a warm cream, the rules are a warm beige, and body copy
   sits in a taupe rather than a blue-grey. The two things that did not change
   are the ones that tie this site to the software it sells: the mark's navy,
   warmed by a few degrees so it belongs on cream, and the deep teal the product
   UI already uses. Signal orange stays reserved for genuine status and is never
   decoration. It is a warm palette that happens to already own a warm status
   colour, which is the one piece of luck in here.

   Corners are large now, and deliberately: 28px on a surface that holds a
   product capture, 20px on a card, 14px on a control. What is NOT large is the
   frame around a screenshot, and the reasoning for that is written where it
   applies, further down.

   Structure: tokens · reset · typography · layout · header · buttons ·
   hero · diagrams · components · journey · form · footer · motion · additions.
   ========================================================================= */

:root {
  /* ink + surface */
  --ink:          #08202E;
  --ink-soft:     #163244;
  --bone:         #F6F1E8;
  --paper:        #FDFAF4;
  --paper-hi:     #FFFFFF;
  --rule:         #E7DECE;
  --rule-strong:  #D0C2AC;
  --mute:         #64584B;

  /* The border of a control a person is meant to aim at. It is a separate
     token from --rule-strong because it has a floor: WCAG 1.4.11 wants 3:1
     against the surface behind it, and --rule-strong is a decorative hairline
     measuring 1.56:1. The old palette used one value for both, which is how
     this site shipped input borders a person with low vision could not find.
     This one measures 3.15:1 on the ground and 3.40:1 on paper. */
  --edge:         #96866C;

  /* accent */
  --accent:       #0A5755;
  --accent-deep:  #06403E;
  --accent-lift:  #5FE0DC;
  --accent-wash:  #E8F0EC;

  /* status */
  --signal:       #A2461A;
  --signal-lift:  #F0A26A;
  --signal-wash:  #F7EADC;

  /* on-ink surfaces */
  --ink-2:        #0F2A39;
  --ink-3:        #17394B;
  --ink-rule:     rgba(255, 251, 244, 0.15);
  --ink-rule-2:   rgba(255, 251, 244, 0.30);
  --ink-text:     #EFE9DE;
  --ink-mute:     #A3AFB4;

  /* type */
  --serif: "Instrument Serif", "Iowan Old Style", Georgia, "Times New Roman", serif;
  --sans:  "Lexend", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Arial, sans-serif;
  --mono:  "JetBrains Mono", ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;

  /* radii */
  --r-xs:   8px;
  --r-sm:   14px;
  --r-md:   20px;
  --r-lg:   28px;
  --r-pill: 999px;

  /* elevation. Tinted to the ground, never neutral grey, or a card on cream
     looks like it is floating over a different page than the one it is on. */
  --lift-1: 0 1px 2px rgba(46, 30, 12, 0.045);
  --lift-2: 0 18px 40px -26px rgba(46, 30, 12, 0.24);
  --lift-3: 0 36px 76px -44px rgba(46, 30, 12, 0.32);

  /* measure + rhythm */
  --w:        1240px;
  --w-mid:    980px;
  --w-narrow: 720px;
  --gutter:   clamp(1.25rem, 5vw, 3.5rem);
  --band:     clamp(6rem, 12vw, 10.5rem);
  --band-sm:  clamp(3.75rem, 7.5vw, 6.5rem);

  /* motion */
  --ease:    cubic-bezier(0.22, 1, 0.36, 1);
  --ease-io: cubic-bezier(0.65, 0, 0.35, 1);

  --header-h: 76px;

  /* How far the floating header pill sits inside the page's text column. It is
     a token because the header subtracts it and the pill adds it back, and the
     two must be the same number or the wordmark stops lining up with the
     headline underneath it. */
  --pill-inset: clamp(0.75rem, 1.2vw, 1.25rem);
}

/* ---------------------------------------------------------------- reset -- */

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--header-h) + 24px);
}

body {
  margin: 0;
  background: var(--bone);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 1.0625rem;
  line-height: 1.65;
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}

body.is-locked { overflow: hidden; }

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

h1, h2, h3, h4, p, figure, blockquote, ul, ol, dl, dd { margin: 0; }
ul, ol { padding: 0; list-style: none; }

a { color: inherit; text-decoration: none; }

button, input, select, textarea { font: inherit; color: inherit; }

hr { border: 0; height: 1px; background: var(--rule); margin: 0; }

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

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

.band--ink :focus-visible,
.footer :focus-visible { outline-color: var(--accent-lift); }

.skip {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 200;
  background: var(--ink);
  color: var(--bone);
  padding: 0.85rem 1.4rem;
  font-family: var(--mono);
  font-size: 0.8125rem;
}
.skip:focus { left: 0; }

.sr {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
}

/* ----------------------------------------------------------- typography -- */

.display {
  font-family: var(--serif);
  font-weight: 400;
  font-size: clamp(2.85rem, 7.4vw, 6.25rem);
  line-height: 0.98;
  letter-spacing: -0.022em;
  text-wrap: balance;
}

.h1 {
  font-family: var(--serif);
  font-weight: 400;
  font-size: clamp(2.4rem, 5.4vw, 4.35rem);
  line-height: 1.02;
  letter-spacing: -0.02em;
  text-wrap: balance;
}

.h2 {
  font-family: var(--serif);
  font-weight: 400;
  font-size: clamp(1.9rem, 3.5vw, 3rem);
  line-height: 1.08;
  letter-spacing: -0.018em;
  text-wrap: balance;
}

.h3 {
  font-family: var(--sans);
  font-weight: 500;
  font-size: clamp(1.125rem, 1.5vw, 1.3125rem);
  line-height: 1.35;
  letter-spacing: -0.011em;
}

.h4 {
  font-family: var(--sans);
  font-weight: 500;
  font-size: 1rem;
  line-height: 1.45;
  letter-spacing: -0.006em;
}

.serif-em { font-family: var(--serif); font-style: italic; }

.lead {
  font-size: clamp(1.125rem, 1.55vw, 1.375rem);
  line-height: 1.55;
  color: var(--mute);
  max-width: 34ch;
  font-weight: 300;
}
.lead--wide { max-width: 50ch; }

.prose { max-width: 66ch; }
.prose p + p { margin-top: 1.15em; }

.muted { color: var(--mute); }
.small { font-size: 0.9375rem; line-height: 1.6; }
.tiny  { font-size: 0.8125rem; line-height: 1.55; }

.label {
  font-family: var(--mono);
  font-size: 0.6875rem;
  font-weight: 500;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--mute);
  display: inline-flex;
  align-items: center;
  gap: 0.6em;
}
.label--accent { color: var(--accent); }

.label::before {
  content: "";
  width: 1.5rem;
  height: 1px;
  background: currentColor;
  opacity: 0.45;
  flex: none;
}
.label--bare::before { display: none; }

.mono {
  font-family: var(--mono);
  font-size: 0.8125rem;
  letter-spacing: 0.02em;
  font-weight: 500;
}

code {
  font-family: var(--mono);
  font-size: 0.875em;
  background: var(--accent-wash);
  color: var(--accent-deep);
  padding: 0.12em 0.4em;
  border-radius: var(--r-xs);
  letter-spacing: 0;
  word-break: break-word;
}
.band--ink code,
.footer code { background: rgba(95, 224, 220, 0.12); color: var(--accent-lift); }

/* ---------------------------------------------------------------- layout -- */

.wrap {
  width: 100%;
  max-width: var(--w);
  margin-inline: auto;
  padding-inline: var(--gutter);
}
.wrap--mid    { max-width: var(--w-mid); }
.wrap--narrow { max-width: var(--w-narrow); }

.band { padding-block: var(--band); position: relative; }
.band--tight { padding-block: var(--band-sm); }

.band--paper { background: var(--paper); }
.band--wash  { background: var(--accent-wash); }

.band--ink {
  background: var(--ink);
  color: var(--ink-text);
}
.band--ink .label,
.band--ink .muted,
.band--ink .lead { color: var(--ink-mute); }
.band--ink .label--accent { color: var(--accent-lift); }
.band--ink hr { background: var(--ink-rule); }

.band--paper + .band:not(.band--paper):not(.band--ink),
.band:not(.band--paper):not(.band--ink) + .band--paper { border-top: 1px solid var(--rule); }

.stack > * + * { margin-top: var(--gap, 1.5rem); }

.band-head {
  display: grid;
  gap: clamp(1.5rem, 3vw, 3rem);
  grid-template-columns: minmax(0, 1fr);
  align-items: end;
  margin-bottom: clamp(2.75rem, 5vw, 4.5rem);
}
@media (min-width: 900px) {
  .band-head--split { grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr); }
  .band-head--split .band-head__aside { padding-bottom: 0.4rem; }
}
/* The default head is a stack: title, then the paragraph that qualifies it,
   held to a readable measure. `--split` puts the paragraph in a second column
   and is kept for the interior pages, where the aside carries a second column
   of content rather than a caption to the headline. */
.band-head--stack { max-width: var(--w-mid); gap: clamp(1.1rem, 2vw, 1.5rem); }
.band-head--stack .band-head__aside { max-width: 64ch; }

/* The 1.1rem exists to clear an eyebrow. A heading that is the first thing in
   its column has no eyebrow to clear. */
.band-head__title { margin-top: 1.1rem; }
.band-head__title:first-child { margin-top: 0; }

.grid { display: grid; gap: clamp(1.25rem, 2.4vw, 2rem); }
@media (min-width: 640px)  { .grid--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 900px)  { .grid--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (min-width: 720px)  { .grid--4 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1080px) { .grid--4 { grid-template-columns: repeat(4, minmax(0, 1fr)); } }

.split {
  display: grid;
  gap: clamp(2rem, 4.5vw, 4.5rem);
  align-items: start;
}
@media (min-width: 940px) {
  .split { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
  .split--wide-left  { grid-template-columns: minmax(0, 1.2fr) minmax(0, 0.8fr); }
  .split--wide-right { grid-template-columns: minmax(0, 0.8fr) minmax(0, 1.2fr); }

  /* Sticky aside. `align-self: start` is what makes this work in a grid: the
     item stays content-sized while the grid *area* stays row-height, and the
     area is the containing block stickiness resolves against. */
  .split--sticky > :last-child {
    position: sticky;
    top: calc(var(--header-h) + 2.5rem);
    align-self: start;
  }
}

/* --------------------------------------------------------------- header -- */

/* The bar floats rather than spanning the window, and it only draws itself
   once the page has moved. At the top of a page there is nothing to separate
   the header from, so a rule there is decoration; the moment content begins
   passing underneath, the same bar earns a surface and an edge.

   It is a painted surface, not a frosted one. A translucent bar over the dark
   bands turned the cream muddy in the old build, and the fix attempted then
   (raise the opacity to 0.94) was the same fix arrived at slowly: paint it. */
/* THE PILL IS INSET FROM THE TEXT COLUMN, AND ITS CONTENTS ARE NOT.
   A floating bar whose wordmark does not line up with the headline beneath it
   looks like a mistake at every width, and the first version of this did
   exactly that: giving .header__inner its own padding-inline overrode the
   gutter it inherits from .wrap, and the logo ended up 34px left of the body
   text. So the inset is taken off the header and given back as the pill's own
   padding. The two cancel, and the content lands on the gutter at every
   width, while the pill's edge floats one inset short of it. */
.header {
  position: sticky;
  top: 0;
  z-index: 100;
  padding-block: 0.6rem;
  padding-inline: var(--pill-inset);
}

.header__inner {
  height: calc(var(--header-h) - 1.2rem);
  max-width: calc(var(--w) - var(--pill-inset) * 2);
  padding-inline: calc(var(--gutter) - var(--pill-inset));
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
  border: 1px solid transparent;
  border-radius: var(--r-pill);
  transition: background-color 0.4s var(--ease), border-color 0.4s var(--ease),
              box-shadow 0.4s var(--ease);
}

.header.is-stuck .header__inner {
  background: var(--paper);
  border-color: var(--rule);
  box-shadow: var(--lift-2);
}

/* Over a dark band the floating bar inverts, because a cream pill sliding onto
   an ink section is the one place this pattern normally falls apart. site.js
   sets the class from whatever band sits under the bar's own midpoint. */
.header.is-over-ink .header__inner {
  background: var(--ink-2);
  border-color: var(--ink-rule);
  box-shadow: var(--lift-3);
}
.header.is-over-ink .brand__word { color: var(--ink-text); }
.header.is-over-ink .brand__chip { border-color: var(--ink-rule-2); }
.header.is-over-ink .nav__link { color: var(--ink-mute); }
.header.is-over-ink .nav__link:hover,
.header.is-over-ink .nav__link[aria-current="page"] { color: var(--ink-text); }
.header.is-over-ink .burger__bars span { background: var(--ink-text); }
.header.is-over-ink .btn {
  background: var(--accent-lift);
  border-color: var(--accent-lift);
  color: var(--ink);
}
.header.is-over-ink .btn::before { background: var(--ink-text); }

.brand { display: inline-flex; align-items: center; gap: 0.7rem; }

/* The mark is used exactly as supplied: an opaque PNG whose background is a
   near-white carrying a slight vertical gradient. Framing it in a hairline
   chip means that edge never reads as an artefact against the page. */
.brand__chip {
  width: 34px;
  height: 34px;
  border-radius: 11px;
  border: 1px solid var(--rule-strong);
  background: #FDFDFD;
  overflow: hidden;
  flex: none;
  display: grid;
  place-items: center;
  transition: border-color 0.3s var(--ease);
}
.brand__chip img { width: 100%; height: 100%; object-fit: contain; }
.brand:hover .brand__chip { border-color: var(--ink); }

.brand--lg .brand__chip { width: 44px; height: 44px; border-radius: 14px; }
.brand--lg .brand__word { font-size: 1.25rem; }

.brand__word {
  font-family: var(--sans);
  font-weight: 500;
  font-size: 1.0625rem;
  letter-spacing: -0.015em;
  color: var(--ink);
}

.footer .brand__word { color: var(--bone); }
.footer .brand__chip { border-color: var(--ink-rule-2); }

.nav { display: none; }
@media (min-width: 980px) {
  .nav { display: flex; align-items: center; gap: 2rem; }
}

.nav__link {
  font-size: 0.9375rem;
  color: var(--mute);
  position: relative;
  padding-block: 0.4rem;
  transition: color 0.25s var(--ease);
}
.nav__link::after {
  content: "";
  position: absolute;
  left: 0; bottom: 0;
  width: 100%;
  height: 1px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: right;
  transition: transform 0.4s var(--ease);
}
.nav__link:hover { color: var(--ink); }
.nav__link:hover::after { transform: scaleX(1); transform-origin: left; }
.nav__link[aria-current="page"] { color: var(--ink); }
.nav__link[aria-current="page"]::after { transform: scaleX(1); background: var(--accent); }

/* Scoped to .header so this outranks `.btn { display: inline-flex }`, which is
   defined later in the file and would otherwise win on source order and leak
   the CTA into the mobile header. */
.header .header__cta { display: none; }
@media (min-width: 980px) { .header .header__cta { display: inline-flex; } }

.burger {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  background: none;
  border: 0;
  padding: 0.5rem 0;
  cursor: pointer;
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--ink);
}
@media (min-width: 980px) { .burger { display: none; } }

.burger__bars { width: 20px; display: grid; gap: 5px; }
.burger__bars span {
  height: 1.5px;
  background: currentColor;
  transition: transform 0.4s var(--ease), opacity 0.25s var(--ease);
}
.burger[aria-expanded="true"] .burger__bars span:nth-child(1) { transform: translateY(6.5px) rotate(45deg); }
.burger[aria-expanded="true"] .burger__bars span:nth-child(2) { opacity: 0; }
.burger[aria-expanded="true"] .burger__bars span:nth-child(3) { transform: translateY(-6.5px) rotate(-45deg); }

.menu {
  position: fixed;
  inset: var(--header-h) 0 0 0;
  z-index: 99;
  background: var(--bone);
  padding: clamp(1.75rem, 6vw, 3.5rem) var(--gutter) 3rem;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: 2.5rem;
  overflow-y: auto;
  opacity: 0;
  visibility: hidden;
  transform: translateY(-10px);
  transition: opacity 0.4s var(--ease), transform 0.4s var(--ease), visibility 0.4s;
}
.menu.is-open { opacity: 1; visibility: visible; transform: none; }
@media (min-width: 980px) { .menu { display: none; } }

.menu__list { display: grid; gap: 0; }
.menu__item {
  border-top: 1px solid var(--rule);
  padding-block: 1.05rem;
  display: flex;
  align-items: baseline;
  gap: 1rem;
}
.menu__item:last-child { border-bottom: 1px solid var(--rule); }
.menu__num { font-family: var(--mono); font-size: 0.6875rem; color: var(--mute); letter-spacing: 0.1em; flex: none; }
.menu__label {
  font-family: var(--serif);
  font-size: clamp(1.75rem, 7.5vw, 2.5rem);
  line-height: 1.05;
  letter-spacing: -0.02em;
}

/* -------------------------------------------------------------- buttons -- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.65rem;
  padding: 0.95rem 1.75rem;
  border-radius: var(--r-pill);
  border: 1px solid var(--ink);
  background: var(--ink);
  color: var(--bone);
  font-size: 0.9375rem;
  font-weight: 400;
  letter-spacing: -0.005em;
  cursor: pointer;
  position: relative;
  overflow: hidden;
  isolation: isolate;
  text-align: center;
  transition: color 0.4s var(--ease), border-color 0.4s var(--ease);
}
.btn::before {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--accent);
  transform: translateY(101%);
  transition: transform 0.5s var(--ease);
  z-index: -1;
}
.btn:hover::before { transform: translateY(0); }
.btn:hover { border-color: var(--accent); }
/* A press should feel like a press. One pixel, and it is the difference
   between a link that changed colour and a control that took the input. */
.btn:active { transform: translateY(1px) scale(0.994); }

.btn__arrow { transition: transform 0.4s var(--ease); flex: none; }
.btn:hover .btn__arrow { transform: translateX(4px); }

.btn--ghost {
  background: transparent;
  color: var(--ink);
  border-color: var(--edge);
}
.btn--ghost:hover { color: var(--bone); border-color: var(--accent); }

.btn--wide { width: 100%; }

.band--ink .btn,
.footer .btn {
  background: var(--bone);
  color: var(--ink);
  border-color: var(--bone);
}
.band--ink .btn::before,
.footer .btn::before { background: var(--accent-lift); }
.band--ink .btn:hover,
.footer .btn:hover { border-color: var(--accent-lift); color: var(--ink); }

.band--ink .btn--ghost,
.footer .btn--ghost {
  background: transparent;
  color: var(--ink-text);
  border-color: var(--ink-rule-2);
}
.band--ink .btn--ghost:hover,
.footer .btn--ghost:hover { color: var(--ink); border-color: var(--accent-lift); }

.btn-row { display: flex; flex-wrap: wrap; gap: 0.85rem; }

.link {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  font-size: 0.9375rem;
  color: var(--accent);
  position: relative;
  padding-bottom: 2px;
}
.link::after {
  content: "";
  position: absolute;
  left: 0; bottom: 0;
  width: 100%; height: 1px;
  background: currentColor;
  opacity: 0.35;
  transform-origin: left;
  transition: transform 0.45s var(--ease), opacity 0.3s var(--ease);
}
.link:hover::after { transform: scaleX(1.03); opacity: 1; }
.link svg { transition: transform 0.4s var(--ease); flex: none; }
.link:hover svg { transform: translateX(4px); }
.band--ink .link { color: var(--accent-lift); }

/* ---------------------------------------------------------------- chips -- */

.chip {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-family: var(--mono);
  font-size: 0.6875rem;
  font-weight: 500;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  padding: 0.4rem 0.7rem;
  border-radius: var(--r-pill);
  border: 1px solid var(--rule-strong);
  color: var(--mute);
  background: var(--paper);
  line-height: 1.3;
}
.chip--accent { border-color: rgba(10, 87, 85, 0.35); color: var(--accent); background: var(--accent-wash); }
.chip--signal { border-color: rgba(180, 83, 26, 0.35); color: var(--signal); background: var(--signal-wash); }
.chip--ink { border-color: var(--ink-rule-2); color: var(--ink-mute); background: transparent; }

.chip__dot {
  width: 6px; height: 6px;
  border-radius: 50%;
  background: currentColor;
  flex: none;
}
.chip__dot--live { animation: pulse 2.4s var(--ease-io) infinite; }
@keyframes pulse {
  0%, 100% { opacity: 1; transform: scale(1); }
  50%      { opacity: 0.35; transform: scale(0.72); }
}

/* ----------------------------------------------------------------- hero -- */

.hero {
  padding-top: clamp(3rem, 8vw, 6.5rem);
  padding-bottom: clamp(3rem, 6vw, 5rem);
  position: relative;
}

.hero__grid { display: grid; gap: clamp(2.5rem, 5vw, 4rem); align-items: center; }
@media (min-width: 1000px) {
  .hero__grid { grid-template-columns: minmax(0, 1.06fr) minmax(0, 0.94fr); gap: clamp(3rem, 5vw, 5rem); }
}

.hero__title { margin-top: 1.5rem; }
.hero__lead { margin-top: 1.75rem; max-width: 46ch; }
.hero__actions { margin-top: 2.5rem; }

/* word-level reveal, applied to the display line only */
.split__word { display: inline-block; overflow: hidden; vertical-align: bottom; }
.split__word > span {
  display: inline-block;
  transform: translateY(105%);
  transition: transform 0.95s var(--ease);
  transition-delay: var(--d, 0s);
}
.is-lit .split__word > span { transform: none; }

/* The status strip is its own band rather than a fifth text element inside the
   hero. It sits close enough to read as part of the opening and far enough that
   it never competes with the headline for the first look. */
.hero--tight { padding-bottom: 0; }
.hero__foot { padding-bottom: clamp(2.5rem, 5vw, 4rem); }

.hero__strip {
  margin-top: clamp(3rem, 6vw, 4.5rem);
  border-top: 1px solid var(--rule);
  padding-top: 1.15rem;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.75rem 1.75rem;
}
.hero__strip .mono {
  color: var(--mute);
  font-size: 0.6875rem;
  letter-spacing: 0.11em;
  text-transform: uppercase;
}

/* page hero for interior pages */
.phero { padding-top: clamp(3rem, 7vw, 5.5rem); padding-bottom: clamp(2.5rem, 5vw, 4rem); }
.phero__title { margin-top: 1.35rem; max-width: 20ch; }
.phero__lead { margin-top: 1.6rem; }
.phero__meta {
  margin-top: clamp(2.5rem, 5vw, 3.5rem);
  border-top: 1px solid var(--rule);
  padding-top: 1.5rem;
  display: grid;
  gap: 1.5rem;
}
@media (min-width: 720px) { .phero__meta { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.phero__meta .fact { border-top: 0; padding-top: 0; }

.hero__art { position: relative; }

/* ------------------------------------------------------------- diagrams -- */

.figure {
  border: 1px solid var(--rule);
  background: var(--paper);
  border-radius: var(--r-lg);
  box-shadow: var(--lift-1);
  padding: clamp(1.25rem, 2.4vw, 2rem);
}
.band--ink .figure { border-color: var(--ink-rule); background: var(--ink-2); }

.figure__cap {
  margin-top: 1.1rem;
  padding-top: 0.9rem;
  border-top: 1px solid var(--rule);
  font-size: 0.8125rem;
  line-height: 1.5;
  color: var(--mute);
}
.band--ink .figure__cap { border-top-color: var(--ink-rule); color: var(--ink-mute); }

.dia { width: 100%; height: auto; overflow: visible; }
.dia__line { fill: none; stroke: var(--edge); stroke-width: 1.25; }
/* Each path carries its own length as `--len` inline, because the dash pattern
   is path-specific. It must be a custom property, not an inline
   stroke-dashoffset: an inline declaration outranks every stylesheet rule, so
   the `stroke-dashoffset: 0` below could never win and the line would never
   draw at all. */
.dia__flow {
  fill: none;
  stroke: var(--accent);
  stroke-width: 1.75;
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-dasharray: var(--len, 1200);
  stroke-dashoffset: var(--len, 1200);
  transition: stroke-dashoffset 2s var(--ease-io);
}
/* Reveal-driven figures draw when they scroll in. Journey scenes are not
   reveals. They are switched by the pinned scrubber, so they draw when their
   step becomes the active one. Without this second selector every flow path
   inside a pinned scene stays at full dashoffset and is simply invisible. */
.is-in .dia__flow,
.journey__scene.is-active .dia__flow { stroke-dashoffset: 0; }
.dia__node { fill: var(--paper); stroke: var(--ink); stroke-width: 1.25; }
.dia__node--on { fill: var(--accent); stroke: var(--accent); }
.dia__box { fill: var(--paper); stroke: var(--edge); stroke-width: 1.25; }
.dia__box--on { fill: var(--accent-wash); stroke: var(--accent); }
.dia__txt {
  font-family: var(--mono);
  font-size: 9.5px;
  letter-spacing: 0.07em;
  fill: var(--mute);
  text-transform: uppercase;
}
.dia__txt--ink { fill: var(--ink); font-weight: 600; }
.dia__txt--accent { fill: var(--accent); font-weight: 600; }
.dia__txt--signal { fill: var(--signal); font-weight: 600; }

.band--ink .dia__line { stroke: var(--ink-rule-2); }
.band--ink .dia__flow { stroke: var(--accent-lift); }
.band--ink .dia__node { fill: var(--ink); stroke: var(--ink-mute); }
.band--ink .dia__node--on { fill: var(--accent-lift); stroke: var(--accent-lift); }
.band--ink .dia__box { fill: var(--ink); stroke: var(--ink-rule-2); }
.band--ink .dia__box--on { fill: rgba(95, 224, 220, 0.08); stroke: var(--accent-lift); }
.band--ink .dia__txt { fill: var(--ink-mute); }
.band--ink .dia__txt--ink { fill: var(--ink-text); }
.band--ink .dia__txt--accent { fill: var(--accent-lift); }
.band--ink .dia__txt--signal { fill: var(--signal-lift); }

/* ---------------------------------------------------- hero floor-plan art -- */

.plan__grid { stroke: var(--rule); stroke-width: 1; }
.plan__room { fill: none; stroke: var(--edge); stroke-width: 1.25; }
.plan__room--hl { fill: var(--accent-wash); stroke: var(--accent); }
.plan__route {
  fill: none;
  stroke: var(--accent);
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-dasharray: 700;
  stroke-dashoffset: 700;
  animation: draw 2.6s var(--ease-io) 0.7s forwards;
}
@keyframes draw { to { stroke-dashoffset: 0; } }

.plan__pin { fill: var(--accent); opacity: 0; animation: pop 0.6s var(--ease) 3.1s forwards; transform-box: fill-box; transform-origin: center; }
.plan__pin--start { animation-delay: 0.6s; }
@keyframes pop { from { opacity: 0; transform: scale(0.3); } to { opacity: 1; transform: scale(1); } }

.plan__blocked {
  stroke: var(--signal);
  stroke-width: 2;
  stroke-linecap: round;
  opacity: 0;
  animation: fadein 0.7s var(--ease) 2.1s forwards;
}
@keyframes fadein { to { opacity: 1; } }

/* --------------------------------------------------------- negation list -- */

.negate { display: grid; gap: 0; }
.negate__item {
  display: flex;
  align-items: baseline;
  gap: 1rem;
  padding-block: 0.95rem;
  border-bottom: 1px solid var(--rule);
}
.negate__item:first-child { border-top: 1px solid var(--rule); }
.negate__mark {
  font-family: var(--mono);
  font-size: 0.8125rem;
  color: var(--signal);
  flex: none;
  width: 1.1rem;
}
.negate__text { font-size: 1rem; }
.negate__note {
  color: var(--mute);
  font-size: 0.75rem;
  margin-left: auto;
  text-align: right;
  font-family: var(--mono);
  letter-spacing: 0.05em;
  flex: none;
}
@media (max-width: 660px) { .negate__note { display: none; } }

.band--ink .negate__item { border-color: var(--ink-rule); }
.band--ink .negate__mark { color: var(--signal-lift); }
.band--ink .negate__note { color: var(--ink-mute); }

/* --------------------------------------------------------- module cards -- */

.mod {
  display: flex;
  flex-direction: column;
  border: 1px solid var(--rule);
  background: var(--paper);
  border-radius: var(--r-md);
  padding: clamp(1.65rem, 2.8vw, 2.3rem);
  height: 100%;
  position: relative;
  box-shadow: var(--lift-1);
  transition: border-color 0.45s var(--ease), transform 0.45s var(--ease),
              box-shadow 0.45s var(--ease);
}
.mod:hover {
  border-color: var(--rule-strong);
  transform: translateY(-4px);
  box-shadow: var(--lift-2);
}
@media (prefers-reduced-motion: reduce) { .mod:hover { transform: none; } }
.mod__head { display: flex; align-items: center; justify-content: space-between; gap: 1rem; min-height: 1.9rem; }
.mod__title {
  margin-top: 1.6rem;
  font-family: var(--serif);
  font-size: clamp(1.5rem, 2.2vw, 1.85rem);
  line-height: 1.1;
  letter-spacing: -0.015em;
}
.mod__desc { margin-top: 0.85rem; color: var(--mute); font-size: 0.9375rem; }
.mod__specs { margin-top: 1.5rem; display: grid; gap: 0.55rem; }
.mod__spec { display: flex; gap: 0.7rem; align-items: baseline; font-size: 0.875rem; color: var(--mute); }
.mod__spec::before {
  content: "";
  width: 5px; height: 5px;
  border-radius: 50%;
  background: var(--accent);
  flex: none;
  transform: translateY(-2px);
}
.mod__foot { margin-top: auto; padding-top: 1.75rem; }

/* ------------------------------------------------------- sticky journey -- */

.journey { padding-block: 0; overflow: clip; }

.journey__track { position: relative; }

.journey__stage {
  position: sticky;
  top: 0;
  min-height: 100vh;
  min-height: 100svh;
  display: flex;
  align-items: center;
  /* The sticky header overlays the top of the pinned stage, so the extra top
     padding is what optically centres the content in the *visible* area. */
  padding-block: calc(var(--header-h) + clamp(2rem, 5vh, 3.5rem)) clamp(2rem, 5vh, 3.5rem);
}

.journey__inner {
  width: 100%;
  max-width: var(--w);
  margin-inline: auto;
  padding-inline: var(--gutter);
  display: grid;
  gap: clamp(2rem, 4vw, 4rem);
  align-items: center;
}
@media (min-width: 980px) {
  .journey__inner { grid-template-columns: minmax(0, 0.95fr) minmax(0, 1.05fr); }
}

.journey__rail { display: flex; gap: 0.5rem; margin: 1.85rem 0 2.4rem; }
.journey__seg { height: 2px; flex: 1; background: var(--ink-rule); position: relative; overflow: hidden; }
.journey__seg::after {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--accent-lift);
  transform: scaleX(var(--fill, 0));
  transform-origin: left;
}

.journey__steps { position: relative; }
.journey__step {
  opacity: 0;
  visibility: hidden;
  transform: translateY(14px);
  transition: opacity 0.55s var(--ease), transform 0.55s var(--ease), visibility 0.55s;
}
.journey__step + .journey__step { position: absolute; inset: 0; }
.journey__step.is-active { opacity: 1; visibility: visible; transform: none; }

.journey__num { font-family: var(--mono); font-size: 0.75rem; letter-spacing: 0.14em; color: var(--accent-lift); }
.journey__title {
  margin-top: 1.15rem;
  font-family: var(--serif);
  font-size: clamp(1.9rem, 3.4vw, 2.9rem);
  line-height: 1.08;
  letter-spacing: -0.018em;
}
.journey__body { margin-top: 1.2rem; color: var(--ink-mute); max-width: 46ch; font-weight: 300; }
.journey__meta {
  margin-top: 1.75rem;
  padding-top: 1.1rem;
  border-top: 1px solid var(--ink-rule);
  font-family: var(--mono);
  font-size: 0.75rem;
  letter-spacing: 0.05em;
  color: var(--ink-mute);
  line-height: 1.6;
}

.journey__art { position: relative; }
.journey__scene { opacity: 0; visibility: hidden; transition: opacity 0.6s var(--ease), visibility 0.6s; }
.journey__scene + .journey__scene { position: absolute; inset: 0; }
.journey__scene.is-active { opacity: 1; visibility: visible; }

/* On small screens pinning fights the mobile address bar; render as a stack. */
@media (max-width: 979px) {
  .journey__track { height: auto !important; }
  .journey__stage { position: static; min-height: 0; padding-block: var(--band-sm); }
  .journey__inner { display: flex; flex-direction: column; }
  .journey__steps { display: grid; gap: 3rem; }
  .journey__step,
  .journey__step + .journey__step {
    position: static;
    opacity: 1;
    visibility: visible;
    transform: none;
    inset: auto;
    padding-top: 2.25rem;
    border-top: 1px solid var(--ink-rule);
  }
  .journey__step:first-child { border-top: 0; padding-top: 0; }
  .journey__rail { display: none; }

  /* The scrubber is gone, so the art column cannot switch scenes. It still
     carries the section's opening image, which is worth keeping: promote the
     first scene to a static lead above the steps and drop the rest. */
  .journey__art { order: -1; margin-bottom: clamp(2rem, 6vw, 3rem); }
  .journey__scene { display: none; }
  .journey__scene:first-child {
    display: block;
    position: static;
    opacity: 1;
    visibility: visible;
    inset: auto;
  }
}

/* ---------------------------------------------------------- fact blocks -- */

.fact { border-top: 1px solid var(--rule); padding-top: 1.4rem; }
.band--ink .fact { border-top-color: var(--ink-rule); }
.fact__k {
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--accent);
}
.band--ink .fact__k { color: var(--accent-lift); }
.fact__v { margin-top: 0.9rem; font-size: 0.9375rem; line-height: 1.6; color: var(--mute); }
.band--ink .fact__v { color: var(--ink-mute); }
.fact__v strong { color: var(--ink); font-weight: 500; }
.band--ink .fact__v strong { color: var(--ink-text); }

.stat__n {
  font-family: var(--serif);
  font-size: clamp(2.4rem, 5vw, 3.5rem);
  line-height: 1;
  letter-spacing: -0.02em;
  display: block;
}
.stat__u { font-family: var(--sans); font-size: 0.42em; letter-spacing: -0.01em; }
.stat__c { margin-top: 0.7rem; font-size: 0.875rem; color: var(--mute); line-height: 1.55; }
.band--ink .stat__c { color: var(--ink-mute); }

/* ------------------------------------------------------------ spec list -- */

.spec { display: grid; }
.spec__row {
  display: grid;
  gap: 0.5rem 2rem;
  padding-block: 1.4rem;
  border-top: 1px solid var(--rule);
  align-items: start;
}
@media (min-width: 780px) {
  .spec__row { grid-template-columns: minmax(0, 0.34fr) minmax(0, 0.66fr); }
  /* Inside a narrow aside the two-column split shreds the key into three lines.
     Viewport media queries cannot see container width, so it is opted out of. */
  .spec--stacked .spec__row { grid-template-columns: minmax(0, 1fr); gap: 0.4rem; }
}
.spec__row:last-child { border-bottom: 1px solid var(--rule); }
.spec__k { font-weight: 500; font-size: 1rem; letter-spacing: -0.008em; }
.spec__v { color: var(--mute); font-size: 0.9375rem; }
.band--ink .spec__row { border-color: var(--ink-rule); }
.band--ink .spec__v { color: var(--ink-mute); }

/* A spec row can also be the link to the page that explains it. The chevron is
   drawn from two borders rather than set as a glyph, so it cannot go missing
   with a font and cannot be read out by a screen reader as punctuation. */
a.spec__row .spec__k { display: flex; align-items: center; gap: 0.65rem; }
a.spec__row .spec__k::after {
  content: "";
  flex: none;
  width: 7px;
  height: 7px;
  border-top: 1.4px solid var(--accent);
  border-right: 1.4px solid var(--accent);
  transform: rotate(45deg);
  transition: transform 0.4s var(--ease);
}
a.spec__row:hover .spec__k,
a.spec__row:focus-visible .spec__k { color: var(--accent); }
a.spec__row:hover .spec__k::after { transform: rotate(45deg) translate(2px, -2px); }
a.spec__row:focus-visible { outline-offset: 6px; }
.band--ink a.spec__row .spec__k::after { border-color: var(--accent-lift); }
.band--ink a.spec__row:hover .spec__k { color: var(--accent-lift); }

/* -------------------------------------------------------------- callout -- */

.callout { border-left: 2px solid var(--accent); padding: 0.35rem 0 0.35rem 1.5rem; }
.callout--signal { border-left-color: var(--signal); }
.band--ink .callout { border-left-color: var(--accent-lift); }
.band--ink .callout--signal { border-left-color: var(--signal-lift); }

.note {
  border: 1px solid var(--rule);
  border-radius: var(--r-md);
  padding: clamp(1.15rem, 2vw, 1.6rem);
  background: var(--paper);
}
.note--signal { border-color: rgba(180, 83, 26, 0.3); background: var(--signal-wash); }
.note--accent { border-color: rgba(10, 87, 85, 0.28); background: var(--accent-wash); }
.band--ink .note { border-color: var(--ink-rule); background: var(--ink-2); }

.quote {
  font-family: var(--serif);
  font-size: clamp(1.5rem, 3vw, 2.35rem);
  line-height: 1.22;
  letter-spacing: -0.015em;
  text-wrap: balance;
}

/* --------------------------------------------------------- language set -- */

/* Thirteen is prime, so the last row always leaves an empty cell. Painting the
   rules as a container background would render that gap as a grey block, so
   each cell draws its own hairline into the 1px gap instead and the leftover
   cell is simply paper. */
.langs {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(148px, 1fr));
  gap: 1px;
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: var(--r-md);
  overflow: hidden;
}
.lang {
  background: var(--paper);
  box-shadow: 0 0 0 1px var(--rule);
  padding: 1.05rem 1.15rem;
  display: grid;
  gap: 0.4rem;
  align-content: start;
  transition: background-color 0.35s var(--ease);
}
.lang:hover { background: var(--accent-wash); }
.lang__native { font-size: 1.0625rem; line-height: 1.35; letter-spacing: -0.01em; }
.lang__native[dir="rtl"] { direction: rtl; text-align: right; }
.lang__meta {
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--mute);
  display: flex;
  gap: 0.5rem;
  align-items: center;
  flex-wrap: wrap;
}
.lang__rtl { color: var(--accent); }

/* -------------------------------------------------------- state machine -- */

.states { display: grid; gap: 0; }
.state {
  display: grid;
  gap: 0.35rem 1.25rem;
  padding: 1.25rem 0;
  border-top: 1px solid var(--rule);
  align-items: baseline;
}
@media (min-width: 760px) { .state { grid-template-columns: 13rem minmax(0, 1fr); } }
.state:last-child { border-bottom: 1px solid var(--rule); }
.state__k {
  font-family: var(--mono);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  color: var(--ink);
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
}
.state__k::before {
  content: "";
  width: 7px; height: 7px;
  border: 1.5px solid var(--accent);
  border-radius: 50%;
  flex: none;
}
.state--warn .state__k::before { border-color: var(--signal); background: var(--signal); }
.state--dead .state__k::before { border-color: var(--mute); background: var(--mute); }
.state__v { color: var(--mute); font-size: 0.9375rem; }
.band--ink .state { border-color: var(--ink-rule); }
.band--ink .state__k { color: var(--ink-text); }
.band--ink .state__k::before { border-color: var(--accent-lift); }
.band--ink .state--warn .state__k::before { border-color: var(--signal-lift); background: var(--signal-lift); }
.band--ink .state--dead .state__k::before { border-color: var(--ink-mute); background: var(--ink-mute); }
.band--ink .state__v { color: var(--ink-mute); }

/* --------------------------------------------------------- event ledger -- */

.ledger {
  border: 1px solid var(--rule);
  border-radius: var(--r-md);
  background: var(--paper);
  overflow: hidden;
  font-family: var(--mono);
  font-size: 0.75rem;
}
.band--ink .ledger { border-color: var(--ink-rule); background: var(--ink-2); }

.ledger__head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 1rem;
  padding: 0.75rem 1rem;
  border-bottom: 1px solid var(--rule);
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--mute);
  font-size: 0.6875rem;
}
.band--ink .ledger__head { border-color: var(--ink-rule); color: var(--ink-mute); }

.ledger__row {
  display: grid;
  grid-template-columns: 5.25rem minmax(0, 1fr);
  gap: 0.3rem 1rem;
  padding: 0.7rem 1rem;
  border-bottom: 1px solid var(--rule);
  align-items: baseline;
}
@media (max-width: 560px) { .ledger__row { grid-template-columns: 1fr; } }
.ledger__row:last-child { border-bottom: 0; }
.band--ink .ledger__row { border-color: var(--ink-rule); }
.ledger__row--struck .ledger__what { text-decoration: line-through; opacity: 0.5; }
.ledger__row--fix { background: var(--accent-wash); }
.band--ink .ledger__row--fix { background: rgba(95, 224, 220, 0.07); }
.ledger__when { color: var(--mute); letter-spacing: 0.03em; }
.band--ink .ledger__when { color: var(--ink-mute); }
.ledger__what { letter-spacing: 0.02em; line-height: 1.55; }
.ledger__tag { color: var(--accent); }
.band--ink .ledger__tag { color: var(--accent-lift); }
.ledger__foot {
  padding: 0.75rem 1rem;
  border-top: 1px solid var(--rule);
  color: var(--mute);
  font-size: 0.6875rem;
  letter-spacing: 0.04em;
  line-height: 1.55;
}
.band--ink .ledger__foot { border-color: var(--ink-rule); color: var(--ink-mute); }

/* ------------------------------------------------------------- thread -- */

/* The equipment room, drawn rather than photographed.

   Built on the ledger's frame on purpose: same hairline, same radius, same mono
   head and foot, because the room and the event log are two views of one record
   and should not look like two products. What differs is the one thing that
   matters, the equipment block sitting inside a sentence rather than in a
   column of its own, which is the whole point of the feature.

   Deliberately not bubbles. The console has them; a marketing page rendering
   fake bubbles would be drawing a chat app, and the argument here is about
   where the machine sits in the words. */

.thread {
  border: 1px solid var(--rule);
  border-radius: var(--r-md);
  background: var(--paper);
  overflow: hidden;
}
.band--ink .thread { border-color: var(--ink-rule); background: var(--ink-2); }

.thread__head,
.thread__foot {
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--mute);
  padding: 0.75rem 1rem;
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 1rem;
}
.thread__head { border-bottom: 1px solid var(--rule); }
.thread__foot {
  border-top: 1px solid var(--rule);
  text-transform: none;
  letter-spacing: 0.04em;
  line-height: 1.55;
  display: block;
}
.band--ink .thread__head,
.band--ink .thread__foot { border-color: var(--ink-rule); color: var(--ink-mute); }

.thread__msg { padding: 0.95rem 1rem; border-bottom: 1px solid var(--rule); }
.thread__msg:last-of-type { border-bottom: 0; }
.band--ink .thread__msg { border-color: var(--ink-rule); }

.thread__who {
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--mute);
  margin: 0 0 0.5rem;
}
.band--ink .thread__who { color: var(--ink-mute); }

.thread__body {
  margin: 0;
  font-size: 0.9375rem;
  line-height: 1.7;
}

/* The equipment block. A code stamped into running text, the way a plate is
   riveted to a machine, so the sentence still reads as one sentence. */
.eq {
  font-family: var(--mono);
  font-size: 0.8125em;
  letter-spacing: 0.06em;
  padding: 0.12em 0.42em;
  border: 1px solid var(--accent);
  border-radius: var(--r-xs);
  color: var(--accent);
  background: var(--accent-wash);
  white-space: nowrap;
}
.band--ink .eq { border-color: var(--accent-lift); color: var(--accent-lift); background: rgba(95, 224, 220, 0.08); }

/* State, as a word and a shape. Never the shape alone. */
.thread__state {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  margin-top: 0.7rem;
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--signal);
}
.thread__state--done { color: var(--accent); }
.band--ink .thread__state { color: var(--signal-lift); }
.band--ink .thread__state--done { color: var(--accent-lift); }

.thread__sys {
  display: flex;
  align-items: center;
  gap: 0.8rem;
  padding: 0.7rem 1rem;
  border-bottom: 1px solid var(--rule);
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.06em;
  color: var(--mute);
}
.band--ink .thread__sys { border-color: var(--ink-rule); color: var(--ink-mute); }
.thread__sys::before,
.thread__sys::after { content: ""; flex: 1; height: 1px; background: var(--rule); }
.band--ink .thread__sys::before,
.band--ink .thread__sys::after { background: var(--ink-rule); }

/* ---------------------------------------------------------------- table -- */

.tbl-scroll { overflow-x: auto; border: 1px solid var(--rule); border-radius: var(--r-md); background: var(--paper); }
.band--ink .tbl-scroll { border-color: var(--ink-rule); background: var(--ink-2); }
.tbl { width: 100%; border-collapse: collapse; min-width: 580px; }
.tbl th, .tbl td { text-align: left; padding: 0.85rem 1.1rem; border-bottom: 1px solid var(--rule); vertical-align: top; }
.band--ink .tbl th, .band--ink .tbl td { border-color: var(--ink-rule); }
.tbl thead th {
  font-family: var(--mono);
  font-size: 0.6875rem;
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--mute);
  white-space: nowrap;
}
.band--ink .tbl thead th { color: var(--ink-mute); }
.tbl tbody th { font-family: var(--mono); font-size: 0.75rem; font-weight: 600; letter-spacing: 0.05em; white-space: nowrap; }
.tbl td { font-size: 0.9375rem; color: var(--mute); }
.band--ink .tbl td { color: var(--ink-mute); }
.tbl tbody tr:last-child th, .tbl tbody tr:last-child td { border-bottom: 0; }
.tbl .yes { color: var(--accent); font-family: var(--mono); font-weight: 600; }
.tbl .no  { color: var(--mute); font-family: var(--mono); }
.tbl .ro  { color: var(--signal); font-family: var(--mono); font-weight: 600; }
.band--ink .tbl .yes { color: var(--accent-lift); }
.band--ink .tbl .no { color: var(--ink-rule-2); }
.band--ink .tbl .ro { color: var(--signal-lift); }
.tbl-note { margin-top: 0.9rem; font-size: 0.8125rem; color: var(--mute); }

/* ----------------------------------------------------------------- form -- */

.form { display: grid; gap: 1.35rem; }
.form__row { display: grid; gap: 1.35rem; }
@media (min-width: 640px) { .form__row--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

.field { display: grid; gap: 0.5rem; }
.field__label {
  font-family: var(--mono);
  font-size: 0.6875rem;
  font-weight: 500;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--mute);
  display: flex;
  gap: 0.5rem;
  align-items: baseline;
}
.field__req { color: var(--accent); }
.field__opt { color: var(--mute); letter-spacing: 0.05em; }
.field__hint { font-size: 0.8125rem; color: var(--mute); }

.input, .select, .textarea {
  width: 100%;
  background: var(--paper-hi);
  border: 1px solid var(--edge);
  border-radius: var(--r-sm);
  padding: 0.8rem 0.95rem;
  font-size: 1rem;
  font-family: var(--sans);
  color: var(--ink);
  transition: border-color 0.3s var(--ease), box-shadow 0.3s var(--ease);
  -webkit-appearance: none;
  appearance: none;
}
.input::placeholder, .textarea::placeholder { color: #97A0AA; }
.input:hover, .select:hover, .textarea:hover { border-color: var(--mute); }
.input:focus, .select:focus, .textarea:focus {
  border-color: var(--accent);
  outline: none;
  box-shadow: 0 0 0 3px rgba(10, 87, 85, 0.12);
}
.textarea { resize: vertical; min-height: 9.5rem; line-height: 1.6; }

.select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5 6 6.5 11 1.5' fill='none' stroke='%2364584B' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 0.95rem center;
  padding-right: 2.6rem;
}

.checks { display: grid; gap: 0.7rem; }
@media (min-width: 560px) { .checks { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.check { display: flex; gap: 0.7rem; align-items: flex-start; cursor: pointer; font-size: 0.9375rem; }
.check input {
  appearance: none;
  -webkit-appearance: none;
  width: 17px; height: 17px;
  border: 1px solid var(--edge);
  border-radius: 6px;
  background: var(--paper);
  flex: none;
  margin: 0;
  margin-top: 4px;
  cursor: pointer;
  transition: border-color 0.25s var(--ease), background-color 0.25s var(--ease);
  position: relative;
}
.check input:checked { background: var(--accent); border-color: var(--accent); }
.check input:checked::after {
  content: "";
  position: absolute;
  left: 5px; top: 1.5px;
  width: 4px; height: 9px;
  border: solid var(--paper);
  border-width: 0 1.75px 1.75px 0;
  transform: rotate(45deg);
}
.check:hover input { border-color: var(--mute); }

.hp { position: absolute; left: -9999px; opacity: 0; pointer-events: none; height: 0; }

.form__status {
  font-size: 0.9375rem;
  line-height: 1.6;
  padding: 0.9rem 1.1rem;
  border-radius: var(--r-sm);
  border: 1px solid transparent;
  display: none;
}
.form__status.is-shown { display: block; }
.form__status--ok   { border-color: rgba(10, 87, 85, 0.3); background: var(--accent-wash); color: var(--accent-deep); }
.form__status--err  { border-color: rgba(180, 83, 26, 0.35); background: var(--signal-wash); color: var(--signal); }
.form__status--busy { border-color: var(--edge); background: var(--paper); color: var(--mute); }
.form__status a { text-decoration: underline; text-underline-offset: 3px; }

.btn[aria-busy="true"] { opacity: 0.6; pointer-events: none; }

/* ------------------------------------------------------------ CTA panel -- */

.cta {
  border: 1px solid var(--ink-rule);
  border-radius: var(--r-lg);
  background: var(--ink-2);
  padding: clamp(1.75rem, 4vw, 3.25rem);
  display: grid;
  gap: clamp(1.5rem, 3vw, 3rem);
  align-items: center;
}
@media (min-width: 860px) { .cta { grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr); } }
.cta__title { font-family: var(--serif); font-size: clamp(1.75rem, 3.2vw, 2.6rem); line-height: 1.1; letter-spacing: -0.018em; }
.cta__body { margin-top: 1rem; color: var(--ink-mute); max-width: 44ch; font-weight: 300; }

/* --------------------------------------------------------------- footer -- */

.footer { background: var(--ink); color: var(--ink-text); padding-block: clamp(3.5rem, 7vw, 5.5rem) 2.25rem; }
.footer__top {
  display: grid;
  gap: clamp(2.5rem, 5vw, 4rem);
  padding-bottom: clamp(2.5rem, 5vw, 3.5rem);
  border-bottom: 1px solid var(--ink-rule);
}
@media (min-width: 880px) { .footer__top { grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr) minmax(0, 1fr); } }

.footer__blurb { color: var(--ink-mute); font-size: 0.9375rem; max-width: 40ch; margin-top: 1.35rem; font-weight: 300; }

.footer__h {
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--ink-mute);
  margin-bottom: 1.15rem;
}
.footer__list { display: grid; gap: 0.65rem; }
.footer__list a { font-size: 0.9375rem; color: var(--ink-text); opacity: 0.82; transition: opacity 0.25s var(--ease), color 0.25s var(--ease); }
.footer__list a:hover { opacity: 1; color: var(--accent-lift); }

.footer__bottom {
  padding-top: 2rem;
  display: flex;
  flex-wrap: wrap;
  gap: 0.85rem 2rem;
  justify-content: space-between;
  align-items: center;
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.07em;
  color: var(--ink-mute);
  text-transform: uppercase;
}

/* --------------------------------------------------- product screenshots -- */

/* Real captures of the running software, taken by the product's own
   accessibility-audit harness on 2026-09-06 and prepared by
   scripts/shots.py: cropped and re-encoded, never composited, never
   retouched. The top chrome is cropped away on every capture that carried a
   facility wordmark, because a deployment name on a marketing page reads as a
   customer and there is no customer.

   The frame is a container around the file and nothing more: one hairline and
   a radius a size below the surfaces around it. NO DROP SHADOW, and that rule
   survived the 2026-09-09 redesign unchanged while almost everything else on
   the page gained one. A photograph of software that has been given a floating
   card shadow stops looking like evidence and starts looking like a sales
   asset, which is the opposite of why it is here. The radius is smaller than a
   card's for the same reason: the frame should read as a window onto the
   capture, not as another card in the layout.

   Two of these captures are dark, because the equipment console was restyled
   dark in September. They are not corrected toward the page. */

.shot { margin: 0; }

.shot__frame {
  border: 1px solid var(--rule);
  border-radius: var(--r-sm);
  overflow: hidden;
  background: var(--paper);
  line-height: 0;
}
.band--ink .shot__frame { border-color: var(--ink-rule); background: var(--ink-2); }

/* Height is reserved by the intrinsic width/height attributes on the image
   itself, so nothing reflows when a capture finishes decoding. */
.shot__img { width: 100%; height: auto; }

.shot--phone .shot__frame { max-width: 390px; margin-inline: auto; }

.shot__cap {
  margin-top: 0.95rem;
  font-size: 0.8125rem;
  line-height: 1.55;
  color: var(--mute);
}
.band--ink .shot__cap { color: var(--ink-mute); }
.shot__cap b { font-weight: 500; color: var(--ink); }
.band--ink .shot__cap b { color: var(--ink-text); }

.shots { display: grid; gap: clamp(1.75rem, 3.2vw, 2.75rem); }
@media (min-width: 760px) {
  .shots--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .shots--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

/* ---------------------------------------------------------------- metrics -- */

/* Audit figures. Serif numerals so they read as a printed result rather than a
   dashboard tile, and no percentage anywhere: the product refuses to render a
   compliance percentage, so its own site does not get to use one either. */

.metrics { display: grid; gap: clamp(1.75rem, 3.5vw, 2.75rem); }
@media (min-width: 720px)  { .metrics { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1040px) { .metrics { grid-template-columns: repeat(4, minmax(0, 1fr)); } }

.metric { border-top: 1px solid var(--rule); padding-top: 1.35rem; }
.band--ink .metric { border-top-color: var(--ink-rule); }

.metric__n {
  display: block;
  font-family: var(--serif);
  font-size: clamp(2.6rem, 5.5vw, 3.6rem);
  line-height: 1;
  letter-spacing: -0.025em;
}
.metric__u { font-family: var(--sans); font-size: 0.36em; letter-spacing: -0.01em; }
.metric__k {
  margin-top: 0.85rem;
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--accent);
}
.band--ink .metric__k { color: var(--accent-lift); }
.metric__v { margin-top: 0.6rem; font-size: 0.875rem; line-height: 1.6; color: var(--mute); }
.band--ink .metric__v { color: var(--ink-mute); }

/* -------------------------------------------------------------- tick list -- */

/* A plain enumerated list inside a note. No bullet glyph and no coloured dot:
   the note it sits in is already accent or signal, which is the only
   distinction these two lists need to carry. Hairlines do the rest. */

.tick-list { display: grid; gap: 0; }
.tick {
  padding-block: 0.7rem;
  border-top: 1px solid rgba(5, 22, 39, 0.09);
  font-size: 0.9375rem;
  line-height: 1.55;
  color: var(--mute);
}
.tick:first-child { border-top: 0; padding-top: 0; }
.tick:last-child { padding-bottom: 0; }
.tick b, .tick strong { color: var(--ink); font-weight: 500; }
.band--ink .tick { border-top-color: var(--ink-rule); color: var(--ink-mute); }
.band--ink .tick b, .band--ink .tick strong { color: var(--ink-text); }

/* ------------------------------------------------------------ tag rows -- */

/* A label and a status chip on one line, above a section title. */
.tagrow { display: flex; flex-wrap: wrap; align-items: center; gap: 0.7rem 1rem; }

/* ---------------------------------------------------------- reveal base -- */

[data-reveal] {
  opacity: 0;
  transform: translateY(20px);
  transition: opacity 0.85s var(--ease), transform 0.85s var(--ease);
  transition-delay: var(--d, 0s);
}
[data-reveal].is-in { opacity: 1; transform: none; }

[data-reveal="rule"] {
  transform: none;
  opacity: 1;
  clip-path: inset(0 100% 0 0);
  transition: clip-path 1.1s var(--ease);
  transition-delay: var(--d, 0s);
}
[data-reveal="rule"].is-in { clip-path: inset(0 0 0 0); }

[data-reveal="plain"] { transform: none; }

/* ------------------------------------------------------- reduced motion -- */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
  [data-reveal] { opacity: 1 !important; transform: none !important; clip-path: none !important; }
  .split__word > span { transform: none !important; }
  .dia__flow { stroke-dashoffset: 0 !important; }
  .plan__route { stroke-dashoffset: 0; animation: none; }
  .plan__pin, .plan__blocked { opacity: 1; animation: none; }
  .journey__track { height: auto !important; }
  .journey__stage { position: static; min-height: 0; padding-block: var(--band-sm); }
  .journey__inner { display: block; }
  .journey__steps { display: grid; gap: 3rem; }
  .journey__step, .journey__step + .journey__step {
    position: static; opacity: 1; visibility: visible; transform: none; inset: auto;
    padding-top: 2.25rem; border-top: 1px solid var(--ink-rule);
  }
  .journey__step:first-child { border-top: 0; padding-top: 0; }
  .journey__rail, .journey__art { display: none; }
}

/* ------------------------------------------------------------ no-script -- */

.no-js [data-reveal] { opacity: 1; transform: none; clip-path: none; }
.no-js .split__word > span { transform: none; }
.no-js .dia__flow { stroke-dashoffset: 0; }
.no-js .journey__track { height: auto; }
.no-js .journey__stage { position: static; min-height: 0; padding-block: var(--band-sm); }
.no-js .journey__inner { display: block; }
.no-js .journey__steps { display: grid; gap: 3rem; }
.no-js .journey__step,
.no-js .journey__step + .journey__step {
  position: static; opacity: 1; visibility: visible; transform: none; inset: auto;
  padding-top: 2.25rem; border-top: 1px solid var(--ink-rule);
}
.no-js .journey__step:first-child { border-top: 0; padding-top: 0; }
.no-js .journey__rail, .no-js .journey__art { display: none; }

/* ============================================================================
   ADDITIONS · 2026-09-09

   Five components the redesign needed and the old system had no vocabulary for.
   Each is here because a section was making an argument the available parts
   could not carry, not because a reference site happened to have one.

   There were six. A three-big-figures row was written, then deleted before this
   shipped: .metrics already did a multi-figure row and .statline already did a
   single one, so it was a third way of doing a job the file did twice.
   ========================================================================= */

/* ------------------------------------------------------------- hero stat -- */

/* One figure under the hero copy. It is a real number every time it is used,
   and it is the same number written in the sentence beside it: the rule the
   counter script already enforces, which is that the attribute repeats the
   text and never supplies it. */

.statline {
  margin-top: clamp(2.75rem, 5vw, 4rem);
  padding-top: 1.5rem;
  border-top: 1px solid var(--rule);
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 0.4rem 1.1rem;
}
.statline__n {
  font-family: var(--serif);
  font-size: clamp(3.25rem, 7vw, 5rem);
  line-height: 0.9;
  letter-spacing: -0.03em;
}
.statline__t {
  color: var(--mute);
  font-size: 0.9375rem;
  line-height: 1.55;
  max-width: 36ch;
}
.band--ink .statline { border-top-color: var(--ink-rule); }
.band--ink .statline__t { color: var(--ink-mute); }

/* ------------------------------------------------------------ comparison -- */

/* Two columns, and the left one is not a straw man. Every line on the left is
   a thing equipment-tracking software genuinely claims, and every line on the
   right names what in this product refuses it. No vendor is named, because the
   argument is about a design habit and not about a competitor. */

.cmp {
  border: 1px solid var(--rule);
  border-radius: var(--r-lg);
  background: var(--paper);
  box-shadow: var(--lift-1);
  overflow: hidden;
}
.cmp__head,
.cmp__row { display: grid; grid-template-columns: minmax(0, 1fr); }
@media (min-width: 780px) {
  .cmp__head,
  .cmp__row { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
}
.cmp__head { border-bottom: 1px solid var(--rule); background: var(--bone); }
.cmp__h {
  padding: 1.1rem clamp(1.25rem, 2.4vw, 2rem);
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--mute);
}
@media (min-width: 780px) {
  .cmp__h--mine { border-left: 1px solid var(--rule); background: var(--accent-wash); color: var(--accent); }
}
.cmp__row + .cmp__row { border-top: 1px solid var(--rule); }
.cmp__a,
.cmp__b { padding: clamp(1.15rem, 2.2vw, 1.65rem) clamp(1.25rem, 2.4vw, 2rem); }
.cmp__a { color: var(--mute); font-size: 0.9375rem; line-height: 1.65; }
.cmp__b { font-size: 0.9375rem; line-height: 1.65; }
@media (min-width: 780px) {
  .cmp__b { border-left: 1px solid var(--rule); background: rgba(232, 240, 236, 0.5); }
}
@media (max-width: 779px) {
  .cmp__head { display: none; }
  .cmp__a { padding-bottom: 0.5rem; }
  .cmp__a::before,
  .cmp__b::before {
    display: block;
    margin-bottom: 0.45rem;
    font-family: var(--mono);
    font-size: 0.625rem;
    letter-spacing: 0.13em;
    text-transform: uppercase;
  }
  .cmp__a::before { content: "Usually"; color: var(--mute); }
  .cmp__b::before { content: "Here"; color: var(--accent); }
}
.cmp__b b, .cmp__b strong { font-weight: 500; }
.cmp__cite {
  display: block;
  margin-top: 0.55rem;
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.03em;
  line-height: 1.5;
  color: var(--accent);
}

/* ------------------------------------------------------------------ FAQ -- */

/* Native <details>. It operates from the keyboard, it announces its own
   expanded state, it survives JavaScript failing, and a browser find matches
   text inside a closed one. An accordion built from divs and a click handler
   does none of that, and is the more common thing to find on a page like
   this. */

.faq { display: grid; }
.faq__item { border-top: 1px solid var(--rule); }
.faq__item:last-child { border-bottom: 1px solid var(--rule); }

.faq__q {
  list-style: none;
  cursor: pointer;
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1.5rem;
  padding-block: clamp(1.35rem, 2.4vw, 1.75rem);
  font-size: clamp(1.0625rem, 1.7vw, 1.25rem);
  line-height: 1.4;
  letter-spacing: -0.014em;
  transition: color 0.3s var(--ease);
}
.faq__q::-webkit-details-marker { display: none; }
.faq__q:hover { color: var(--accent); }

.faq__sign {
  flex: none;
  position: relative;
  width: 14px;
  height: 14px;
  margin-top: 0.4rem;
}
.faq__sign::before,
.faq__sign::after {
  content: "";
  position: absolute;
  inset: 50% 0 auto 0;
  height: 1.5px;
  background: var(--accent);
  transition: transform 0.4s var(--ease);
}
.faq__sign::after { transform: rotate(90deg); }
.faq__item[open] .faq__sign::after { transform: rotate(0deg); }

.faq__a {
  padding-bottom: clamp(1.35rem, 2.4vw, 1.75rem);
  max-width: 70ch;
  color: var(--mute);
  font-size: 0.9375rem;
  line-height: 1.7;
}
.faq__a p + p { margin-top: 0.9em; }
.faq__a strong, .faq__a b { color: var(--ink); font-weight: 500; }
.faq__item[open] .faq__a { animation: faq-in 0.45s var(--ease); }
@keyframes faq-in { from { opacity: 0; transform: translateY(-6px); } }

/* -------------------------------------------------------------- marquee -- */

/* The thirteen languages, moving. The set is duplicated in the markup and the
   track translates by exactly half its own width, which is the only way this
   loops without a seam. The second copy carries aria-hidden: a screen reader
   should hear the list once. */

.marquee {
  overflow: hidden;
  border-block: 1px solid var(--rule);
  padding-block: clamp(1.1rem, 2vw, 1.5rem);
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
          mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
}
.marquee__track {
  display: flex;
  width: max-content;
  animation: marquee 52s linear infinite;
}
.marquee:hover .marquee__track { animation-play-state: paused; }
.marquee__set { display: flex; flex: none; }
.marquee__item {
  display: flex;
  align-items: center;
  gap: 1.4rem;
  padding-inline: 1.4rem;
  font-size: 1.125rem;
  letter-spacing: -0.012em;
  white-space: nowrap;
}
.marquee__item::after {
  content: "";
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: var(--rule-strong);
}
.marquee__item[dir="rtl"] { direction: rtl; }
.marquee__tag {
  font-family: var(--mono);
  font-size: 0.625rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--accent);
}
@keyframes marquee { to { transform: translateX(-50%); } }
.band--ink .marquee { border-color: var(--ink-rule); }
.band--ink .marquee__item::after { background: var(--ink-rule-2); }
.band--ink .marquee__tag { color: var(--accent-lift); }
@media (prefers-reduced-motion: reduce) {
  .marquee { overflow-x: auto; }
  .marquee__track { animation: none; }
}
.no-js .marquee__track { animation: none; }

/* -------------------------------------------------------- scrubbed prose -- */

/* One sentence that arrives a word at a time as the page scrolls through it.
   Used once per page at most, on the line that section exists to say. site.js
   lights words as the block crosses the viewport; the unlit ones are dim
   rather than absent, so the sentence is legible at any scroll position and
   legible in full with the script dead. */

.scrub {
  font-family: var(--serif);
  font-size: clamp(1.75rem, 4.2vw, 3.1rem);
  line-height: 1.22;
  letter-spacing: -0.02em;
  max-width: 24ch;
}
.scrub--wide { max-width: 32ch; }
.scrub__w { opacity: 0.24; transition: opacity 0.5s var(--ease); }
.scrub__w.is-lit { opacity: 1; }
.no-js .scrub__w { opacity: 1; }
@media (prefers-reduced-motion: reduce) { .scrub__w { opacity: 1 !important; } }

/* ---------------------------------------------------- numbered principles -- */

/* Not a three-card row. A number, a claim, and the reason for it, on one line
   at desktop width, separated from the next by a rule rather than by two card
   edges and a gutter. */

.tenets { display: grid; gap: 0; }
.tenet {
  display: grid;
  gap: 0.85rem 3rem;
  padding-block: clamp(1.75rem, 3vw, 2.5rem);
  border-top: 1px solid var(--rule);
}
@media (min-width: 900px) {
  .tenet { grid-template-columns: 3.5rem minmax(0, 1.05fr) minmax(0, 1fr); align-items: start; }
}
.tenet:last-child { border-bottom: 1px solid var(--rule); }
.tenet__n {
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.14em;
  color: var(--accent);
  padding-top: 0.55rem;
}
.tenet__k {
  font-family: var(--serif);
  font-size: clamp(1.4rem, 2.6vw, 2rem);
  line-height: 1.13;
  letter-spacing: -0.018em;
}
.tenet__v { color: var(--mute); font-size: 0.9375rem; line-height: 1.7; }
.tenet__v strong, .tenet__v b { color: var(--ink); font-weight: 500; }
.band--ink .tenet { border-color: var(--ink-rule); }
.band--ink .tenet__n { color: var(--accent-lift); }
.band--ink .tenet__v { color: var(--ink-mute); }
.band--ink .tenet__v strong, .band--ink .tenet__v b { color: var(--ink-text); }
