/* Wellplanner marketing site, v2.
   Spec: docs/design/WEBSITE_SPEC.md, design: "Wellplanner Website v2.dc.html".
   The design file wins where the two disagree.

   The whole visual system is one rule at three scales: the mark is a disc cut
   by a wave, so section edges are wave cuts, giant discs sit behind heroes, and
   the lifecycle is drawn on the wave itself. Nothing else decorates this site -
   no gradients, patterns, textures or photography.

   Marketing runs dark by default, which is the inverse of the product. */

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

:root {
  /* Three darks and one white. There is no accent colour: status hues appear
     only inside product screenshots, where they carry real meaning. */
  --page: #08222a;
  --raised: #0b2b34;
  --footer: #061a20;
  --tint: #f6f8f8;
  /* Glacier. The palette is one deep, one surface, one ramp - this is the
     surface. Brand Profile §04: "a surface for large areas and chart fills,
     never text." So it never carries a letter, never signals status and never
     colours the mark, which stays navy on light and white on dark. Fathom 500
     on Glacier is 3.90:1 and fails, so anything sitting on it takes ink or
     ink-body, both of which clear AA. */
  --glacier: #c3dce3;
  --line: #ebefef;

  --on-dark-lede: rgba(255, 255, 255, 0.78);
  --on-dark-soft: rgba(255, 255, 255, 0.65);
  --on-dark-faint: rgba(255, 255, 255, 0.5);

  --ink: #0b2b34;
  --ink-body: #3d4747;
  --ink-meta: #5f6a6a;
  --rule-light: #d8dede;

  --display: "Space Grotesk", system-ui, sans-serif;
  --sans: "IBM Plex Sans", system-ui, sans-serif;
  --mono: "IBM Plex Mono", ui-monospace, monospace;

  --maxw: 1340px;
  --pad: clamp(20px, 4vw, 56px);
  --section-y: clamp(48px, 6vw, 112px);
}

/* Before anything else. Without it every authored min-height lands on the
   content box and the padding adds on top, which is how a 46px field comes
   out at 74px. */
*, *::before, *::after { box-sizing: border-box; }
html { scroll-behavior: smooth; }
body {
  margin: 0;
  font-family: var(--sans);
  font-size: 16px;
  line-height: 1.7;
  color: #fff;
  background: var(--page);
  overflow-x: hidden;
  -webkit-font-smoothing: antialiased;
}
a { color: inherit; text-decoration: none; }
img, svg { display: block; }
::selection { background: #fff; color: var(--page); }
h1, h2, h3 { font-family: var(--display); margin: 0; }

.container { max-width: var(--maxw); margin: 0 auto; padding: 0 var(--pad); }

/* ── Type ────────────────────────────────────────────────────────────────
   The headline is the design. At full size it is the largest element on the
   page by a wide margin, and everything else stays quiet around it.

   Measure caps live on the heading itself, never on a wrapper: ch resolves
   against the element's own font size, so a 19ch cap on a 16px wrapper would
   produce a 170px column. */
.h-hero {
  font-weight: 500;
  font-size: clamp(48px, 8.4vw, 118px);
  line-height: 0.94;
  letter-spacing: -0.042em;
  max-width: 14ch;
}
.h-page {
  font-weight: 500;
  font-size: clamp(38px, 6vw, 82px);
  line-height: 0.98;
  letter-spacing: -0.038em;
  max-width: 20ch;
}
.h-section {
  font-weight: 500;
  font-size: clamp(30px, 4vw, 56px);
  line-height: 1.04;
  letter-spacing: -0.03em;
  max-width: 22ch;
}
/* The closing call to action: larger than a section head, smaller than a hero,
   because it is the last thing read rather than the first. */
.h-cta {
  font-weight: 500;
  font-size: clamp(34px, 5.2vw, 72px);
  line-height: 1;
  letter-spacing: -0.035em;
  max-width: 16ch;
}
.h-card { font-family: var(--display); font-weight: 600; font-size: 19px; line-height: 1.25; }

.eyebrow {
  font-family: var(--mono);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--on-dark-faint);
  margin: 0;
}
.lede {
  font-size: clamp(17px, 1.4vw, 20px);
  line-height: 1.65;
  color: var(--on-dark-lede);
  margin: 0;
  max-width: 52ch;
  text-wrap: pretty;
}
.body { font-size: 16px; line-height: 1.7; color: var(--on-dark-soft); margin: 0; max-width: 58ch; }
.mono { font-family: var(--mono); }
.vh {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.note {
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.6);
  margin: 0;
}

