/* ── Unclouded.ai components ──────────────────────────────────────────────
   Loaded last. Every background behind text here is a flat token colour —
   see the rule at the top of tokens.css and the reason it exists.

   The "console" read comes from three things and nothing else: mono type on
   labels, hairline borders, and the field steps in tokens.css. There is no
   glow, no scanline, no glass. Those all put something translucent behind
   text, which is the one thing this stylesheet will not do.
   ───────────────────────────────────────────────────────────────────────── */

/* ═══════════════════════════════════════════════════════════════════════
   Masthead
   ═══════════════════════════════════════════════════════════════════════ */

.masthead {
  position: sticky;
  top: 0;
  z-index: 100;
  background: var(--bg);
  border-bottom: 1px solid var(--border);
}

.masthead-inner {
  display: flex;
  align-items: center;
  gap: 20px;
  min-height: 66px;
  padding-block: 10px;
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  text-decoration: none;
  flex: 0 0 auto;
}
.brand-mark { width: 30px; height: 30px; flex: 0 0 auto; }
/* The wordmark is two leaf spans rather than a text node with one coloured
   child inside it. A parent with both its own text and a child painting a
   different colour over part of its box is what makes axe report "background
   colour could not be determined because it partially overlaps other
   elements" — an undecidable result on a pair that is actually 16:1. Each
   part owns its own colour and its own opaque background, so there is
   nothing left to resolve. */
.brand-word {
  font-family: var(--font-sans);
  font-weight: 700;
  font-size: 1.12rem;
  letter-spacing: -.03em;
  white-space: nowrap;
}
.brand-part { color: var(--text); background: var(--bg); }
.brand-part.brand-tld { color: var(--accent); }
.brand:hover .brand-part { color: #fff; }
.brand:hover .brand-part.brand-tld { color: var(--accent); }

/* ── Primary navigation ─────────────────────────────────────────────────
   Six items plus a call to action reading "Talk About Your Project" does not
   fit next to the wordmark until about 1100px, so the drawer breakpoint sits
   there rather than at the more usual 900. */

.nav-toggle {
  margin-left: auto;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 9px 14px;
  font: 600 .82rem/1 var(--font-mono);
  letter-spacing: .04em;
  color: var(--text);
  background: var(--surface-2);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius);
  cursor: pointer;
}
.nav-toggle:hover { background: var(--raised); border-color: var(--border-input); }
.nav-toggle .bar { transition: opacity .14s ease, transform .14s ease; }
.nav-toggle[aria-expanded="true"] .bar-top { transform: translateY(5px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] .bar-mid { opacity: 0; }
.nav-toggle[aria-expanded="true"] .bar-bot { transform: translateY(-5px) rotate(-45deg); }

.primary-nav ul {
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  align-items: center;
  gap: 2px;
}
.primary-nav li { margin: 0; }
.primary-nav a:not(.btn) {
  display: block;
  padding: 8px 11px;
  border-radius: var(--radius);
  font-size: .91rem;
  font-weight: 500;
  color: var(--text-soft);
  text-decoration: none;
  white-space: nowrap;
}
.primary-nav a:not(.btn):hover { color: var(--text); background: var(--surface-2); }
.primary-nav a.is-current {
  color: var(--text);
  background: var(--surface-2);
  box-shadow: inset 0 -2px 0 var(--accent);
}
.nav-cta { margin-left: 8px; }

@media (max-width: 1099px) {
  .primary-nav {
    position: absolute;
    left: 0;
    right: 0;
    top: 100%;
    background: var(--bg-soft);
    border-bottom: 1px solid var(--border);
    padding: 12px 24px 20px;
    display: none;
  }
  .primary-nav.is-open { display: block; }
  .primary-nav ul { flex-direction: column; align-items: stretch; gap: 2px; }
  .primary-nav a:not(.btn) { padding: 12px; font-size: 1rem; }
  .nav-cta { margin: 10px 0 0; }
  .nav-cta .btn { width: 100%; justify-content: center; }
}
@media (min-width: 1100px) {
  .nav-toggle { display: none; }
  .primary-nav { margin-left: auto; }
}

/* ═══════════════════════════════════════════════════════════════════════
   Buttons
   ═══════════════════════════════════════════════════════════════════════ */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  padding: 11px 20px;
  font: 620 .94rem/1.25 var(--font-sans);
  letter-spacing: -.01em;
  border: 1px solid transparent;
  border-radius: var(--radius);
  text-decoration: none;
  cursor: pointer;
  text-align: center;
}
/* Cyan fill, near-black label: 11.3:1. */
.btn-primary { background: var(--accent); color: var(--on-signal); border-color: var(--accent); }
.btn-primary:hover { background: var(--focus); border-color: var(--focus); color: var(--on-signal); }

.btn-secondary { background: transparent; color: var(--text); border-color: var(--border-input); }
.btn-secondary:hover { background: var(--surface-2); color: var(--text); border-color: var(--accent); }

.btn-lg { padding: 14px 26px; font-size: 1rem; }
.btn-block { width: 100%; }

/* ═══════════════════════════════════════════════════════════════════════
   Section furniture
   ═══════════════════════════════════════════════════════════════════════ */

/* The mono eyebrow and its short cyan rule are the one repeated ornament. */
.eyebrow {
  display: block;
  margin: 0 0 14px;
  font: 500 .74rem/1.4 var(--font-mono);
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--accent);
}
.eyebrow::after {
  content: "";
  display: block;
  width: 30px;
  height: 2px;
  margin-top: 10px;
  background: var(--accent);
}

.section-head { max-width: 46rem; margin-bottom: clamp(28px, 3.5vw, 44px); }
.section-head p:last-child { margin-bottom: 0; }

.prose > * + h2 { margin-top: 2.1em; }
.prose > * + h3 { margin-top: 1.7em; }
.prose h2 + p, .prose h3 + p { margin-top: 0; }
.prose { max-width: 68ch; }

/* ── Page header (interior pages) ───────────────────────────────────── */

.page-header {
  background: var(--bg-soft);
  border-bottom: 1px solid var(--border);
  padding: clamp(32px, 5vw, 52px) 0 clamp(38px, 5.5vw, 58px);
}
.page-header h1 { max-width: 22ch; }
.page-header .lead { max-width: 62ch; }
.page-header-wide h1 { max-width: 30ch; }

.breadcrumb { margin-bottom: 20px; }
.breadcrumb ol {
  margin: 0; padding: 0; list-style: none;
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px;
  font: 400 .8rem/1.5 var(--font-mono);
}
.breadcrumb li { margin: 0; color: var(--muted); }
.breadcrumb li + li::before { content: "/"; margin-right: 8px; color: var(--muted); }
.breadcrumb a:not(.btn) { color: var(--muted); text-decoration: none; }
.breadcrumb a:not(.btn):hover { color: var(--accent); text-decoration: underline; }
.breadcrumb [aria-current="page"] { color: var(--text-soft); }

/* ═══════════════════════════════════════════════════════════════════════
   Hero
   ═══════════════════════════════════════════════════════════════════════ */

.hero {
  padding: clamp(46px, 6.5vw, 82px) 0 0;
  border-bottom: 1px solid var(--border);
}
.hero-grid { display: grid; gap: 34px; grid-template-columns: 1fr; align-items: start; }
@media (min-width: 1000px) {
  .hero-grid { grid-template-columns: minmax(0, 1.05fr) minmax(0, .95fr); gap: 52px; }
}
.hero h1 { max-width: 15ch; }
.hero-lead { font-size: clamp(1.08rem, 1rem + .4vw, 1.26rem); color: var(--text-soft); max-width: 52ch; }
.hero-lead strong { color: var(--text); }
.hero-actions { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 28px; }
.hero-note { margin-top: 18px; font: 400 .86rem/1.6 var(--font-mono); color: var(--muted); }

/* The three-clause brand line, set as a mono rule. */
.creed {
  margin: 26px 0 0;
  padding: 14px 0 0;
  border-top: 1px solid var(--border);
  display: flex;
  flex-wrap: wrap;
  gap: 6px 18px;
  font: 500 .8rem/1.5 var(--font-mono);
  letter-spacing: .02em;
  color: var(--muted);
  list-style: none;
}
.creed li { margin: 0; display: flex; align-items: center; gap: 8px; }
.creed li::before {
  content: "";
  width: 5px; height: 5px;
  flex: 0 0 auto;
  background: var(--accent);
}
.creed strong { color: var(--text-soft); font-weight: 500; }

/* ── Boundary panel — what leaves, what does not ─────────────────────────
   Sits beside the hero copy. Two labelled zones with a policy line between
   them; the whole point of the business in one picture. */

.boundary {
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-lg);
  overflow: hidden;
}
.boundary-head {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 11px 16px;
  background: var(--surface-2);
  border-bottom: 1px solid var(--border);
  font: 500 .76rem/1.5 var(--font-mono);
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--muted);
}
.boundary-dots { display: flex; gap: 5px; flex: 0 0 auto; }
.boundary-dots span { width: 8px; height: 8px; border-radius: 50%; background: var(--border-strong); }
.boundary-dots span:first-child { background: var(--accent-line); }
.boundary-body { padding: 18px 16px 20px; display: grid; gap: 14px; }