/* On a white band the same roles take ink values. */
.band-white { background: #fff; color: var(--ink-body); }
.band-white h1, .band-white h2, .band-white h3 { color: var(--ink); }
.band-white .eyebrow, .band-white .note { color: var(--ink-meta); }
.band-white .lede, .band-white .body { color: var(--ink-body); }

/* ── Bands and wave edges ────────────────────────────────────────────────
   Every transition between a dark and a light band is a wave cut, alternating
   direction so one silhouette does not repeat down the page. */
.band { padding: var(--section-y) var(--pad); }
.band-page { background: var(--page); }
.band-raised { background: var(--raised); }
/* The tint step is what separates two light sections. They were one long band
   originally and are held apart by the step, not by a rule. */
.band-tint { background: var(--tint); color: var(--ink-body); }
.band-tint h1, .band-tint h2, .band-tint h3 { color: var(--ink); }
.band-tint .eyebrow, .band-tint .note { color: var(--ink-meta); }
.band-tint .lede, .band-tint .body { color: var(--ink-body); }

.wave { line-height: 0; }
.wave svg { display: block; width: 100%; height: clamp(38px, 4.6vw, 78px); }
.wave-flip svg { transform: scaleX(-1); }

/* A short wave rule above a column: the same figure at small scale. */
.wave-rule { position: absolute; top: 0; left: 0; width: 100%; height: 8px; }

/* ── Header ──────────────────────────────────────────────────────────────
   Full bleed and sticky, the same colour as the page so it dissolves into it. */
.site-header { position: sticky; top: 0; z-index: 40; background: var(--page); }
.nav {
  display: flex; align-items: center; justify-content: space-between;
  gap: 24px; padding: 0 var(--pad); flex-wrap: wrap;
}
/* The mark is bare at 44px and the wordmark sits beside it at 25px. Both
   together are the home link. The wordmark hides below 1100px, which is the
   one breakpoint on this site. */
.brand { display: flex; align-items: center; gap: 15px; padding: 18px 0; }
.brand img { width: 44px; height: 44px; }
.wordmark {
  font-family: var(--display); font-weight: 600; font-size: 25px;
  letter-spacing: 0.1em; text-transform: uppercase; color: #fff;
}
@media (max-width: 1100px) { .brand .wordmark { display: none; } }
.nav-links { display: flex; align-items: center; gap: 4px; flex-wrap: wrap; }
/* The padding scales with the viewport rather than through a breakpoint: at
   full width it sets the bar height, and on a phone the row wraps to two
   compact lines instead of three tall ones. 44px stays the floor. */
.nav-links a {
  display: inline-flex; align-items: center; min-height: 44px;
  /* 16px rather than the design file's 14px: the owner asked for a larger
     menu. Deliberate override, not drift - do not "correct" it back. */
  font-size: 16px; font-weight: 500; color: rgba(255, 255, 255, 0.7);
  padding: clamp(11px, 2.4vw, 26px) clamp(9px, 1vw, 14px);
  transition: color 160ms ease-out;
}
.nav-links a:hover, .nav-links a[aria-current="page"] { color: #fff; }
/* Every call to action is a real control, so it carries a pointer and a
   hover state whether it is a link or a button. */
.nav-links a, .btn { cursor: pointer; }

/* ── Buttons ─────────────────────────────────────────────────────────────
   Never transition background and colour together: the crossfade passes
   through a midpoint where the label is invisible against its own fill. */
.btn {
  display: inline-flex; align-items: center; justify-content: center;
  font-family: var(--sans); font-size: 15px; font-weight: 600;
  border: 1px solid transparent; border-radius: 8px; padding: 17px 30px;
  cursor: pointer; transition: background 160ms ease-out, border-color 160ms ease-out;
}
.btn-primary { background: #fff; color: var(--page); }
.btn-primary:hover { background: #e3e9e9; }
.btn-ghost {
  background: rgba(255, 255, 255, 0.08);
  border-color: rgba(255, 255, 255, 0.28); color: #fff;
}
.btn-ghost:hover { background: rgba(255, 255, 255, 0.16); }
/* On any white surface the primary inverts; the ghost becomes a bordered
   white button. The form card is a white surface inside a dark band. */
.band-white .btn-primary, .band-tint .btn-primary, .form-card .btn-primary { background: var(--ink); color: #fff; }
.band-white .btn-primary:hover, .band-tint .btn-primary:hover, .form-card .btn-primary:hover { background: #12414d; }
.band-white .btn-ghost, .band-tint .btn-ghost { background: #fff; border-color: var(--rule-light); color: var(--ink); }
.band-white .btn-ghost:hover, .band-tint .btn-ghost:hover { background: #ebefef; }

/* ── The menu button ─────────────────────────────────────────────────────
   Hidden above 700px, where every link is already in the bar. The bars are
   one element and two pseudo-elements, which is what lets them become a
   cross without a second icon. */
.nav-toggle {
  display: none; width: 48px; height: 48px; margin-right: -12px;
  align-items: center; justify-content: center;
  background: none; border: 0; padding: 0; cursor: pointer; color: #fff;
}
.nav-bars { position: relative; display: block; width: 22px; height: 2px; background: currentColor; }
.nav-bars::before, .nav-bars::after {
  content: ""; position: absolute; left: 0; width: 22px; height: 2px; background: currentColor;
  transition: transform 160ms ease-out;
}
.nav-bars::before { top: -7px; }
.nav-bars::after { top: 7px; }
.nav-toggle[aria-expanded="true"] .nav-bars { background: transparent; }
.nav-toggle[aria-expanded="true"] .nav-bars::before { transform: translateY(7px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] .nav-bars::after { transform: translateY(-7px) rotate(-45deg); }
.site-header-light .nav-toggle { color: var(--ink); }

/* Written against .nav-links a so it outranks the plain link colour above. */
.nav-links a.nav-cta {
  font-size: 16px; font-weight: 600; padding: 12px 22px; border-radius: 6px;
  margin-left: 12px; background: #fff; color: var(--page);
  transition: background 160ms ease-out;
}
.nav-links a.nav-cta:hover { background: #e3e9e9; color: var(--page); }

/* ── Discs ───────────────────────────────────────────────────────────────
   Sized in vw so they scale with the viewport, absolutely placed inside a
   section that clips them, and never interactive. */
.has-disc { position: relative; overflow: hidden; }
.has-disc > .container, .has-disc > .band-inner { position: relative; }
.disc { position: absolute; pointer-events: none; width: var(--s); height: var(--s); }

/* Sized in vw so the disc scales with the viewport, but capped at the size it
   has at 1440: past that the decoration would keep growing until it was the
   dominant field on the page rather than an arc behind the headline. The
   offsets are a fraction of the size, so the framing holds at every width.

   A disc must also fit inside the section that clips it. Where it does not,
   the band boundary saws it off in a straight line - which is what a giant
   disc behind a short hero looks like. */
.disc-hero { --s: min(74vw, 1060px); top: calc(var(--s) * -0.19); right: calc(var(--s) * -0.27); }
.disc-hero-sm { --s: min(58vw, 560px); top: calc(var(--s) * -0.30); right: calc(var(--s) * -0.34); }
.disc-top-left { --s: min(58vw, 560px); top: calc(var(--s) * -0.34); left: calc(var(--s) * -0.32); }
.disc-left { --s: min(46vw, 620px); bottom: calc(var(--s) * -0.52); left: calc(var(--s) * -0.30); }
.disc-bottom-right { --s: min(46vw, 620px); bottom: calc(var(--s) * -0.52); right: calc(var(--s) * -0.26); }
.disc-card { --s: 190px; right: -56px; bottom: -56px; }

/* A wave that closes a section carrying a disc belongs inside it, not between
   two sections: as a sibling its own background is an opaque strip that cuts
   the disc off square. Inside, the section's colour shows through the
   transparent half and the disc is cut by the wave itself - which is the
   whole idea of the mark. */
.wave-bottom { position: absolute; left: 0; right: 0; bottom: 0; background: none; }
.has-wave-bottom { padding-bottom: calc(var(--section-y) + clamp(38px, 4.6vw, 78px)); }

/* ── Footer ─────────────────────────────────────────────────────────────── */
.site-footer { background: var(--footer); padding: clamp(52px, 6vw, 80px) var(--pad) 34px; }
.footer-inner { max-width: var(--maxw); margin: 0 auto; display: flex; flex-direction: column; gap: 44px; }
.footer-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 32px; }
/* The mark is large here and carries the wordmark with it. */
.footer-lockup { display: flex; align-items: center; gap: 15px; }
.footer-lockup img { width: 40px; height: 40px; }
.footer-lockup .wordmark { font-size: 22px; }
/* Every low-alpha white label on the #061A20 footer is 0.62, not 0.4: below
   that it does not clear 4.5:1 on this ground. */
.footer-col h4 {
  margin: 0 0 12px; font-family: var(--mono); font-size: 11px; font-weight: 400;
  letter-spacing: 0.2em; text-transform: uppercase; color: rgba(255, 255, 255, 0.62);
}
.footer-col a, .footer-col span {
  display: block; font-size: 14px; color: rgba(255, 255, 255, 0.8); margin-bottom: 8px;
}
.footer-col a:hover { color: #fff; }
/* Documentation, API and the legal pages are not written yet. They sat in
   the footer styled exactly like links, which is how a reader ends up
   clicking one and finding nothing - the fault that Status was reported for.
   Until each has a page, it reads as a plain word rather than as a link. */
.footer-col span { color: rgba(255, 255, 255, 0.34); cursor: default; }
.footer-bottom {
  border-top: 1px solid rgba(255, 255, 255, 0.1); padding-top: 22px;
  display: flex; justify-content: space-between; gap: 20px; flex-wrap: wrap;
}
.footer-bottom span { font-family: var(--mono); font-size: 11px; color: rgba(255, 255, 255, 0.62); }
.footer-bottom a { color: rgba(255, 255, 255, 0.62); }
.footer-bottom a:hover { color: #fff; }

/* ══ PRODUCT SCREENSHOTS ═════════════════════════════════════════════════
   Five shots, built as live DOM rather than images: job list, mapping,
   workshop, finance and the rig app. They share one chrome - navy bar,
   wordmark, tenant name, four nav items with the active one white - so the
   chrome is defined once here and each shot writes only its own body.

   These are real interface, not illustrations. Every column, pill and figure
   is what the product shows, and the figures agree with each other: planned
   >= actual >= invoiced >= paid, and no percentage contradicts the figure
   beside it. The data is fictional but realistic, with Norwegian well and
   company names long enough to prove the layout survives real content.

   Status hues live only in here, where they carry meaning. Nothing outside a
   screenshot on this site is coloured. */

/* A screenshot of a desktop application cannot reflow into a phone: squeezing
   it turns every well name into an ellipsis, which destroys the one thing the
   shot is there to prove. So the shot keeps its true proportions and scrolls
   sideways inside its own frame instead. On a wide screen the minimum is never
   reached and nothing changes. */
.shot { background: #fff; overflow: auto hidden; min-width: 0; overscroll-behavior-x: contain; }
.shot-chrome, .shot-body { min-width: 760px; }
/* The hero shot runs up out of the section and into the wave edge below it. */
.shot-hero { border-radius: 16px 16px 0 0; box-shadow: 0 -30px 80px -20px rgba(0, 0, 0, 0.6); }
/* On a dark band the shot carries its own shadow; on white it takes a hairline. */
.shot-framed { border-radius: 16px; box-shadow: 0 30px 70px -28px rgba(0, 0, 0, 0.55); }
.shot-outlined { border-radius: 16px; border: 1px solid #ebefef; }

/* Every variable-width cell truncates rather than pushing the grid open. */
.shot .cell { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }

/* ── The shared chrome ─────────────────────────────────────────────────── */
.shot-chrome {
  background: var(--raised); padding: 13px 20px;
  display: flex; align-items: center; gap: clamp(10px, 1.4vw, 18px);
  border-bottom: 1px solid rgba(255, 255, 255, 0.12);
}
.shot-chrome .wordmark { font-size: 12px; flex-shrink: 0; }
.shot-chrome .sep { width: 1px; height: 14px; background: rgba(255, 255, 255, 0.22); flex-shrink: 0; }
/* On a narrow screen the tenant name gives way first: the nav is the part
   that has to stay readable, because it is what the shot is showing. */
.shot-tenant {
  font-size: 12px; color: rgba(255, 255, 255, 0.7);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0;
}
.shot-nav { display: flex; gap: clamp(9px, 1.2vw, 16px); margin-left: auto; flex-shrink: 0; }
.shot-nav span { font-size: 12px; color: rgba(255, 255, 255, 0.5); }
.shot-nav .is-active { color: #fff; }

.shot-body { padding: 22px 24px; display: flex; flex-direction: column; gap: 16px; }

/* ── The page header inside a shot ─────────────────────────────────────── */
.shot-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 16px; }
.shot-head-text { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.shot-eyebrow {
  font-family: var(--mono); font-size: 10px; letter-spacing: 0.18em;
  text-transform: uppercase; color: var(--ink-meta);
}
.shot-title { font-family: var(--display); font-size: 24px; font-weight: 500; letter-spacing: -0.02em; color: var(--ink); }
.shot-action {
  font-size: 12px; font-weight: 600; color: #fff; background: var(--ink);
  border-radius: 5px; padding: 10px 16px; white-space: nowrap; flex-shrink: 0;
}

/* ── Status pills ──────────────────────────────────────────────────────────
   A pill is the hue at 15 per cent behind a darkened version of the same hue,
   because no single label colour clears 4.5:1 on eleven status backgrounds. */
.pill {
  font-family: var(--mono); font-size: 9px; letter-spacing: 0.1em; text-transform: uppercase;
  padding: 4px 9px; border-radius: 999px; display: inline-block; white-space: nowrap;
  justify-self: start;
}
.pill-execute { background: #3f8f7326; color: #235f52; }
.pill-design { background: #a8863a26; color: #7e6224; }
.pill-prepare { background: #7e622426; color: #5e4a1b; }
.pill-close { background: #235f5226; color: #235f52; }
.pill-p100 { background: #1e587626; color: #1e5876; }
.pill-p90 { background: #35708f26; color: #2a5d77; }
.pill-received { background: #5c8ca626; color: #486d81; }
.pill-qa { background: #a8863a26; color: #7e6224; }
.pill-ready { background: #2e7d6b26; color: #235f52; }

/* ── 1. Job list ───────────────────────────────────────────────────────── */
.shot-kpis { display: grid; grid-template-columns: repeat(auto-fit, minmax(96px, 1fr)); gap: 10px; }
.kpi {
  border-radius: 9px; padding: 13px 15px; border: 1px solid #ebefef;
  display: flex; flex-direction: column;
}
.kpi-on { background: var(--ink); border-color: var(--ink); }
.kpi span {
  font-family: var(--mono); font-size: 8px; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--ink-meta);
}
.kpi b { font-family: var(--display); font-size: 22px; font-weight: 500; color: var(--ink); }
.kpi-on span { color: rgba(255, 255, 255, 0.65); }
.kpi-on b { color: #fff; }

.shot-table { border: 1px solid #ebefef; border-radius: 10px; overflow: hidden; }
.jobs-row {
  display: grid; grid-template-columns: minmax(0, 1.4fr) 108px minmax(0, 1.05fr) minmax(0, 0.75fr);
  gap: 12px; padding: 11px 16px; border-bottom: 1px solid #f2f5f5; align-items: center;
}
.jobs-row:last-child { border-bottom: none; }
.jobs-head { padding: 9px 16px; background: #f6f8f8; border-bottom: 1px solid #ebefef; }
.jobs-head span {
  font-family: var(--mono); font-size: 8px; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--ink-meta);
}
.jobs-row .well { font-size: 12px; color: #1a2224; }
.jobs-row .meta { font-size: 12px; color: var(--ink-body); }
.jobs-row .pill { font-size: 8px; }

/* ── 2. Mapping ────────────────────────────────────────────────────────── */
.map-row { display: grid; grid-template-columns: 210px minmax(0, 1fr); border-bottom: 1px solid #f2f5f5; }
.map-row:last-child { border-bottom: none; }
.map-head { background: #f6f8f8; border-bottom: 1px solid #ebefef; }
.map-label {
  padding: 13px 16px; font-size: 12px; color: #1a2224; border-right: 1px solid #ebefef;
}
.map-head .map-label {
  padding: 10px 16px; font-family: var(--mono); font-size: 8px;
  letter-spacing: 0.14em; text-transform: uppercase; color: var(--ink-meta);
}
.map-months, .map-track { display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); }
.map-months span {
  padding: 10px 8px; font-family: var(--mono); font-size: 9px;
  color: var(--ink-meta); border-right: 1px solid #ebefef;
}
.map-track { align-items: center; padding: 7px 0; }
/* Each bar states its own start month, length and status hue as data. */
.map-bar {
  grid-column: var(--col) / span var(--span); background: var(--hue);
  height: 22px; margin: 0 5px; border-radius: 4px; overflow: hidden;
  display: flex; align-items: center; padding: 0 5px;
}
/* The label carries its own surface: no single colour clears 4.5:1 on every bar. */
.map-bar span {
  font-family: var(--mono); font-size: 8px; letter-spacing: 0.06em; text-transform: uppercase;
  padding: 2px 6px; border-radius: 3px; background: rgba(255, 255, 255, 0.94); color: var(--ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* ── 3. Workshop ───────────────────────────────────────────────────────── */
.shot-chips { display: flex; gap: 8px; flex-wrap: wrap; }
.chip {
  font-family: var(--mono); font-size: 9px; letter-spacing: 0.08em; text-transform: uppercase;
  padding: 6px 11px; border-radius: 999px; white-space: nowrap;
}
.chip-inbound { background: #5c8ca61f; color: #486d81; }
.chip-qa { background: #7e62241f; color: #7e6224; }
.chip-ready { background: #235f521f; color: #235f52; }

.shot-rows { display: flex; flex-direction: column; gap: 8px; }
.tool-row {
  border: 1px solid #ebefef; border-radius: 8px; padding: 12px 14px;
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
}
.tool-id { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.tool-id b { font-size: 13px; font-weight: 600; color: #1a2224; }
.tool-id span { font-family: var(--mono); font-size: 10px; color: var(--ink-meta); }
.tool-act { display: flex; align-items: center; gap: 10px; flex-shrink: 0; }
.tool-act .shot-action { font-size: 11px; padding: 8px 13px; }

/* ── 4. Finance ────────────────────────────────────────────────────────────
   The figure and the bar read the same two custom properties, so a percentage
   cannot drift away from the amount beside it. */
.fin-planned { --hue: #1e5876; --pct: 100%; }
.fin-actual { --hue: #3f8f73; --pct: 38%; }
.fin-invoiced { --hue: #35708f; --pct: 15%; }
.fin-paid { --hue: #2e7d6b; --pct: 13%; }

.fin-stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); gap: 10px; }
.fin-stat { border: 1px solid #ebefef; border-radius: 9px; padding: 13px 15px; display: flex; flex-direction: column; }
.fin-stat span {
  font-family: var(--mono); font-size: 8px; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--ink-meta);
}
.fin-stat b { font-family: var(--display); font-size: 22px; font-weight: 500; font-variant-numeric: tabular-nums; color: var(--hue); }

.fin-bars { border: 1px solid #ebefef; border-radius: 10px; padding: 16px 18px; display: flex; flex-direction: column; gap: 11px; }
.fin-bar { display: grid; grid-template-columns: 82px minmax(0, 1fr) 42px; gap: 12px; align-items: center; }
.fin-bar > span { font-size: 12px; color: var(--ink-body); }
/* The unfilled part of the bar is a chart fill, which is what Glacier is
   for. The filled part keeps its status hue, because colour is reserved
   for data. */
.fin-bar > i { height: 12px; border-radius: 3px; background: var(--glacier); display: block; }
.fin-bar > i::after { content: ""; display: block; height: 100%; width: var(--pct); border-radius: 3px; background: var(--hue); }
.fin-bar > b {
  font-family: var(--mono); font-size: 10px; font-weight: 400;
  font-variant-numeric: tabular-nums; color: var(--ink-body); text-align: right;
}
/* A missing figure is named as a gap, never rendered as a zero. */
.fin-gap { border: 1px solid #ebefef; border-radius: 8px; padding: 12px 15px; display: flex; flex-direction: column; gap: 3px; }
.fin-gap b { font-size: 13px; font-weight: 600; color: var(--ink); }
.fin-gap span { font-size: 12px; line-height: 1.55; color: var(--ink-body); }

/* ── 5. Rig app ────────────────────────────────────────────────────────────
   Dark by default, every control at least 48 px, and offline is a state with
   a queue count rather than a blocked action. */
.rig-shot {
  background: var(--page); border: 1px solid rgba(255, 255, 255, 0.14); border-radius: 16px;
  overflow: hidden; box-shadow: 0 30px 60px -24px rgba(0, 0, 0, 0.6);
}
.rig-head {
  padding: 16px 20px; border-bottom: 1px solid rgba(255, 255, 255, 0.12);
  display: flex; align-items: center; justify-content: space-between; gap: 14px;
}
.rig-head b { font-size: 15px; font-weight: 600; color: #fff; }
.rig-badge {
  font-family: var(--mono); font-size: 10px; letter-spacing: 0.1em; text-transform: uppercase;
  padding: 5px 11px; border-radius: 999px; background: rgba(79, 203, 232, 0.19);
  color: #4fcbe8; white-space: nowrap;
}
.rig-row {
  padding: 15px 20px; border-bottom: 1px solid rgba(255, 255, 255, 0.07);
  display: flex; align-items: center; justify-content: space-between; gap: 14px;
}
.rig-tool { display: flex; flex-direction: column; gap: 5px; min-width: 0; }
.rig-tool b { font-size: 14px; font-weight: 600; color: #fff; }
.rig-tool span { font-family: var(--mono); font-size: 11px; color: rgba(255, 255, 255, 0.6); }
.rig-btn {
  font-size: 13px; font-weight: 600; color: #fff; border-radius: 7px;
  padding: 11px 17px; white-space: nowrap; flex-shrink: 0;
}
.rig-start { background: #2e7d6b; }
.rig-end { background: #b23b2e; }
.rig-offline { padding: 15px 20px; display: flex; align-items: center; gap: 11px; }
.rig-offline span { width: 7px; height: 7px; border-radius: 999px; background: #fff; flex-shrink: 0; }
.rig-offline b { font-size: 13px; font-weight: 400; color: rgba(255, 255, 255, 0.7); }

/* ══ PAGE FURNITURE ══════════════════════════════════════════════════════ */

.band-inner { max-width: var(--maxw); margin: 0 auto; }
.stack { display: flex; flex-direction: column; gap: 20px; }
.stack-sm { gap: 12px; }
.stack-md { gap: 26px; }
.stack-lg { gap: 34px; }
.stack-xl { gap: 46px; }
.btn-row { display: flex; gap: 12px; flex-wrap: wrap; }

/* Two columns that collapse without a breakpoint: headline left, copy right. */
.two-col {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
  gap: clamp(32px, 5vw, 72px); align-items: start;
}
.two-col-mid { align-items: center; }
.two-col-tight { gap: clamp(28px, 4vw, 60px); grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); }
.col-offset { padding-top: 8px; }

.bullets { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 9px; }
.bullets li {
  position: relative; padding-left: 17px; font-size: 15px; line-height: 1.6;
  color: rgba(255, 255, 255, 0.82);
}
.bullets li::before {
  content: ""; position: absolute; left: 0; top: 9px; width: 6px; height: 6px;
  border-radius: 999px; background: rgba(255, 255, 255, 0.5);
}
/* Both light grounds take the ink values, not just the white one. The dot is
   a plain 6px #A3ADAD: the mark is not a list bullet - it has a 20px floor
   and only two sanctioned uses inside the UI. */
.band-white .bullets li, .band-tint .bullets li { color: var(--ink-body); }
.band-white .bullets li::before, .band-tint .bullets li::before { background: #a3adad; }

/* ── Wave edges ────────────────────────────────────────────────────────────
   The fill is the colour of the band below; the background is the colour of
   the band above, so the cut reads as one band biting into the other. */
.wave-raised path { fill: var(--raised); }
.wave-white path { fill: #fff; }
.wave-page path { fill: var(--page); }
.wave-on-page { background: var(--page); }
.wave-on-raised { background: var(--raised); }
.wave-on-white { background: #fff; }
.wave-rule path { fill: none; stroke: rgba(255, 255, 255, 0.3); stroke-width: 1.4; }
.band-white .wave-rule path { stroke: #a3adad; }

/* ── Discs ───────────────────────────────────────────────────────────────
   One mask definition per page; every disc is that mask over a circle. */
.mask-defs { position: absolute; width: 0; height: 0; overflow: hidden; }
.disc svg { width: 100%; height: 100%; }
.disc-raised circle { fill: var(--raised); }
.disc-deep circle { fill: #0f3038; }
.disc-faint circle { fill: rgba(255, 255, 255, 0.045); }
.disc-top-left { top: -20vw; left: -18vw; width: 62vw; height: 62vw; }
.disc-bottom-right { bottom: -20vw; right: -14vw; width: 52vw; height: 52vw; }

/* ── Hero ────────────────────────────────────────────────────────────────
   The headline is the design: nothing else in a hero competes with it. */
.hero { position: relative; overflow: hidden; background: var(--page); padding: clamp(64px, 8vw, 118px) 0 0; }
.hero-inner { position: relative; max-width: var(--maxw); margin: 0 auto; padding: 0 var(--pad); }
.hero-copy { display: flex; flex-direction: column; gap: 26px; max-width: 46ch; margin-top: 38px; }
.hero-shot { position: relative; max-width: var(--maxw); margin: 56px auto 0; padding: 0 var(--pad); }
.hero-shot + .wave { margin-top: -1px; }
/* A page hero without a screenshot under it. */
.hero-plain { padding: clamp(56px, 7vw, 96px) var(--pad) clamp(48px, 6vw, 84px); }
.hero-plain .hero-inner { padding: 0; }

/* ── One data model, and the About principles ────────────────────────────
   A column under a small wave rule: the mark's figure at text scale. */
.rule-cols { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 28px; }
.rule-col { position: relative; padding-top: 18px; display: flex; flex-direction: column; gap: 9px; }
.noun {
  font-family: var(--display); font-weight: 500; font-size: clamp(26px, 2.6vw, 36px);
  letter-spacing: -0.02em; line-height: 1.05;
}
.rule-col p { margin: 0; font-size: 14px; line-height: 1.6; color: var(--on-dark-soft); }
.band-white .rule-col p { color: var(--ink-body); }

/* ── The lifecycle thread ──────────────────────────────────────────────────
   The five stage markers sit at the computed y of the wave path itself, so
   the thread and the mark are one figure rather than dots near a line. The
   svg keeps a fixed 96px height, so those y values hold at any width. */
/* Same rule as the screenshots: five stage labels in 59px each is not a
   smaller version of this figure, it is a broken one. */
.scroll-x { overflow: auto hidden; overscroll-behavior-x: contain; }
.thread { position: relative; width: 100%; min-width: 620px; }
.thread > svg { display: block; width: 100%; height: 96px; }
.thread > svg path { fill: none; stroke: rgba(255, 255, 255, 0.22); stroke-width: 2; }
.thread-dots, .thread-labels { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); }
.thread-dots { position: absolute; inset: 0; }
.thread-dots div { position: relative; }
.thread-dots span {
  position: absolute; top: var(--top); left: 50%; margin-left: -7.5px;
  width: 15px; height: 15px; border-radius: 999px;
  background: var(--hue); box-shadow: 0 0 0 5px var(--raised);
}
.thread-labels { gap: 10px; margin-top: 8px; }
.thread-labels div { display: flex; flex-direction: column; gap: 5px; align-items: center; text-align: center; }
.thread-labels b {
  font-family: var(--mono); font-size: 12px; font-weight: 500;
  letter-spacing: 0.16em; text-transform: uppercase; color: #fff;
}
.thread-labels span { font-size: 12px; line-height: 1.5; color: rgba(255, 255, 255, 0.55); }

/* ── Surface cards ───────────────────────────────────────────────────────
   Each carries a faint disc in its corner and leads to its own page. */
.cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 20px; }
.card {
  position: relative; overflow: hidden; background: var(--raised); border-radius: 16px;
  padding: 28px; display: flex; flex-direction: column; gap: 14px;
  transition: background 160ms ease-out;
}
.card:hover { background: #12414d; }
.card > *:not(.disc) { position: relative; }
.card-icon {
  width: 42px; height: 42px; border-radius: 10px; background: rgba(255, 255, 255, 0.1);
  display: flex; align-items: center; justify-content: center;
}
.card-icon svg { width: 20px; height: 20px; stroke: #fff; stroke-width: 1.5; fill: none; stroke-linecap: round; stroke-linejoin: round; }
.card h3 { font-family: var(--display); font-size: 20px; font-weight: 600; }
.card p { margin: 0; font-size: 14px; line-height: 1.65; color: rgba(255, 255, 255, 0.68); }
.card-more {
  margin-top: auto; padding-top: 4px; font-family: var(--mono); font-size: 11px;
  letter-spacing: 0.16em; text-transform: uppercase; color: rgba(255, 255, 255, 0.6);
}

/* ── Also included, and the About facts ──────────────────────────────────── */
.extras { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 26px; }
.extra { display: flex; flex-direction: column; gap: 7px; border-top: 2px solid var(--ink); padding-top: 15px; }
.extra b { font-family: var(--display); font-size: 17px; font-weight: 600; color: var(--ink); }
.extra span { font-size: 14px; line-height: 1.65; color: var(--ink-body); }
.band-page .extra, .band-raised .extra { border-top-color: rgba(255, 255, 255, 0.35); }
.band-page .extra b, .band-raised .extra b { color: #fff; }
.band-page .extra span, .band-raised .extra span { color: var(--on-dark-soft); }

.facts { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 20px; }
.fact { display: flex; flex-direction: column; gap: 5px; }
.fact dt {
  font-family: var(--mono); font-size: 10px; letter-spacing: 0.16em;
  text-transform: uppercase; color: rgba(255, 255, 255, 0.45);
}
.fact dd { margin: 0; font-size: 15px; color: #fff; }

/* ── Numbered surface sections on the Product page ───────────────────────── */
.surface-shot { margin-top: 36px; }

/* ── Contact ─────────────────────────────────────────────────────────────
   Minimum 44px on every control, 48px on inputs, and the segment question is
   buttons rather than a dropdown because it has four options. */
.contact-block { display: flex; flex-direction: column; gap: 18px; border-top: 1px solid rgba(255, 255, 255, 0.14); padding-top: 26px; }
.contact-block > .note { font-size: 10px; letter-spacing: 0.18em; color: rgba(255, 255, 255, 0.62); }
/* Written after the dark rule above, and at the same specificity, so the
   light ground wins on order rather than by accident. */
.band-white .contact-block > .note { color: var(--ink-meta); }
.note-sm { font-size: 10px; letter-spacing: 0.18em; }
/* Contact now sits on a white page rather than in a dark hole, so the key,
   the value and the rule above "what to bring" all take ink values. */
.band-white .contact-block { border-top-color: var(--line); }
.band-white .contact-row dt { color: var(--ink-meta); }
.band-white .contact-row dd { color: #1a2224; }
.contact-rows { display: flex; flex-direction: column; gap: 12px; margin: 0; }
.contact-row { display: grid; grid-template-columns: 92px minmax(0, 1fr); gap: 14px; align-items: baseline; }
.contact-row dt { font-size: 14px; color: rgba(255, 255, 255, 0.55); }
.contact-row dd { margin: 0; font-size: 15px; color: #fff; }
.contact-row a:hover { text-decoration: underline; }

/* The form sits on a page rather than floating in a hole: a tinted card with
   a hairline border and no shadow. */
.form-card {
  background: var(--tint); color: var(--ink-body); border: 1px solid var(--line);
  border-radius: 16px; padding: clamp(28px, 3vw, 40px);
  display: flex; flex-direction: column; gap: 18px;
}
.form-card h2 { font-family: var(--display); font-size: 22px; font-weight: 500; letter-spacing: -0.02em; color: var(--ink); }
.form-card .meta { font-size: 14px; line-height: 1.6; color: var(--ink-meta); }
.field { display: flex; flex-direction: column; gap: 7px; }
.field > label, .field > span { font-size: 13px; font-weight: 500; color: var(--ink-body); }
.field-pair { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 14px; }
/* 46px, which is the authored height and is what it measures now that the
   reset puts padding inside the box. */
.form-card input, .form-card textarea {
  font-family: var(--sans); font-size: 15px; color: #1a2224; background: #fff;
  border: 1px solid var(--rule-light); border-radius: 10px; padding: 13px 15px;
  min-height: 46px; width: 100%; outline: none;
  transition: border-color 160ms ease-out;
}
.form-card textarea { min-height: 96px; resize: vertical; }
.form-card input:focus, .form-card textarea:focus { border-color: var(--ink); }
.form-card input::placeholder, .form-card textarea::placeholder { color: #a3adad; }
.segments { display: flex; gap: 8px; flex-wrap: wrap; }
.segment {
  font-family: var(--sans); font-size: 14px; font-weight: 600; cursor: pointer;
  border-radius: 8px; padding: 12px 18px; min-height: 44px;
  background: #fff; border: 1px solid var(--rule-light); color: var(--ink);
  transition: background 160ms ease-out, border-color 160ms ease-out;
}
.segment:hover { background: #f6f8f8; }
.segment input { position: absolute; opacity: 0; pointer-events: none; }
.segment:has(input:checked) { background: var(--ink); border-color: var(--ink); color: #fff; }
.segment:has(input:focus-visible) { outline: 2px solid var(--ink); outline-offset: 2px; }
.form-send { min-height: 52px; padding: 16px; width: 100%; }
.form-note { font-size: 13px; line-height: 1.6; color: var(--ink-meta); }

/* ══ WEBSITE C COMPONENTS ════════════════════════════════════════════════ */

/* The lead hero on Home: taller than a page hero, and the only place the
   headline runs to 118px. */
.hero-lead {
  position: relative; overflow: hidden; background: var(--page);
  padding: clamp(72px, 9vw, 132px) var(--pad) clamp(80px, 10vw, 140px);
}
.hero-lead .hero-inner { padding: 0; }
.lede-lg {
  font-size: clamp(18px, 1.5vw, 22px); line-height: 1.6; margin: 0;
  color: rgba(255, 255, 255, 0.8); max-width: 54ch; text-wrap: pretty;
}
/* A statement heading: larger than a section head, smaller than a hero. */
.h-statement {
  font-family: var(--display); font-weight: 500; margin: 0;
  font-size: clamp(32px, 4.8vw, 64px); line-height: 1; letter-spacing: -0.035em;
  max-width: 17ch;
}
.btn-sm { padding: 15px 26px; }
.disc-visibility { --s: min(58vw, 835px); bottom: calc(var(--s) * -0.41); left: calc(var(--s) * -0.34); }
.figures-tight { grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 28px; }

/* Swell sits where a hero disc would, capped at its size at 1440 so it stays
   an arc on a large display rather than becoming the field. */
.swell {
  --s: min(56vw, 806px); position: absolute; pointer-events: none;
  width: var(--s); height: var(--s);
  top: calc(var(--s) * -0.32); right: calc(var(--s) * -0.25);
}
.swell svg { width: 100%; height: 100%; }

/* ── The cut disc, set as a figure ───────────────────────────────────────
   One disc, cut by the wave. No satellites: a plain circle is not part of
   this system, and the mark only ever appears as the disc and the wave. */
/* An <img> rather than an inline masked <svg>: iOS Safari drops the mask on
   an inline SVG sized with height:auto and paints a bare circle instead of
   a disc cut by a wave. The same file as an <img> is correct there - it is
   the header mark on every page. */
.disc-figure { display: block; width: 100%; max-width: 440px; aspect-ratio: 1; margin: 0 auto; }

/* ── A figure under a wave rule ──────────────────────────────────────────
   A ring reads as a proportion, so only a proportional figure could carry
   one. These are not all proportions, so none of them do: the number is set
   large in the display face under the same rule the scale figures use. */
.figures { display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); gap: 24px; }
.figure { position: relative; padding-top: 18px; display: flex; flex-direction: column; gap: 10px; align-items: flex-start; }
/* The number is qualified with its element, because a bare .figure-n would
   lose to the .figure span rule below it on specificity, not on order. */
.figure span.figure-n {
  font-family: var(--display); font-size: clamp(34px, 4vw, 52px); font-weight: 500;
  letter-spacing: -0.03em; line-height: 1; color: var(--ink);
}
.figure b { font-family: var(--display); font-size: 19px; font-weight: 600; color: var(--ink); }
.figure span { font-size: 14px; line-height: 1.6; color: var(--ink-meta); max-width: 26ch; }
.band-page .figure span.figure-n, .band-raised .figure span.figure-n,
.band-page .figure b, .band-raised .figure b { color: #fff; }
.band-page .figure span, .band-raised .figure span { color: rgba(255, 255, 255, 0.62); }
/* Every figure states its basis. */
.basis { font-size: 13px; line-height: 1.6; color: var(--ink-meta); max-width: 76ch; margin: 0; }
.band-page .basis, .band-raised .basis { color: rgba(255, 255, 255, 0.62); }

/* ── Credentials, which is the honest replacement for a logo wall ──────── */
.cred-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 20px; }
.cred {
  background: #fff; border: 1px solid var(--line); border-radius: 14px;
  padding: 24px; display: flex; flex-direction: column; gap: 9px;
}
.cred dt {
  font-family: var(--mono); font-size: 10px; letter-spacing: 0.18em;
  text-transform: uppercase; color: var(--ink-meta);
}
.cred dd { margin: 0; font-family: var(--display); font-size: 17px; font-weight: 600; line-height: 1.25; color: var(--ink); }

/* ── FAQ. A details element, so it opens with no script. ───────────────── */
.faq { display: flex; flex-direction: column; }
.faq details { border-top: 1px solid var(--line); }
.faq details:last-of-type { border-bottom: 1px solid var(--line); }
.faq summary {
  list-style: none; cursor: pointer; padding: 20px 0;
  display: flex; align-items: flex-start; justify-content: space-between; gap: 20px;
  font-family: var(--display); font-size: 17px; font-weight: 600; line-height: 1.35; color: var(--ink);
}
.faq summary::-webkit-details-marker { display: none; }
/* The sign is two rules; the vertical one is hidden when the panel is open. */
.faq summary svg { flex-shrink: 0; margin-top: 4px; stroke: var(--ink-meta); }
.faq details[open] summary .sign-v { display: none; }
.faq p { margin: 0 0 20px; font-size: 15px; line-height: 1.7; color: var(--ink-body); max-width: 62ch; }

/* ── Solution stages ─────────────────────────────────────────────────────
   The same shape three times, because the argument is that each artefact is
   the next artefact. */
.stage-tags { display: flex; gap: 10px; flex-wrap: wrap; padding-top: 8px; }
/* The tags are real controls: each one jumps to its stage. */
.stage-tag {
  display: inline-flex; align-items: center; min-height: 44px;
  font-family: var(--mono); font-size: 11px; letter-spacing: 0.14em; text-transform: uppercase;
  color: rgba(255, 255, 255, 0.75); border: 1px solid rgba(255, 255, 255, 0.24);
  border-radius: 999px; padding: 10px 18px;
  transition: background 160ms ease-out, border-color 160ms ease-out;
}
.stage-tag:hover { background: rgba(255, 255, 255, 0.08); border-color: rgba(255, 255, 255, 0.45); }
.stage-mark { display: flex; align-items: center; gap: 11px; color: var(--ink-meta); }
.stage-mark span {
  font-family: var(--mono); font-size: 11px; letter-spacing: 0.22em;
  text-transform: uppercase; color: var(--ink-meta);
}

/* ── The module list, for anyone doing diligence ─────────────────────────── */
.modules { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 30px; }
.module { display: flex; flex-direction: column; gap: 12px; }
.module h3 { font-family: var(--display); font-size: 17px; font-weight: 600; color: #fff; }
.module ul { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 7px; }
.module li { font-size: 14px; line-height: 1.55; color: rgba(255, 255, 255, 0.68); }
.module a:hover { color: #fff; text-decoration: underline; }

/* ── A key and value list, used for security and tenancy ─────────────────── */
.kv { display: flex; flex-direction: column; gap: 14px; margin: 0; }
.kv div {
  display: grid; grid-template-columns: 150px minmax(0, 1fr); gap: 16px; align-items: baseline;
  border-bottom: 1px solid rgba(255, 255, 255, 0.12); padding-bottom: 13px;
}
.kv dt {
  font-family: var(--mono); font-size: 11px; letter-spacing: 0.14em;
  text-transform: uppercase; color: rgba(255, 255, 255, 0.62);
}
.kv dd { margin: 0; font-size: 15px; line-height: 1.55; color: #fff; }

/* ── The BHA builder shot ────────────────────────────────────────────────
   The one screen that shows the tool string as an object rather than a row:
   a template list, the job header, and the string itself top to bit. */
.bha-cols { display: grid; grid-template-columns: 260px minmax(0, 1fr); gap: 20px; align-items: start; }
.bha-panel { border: 1px solid var(--line); border-radius: 12px; padding: 16px; display: flex; flex-direction: column; gap: 12px; }
.bha-panel h4 { margin: 0; font-family: var(--display); font-size: 15px; font-weight: 600; color: var(--ink); }
.bha-tpl { padding: 9px 11px; display: flex; flex-direction: column; gap: 2px; border: 1px solid transparent; border-radius: 6px; }
.bha-tpl b { font-size: 12px; font-weight: 400; color: #1a2224; }
.bha-tpl span { font-family: var(--mono); font-size: 10px; color: var(--ink-meta); }
.bha-tpl-on { border-color: #7e6224; background: rgba(168, 134, 58, 0.1); }
.bha-tpl-on b { font-weight: 600; color: var(--ink); }
.bha-meta { display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); border: 1px solid var(--line); border-radius: 10px; overflow: hidden; }
.bha-meta div { padding: 11px 14px; border-right: 1px solid var(--line); display: flex; flex-direction: column; gap: 3px; }
.bha-meta div:last-child { border-right: none; }
.bha-meta dt {
  font-family: var(--mono); font-size: 8px; letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--ink-meta);
}
.bha-meta dd { margin: 0; font-size: 12px; color: #1a2224; }
.bha-meta .num { font-family: var(--mono); }
.bha-row {
  display: grid; grid-template-columns: 26px minmax(0, 2fr) minmax(0, 1.1fr) 58px 58px minmax(0, 0.9fr);
  gap: 12px; padding: 10px 16px; border-bottom: 1px solid #f2f5f5; align-items: center;
}
.bha-row:last-child { border-bottom: none; }
.bha-head { padding: 9px 16px; background: var(--tint); border-bottom: 1px solid var(--line); }
.bha-head span {
  font-family: var(--mono); font-size: 8px; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--ink-meta);
}
.bha-row .n { font-family: var(--mono); font-size: 11px; color: var(--ink-meta); }
.bha-row .name { font-size: 12px; color: #1a2224; }
/* Quantities are measured, so they are mono and tabular: the columns line up
   and a decimal reads against the one above it. */
.bha-row .num { font-family: var(--mono); font-size: 11px; font-variant-numeric: tabular-nums; color: var(--ink-body); }

/* ══ ICONS ═══════════════════════════════════════════════════════════════
   One component, two sets: Heroicons v2 outline for what any business
   application needs, and eight domain glyphs for what no general library has.
   Both live in assets/icons.svg and are drawn on the same 24px grid at 1.5
   stroke in currentColor, so a glyph takes the colour of the text beside it.

   Sizes are 16, 20 and 22px inline, and 22px inside a 44px navy holder. If a
   concept is in neither set it does not get an icon - a word beats a guessed
   glyph. */
.icon {
  width: 20px; height: 20px; flex-shrink: 0;
  fill: none; stroke: currentColor; stroke-width: 1.5;
  stroke-linecap: round; stroke-linejoin: round;
}
.icon-16 { width: 16px; height: 16px; }
.icon-22 { width: 22px; height: 22px; }
.icon-holder {
  width: 44px; height: 44px; border-radius: 10px; background: var(--raised);
  display: flex; align-items: center; justify-content: center; color: #fff; flex-shrink: 0;
}
.band-white .icon-holder, .band-tint .icon-holder { background: var(--ink); }

/* ══ MOTION ══════════════════════════════════════════════════════════════
   Six named studies exist; this site ships three. Fleet is the only
   sanctioned dark-section background treatment - never a gradient, never a
   photograph, never a grid.

   Two rules that fail silently, because reduced motion clears animation and
   transform but nothing else:
     1. An animated element rests at the START of its story, so whatever it
        rests at is what a reduced-motion reader sees.
     2. transform never carries layout. A centring translate would be
        destroyed along with the animation, so centring is done with
        line-height, margin or inset instead.
   Percentage margin also resolves against width, not height, so a fraction of
   height is positioned with top inside an overflow: hidden parent. */

/* 03 Fleet. Several discs at different sizes, one continuous wave cutting all
   of them, drifting on an 18s linear loop. Each disc is cut where the wave
   happens to meet it, so no two are cut alike and all are visibly governed by
   one rule. */
.fleet { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }

/* ── Hero video ──────────────────────────────────────────────────────────
   Full bleed under the copy. The clip is dark, but the joint it shows runs
   straight through the headline's middle line, so a flat wash of the page
   colour sits over it - not a gradient and not a new colour, the page's own
   #08222A at 58% - which keeps white type legible over the brightest frame
   and keeps the video visibly a video rather than a texture. */
.hero-has-video .hero-video {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; object-position: center; pointer-events: none;
  background: var(--page);
}
.hero-has-video .hero-scrim { position: absolute; inset: 0; background: rgba(8, 34, 42, 0.58); pointer-events: none; }
.hero-has-video .hero-inner { position: relative; z-index: 1; }
/* Over the video the header is glass: it takes no space and no colour, so
   the clip runs to the top edge and the copy sits at the same height it
   always did. Once the page scrolls it fixes to the top and takes the page
   colour back, which is what a sticky header was for. On a phone it stays
   out of the way and scrolls off with the hero, as before. */
.home-video .site-header {
  position: absolute; top: 0; left: 0; right: 0;
  background: transparent; transition: background 200ms ease-out;
}
.home-video .site-header.is-scrolled { position: fixed; background: var(--page); }
.home-video .hero-has-video { padding-top: calc(80px + clamp(64px, 8vw, 118px)); }
@media (max-width: 700px) {
  .home-video .site-header.is-scrolled { position: absolute; background: transparent; }
  .home-video .hero-has-video { padding-top: calc(62px + clamp(64px, 8vw, 118px)); }
}

/* Pages with a subnav: it hangs under the glass header, glass itself, and
   the hero pads for both. It scrolls away with the hero while the header
   fixes, which is the behaviour the phone already had. */
.home-video.has-subnav .subnav {
  position: absolute; top: 80px; left: 0; right: 0; z-index: 39;
  background: transparent;
}
.home-video.has-subnav .hero-has-video { padding-top: calc(126px + clamp(64px, 8vw, 118px)); }
@media (max-width: 700px) {
  .home-video.has-subnav .subnav { top: 62px; }
  .home-video.has-subnav .hero-has-video { padding-top: calc(108px + clamp(64px, 8vw, 118px)); }
}

/* Company: the bore is pinned to the same point of the box at every
   viewport, so it sits right of the copy whatever the crop, and the
   headline is sized to stay left of the ring. */
.has-disc.hero-has-video .hero-video { object-position: 66.18% 44.22%; }
.has-disc.hero-has-video .h-page { font-size: clamp(34px, 3.4vw, 50px); max-width: 21ch; }
.has-disc.hero-has-video .lede { max-width: 50ch; }

/* Anyone who has asked for less motion gets the still. */
@media (prefers-reduced-motion: reduce) {
  .hero-has-video .hero-video { display: none; }
  .hero-has-video { background: var(--page) url("assets/hero-poster.jpg") center / cover no-repeat; }
}
@keyframes wp-fleet-drift { from { transform: translateX(0); } to { transform: translateX(360px); } }

/* 04 Swell. Amplitude flexes, band thickness fixed. Ambient rather than
   eventful, which is why it carries the one page with no product on it. The
   flat-wave layer rests at opacity 1 - the start of its story - so reduced
   motion leaves the mark cut, not a featureless circle. */
@keyframes wp-swell { 0%, 100% { opacity: 1; } 50% { opacity: 0; } }


/* ── Solution sub-nav ─────────────────────────────────────────────────────
   The five surface pages hang off Solution and previously reached each other
   only through the footer. This is a peer row, not a dropdown: no JavaScript,
   no hover menu, and it wraps on a phone like everything else. It sits under
   the sticky header on the same ground, so it reads as chrome rather than as
   page content. */
.subnav {
  background: var(--page);
  border-bottom: 1px solid rgba(255, 255, 255, 0.12);
  padding: 0 var(--pad);
}
.subnav-inner {
  max-width: var(--maxw); margin: 0 auto;
  display: flex; flex-wrap: wrap; gap: 2px; align-items: center;
}
.subnav a {
  display: inline-flex; align-items: center; min-height: 44px;
  padding: 10px 14px;
  font-size: 15px; color: rgba(255, 255, 255, 0.7);
  transition: color 160ms ease-out;
}
.subnav a:hover { color: #fff; }
/* The current page is white and carries a rule, so position is readable
   without relying on colour alone. */
.subnav a[aria-current="page"] {
  color: #fff;
  box-shadow: inset 0 -2px 0 0 #fff;
}

/* ── Mobile ──────────────────────────────────────────────────────────────
   Every grid on this site collapses on its own, so the body needs no
   breakpoint. The chrome does.

   The header used to claim it wrapped to two rows here. It wrapped to three -
   mark, then links, then the demo button - because the button is inside
   .nav-links and a flex row breaks wherever it runs out of width. That was
   200px of header on a 375px phone, a quarter of the screen.

   Laying those links out on a tidier second row was still not a menu; it was
   a desktop nav folded in half. So this is a menu: one bar holding the mark
   and a button, and a panel that covers the page when it is opened. The
   demo button moves into the panel as its only filled control rather than
   competing with the mark in a 375px bar.

   The panel is collapsed under .js only, set by an inline snippet in <head>
   before first paint. That keeps the links from flashing open on load, and
   leaves a browser with scripting off showing the plain row rather than no
   navigation at all. The footer carries every page regardless. */
@media (max-width: 700px) {
  /* A sticky header would hold that chrome for the whole scroll. */
  .site-header { position: static; }

  /* Positioned, because the panel hangs off it. */
  .nav { position: relative; }
  .brand { padding: 12px 0; }
  .brand img { width: 38px; height: 38px; }

  /* One row that scrolls beats two rows that wrap: the surface pages carry
     six sub-links, and wrapping them doubles the chrome all over again. */
  .subnav-inner { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; }
  .subnav-inner::-webkit-scrollbar { display: none; }
  .subnav a { padding: 10px 12px; white-space: nowrap; }

  /* The footer is the main navigation on a phone - it carries every page the
     header does not - so its links get a real tap target instead of the
     desktop's tight stack. */
  .footer-col a { min-height: 40px; display: flex; align-items: center; }

  /* 10px is legible on a laptop at arm's length and is not on a phone. */
  .note { font-size: 12px; }

  /* The mark on its own is not the brand. Hiding the wordmark makes sense at
     1100px, where it is competing with a full nav for the same row; on a
     phone the bar holds only the mark and the menu button, so it fits. */
  .brand .wordmark { display: block; font-size: 17px; letter-spacing: 0.08em; }
  .brand { gap: 11px; }

  /* One bar: mark on the left, menu button on the right. */
  .nav { flex-wrap: nowrap; gap: 0; justify-content: space-between; }
  .nav-toggle { display: inline-flex; }

  /* The panel. Absolute rather than in flow, so opening it covers the page
     instead of pushing the hero down the screen. */
  .js .nav-links {
    display: none;
    position: absolute; top: 100%; left: 0; right: 0;
    flex-direction: column; align-items: stretch; gap: 0;
    /* Raised rather than page, so the panel reads as a surface over the
       hero instead of bleeding into it. Dark mode carries no shadows, so
       the step has to do that work. */
    background: var(--raised);
    border-bottom: 1px solid rgba(255, 255, 255, 0.14);
    padding: 4px var(--pad) 22px;
    z-index: 50;
  }
  .js .nav-links.is-open { display: flex; }
  .nav-links a:not(.nav-cta) {
    min-height: 54px; font-size: 17px; padding: 0;
    border-bottom: 1px solid rgba(255, 255, 255, 0.1);
  }
  /* The call to action is the last thing in the panel and the only filled
     control in it, so it does not need to compete in the bar as well. */
  .nav-links a.nav-cta {
    margin: 18px 0 0; justify-content: center;
    font-size: 16px; padding: 16px 20px; border-radius: 8px;
  }

  /* The light header repaints the panel rather than redesigning it. */
  .site-header-light .nav-links { background: #fff; border-bottom-color: var(--rule-light); }
  .site-header-light .nav-links a:not(.nav-cta) { border-bottom-color: var(--line); }

  /* 440px of decoration is a whole phone screen of nothing between two
     paragraphs. */
  .disc-figure { max-width: 168px; }
}

/* Two buttons of different widths stacked under each other read as a mistake
   rather than as a pair. */
@media (max-width: 480px) {
  .btn-row { flex-direction: column; align-items: stretch; }
  .btn-row .btn { width: 100%; }
}

/* ── Motion ──────────────────────────────────────────────────────────────
   The site is static apart from hover. Transform never carries layout, so
   clearing transforms under reduced motion cannot destroy a centring. */
@media (prefers-reduced-motion: reduce) {
  [data-wp-anim] { animation: none !important; transition: none !important; }
  html { scroll-behavior: auto; }
}

/* ── Light hero variant ──────────────────────────────────────────────────
   A comparison against the dark hero in the design reference. The argument
   for it: on the dark hero the mark must be white, so North Sea Deep is
   spent as a background and never appears as the brand. Here the canvas is
   Fathom 50, the mark and the headline carry #0B2B34, and dark is kept for
   the credibility bands further down - the structure Kabal uses.
   No accent colour is introduced; the primary CTA is the brand, as on every
   other light surface in the system. */
.site-header-light { background: var(--tint); }
.site-header-light .wordmark { color: var(--ink); }
.site-header-light .nav-links a { color: var(--ink-body); }
.site-header-light .nav-links a:hover { color: var(--ink); }
/* Matches the base's specificity (.nav-links a.nav-cta) and adds one class,
   or the generic nav-link colour wins and the CTA loses its fill. */
.site-header-light .nav-links a.nav-cta {
  background: var(--ink); color: #fff; border-color: var(--ink);
}
.site-header-light .nav-links a.nav-cta:hover { background: #12414d; border-color: #12414d; }

.hero-light { background: var(--tint); }
.hero-light .h-hero { color: var(--ink); }
.hero-light .lede { color: var(--ink-body); }
/* Same inversion the white and tint bands already use, so the CTA pair is
   the system's, not a one-off for this page. */
.hero-light .btn-primary { background: var(--ink); color: #fff; }
.hero-light .btn-primary:hover { background: #12414d; }
.hero-light .btn-ghost {
  background: transparent; border-color: var(--rule-light); color: var(--ink);
}
.hero-light .btn-ghost:hover { background: #fff; border-color: var(--ink); }
/* The drifting disc fleet reads as a watermark on light rather than a glow. */
.hero-light .fleet g[mask] { fill: var(--ink); }

/* ── Light home ground ───────────────────────────────────────────────────
   Fathom 50 as the canvas rather than white. On the dark home, white is the
   ground and the tint step is what holds two light sections apart. Here that
   inverts: #f6f8f8 is the floor and white is what sits on it - the
   credential cells, the form card, the product frames. It gives the page one
   continuous light surface instead of two shades of nearly-white alternating
   down the scroll.
   Scoped to .home-light, so index.html is untouched. */
/* The body itself, so an overscroll bounce shows the light ground and not
   the dark page colour behind it. */
.home-light { background: var(--tint); }
.home-light .band-white { background: var(--tint); }
/* The stroke was keyed to the white band; the band is tint now. */
.home-light .band-white .wave-rule path { stroke: #a3adad; }
/* Two light sections that used to be held apart by the step now meet on the
   same colour, so the seam becomes a hairline. Only where light meets light:
   a band following a dark one needs nothing. */
.home-light .hero-light + .band,
.home-light .band-white + .band-tint,
.home-light .band-tint + .band-white { border-top: 1px solid var(--rule-light); }
/* Ghost buttons inverted against a white band; on tint they need the fill to
   stay the raised surface. */
.home-light .band-white .btn-ghost { background: #fff; }
/* --line was picked to divide a white band. On tint it all but vanishes, so
   the FAQ rows take the heavier rule. */
.home-light .faq details { border-top-color: var(--rule-light); }

/* ── Status page ─────────────────────────────────────────────────────────
   A component per row, each with a pill that says what a check actually
   found. The four states are the system's own status families: green
   settled, red bad, grey inert, and "not ours" for a dependency we do not
   run. Brand colour is never a status, so nothing here is North Sea Deep. */
.st-head {
  display: flex; flex-wrap: wrap; gap: 12px 24px;
  align-items: baseline; justify-content: space-between;
}
.st-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; }
.st-row {
  display: flex; gap: 20px; align-items: center; justify-content: space-between;
  padding: 20px 0; border-top: 1px solid var(--line);
}
.st-row:last-child { border-bottom: 1px solid var(--line); }
.st-what { display: flex; flex-direction: column; gap: 5px; min-width: 0; }
.st-what b { font-family: var(--display); font-size: 18px; font-weight: 600; color: var(--ink); }
.st-what span { font-size: 15px; line-height: 1.55; color: var(--ink-body); }
.st-what a { color: var(--ink); text-decoration: underline; }

/* Same construction as the product pills: the hue at 15 per cent behind a
   darkened version of itself, because no single label colour clears 4.5:1
   across all four backgrounds. */
.st-pill {
  flex-shrink: 0; padding: 7px 13px; border-radius: 999px;
  font-size: 11px; letter-spacing: 0.1em; text-transform: uppercase; white-space: nowrap;
}
.st-ok { background: #3f8f7326; color: #235f52; }
.st-down { background: #b23b2e26; color: #8c2e24; }
.st-unknown { background: #5f6a6a1f; color: #5f6a6a; }
.st-external { background: #5f6a6a1f; color: #5f6a6a; }

.contact-list { display: flex; flex-direction: column; gap: 0; margin: 8px 0 0; width: 100%; }
.contact-list .contact-row {
  padding: 14px 0; border-top: 1px solid rgba(255, 255, 255, 0.14); align-items: baseline;
}
.contact-list .contact-row:last-child { border-bottom: 1px solid rgba(255, 255, 255, 0.14); }
.contact-list dt {
  font-family: var(--mono); font-size: 11px; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--on-dark-soft);
}
.contact-list dd { margin: 0; font-size: 15px; line-height: 1.6; color: #fff; }
.contact-list dd a { color: #fff; text-decoration: underline; }

@media (max-width: 560px) {
  /* The pill drops under the name rather than squeezing it to two words. */
  .st-row { flex-direction: column; align-items: flex-start; gap: 12px; }
}

/* ── Security page ───────────────────────────────────────────────────────
   The same cell as .cred, in a denser grid: these are answers to a vendor
   questionnaire, so there are more of them and each is a sentence rather
   than a phrase. */
.sec-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 20px; }
.sec {
  background: #fff; border: 1px solid var(--line); border-radius: 14px;
  padding: 22px; display: flex; flex-direction: column; gap: 9px;
}
.band-tint .sec { background: #fff; }
.sec dt {
  font-family: var(--mono); font-size: 10px; letter-spacing: 0.18em;
  text-transform: uppercase; color: var(--ink-meta);
}
.sec dd { margin: 0; font-size: 15px; line-height: 1.55; color: var(--ink); }


/* ── The first-run wizard, as a shot ─────────────────────────────────────
   Selection is a full border and a 6% brand tint, per the design system.
   Never a left edge bar. */
.start-sub { margin: 0; padding: 0 16px; font-size: 11px; line-height: 1.5; color: var(--ink-meta); }
.start-picks { list-style: none; margin: 0; padding: 12px 16px 4px; display: flex; flex-direction: column; gap: 7px; }
.start-pick {
  display: flex; flex-direction: column; gap: 3px;
  padding: 10px 12px; border: 1px solid var(--line); border-radius: 8px; background: #fff;
}
.start-pick.is-picked { border-color: #0b2b34; background: rgba(11, 43, 52, 0.06); }
.start-pick b { font-size: 12px; font-weight: 600; color: var(--ink); }
.start-pick span { font-size: 11px; line-height: 1.45; color: var(--ink-meta); }
.start-foot { margin: 0; padding: 8px 16px 16px; font-size: 10px; line-height: 1.5; color: var(--ink-meta); }