.zone { border: 1px solid var(--border); border-radius: var(--radius); padding: 13px 14px 14px; }
.zone-title {
  margin: 0 0 10px;
  font: 500 .72rem/1.4 var(--font-mono);
  letter-spacing: .12em;
  text-transform: uppercase;
}
.zone-local   { border-color: var(--local-line);   background: var(--local-soft); }
.zone-local   .zone-title { color: var(--local); }
.zone-managed { border-color: var(--managed-line); background: var(--managed-soft); }
.zone-managed .zone-title { color: var(--managed); }
.zone-cloud   { border-color: var(--cloud-line);   background: var(--cloud-soft); }
.zone-cloud   .zone-title { color: var(--cloud); }

.zone-items { margin: 0; padding: 0; list-style: none; display: grid; gap: 7px; }
.zone-items li {
  margin: 0;
  display: flex;
  gap: 9px;
  align-items: baseline;
  font: 400 .85rem/1.5 var(--font-mono);
  color: var(--text-soft);
}
.zone-items li::before { content: "▪"; flex: 0 0 auto; color: var(--muted); }

.boundary-rule {
  display: flex;
  align-items: center;
  gap: 12px;
  font: 500 .72rem/1.4 var(--font-mono);
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--muted);
}
.boundary-rule::before,
.boundary-rule::after {
  content: "";
  flex: 1 1 auto;
  height: 1px;
  background: var(--border-strong);
}

/* ═══════════════════════════════════════════════════════════════════════
   Pipeline diagram — the signature component
   ═══════════════════════════════════════════════════════════════════════

   An <ol>, so it is announced as a sequence with a count. The placement is a
   text label as well as a colour, so nothing depends on colour alone
   (WCAG 1.4.1). The connecting arrows are drawn with borders on a
   pseudo-element that sits in the GAP between steps, never over a step's
   text — a pseudo-element behind text is what makes axe file a contrast
   result as "incomplete". */

.pipeline {
  margin: 0 0 1.4em;
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius);
  overflow: hidden;
}
.pipeline-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px 10px;
  padding: 10px 16px;
  background: var(--surface-2);
  border-bottom: 1px solid var(--border);
  font: 400 .8rem/1.5 var(--font-mono);
}
.pipeline-kind { color: var(--muted); }
.pipeline-kind::after { content: ":"; }
.pipeline-name { color: var(--accent); font-weight: 500; }
.pipeline-note { color: var(--muted); margin-left: auto; }

.pipeline-steps {
  margin: 0;
  padding: 20px 16px;
  list-style: none;
  display: grid;
  gap: 26px;
  grid-template-columns: 1fr;
}
@media (min-width: 760px) {
  .pipeline-steps { grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); gap: 30px; }
}

.pipeline-step {
  margin: 0;
  position: relative;
  display: grid;
  gap: 5px;
  align-content: start;
}
.step-index {
  font: 500 .72rem/1 var(--font-mono);
  letter-spacing: .1em;
  /* --muted, not --border-input. This is visible text at .72rem, so the bar is
     4.5:1, not the 3:1 that --border-input was chosen to clear. It reads as
     quiet either way; the first version was 4.05:1 and axe was right. */
  color: var(--muted);
}
.step-name {
  font: 500 .95rem/1.35 var(--font-sans);
  color: var(--text);
  letter-spacing: -.01em;
}
.step-detail { font: 400 .82rem/1.5 var(--font-mono); color: var(--muted); }

/* The chevron between steps. Sits inside the grid gap — 30px wide on desktop,
   so a 7px arrow centred at -15px cannot touch either neighbour's text. */
.pipeline-step:not(:last-child)::after {
  content: "";
  position: absolute;
  width: 7px;
  height: 7px;
  border: solid var(--border-input);
  border-width: 2px 2px 0 0;
  left: 50%;
  bottom: -17px;
  transform: translateX(-50%) rotate(135deg);
}
@media (min-width: 760px) {
  .pipeline-step:not(:last-child)::after {
    left: auto;
    right: -18px;
    top: 6px;
    bottom: auto;
    transform: rotate(45deg);
  }
}

/* ── Placement tag ─────────────────────────────────────────────────────── */

.tag {
  justify-self: start;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-top: 3px;
  padding: 2px 8px;
  font: 500 .7rem/1.6 var(--font-mono);
  letter-spacing: .06em;
  text-transform: uppercase;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  color: var(--text-soft);
  background: var(--surface-2);
  white-space: nowrap;
}
.tag-local   { color: var(--local);   background: var(--local-soft);   border-color: var(--local-line); }
.tag-managed { color: var(--managed); background: var(--managed-soft); border-color: var(--managed-line); }
.tag-cloud   { color: var(--cloud);   background: var(--cloud-soft);   border-color: var(--cloud-line); }
.tag-any     { color: var(--muted);   background: var(--surface-2);    border-color: var(--border-strong); }

/* A legend explaining the three placements. Each entry names its placement in
   words, so the swatch is decoration rather than the message. */
.tag-legend {
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: 10px 20px;
}
.tag-legend li { margin: 0; display: flex; align-items: center; gap: 9px; font-size: .9rem; }
.tag-legend .tag { margin-top: 0; }

/* ═══════════════════════════════════════════════════════════════════════
   Spec block — a terminal-flavoured key/value panel
   ═══════════════════════════════════════════════════════════════════════ */

.spec {
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius);
  overflow: hidden;
  margin: 0 0 1.2em;
}
.spec-head {
  padding: 10px 16px;
  background: var(--surface-2);
  border-bottom: 1px solid var(--border);
  font: 500 .78rem/1.5 var(--font-mono);
  letter-spacing: .06em;
  color: var(--text-soft);
}
.spec-body { margin: 0; padding: 16px; display: grid; gap: 10px; }
@media (min-width: 620px) { .spec-body { grid-template-columns: 10rem minmax(0, 1fr); gap: 10px 18px; } }
.spec-body dt {
  font: 400 .8rem/1.55 var(--font-mono);
  color: var(--muted);
  letter-spacing: .02em;
}
.spec-body dd { margin: 0; font-size: .95rem; color: var(--text-soft); }
.spec-body dd strong { color: var(--text); }

/* ═══════════════════════════════════════════════════════════════════════
   Cards
   ═══════════════════════════════════════════════════════════════════════ */

.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-top: 2px solid var(--border-strong);
  border-radius: var(--radius);
  padding: 22px 22px 20px;
}
/* A card's heading level follows the document outline, so a card can carry an
   h3 or an h4 depending on where it sits. Both get the same size. */
.card h3, .card h4 { font-size: 1.12rem; margin-bottom: .4em; }
.card p { font-size: .95rem; }
.card p:last-child { margin-bottom: 0; }
.card-accent  { border-top-color: var(--accent); }
.card-local   { border-top-color: var(--local); }
.card-managed { border-top-color: var(--managed); }
.card-cloud   { border-top-color: var(--cloud); }

.card-link {
  display: flex;
  flex-direction: column;
  text-decoration: none;
  color: inherit;
}
.card-link:hover { background: var(--surface-2); border-color: var(--border-strong); border-top-color: var(--accent); }
.card-link h3, .card-link h4 { color: var(--text); }
.card-link:hover h3, .card-link:hover h4 { color: var(--accent); }
.card-more {
  margin-top: auto;
  padding-top: 16px;
  font: 500 .78rem/1.5 var(--font-mono);
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--accent);
}
.card-more::after { content: " →"; }

/* ── Callout ────────────────────────────────────────────────────────── */

.callout {
  background: var(--surface);
  border: 1px solid var(--border);
  border-left: 3px solid var(--accent);
  border-radius: var(--radius);
  padding: 22px 24px;
}
.callout + .callout { margin-top: 20px; }
/* Keep the heading level correct for the document outline, but not at the
   full h2 scale — inside a callout that dwarfs the body copy. */
.callout > h2 { font-size: 1.14rem; margin-bottom: .5em; }
.callout > h3 { font-size: 1.04rem; }
.callout-local { border-left-color: var(--local); background: var(--local-soft); border-color: var(--local-line); }
.callout-cloud { border-left-color: var(--cloud); background: var(--cloud-soft); border-color: var(--cloud-line); }
.callout-alert { border-left-color: var(--alert); background: var(--alert-soft); border-color: var(--alert-line); }
.callout-plain { border-left-color: var(--border-strong); }

/* ── Pull statement ─────────────────────────────────────────────────── */

.statement {
  margin: clamp(28px, 4vw, 44px) 0;
  padding: 4px 0 4px 22px;
  border-left: 3px solid var(--accent);
  font-size: clamp(1.2rem, 1.05rem + .75vw, 1.6rem);
  line-height: 1.32;
  font-weight: 620;
  letter-spacing: -.022em;
  color: var(--text);
}

/* ═══════════════════════════════════════════════════════════════════════
   Lists
   ═══════════════════════════════════════════════════════════════════════ */

/* A long inventory of things we handle — dense, two or three columns.
   The bottom margin matters: these lists are usually followed by prose, and
   `gap` does not create space *after* the last row. */
.inventory { margin: 0 0 1.2em; padding: 0; list-style: none; display: grid; gap: 9px 26px; }
@media (min-width: 620px) { .inventory { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 960px) { .inventory-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); } }

/* The column rules above key off the VIEWPORT, but a card is a third of the
   container wide. On the deployment page that gave one card a single column of
   items and its neighbour two, at the same moment, for no reason a reader could
   see — three cards in a row that no longer looked like a set. Inside a card
   the list is always one column; container queries would be the general fix,
   and this is the only place it comes up. */
.card .inventory { grid-template-columns: 1fr; }
.inventory li {
  margin: 0;
  padding-left: 18px;
  position: relative;
  font: 400 .92rem/1.6 var(--font-mono);
  color: var(--text-soft);
}
.inventory li::before {
  content: "";
  position: absolute;
  left: 0; top: .68em;
  width: 6px; height: 6px;
  background: var(--accent-line);
}

/* A checked list — things included, things we do. */
.checklist { margin: 0 0 1.1em; padding: 0; list-style: none; display: grid; gap: 10px; }
.checklist li { margin: 0; padding-left: 30px; position: relative; color: var(--text-soft); }
.checklist li::before {
  content: "";
  position: absolute;
  left: 0; top: .34em;
  width: 18px; height: 18px;
  border-radius: var(--radius-sm);
  background: var(--local-soft);
  border: 1px solid var(--local-line);
}
.checklist li::after {
  content: "";
  position: absolute;
  left: 6px; top: .6em;
  width: 5px; height: 9px;
  border: solid var(--local);
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}

/* The negative counterpart, for "what we are not" and lists of things we will
   not do. A green tick beside "a GPU reseller" in a list headed *What we are
   not* reads as agreement — no automated check will ever catch that, and
   looking at a screenshot will.

   Both markers are drawn with borders rather than glyph content, so neither
   gets announced. The heading carries the meaning; the marker only has to
   stop contradicting it. */
.crosslist { margin: 0 0 1.1em; padding: 0; list-style: none; display: grid; gap: 10px; }
.crosslist li { margin: 0; padding-left: 30px; position: relative; color: var(--text-soft); }
.crosslist li::before {
  content: "";
  position: absolute;
  left: 0; top: .34em;
  width: 18px; height: 18px;
  border-radius: var(--radius-sm);
  background: var(--alert-soft);
  border: 1px solid var(--alert-line);
}
.crosslist li::after {
  content: "";
  position: absolute;
  left: 5px; top: calc(.34em + 8px);
  width: 8px; height: 0;
  border-top: 2px solid var(--alert);
}

/* ── Contrast pairs: the assumption, and what we do instead ──────────── */

.swaps { margin: 0 0 1.2em; padding: 0; list-style: none; display: grid; gap: 2px; }
.swaps li {
  margin: 0;
  display: grid;
  gap: 3px 18px;
  padding: 14px 0;
  border-bottom: 1px solid var(--border);
}
.swaps li:first-child { border-top: 1px solid var(--border); }
@media (min-width: 760px) {
  .swaps li { grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr); align-items: baseline; }
}
.swap-from { color: var(--muted); font-size: .94rem; }
.swap-to { color: var(--text); font-weight: 560; font-size: .99rem; }
.swap-to::before { content: "→ "; color: var(--accent); }

/* ═══════════════════════════════════════════════════════════════════════
   Numbered process steps
   ═══════════════════════════════════════════════════════════════════════ */

.steps { margin: 0; padding: 0; list-style: none; counter-reset: step; display: grid; gap: 4px; }
.steps > li {
  counter-increment: step;
  margin: 0;
  display: grid;
  gap: 4px 22px;
  padding: 24px 0;
  border-top: 1px solid var(--border);
}
.steps > li:last-child { border-bottom: 1px solid var(--border); }
@media (min-width: 780px) { .steps > li { grid-template-columns: 4.5rem minmax(0, 1fr); } }
.step-num {
  font: 500 1.9rem/1 var(--font-mono);
  letter-spacing: -.03em;
  color: var(--border-input);
}
.step-num::before { content: counter(step, decimal-leading-zero); }
.step-body h3 { margin-bottom: .35em; }
.step-body p:last-child { margin-bottom: 0; }

/* ═══════════════════════════════════════════════════════════════════════
   Split layout — body plus aside
   ═══════════════════════════════════════════════════════════════════════ */

.split { display: grid; gap: 34px; grid-template-columns: 1fr; align-items: start; }
@media (min-width: 940px) {
  .split { grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr); gap: 48px; }
  .split-even { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .split-aside-first > :first-child { order: 2; }
}
@media (min-width: 940px) {
  .sticky-aside { position: sticky; top: 92px; }
}

/* ═══════════════════════════════════════════════════════════════════════
   Tables
   ═══════════════════════════════════════════════════════════════════════ */

/* The wrapper scrolls, so the page body never scrolls sideways — but the
   table is sized to FIT a phone rather than to depend on that scroll. A
   min-width wider than a 390px viewport pushes columns outside the wrapper's
   box, and axe can then only report those cells as "background could not be
   determined because it's partially obscured" — dozens of undecidable results
   standing in for one ordinary layout problem, plus a real
   scrollable-region-focusable violation. Fitting the content is the fix; the
   scroll is the fallback for 320px and for body text at 200%, and the wrapper
   carries role="region" + tabindex="0" so it stays reachable when it happens. */
.table-wrap { overflow-x: auto; margin: 0 0 1.2em; }
.table-wrap:focus-visible { outline-offset: 4px; }
.data-table { width: 100%; border-collapse: collapse; font-size: .93rem; }
.data-table caption {
  text-align: left;
  font-size: .88rem;
  color: var(--muted);
  padding-bottom: 10px;
}
.data-table caption strong { color: var(--text-soft); }
.data-table th, .data-table td {
  text-align: left;
  padding: 11px 14px 11px 0;
  border-bottom: 1px solid var(--border);
  vertical-align: top;
}
.data-table th:last-child, .data-table td:last-child { padding-right: 0; }
.data-table thead th {
  font: 500 .74rem/1.5 var(--font-mono);
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--muted);
  border-bottom: 1px solid var(--border-strong);
}
.data-table tbody th { font-weight: 600; color: var(--text); }
.data-table td { color: var(--text-soft); }
@media (min-width: 560px) {
  .data-table th, .data-table td { padding: 11px 18px 11px 0; }
  .data-table thead th { white-space: nowrap; }
}
.data-table tbody tr:last-child th,
.data-table tbody tr:last-child td { border-bottom: 0; }
/* Set by the planner when a row matches the visitor's answers. */
.data-table tr.is-match th,
.data-table tr.is-match td { background: var(--accent-soft); }

/* ═══════════════════════════════════════════════════════════════════════
   FAQ — native details/summary, keyboard-operable with no JavaScript
   ═══════════════════════════════════════════════════════════════════════ */

.faq-list { display: grid; gap: 2px; }
.faq-item { border-bottom: 1px solid var(--border); }
.faq-item:first-child { border-top: 1px solid var(--border); }
.faq-item > summary {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  padding: 18px 4px;
  cursor: pointer;
  font-size: 1.08rem;
  font-weight: 600;
  letter-spacing: -.018em;
  color: var(--text);
  list-style: none;
}
.faq-item > summary::-webkit-details-marker { display: none; }
.faq-item > summary:hover { color: var(--accent); }
.faq-item > summary::after {
  content: "";
  flex: 0 0 auto;
  width: 10px; height: 10px;
  margin-top: .42em;
  border: solid var(--accent);
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
  transition: transform .16s ease;
}
.faq-item[open] > summary::after { transform: rotate(-135deg); margin-top: .62em; }
.faq-answer { padding: 0 4px 22px; max-width: 68ch; }
.faq-answer > :last-child { margin-bottom: 0; }

/* ═══════════════════════════════════════════════════════════════════════
   Forms
   ═══════════════════════════════════════════════════════════════════════ */

.form-wrap {
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-lg);
  padding: clamp(22px, 3vw, 32px);
}

.field { margin: 0 0 22px; display: grid; gap: 6px; }
.field-label { font-weight: 600; font-size: .93rem; color: var(--text); }
.req { color: var(--alert); }
.opt { font-weight: 400; color: var(--muted); font-size: .87rem; }

.field input[type="text"],
.field input[type="email"],
.field input[type="url"],
.field select,
.field textarea {
  width: 100%;
  padding: 11px 13px;
  font: 400 1rem/1.5 var(--font-sans);
  color: var(--text);
  background: var(--surface-2);
  /* --border-input, not --border: this is the visible boundary of a control
     and WCAG 1.4.11 wants 3:1 against the surface behind it. */
  border: 1px solid var(--border-input);
  border-radius: var(--radius);
}
.field textarea { resize: vertical; min-height: 9em; }
.field input::placeholder, .field textarea::placeholder { color: var(--muted); opacity: 1; }

/* The select keeps its native arrow.
   A custom chevron means `appearance: none` plus a background-image — and any
   background-image makes axe report "background color could not be
   determined" and file the control as an *incomplete*, the undecidable bucket
   this stylesheet exists not to have. `color-scheme: dark` in tokens.css
   already makes the platform arrow render light on the dark control, and it
   is the control users recognise, correct at every zoom level and in
   forced-colors mode without help. Restyling it buys nothing worth that. */
.field select { padding-right: 34px; }
.field input:hover, .field select:hover, .field textarea:hover { border-color: var(--accent); }
.field [aria-invalid="true"] { border-color: var(--alert); border-width: 2px; }

.field-hint { font: 400 .85rem/1.55 var(--font-sans); color: var(--muted); }
.field-error { font-size: .88rem; font-weight: 600; color: var(--alert); }
.field-error::before { content: "⚠ "; }

.form-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 14px 20px;
  margin-top: 26px;
  padding-top: 22px;
  border-top: 1px solid var(--border);
}
.form-actions .meta { margin: 0; font-size: .87rem; color: var(--muted); }

.fieldset-group { border: 0; margin: 0 0 18px; padding: 0; }
.fieldset-group > legend { padding: 0; margin-bottom: 6px; font-weight: 600; font-size: .93rem; color: var(--text); }

/* Off-screen, honestly labelled, and NOT inside aria-hidden — a focusable
   control inside aria-hidden="true" is axe's aria-hidden-focus violation. */
.honeypot {
  position: absolute;
  left: -9999px;
  top: auto;
  width: 1px; height: 1px;
  overflow: hidden;
}

/* ── Alerts ─────────────────────────────────────────────────────────── */

.alert {
  padding: 18px 20px;
  border-radius: var(--radius);
  border: 1px solid var(--border);
  border-left: 3px solid var(--border-input);
  margin-bottom: 24px;
}
.alert h2 { font-size: 1.08rem; margin-bottom: .35em; }
.alert p:last-child, .alert ul:last-child { margin-bottom: 0; }
.alert ul { margin: .6em 0 0; padding-left: 1.2em; }
.alert-error { background: var(--alert-soft); border-color: var(--alert-line); border-left-color: var(--alert); }
.alert-error h2 { color: var(--alert); }
.alert-info { background: var(--accent-soft); border-color: var(--accent-line); border-left-color: var(--accent); }
.alert-good { background: var(--local-soft); border-color: var(--local-line); border-left-color: var(--local); }

/* ═══════════════════════════════════════════════════════════════════════
   Workload placement planner
   ═══════════════════════════════════════════════════════════════════════ */

.planner {
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-lg);
  padding: clamp(20px, 3vw, 28px);
}
.planner-q { border: 0; margin: 0 0 24px; padding: 0; }
.planner-q:last-of-type { margin-bottom: 0; }
.planner-q legend {
  padding: 0;
  margin-bottom: 12px;
  font: 600 1rem/1.35 var(--font-sans);
  color: var(--text);
}
.planner-q .field-hint { display: block; margin: -6px 0 12px; }

.choices { display: grid; gap: 8px; }
@media (min-width: 700px) { .choices-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.choice {
  display: flex;
  align-items: flex-start;
  gap: 11px;
  padding: 11px 14px;
  background: var(--surface-2);
  border: 1px solid var(--border-input);
  border-radius: var(--radius);
  cursor: pointer;
  font-size: .94rem;
  color: var(--text-soft);
}
.choice:hover { background: var(--raised); }
.choice input { margin: .24em 0 0; flex: 0 0 auto; accent-color: var(--accent); width: 17px; height: 17px; }
.choice:has(input:checked) { background: var(--accent-soft); border-color: var(--accent); color: var(--text); }
.choice-body { display: grid; gap: 2px; }
.choice-note { font: 400 .8rem/1.5 var(--font-mono); color: var(--muted); }
.choice:has(input:checked) .choice-note { color: var(--text-soft); }

.planner-result {
  margin-top: 26px;
  padding-top: 24px;
  border-top: 1px solid var(--border);
}
.planner-verdict {
  font-size: clamp(1.35rem, 1.15rem + 1vw, 1.85rem);
  font-weight: 650;
  letter-spacing: -.026em;
  line-height: 1.2;
  color: var(--accent);
  margin: 0 0 8px;
}
.planner-because { margin: 0 0 16px; color: var(--text-soft); }
.planner-facts { margin: 0 0 4px; display: grid; gap: 10px; }
/* 11.5rem, not 9.5: "ROUGHLY WHAT IT TAKES" is the longest label and it
   wrapped to two lines against a one-line value at the narrower width. */
@media (min-width: 620px) { .planner-facts { grid-template-columns: 11.5rem minmax(0, 1fr); gap: 10px 18px; } }
.planner-facts dt { font: 400 .78rem/1.6 var(--font-mono); letter-spacing: .08em; text-transform: uppercase; color: var(--muted); }
.planner-facts dd { margin: 0; font-size: .95rem; color: var(--text-soft); }
.planner-detail { margin-top: 16px; color: var(--text-soft); }
.planner-notes { margin-top: 18px; }

/* Caveats, not endorsements.
   These started out on .checklist, which draws a green tick. A green tick
   beside "real time is the expensive choice, and it is chosen far more often
   than it is needed" reads as agreement with the choice the visitor just made
   — the same failure the .crosslist comment describes, arriving from the other
   direction. No automated check will ever catch it; looking at a screenshot
   will. The marker here is a neutral cyan bar that says "note", not "good". */
.notelist { margin: 0 0 1.1em; padding: 0; list-style: none; display: grid; gap: 12px; }
.notelist li { margin: 0; padding-left: 22px; position: relative; color: var(--text-soft); }
.notelist li::before {
  content: "";
  position: absolute;
  left: 0; top: .45em;
  width: 3px; height: 1.1em;
  background: var(--accent);
  border-radius: 1px;
}
.planner-actions { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 22px; }

/* Heading above a reference table, with room to breathe after the one before. */
.table-heading { margin-top: clamp(30px, 4vw, 44px); }

/* ═══════════════════════════════════════════════════════════════════════
   CTA
   ═══════════════════════════════════════════════════════════════════════ */

.cta-band {
  background: var(--bg-soft);
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
  padding: clamp(44px, 6vw, 70px) 0;
}
.cta-band h2 { max-width: 22ch; }
.cta-band p { max-width: 60ch; }
.cta-inner { display: grid; gap: 26px; align-items: center; }
@media (min-width: 900px) {
  .cta-inner { grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr); gap: 44px; }
}
.cta-actions { display: flex; flex-wrap: wrap; gap: 12px; }
@media (min-width: 900px) { .cta-actions { justify-content: flex-end; } }

.cta-inline {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 18px 26px;
  margin: clamp(28px, 4vw, 44px) 0 0;
  padding: 22px 24px;
  background: var(--accent-soft);
  border: 1px solid var(--accent-line);
  border-left: 3px solid var(--accent);
  border-radius: var(--radius);
}
.cta-inline h2, .cta-inline h3 { font-size: 1.14rem; margin: 0 0 .25em; }
.cta-inline p { margin: 0; font-size: .94rem; }
.cta-inline > div { min-width: min(100%, 22rem); flex: 1 1 22rem; }

/* ═══════════════════════════════════════════════════════════════════════
   Footer
   ═══════════════════════════════════════════════════════════════════════ */

.site-footer {
  background: var(--bg);
  border-top: 1px solid var(--border);
  padding: clamp(44px, 5.5vw, 64px) 0 28px;
}
.footer-grid { display: grid; gap: 32px; grid-template-columns: 1fr; }
@media (min-width: 640px)  { .footer-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1000px) { .footer-grid { grid-template-columns: 1.5fr 1fr 1fr 1fr; gap: 38px; } }

.footer-brand p { color: var(--muted); font-size: .92rem; max-width: 36ch; margin-top: 14px; }

.footer-col h2 {
  font: 500 .74rem/1.5 var(--font-mono);
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 14px;
}
.footer-col ul { margin: 0; padding: 0; list-style: none; display: grid; gap: 9px; }
.footer-col li { margin: 0; }
/* :not(.btn) is mandatory here — a bare `.footer-col a` rule outranks
   `.btn-primary` and quietly turns the CTA text low-contrast grey. */
.footer-col a:not(.btn) { color: var(--text-soft); text-decoration: none; font-size: .92rem; }
.footer-col a:not(.btn):hover { color: var(--accent); text-decoration: underline; }
.footer-cta .btn { margin-top: 18px; }

.footer-meta {
  margin: 34px 0 0;
  padding-top: 22px;
  border-top: 1px solid var(--border);
  display: grid;
  gap: 10px;
  font: 400 .8rem/1.6 var(--font-mono);
  color: var(--muted);
}
.footer-meta a:not(.btn) { color: var(--text-soft); }
.footer-meta a:not(.btn):hover { color: var(--accent); }
@media (min-width: 800px) {
  .footer-meta { grid-template-columns: auto auto; justify-content: space-between; align-items: center; }
}

.disclaimer {
  margin: 22px 0 0;
  padding-top: 20px;
  border-top: 1px solid var(--border);
  font-size: .82rem;
  line-height: 1.6;
  color: var(--muted);
  max-width: 92ch;
}

/* ═══════════════════════════════════════════════════════════════════════
   Scroll reveal — additive only; without JS everything is already visible
   ═══════════════════════════════════════════════════════════════════════ */

.reveal { opacity: 0; transform: translateY(12px); transition: opacity .5s ease, transform .5s ease; }
.reveal.is-visible { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
  .reveal { opacity: 1; transform: none; }
}
