/* CloudCastle marketing — component layer.
 *
 * Consumes /brand/brand.css and the marketing theme layer below, and nothing
 * else. No component rule authors a colour, spacing, radius, shadow, or motion
 * value: every one of them is a token.
 *
 * The marketing site is LIGHT. The operator console (`admin.css`) and the
 * remote-session surfaces (`web.html`, `web-session.html`) link brand.css
 * WITHOUT this file and stay dark — which is exactly why the light palette is
 * overridden here instead of in brand.css. Reserved dark bands opt in with
 * `.on-dark`.
 *
 * This file has exactly one author. Need a new shared class? Ask for it;
 * do not fork a parallel style into a page-local <style> block.
 *
 * Order: local constants · theme · base · layout · chrome · controls · forms ·
 *        content · hero · page shapes · breakpoints (768 / 1100 / 1440).
 */

/* ── Local layout constants ───────────────────────────────────────────────
 * Structural dimensions that are not design tokens: container widths, the
 * icon box, the derived focus ring, the mono stack, the shimmer wash.
 * Declared once so no literal is ever repeated in a rule below.
 */
:root {
  --wrap-max: 1200px;
  --hero-copy-max: 560px;
  --measure: 640px;
  --headline: 896px;
  --grid-min: 320px;
  --footer-col-min: 160px;
  --icon-sz: 20px;
  --icon-lg: 20px;
  --rail: 2px;
  --glow-blur: 120px;
  --focus-ring: 0 0 0 3px var(--accent-ring);
  --font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
  --shimmer: rgba(15, 23, 42, 0.05);
  --t-shimmer: 1.4s;
  /* Height of the feathered fade at the dark landing hero's top/bottom edge. */
  --band-fade: clamp(64px, 10vh, 120px);
  /* Closing callout width — a full-wrap CTA plate reads as a banner, not a card. */
  --cta-band-max: 880px;
}

/* ── Marketing theme ──────────────────────────────────────────────────────
 * The D1 palette, elevation and scrim tokens, re-pointed for a light surface.
 * Same token NAMES as brand.css, so every rule in brand.css and below keeps
 * resolving through tokens and nothing hardcodes a colour. Deep-slate ink on
 * white/near-white gives the contrast the dark build could not, and magenta
 * carries CTAs, active states and accents.
 *
 * On light, emphasis goes DARKER, not brighter: --accent-hi is a deeper
 * magenta than --accent, the inverse of the dark build.
 */
:root {
  --canvas: #f8fafc;
  /* The light canvas under its own name so .on-dark subtrees (which remap
   * --canvas) can still feather their edges INTO the light page. */
  --page-canvas: #f8fafc;
  --canvas-2: #ffffff;
  --surface-1: #ffffff;
  --surface-2: #f8fafc;
  --surface-3: #edf1f7;
  --ink: #0f172a;
  --ink-2: #1e293b;
  --muted: #475569;
  --line: rgba(15, 23, 42, 0.1);
  --line-strong: rgba(15, 23, 42, 0.22);
  --accent: #d24f87;
  --accent-hi: #b03a6c;
  --brand-grad: linear-gradient(135deg, #d24f87 0%, #b03a6c 100%);
  --accent-tint: rgba(210, 79, 135, 0.1);
  --accent-ring: rgba(210, 79, 135, 0.28);

  /* Text that sits ON --accent / --brand-grad. --ink would fail contrast. */
  --on-accent: #ffffff;

  /* Status hues darkened for AA on white; tints keep the 12% recipe. */
  --ok: #0a7a3e;
  --warn: #b45309;
  --bad: #b91c1c;
  --info: #0369a1;
  --ok-tint: rgba(10, 122, 62, 0.12);
  --warn-tint: rgba(180, 83, 9, 0.12);
  --bad-tint: rgba(185, 28, 28, 0.12);
  --info-tint: rgba(3, 105, 161, 0.12);

  /* Light surfaces need drop shadow, not the dark build's inset key light. */
  --e1: 0 1px 2px rgba(15, 23, 42, 0.06);
  --e2: 0 8px 24px rgba(15, 23, 42, 0.08), 0 1px 2px rgba(15, 23, 42, 0.06);
  --e3: 0 24px 64px rgba(15, 23, 42, 0.12), 0 1px 2px rgba(15, 23, 42, 0.06);
  --scrim: rgba(15, 23, 42, 0.55);
}

/* Reserved dark band — executive hero banners, platform demo cards, footer
 * callouts. Remaps the same tokens for its own subtree, so every component
 * inside inverts without a single dark-variant rule. Use sparingly: the point
 * of the light build is that body copy is never on a dark surface.
 *
 * The dark palette IS the light theme's ink ramp (#0f172a / #1e293b / #334155
 * slate), so a dark band reads as the page's own ink colour made ambient
 * instead of an unrelated near-black. --band grades top-to-bottom from canvas
 * into surface-1, so the edge that meets light content is the lighter slate —
 * a gradual handoff rather than a hard cut.
 */
.on-dark {
  --canvas: #0f172a;
  --canvas-2: #1e293b;
  --surface-1: #1e293b;
  --surface-2: #273549;
  --surface-3: #334155;
  --ink: #f5f7fb;
  --ink-2: #cbd5e1;
  --muted: #94a3b8;
  --band: linear-gradient(180deg, var(--canvas) 0%, var(--surface-1) 100%);
  --line: rgba(255, 255, 255, 0.1);
  --line-strong: rgba(255, 255, 255, 0.22);
  /* Emphasis brightens again once the surface is dark. */
  --accent-hi: #f07cae;
  --e1: 0 1px 2px rgba(0, 0, 0, 0.4), inset 0 1px 0 rgba(255, 255, 255, 0.04);
  --e2: 0 8px 24px rgba(0, 0, 0, 0.45), inset 0 1px 0 rgba(255, 255, 255, 0.06);
  --e3: 0 24px 64px rgba(0, 0, 0, 0.6), inset 0 1px 0 rgba(255, 255, 255, 0.08);
  --scrim: rgba(4, 6, 12, 0.6);
  --shimmer: rgba(255, 255, 255, 0.05);
  background: var(--band);
  color: var(--ink);
}

/* The landing hero re-declares `background` later in this file at the same
 * specificity, which would flatten the band back to a solid fill. Two
 * classes outrank it and keep the canvas→surface-1 grade. */
.hero.on-dark {
  background: var(--band);
}

/* Edge feathering — the actual fix for the hard light/dark cut on the
 * landing hero (the only dark band left; inner page-heros and CTA bands
 * are light). These edge fades dissolve the band's top and bottom into
 * --page-canvas (the LIGHT canvas, declared at :root and deliberately NOT
 * remapped by .on-dark) so the hero hands off to whatever light section
 * follows with no visible line. The top fade also softens the junction
 * with the light sticky header.
 * z-index: above the hero's z-index:-2/-1 scene layers, below the copy. */
.hero.on-dark::before,
.hero.on-dark::after {
  content: "";
  position: absolute;
  inset-inline: 0;
  height: var(--band-fade);
  pointer-events: none;
}

.hero.on-dark::before {
  top: 0;
  background: linear-gradient(180deg, var(--page-canvas), transparent);
}

.hero.on-dark::after {
  bottom: 0;
  background: linear-gradient(0deg, var(--page-canvas), transparent);
}

.hero-copy {
  position: relative;
  z-index: 1;
}

/* ── Base ─────────────────────────────────────────────────────────────── */
html {
  scroll-behavior: smooth;
  background: var(--canvas);
}

body {
  min-height: 100dvh;
}

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

img {
  height: auto;
}

/* DO NOT DELETE THIS RULE AS A DUPLICATE. Read this first.
 *
 * `[hidden]` is now also in brand.css, so that half IS redundant. `.hidden`
 * is NOT: this is the ONLY definition of the class anywhere under static/.
 * downloads.html, portal.html and accept-invite.html each carried a private
 * `.hidden { display: none !important }` and deleted it once this rule
 * landed, so 13 elements across those three pages now depend on it —
 * including `portal.html`'s `<section id="dashView" class="hidden">`. Drop
 * this rule and a signed-out visitor sees the login form and the dashboard
 * at once, and accept-invite.html shows its form before the invite is
 * validated. brand.css calling this copy "redundant but identical" is true
 * of the `[hidden]` half only.
 *
 * Why it is needed at all: this file sets `display` on 46 rules, and an
 * author `display` declaration beats the UA `[hidden] { display: none }`.
 * `<p class="notice" hidden>` on pricing.html rendered VISIBLE before this.
 * The `!important` is load-bearing too — without it this loses to
 * `.notice { display: flex }` and to `#loginView`/`#dashView`.
 *
 * Both forms are covered because the pages drive some elements by attribute
 * (`el.hidden = bool`) and others by class (`classList.toggle("hidden", …)`).
 * `.hidden` is an active mechanism, not legacy.
 *
 * Safe because no marketing page uses `data-hidden`, and the only element
 * revealed via `style.display` (pricing.html showNotice) also clears the
 * attribute. A reveal path that cleared just the inline style while leaving
 * `hidden` set would be permanently hidden by this rule — never add one.
 * Pair `hidden` with `el.hidden = false`, never with `style.display = ""`.
 */
[hidden],
.hidden {
  display: none !important;
}

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

/* Anything a header CTA jumps to clears the sticky header. */
:target,
.anchor-target {
  scroll-margin-top: var(--s8);
}

.muted {
  color: var(--muted);
}

/* Body copy never runs wider than a comfortable measure. */
.measure {
  max-width: var(--measure);
}

.icon {
  width: var(--icon-sz);
  height: var(--icon-sz);
  flex: 0 0 auto;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.icon-sm {
  --icon-sz: var(--s4);
}

.icon-20 {
  --icon-sz: var(--icon-lg);
}

/* ── Layout ───────────────────────────────────────────────────────────── */
.wrap {
  width: 100%;
  max-width: var(--wrap-max);
  margin-inline: auto;
  padding-inline: var(--s5);
}

.section {
  background: var(--canvas);
  padding-block: var(--s8);
}

/* At most one alternation per page. */
.section-alt {
  background: var(--canvas-2);
  border-block: 1px solid var(--line);
}

.section-head {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--s3);
  margin-bottom: var(--s6);
}

.section-head .lead {
  max-width: var(--measure);
}

/* A 28px heading across the full 1200px wrap is one long line; cap it. */
.section-head h2 {
  max-width: var(--headline);
}

/* Inline text link. brand.css strips underlines globally, so prose links
 * need an explicit affordance or they read as bold body copy. */
.link {
  color: var(--ink);
  text-decoration: underline;
  text-decoration-color: var(--line-strong);
  text-underline-offset: var(--s1);
  transition: text-decoration-color var(--t-micro) var(--ease);
}

.link:hover {
  text-decoration-color: var(--accent-hi);
}

.grid-2,
.grid-3 {
  display: grid;
  gap: var(--s4);
  grid-template-columns: repeat(auto-fit, minmax(var(--grid-min), 1fr));
}

.grid-2 {
  max-width: calc(var(--grid-min) * 3);
}

.split {
  display: grid;
  grid-template-columns: 1fr minmax(var(--grid-min), 0.62fr);
  gap: var(--s7);
  align-items: start;
}

.stack {
  display: flex;
  flex-direction: column;
  gap: var(--s3);
}

/* Section-level grouping. .stack's s3 is tighter than a grid's own s4 gap,
 * which reads as a mistake when a notice sits below a card grid. */
.stack-lg {
  gap: var(--s5);
}

.row {
  display: flex;
  align-items: center;
  gap: var(--s2);
}

.crumbs {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s2);
  padding-block: var(--s5) 0;
  font-size: var(--fs-caption);
  color: var(--muted);
}

.crumbs a {
  color: var(--muted);
  transition: color var(--t-micro) var(--ease);
}

.crumbs a:hover {
  color: var(--ink);
}

.crumbs .sep {
  color: var(--line-strong);
}

/* ── Chrome: header ───────────────────────────────────────────────────── */
.site-header {
  position: sticky;
  top: 0;
  z-index: 50;
}

.site-header-inner,
.site-header > .wrap {
  display: flex;
  align-items: center;
  gap: var(--s4);
  min-height: var(--s8);
  padding-block: var(--s2);
}

.site-brand {
  display: inline-flex;
  align-items: center;
  gap: var(--s2);
  flex: 0 0 auto;
  margin-right: auto;
}

.site-brand img {
  height: var(--s5);
  width: auto;
}

.site-nav {
  display: flex;
  align-items: center;
  gap: var(--s1);
}

.site-nav a {
  display: inline-flex;
  align-items: center;
  gap: var(--s2);
  padding: var(--s2) var(--s3);
  border-radius: var(--r-sm);
  font-size: var(--fs-body);
  font-weight: 500;
  color: var(--ink-2);
  transition: color var(--t-micro) var(--ease),
    background-color var(--t-micro) var(--ease);
}

.site-nav a:hover {
  color: var(--ink);
  background: var(--surface-1);
}

.site-nav a[aria-current="page"] {
  color: var(--ink);
}

.site-nav .btn {
  margin-left: var(--s2);
}

/* `.site-nav a` is more specific than `.btn-primary`, so the header CTA would
 * otherwise take the nav's --ink-2 and render dark slate on the magenta fill.
 * Text on an accent fill is always --on-accent. */
.site-nav .btn-primary,
.site-nav .btn-primary:hover {
  color: var(--on-accent);
}

.site-nav .btn-secondary:hover {
  color: var(--ink);
}

.site-nav .btn-secondary:hover {
  background: var(--surface-3);
}

/* ≤768px only. */
.nav-toggle {
  display: none;
  flex: 0 0 auto;
  width: var(--s7);
  height: var(--s7);
  padding: 0;
  align-items: center;
  justify-content: center;
  flex-direction: column;
  gap: var(--s1);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--surface-1);
  color: var(--ink);
  cursor: pointer;
}

.nav-toggle span {
  display: block;
  width: var(--s4);
  height: var(--rail);
  border-radius: var(--r-pill);
  background: currentColor;
  transition: transform var(--t-micro) var(--ease),
    opacity var(--t-micro) var(--ease);
}

.nav-toggle[aria-expanded="true"] span:nth-child(1) {
  transform: translateY(calc(var(--s1) + var(--rail))) rotate(45deg);
}

.nav-toggle[aria-expanded="true"] span:nth-child(2) {
  opacity: 0;
}

.nav-toggle[aria-expanded="true"] span:nth-child(3) {
  transform: translateY(calc(-1 * (var(--s1) + var(--rail)))) rotate(-45deg);
}

/* ── Chrome: footer ───────────────────────────────────────────────────── */
.site-footer {
  background: var(--canvas-2);
  border-top: 1px solid var(--line);
  padding-block: var(--s7) var(--s6);
}

.footer-cols {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(var(--footer-col-min), 1fr));
  gap: var(--s6);
  margin-bottom: var(--s6);
}

.footer-col {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--s2);
}

.footer-col > .eyebrow {
  margin-bottom: var(--s1);
}

.footer-col a,
.footer-col p {
  font-size: var(--fs-compact);
  color: var(--ink-2);
}

.footer-col a {
  transition: color var(--t-micro) var(--ease);
}

.footer-col a:hover {
  color: var(--ink);
}

.footer-bottom {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--s4);
  padding-block-start: var(--s5);
  border-top: 1px solid var(--line);
  font-size: var(--fs-caption);
  color: var(--muted);
}

/* ── Controls ─────────────────────────────────────────────────────────── */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s2);
  min-height: var(--s7);
  padding: var(--s3) var(--s4);
  border: 1px solid transparent;
  border-radius: var(--r-md);
  font-family: inherit;
  font-size: var(--fs-body);
  font-weight: 600;
  line-height: var(--lh-label);
  color: var(--ink);
  background: transparent;
  cursor: pointer;
  white-space: nowrap;
  transition: background-color var(--t-micro) var(--ease),
    border-color var(--t-micro) var(--ease), color var(--t-micro) var(--ease),
    opacity var(--t-micro) var(--ease);
}

.btn[disabled],
.btn[aria-disabled="true"] {
  opacity: 0.4;
  pointer-events: none;
}

/* The only --brand-grad fill on a marketing page. */
.btn-primary {
  background-image: var(--brand-grad);
  background-size: 160% 160%;
  background-position: 0% 50%;
  border-color: transparent;
  color: var(--on-accent);
  transition: background-position var(--t-ui) var(--ease);
}

.btn-primary:hover {
  background-position: 100% 50%;
}

.btn-secondary {
  background: var(--surface-2);
  border-color: var(--line);
  color: var(--ink);
}

.btn-secondary:hover {
  border-color: var(--line-strong);
  background: var(--surface-3);
}

.btn-ghost {
  background: transparent;
  color: var(--ink-2);
}

.btn-ghost:hover {
  background: var(--surface-1);
  color: var(--ink);
}

.btn-lg {
  min-height: var(--s8);
  padding: var(--s4) var(--s5);
  font-size: var(--fs-lead);
}

.cta-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s3);
}

/* ── Forms ────────────────────────────────────────────────────────────── */
.field {
  display: flex;
  flex-direction: column;
  gap: var(--s2);
  min-width: 0;
}

/* Never a placeholder — always a real label above the control. */
.field-label {
  font-size: var(--fs-caption);
  font-weight: 500;
  line-height: var(--lh-label);
  color: var(--ink-2);
}

.input,
.select,
.textarea {
  width: 100%;
  min-height: var(--s7);
  padding: var(--s3);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--surface-1);
  color: var(--ink);
  font-family: inherit;
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  transition: border-color var(--t-micro) var(--ease),
    box-shadow var(--t-micro) var(--ease);
}

.textarea {
  min-height: calc(var(--s8) * 2);
  resize: vertical;
}

.input::placeholder,
.textarea::placeholder {
  color: var(--muted);
}

.input:focus,
.select:focus,
.textarea:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: var(--focus-ring);
}

.field-error {
  font-size: var(--fs-caption);
  color: var(--bad);
}

.field-hint {
  font-size: var(--fs-caption);
  color: var(--muted);
}

.form-row {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: var(--s3);
}

.form-row .field {
  flex: 1 1 var(--footer-col-min);
}

/* ── Content ──────────────────────────────────────────────────────────── */
.lead {
  font-size: var(--fs-lead);
  line-height: var(--lh-body);
  color: var(--ink-2);
}

/* Never nested. Subdivide the interior with .card-divide instead. */
.card {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--s3);
  padding: var(--s5);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--surface-1);
  box-shadow: var(--e1);
  transition: border-color var(--t-micro) var(--ease),
    transform var(--t-micro) var(--ease);
}

a.card:hover,
.card-link:hover {
  border-color: var(--line-strong);
}

.card-hero {
  border-radius: var(--r-hero);
  padding: var(--s6);
}

.card-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--s3);
}

.card-head h3 {
  min-width: 0;
}

.card-body {
  display: flex;
  flex-direction: column;
  gap: var(--s3);
  font-size: var(--fs-body);
  color: var(--ink-2);
}

/* Hairline divider inside a card — the alternative to nesting one. */
.card-divide {
  border: 0;
  border-top: 1px solid var(--line);
  margin: 0;
}

/* Small logo / icon tile. Replaces the retired .ico. */
.media {
  display: grid;
  place-items: center;
  width: var(--s7);
  height: var(--s7);
  flex: 0 0 auto;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--surface-2);
  color: var(--accent-hi);
  overflow: hidden;
}

.media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.chip {
  display: inline-flex;
  align-items: center;
  gap: var(--s1);
  padding: var(--s1) var(--s2);
  border-radius: var(--r-pill);
  font-size: var(--fs-eyebrow);
  font-weight: 600;
  line-height: var(--lh-label);
  white-space: nowrap;
  background: var(--surface-2);
  color: var(--ink-2);
}

/* A dot inside a chip inherits the chip's hue — no second modifier needed. */
.chip .dot {
  background: currentColor;
}

/* A chip used as a card's status badge. `.card` is a flex column, so the chip's
 * default cross-axis stretch makes it span the full card width and stop reading
 * as a badge. Scoped to a direct child so the footer status pill, which lives in
 * a centred flex row, keeps its own alignment. */
.card > .chip {
  align-self: flex-start;
}

.chip-ok {
  background: var(--ok-tint);
  color: var(--ok);
}
.chip-warn {
  background: var(--warn-tint);
  color: var(--warn);
}
.chip-bad {
  background: var(--bad-tint);
  color: var(--bad);
}
.chip-info {
  background: var(--info-tint);
  color: var(--info);
}
.chip-accent {
  background: var(--accent-tint);
  color: var(--accent-hi);
}

.dot {
  width: var(--s2);
  height: var(--s2);
  flex: 0 0 auto;
  border-radius: var(--r-pill);
  background: var(--muted);
}

.dot-ok {
  background: var(--ok);
}
.dot-warn {
  background: var(--warn);
}
.dot-bad {
  background: var(--bad);
}
.dot-info {
  background: var(--info);
}
.dot-accent {
  background: var(--accent);
}

.stat {
  display: flex;
  flex-direction: column;
  gap: var(--s1);
}

.stat-value {
  font-size: var(--fs-h3);
  font-weight: 600;
  line-height: var(--lh-heading);
  /* Matches admin.css's .stat-value so the same named element is set the
   * same way on both surfaces. --track-tight arrived in brand.css for this. */
  letter-spacing: var(--track-tight);
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}

.stat-label {
  font-size: var(--fs-caption);
  color: var(--muted);
}

.check-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
}

.check-list li {
  display: flex;
  align-items: flex-start;
  gap: var(--s3);
  padding-block: var(--s3);
  border-top: 1px solid var(--line);
  font-size: var(--fs-body);
  color: var(--ink-2);
}

.check-list li:first-child {
  border-top: 0;
}

.check-list .dot,
.check-list .icon {
  margin-top: var(--s1);
}

.check-list .icon {
  color: var(--accent-hi);
}

.check-list strong {
  color: var(--ink);
  font-weight: 500;
}

.faq {
  display: flex;
  flex-direction: column;
}

.faq-item {
  padding-block: var(--s5);
  border-top: 1px solid var(--line);
}

.faq-item:first-child {
  border-top: 0;
}

.faq-q {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s3);
  margin-bottom: var(--s2);
  font-size: var(--fs-lead);
  font-weight: 600;
  color: var(--ink);
  cursor: pointer;
  list-style: none;
}

/* <details><summary class="faq-q"> — the default marker is removed. */
.faq-q::-webkit-details-marker {
  display: none;
}

.faq-q::marker {
  content: "";
}

details[open] > .faq-q {
  margin-bottom: var(--s3);
}

/* Chevron affordance in a <summary class="faq-q">. */
.faq-q .icon {
  color: var(--muted);
  transition: transform var(--t-ui) var(--ease);
}

details[open] > .faq-q .icon {
  transform: rotate(180deg);
}

.faq-a {
  font-size: var(--fs-body);
  color: var(--ink-2);
  max-width: var(--measure);
}

.notice {
  display: flex;
  align-items: flex-start;
  gap: var(--s3);
  padding: var(--s4);
  border: 1px solid var(--line);
  border-left: var(--rail) solid var(--line-strong);
  border-radius: var(--r-sm);
  background: var(--surface-1);
  font-size: var(--fs-body);
  color: var(--ink-2);
}

.notice .icon {
  margin-top: var(--s1);
}

.notice-ok {
  border-left-color: var(--ok);
  background: var(--ok-tint);
}

.notice-ok .icon {
  color: var(--ok);
}

.notice-warn {
  border-left-color: var(--warn);
  background: var(--warn-tint);
}

.notice-warn .icon {
  color: var(--warn);
}

.notice-bad {
  border-left-color: var(--bad);
  background: var(--bad-tint);
}

.notice-bad .icon {
  color: var(--bad);
}

/* <div class="empty"><svg class="icon"/><p class="empty-title"/><p class="empty-hint"/></div> */
.empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--s2);
  padding: var(--s7) var(--s5);
  color: var(--muted);
}

.empty .icon {
  color: var(--muted);
}

.empty-title {
  font-size: var(--fs-body);
  color: var(--ink-2);
}

.empty-hint {
  font-size: var(--fs-caption);
  color: var(--muted);
}

.skeleton {
  display: block;
  border-radius: var(--r-sm);
  background-color: var(--surface-2);
  background-image: linear-gradient(
    90deg,
    transparent 0%,
    var(--shimmer) 50%,
    transparent 100%
  );
  background-size: 200% 100%;
  background-repeat: no-repeat;
  min-height: var(--s5);
}

/* Sized placeholders — a bare .skeleton has no intrinsic width. */
.skeleton-line {
  min-height: 0;
  height: var(--fs-body);
  width: 60%;
}

.skeleton-title {
  min-height: 0;
  height: var(--fs-h3);
  width: var(--footer-col-min);
}

.skeleton-price {
  min-height: 0;
  height: var(--fs-h1);
  width: 7ch;
}

.skeleton-row {
  min-height: 0;
  height: var(--row-h);
  width: 100%;
}

/* Copyable install command well.
 * <p class="cmd-label">Label</p>
 * <div class="cmd"><code>…</code><button class="btn btn-ghost cmd-copy">Copy</button></div>
 */
.cmd {
  display: flex;
  align-items: center;
  gap: var(--s3);
  padding: var(--s3);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--surface-2);
  font-family: var(--font-mono);
  font-size: var(--fs-compact);
  color: var(--ink-2);
}

.cmd code,
.cmd pre {
  flex: 1 1 auto;
  min-width: 0;
  margin: 0;
  font: inherit;
  overflow-x: auto;
  white-space: pre;
}

.cmd-label {
  font-family: var(--font);
  font-size: var(--fs-eyebrow);
  font-weight: 600;
  letter-spacing: var(--track-eyebrow);
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: var(--s2);
}

.cmd-copy {
  flex: 0 0 auto;
  margin-left: auto;
  font-family: var(--font);
}

/* ── Hero (landing page only; inner pages use .page-hero) ─────────────── */
.hero {
  position: relative;
  display: flex;
  align-items: center;
  min-height: calc(100svh - var(--s8));
  padding-block: var(--s8);
  background: var(--canvas);
  overflow: hidden;
  isolation: isolate;
}

.hero-canvas,
.hero-poster {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: -2;
}

.hero-poster {
  object-fit: cover;
  opacity: 0.55;
}

/* When the poster is permanent — reduced motion, or WebGL refused a context —
 * it is the hero rather than a placeholder, so it carries full strength. */
.hero.poster-only .hero-poster {
  opacity: 1;
}

.hero-canvas {
  opacity: 0;
  transition: opacity var(--t-scene) var(--ease-enter);
}

.hero-canvas.is-live {
  opacity: 1;
}

/* Once WebGL owns the frame the poster stops competing with it. */
.hero.is-live .hero-poster {
  opacity: 0;
  transition: opacity var(--t-scene) var(--ease-enter);
}

/* Bottom feather for the LIGHT hero, the counterpart of the .on-dark edge
 * fades above: without it the WebGL grid and fog stop dead at the section
 * boundary. Fades into --page-canvas (which the hero never remaps), so the
 * scene dissolves into whatever section follows. z-index auto stacks it
 * above the z-index:-2/-1 scene layers and below the copy. */
.hero::after {
  content: "";
  position: absolute;
  inset-inline: 0;
  bottom: 0;
  height: var(--band-fade);
  pointer-events: none;
  background: linear-gradient(0deg, var(--page-canvas), transparent);
}

.hero-scrim {
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background: linear-gradient(
    90deg,
    var(--canvas) 0%,
    color-mix(in srgb, var(--canvas) 70%, transparent) 45%,
    transparent 75%
  );
}

/* The one --brand-grad glow allowed per marketing page. */
.hero-glow {
  position: absolute;
  z-index: -1;
  inset-block-start: 0;
  inset-inline-start: 0;
  width: calc(var(--hero-copy-max) * 1.4);
  height: calc(var(--hero-copy-max) * 1.4);
  transform: translate(-35%, -35%);
  border-radius: var(--r-pill);
  background: var(--brand-grad);
  filter: blur(var(--glow-blur));
  opacity: 0.22;
  pointer-events: none;
}

.hero-copy {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--s5);
  max-width: var(--hero-copy-max);
}

.hero-copy h1 {
  font-size: var(--fs-display);
  font-weight: 700;
  letter-spacing: var(--track-display);
  line-height: 1.05;
}

.hero-copy .lead {
  max-width: var(--hero-copy-max);
}

/* Inner-page header band: no WebGL, no poster, same rhythm. */
.page-hero {
  background: var(--canvas);
  padding-block: var(--s8) var(--s7);
  border-bottom: 1px solid var(--line);
}

.page-hero-copy {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--s4);
  max-width: var(--measure);
}

/* Downloads header: copy on the left, the visitor's own installer on the right.
 * Single column below the tablet breakpoint so the card never squeezes the
 * numbered steps. */
.page-hero-split {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--s6);
  align-items: start;
}

@media (min-width: 60rem) {
  .page-hero-split {
    grid-template-columns: minmax(0, 1fr) minmax(0, 22rem);
    gap: var(--s7);
  }
}

.dl-hero {
  display: flex;
  flex-direction: column;
  gap: var(--s3);
  padding: var(--s5);
  border: 1px solid var(--accent-ring);
  border-radius: var(--r-lg);
  background: var(--surface-1);
  box-shadow: var(--e1);
}

.dl-hero .eyebrow {
  color: var(--accent-hi);
}

/* The hero reuses the grid's card markup; strip the nested plate so it reads as
 * one panel rather than a card inside a card. */
.dl-hero .dl-card {
  padding: 0;
  border: 0;
  border-radius: 0;
  background: none;
  box-shadow: none;
}

/* ── Page shapes ──────────────────────────────────────────────────────── */

/* Home · Business · MSP trio. Used as `<a class="card audience-card">`. */
.audience-card {
  gap: var(--s4);
}

.audience-card .eyebrow {
  color: var(--accent-hi);
}

.audience-card p {
  flex: 1 1 auto;
}

.card-cta {
  display: inline-flex;
  align-items: center;
  gap: var(--s2);
  font-size: var(--fs-body);
  font-weight: 600;
  color: var(--ink);
}

.card-cta .icon {
  transition: transform var(--t-micro) var(--ease);
}

.card:hover .card-cta .icon,
a.card-cta:hover .icon {
  transform: translateX(var(--s1));
}

/* Pricing. Used as `<article class="card price-card">`. */
.price-card {
  gap: var(--s4);
}

.price-card.is-featured {
  border-color: var(--accent);
}

.price-value {
  font-size: var(--fs-h1);
  font-weight: 600;
  letter-spacing: var(--track-display);
  line-height: var(--lh-heading);
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}

.price-period {
  font-size: var(--fs-body);
  font-weight: 400;
  color: var(--muted);
}

.price-features {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--s3);
  flex: 1 1 auto;
  font-size: var(--fs-body);
  color: var(--ink-2);
}

.price-features li {
  display: flex;
  align-items: flex-start;
  gap: var(--s3);
}

.price-features .icon {
  color: var(--accent-hi);
  margin-top: var(--s1);
}

/* Two stacked actions: the plan CTA, then the optional "see what you get". */
.price-cta {
  margin-top: auto;
  display: flex;
  flex-direction: column;
  gap: var(--s2);
}

.price-cta .btn {
  width: 100%;
}

.btn-sm {
  min-height: var(--s6);
  padding: var(--s2) var(--s3);
  font-size: var(--fs-compact);
}

/* The tier a visitor picked, while its pictures are open. */
.tier-card.is-selected {
  border-color: var(--accent);
  box-shadow: var(--e2);
}

/* Per-tier illustration panel. Hidden until a tier is chosen, so the page does
 * not open on a wall of art that belongs to no plan in particular. */
.tier-visuals {
  display: flex;
  flex-direction: column;
  gap: var(--s5);
  padding: var(--s5);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--surface-2);
}

.tier-visuals-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s4);
}

.tier-visuals-head h3 {
  margin: 0;
}

.tier-visuals .illo {
  background: var(--surface-1);
}

/* ── Pricing matrix (track tabs, tier cards, pooled-storage estimator,
 * capability comparison table). Appended rather than folded into the local-
 * constants :root at the top of this file so that block stays untouched;
 * this is the one dimension the token set has no name for. ────────────── */
:root {
  /* The 1px/-1px "clip a 1x1 box" idiom used by .sr-only below — not a
     spacing decision, just the mechanics of the visually-hidden technique. */
  --sr-only-sz: 1px;
}

.sr-only {
  position: absolute;
  width: var(--sr-only-sz);
  height: var(--sr-only-sz);
  padding: 0;
  margin: calc(var(--sr-only-sz) * -1);
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* Track selector. Same underline-tab convention as the console's .tabs/.tab
 * (same --tab-h token from brand.css), reimplemented here because admin.css
 * never loads on a marketing page. */
.track-tabs {
  display: flex;
  gap: var(--s2);
  overflow-x: auto;
  border-bottom: 1px solid var(--line);
}

.track-tab {
  appearance: none;
  display: inline-flex;
  align-items: center;
  flex: 0 0 auto;
  height: var(--tab-h);
  padding-inline: var(--s4);
  border: 0;
  border-bottom: 1px solid transparent;
  background: transparent;
  font-family: inherit;
  font-size: var(--fs-body);
  font-weight: 600;
  color: var(--muted);
  cursor: pointer;
  white-space: nowrap;
  transition: color var(--t-micro) var(--ease), border-color var(--t-micro) var(--ease);
}

.track-tab:hover {
  color: var(--ink);
}

.track-tab[aria-selected="true"] {
  color: var(--ink);
  border-bottom-color: var(--accent);
}

.track-tab:focus-visible {
  outline: none;
  border-radius: var(--r-sm);
  box-shadow: var(--focus-ring);
}

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

/* Pooled-storage estimator. Built from .card + .field + .input; these three
 * classes only add the calculator's own layout and JS hooks. */
.pool-calc {
  align-items: flex-start;
}

.pool-line {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--s3);
}

.pool-input {
  max-width: var(--footer-col-min);
}

.pool-out {
  font-weight: 600;
  color: var(--accent-hi);
  font-variant-numeric: tabular-nums;
}

/* Tier cards. `<article class="card price-card tier-card">` — price-card's
 * gap/is-featured rules above already apply; these add the matrix-specific
 * pieces (level eyebrow, "Most popular" badge, stack line, storage line). */
.tier-grid {
  display: grid;
  gap: var(--s4);
  grid-template-columns: repeat(auto-fit, minmax(var(--grid-min), 1fr));
  align-items: stretch;
}

.tier-card {
  min-width: 0;
}

.tier-level {
  color: var(--accent-hi);
}

.tier-name {
  min-width: 0;
}

/* The stack line ("AI-EDR + email defense + operations RMM") is product prose,
 * not a command or a checksum — the mono stack is reserved for things a reader
 * might copy. A tracked caption instead. */
.tier-stack {
  font-size: var(--fs-caption);
  letter-spacing: var(--track-tight);
}

/* A level that no catalog plan maps to. Same slot and rhythm as a real price,
 * without pretending to be a figure. */
.tier-quoted {
  color: var(--muted);
  font-size: var(--fs-h3);
}

.tier-summary {
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  color: var(--ink-2);
}

.tier-badge {
  display: inline-flex;
  align-items: center;
  align-self: flex-start;
  padding: var(--s1) var(--s3);
  border-radius: var(--r-pill);
  background: var(--accent);
  color: var(--on-accent);
  font-size: var(--fs-caption);
  font-weight: 600;
  letter-spacing: var(--track-eyebrow);
  text-transform: uppercase;
}

.tier-storage {
  padding-top: var(--s3);
  border-top: 1px solid var(--line);
  font-size: var(--fs-caption);
  color: var(--muted);
}

/* Capability comparison matrix. No `position: sticky` on `thead th` — the
 * site header is already sticky and the two collide. */
.compare-scroll {
  overflow-x: auto;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
}

.compare {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--fs-body);
}

.compare th,
.compare td {
  padding: var(--s3) var(--s4);
  border-bottom: 1px solid var(--line);
  text-align: center;
  vertical-align: middle;
}

.compare thead th {
  background: var(--surface-2);
  border-bottom: 1px solid var(--line-strong);
}

.compare tbody th[scope="row"] {
  text-align: left;
  font-weight: 500;
  color: var(--ink);
  background: var(--surface-1);
}

.compare tbody tr:last-child th,
.compare tbody tr:last-child td {
  border-bottom: 0;
}

.ch-level {
  min-width: 0;
}

.ch-name {
  display: block;
  font-size: var(--fs-caption);
  font-weight: 600;
  color: var(--ink);
}

.cap-label {
  display: block;
  color: var(--ink);
}

.cap-note {
  display: block;
  margin-top: var(--s1);
  font-size: var(--fs-caption);
  font-weight: 400;
  color: var(--muted);
}

.tick {
  color: var(--accent-hi);
}

.dash {
  color: var(--muted);
}

.quota-row th,
.quota-row td {
  background: var(--surface-2);
  font-weight: 600;
  color: var(--ink);
}

/* Downloads. Used as `<article class="card dl-card">`. */
.dl-card {
  gap: var(--s4);
}

.dl-os {
  display: flex;
  align-items: center;
  gap: var(--s3);
}

.dl-os h3 {
  min-width: 0;
}

.dl-meta {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s1) var(--s3);
  font-size: var(--fs-caption);
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

.dl-meta code {
  font-family: var(--font-mono);
  font-size: var(--fs-eyebrow);
  color: var(--muted);
  overflow-wrap: anywhere;
}

/* The ONLY region on any marketing page where copy is centred. Now that the
 * dark build is retired here, the closing callout stands out with an accent
 * tint and ring instead of an inverted surface — and stays card-sized rather
 * than spanning the full wrap. */
.cta-band {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: var(--s5);
  max-width: var(--cta-band-max);
  margin-inline: auto;
  padding: var(--s8) var(--s5);
  border: 1px solid var(--accent-ring);
  border-radius: var(--r-hero);
  background: var(--accent-tint);
  box-shadow: var(--e1);
}

.cta-band p {
  max-width: var(--hero-copy-max);
}

/* Partner / customer logo strip. */
.logo-strip {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s6);
}

.logo-strip img {
  height: var(--s6);
  width: auto;
  opacity: 0.7;
  transition: opacity var(--t-micro) var(--ease);
}

.logo-strip img:hover {
  opacity: 1;
}

/* Third-party marks are dark artwork on transparency, so a light --surface-1
 * plate reads them correctly. Kept as a plate rather than dropped so the strip
 * stays visually even when a vendor does ship a light-background mark. */
.logo-plate {
  display: grid;
  place-items: center;
  padding: var(--s3) var(--s4);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--surface-1);
}

/* Dimming a mark that already sits on a light plate only looks faded. */
.logo-plate img,
.logo-plate img:hover {
  opacity: 1;
}

/* ── 1440: display type earns its extra size ──────────────────────────── */
@media (min-width: 1440px) {
  .hero-copy h1 {
    font-size: var(--fs-display-lg);
  }
}

/* ── 1100: split stacks, the hero restacks copy-over-scene ────────────── */
@media (max-width: 1100px) {
  .split {
    grid-template-columns: 1fr;
    gap: var(--s6);
  }

  /* There is no room for a 560px column beside the scene, so the copy moves
   * to the top of the hero and the scene keeps the space below it. The scrim
   * turns vertical to match: opaque behind the copy, clear over the scene. */
  .hero {
    align-items: flex-start;
  }

  .hero-scrim {
    background: linear-gradient(
      180deg,
      var(--canvas) 0%,
      color-mix(in srgb, var(--canvas) 82%, transparent) 48%,
      transparent 100%
    );
  }
}

/* ── 768: single column, collapsible nav ──────────────────────────────── */
@media (max-width: 768px) {
  .wrap {
    padding-inline: var(--s4);
  }

  .section {
    padding-block: var(--s7);
  }

  .hero-copy h1 {
    font-size: var(--fs-h1);
  }

  .hero-copy {
    gap: var(--s4);
  }

  .site-header-inner,
  .site-header > .wrap {
    flex-wrap: wrap;
  }

  .nav-toggle {
    display: inline-flex;
  }

  .site-nav {
    display: none;
    width: 100%;
    flex-direction: column;
    align-items: stretch;
    gap: var(--s1);
    padding-block: var(--s3);
    border-top: 1px solid var(--line);
  }

  .site-nav.is-open {
    display: flex;
  }

  .site-nav .btn {
    width: 100%;
    margin-left: 0;
  }

  .cta-row .btn {
    flex: 1 1 auto;
  }

  .cta-band {
    padding: var(--s7) var(--s4);
  }

  .footer-cols {
    gap: var(--s5);
  }

  .grid-2 {
    max-width: none;
  }
}

/* ── Motion, gated on the user's preference ───────────────────────────── */
@media (prefers-reduced-motion: no-preference) {
  .skeleton {
    animation: cc-shimmer var(--t-shimmer) linear infinite;
  }

  @keyframes cc-shimmer {
    from {
      background-position: 200% 0;
    }
    to {
      background-position: -200% 0;
    }
  }

  a.card:hover,
  .card-link:hover {
    transform: translateY(-1px);
  }
}

/* ── Explainer illustrations ───────────────────────────────────────────────
 * The animated SVGs at /brand/illo-*.svg. They are loaded through <img> so the
 * page cannot restyle them; these rules only frame and size them. Each one is
 * 640x400, so `aspect-ratio` reserves the box and the page never reflows when
 * the image lands.
 */
.illo {
  display: block;
  width: 100%;
  aspect-ratio: 8 / 5;
  border-radius: var(--r-lg);
  background: var(--surface-1);
  border: 1px solid var(--line);
}

/* Inside a card the frame is already drawn by the card itself. */
.card > .illo,
.card > .figure > .illo {
  border: 0;
  border-radius: var(--r-md);
  background: var(--surface-2);
}

.figure {
  display: flex;
  flex-direction: column;
  gap: var(--s3);
  margin: 0;
}

.figure figcaption {
  font-size: var(--fs-compact);
  color: var(--muted);
  max-width: var(--measure);
}

/* A capability: illustration above, short claim below. Three across, one down
 * at 768. */
.explain {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(var(--grid-min), 1fr));
  gap: var(--s5);
}

.explain h3 {
  margin-bottom: var(--s1);
}

/* Alternating illustration-beside-copy row. `.flip` puts the art first on wide
 * screens; both orders collapse to art-then-copy when the row stacks. */
.showcase {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--s7);
  align-items: center;
}

.showcase + .showcase {
  margin-top: var(--s7);
}

.showcase-copy {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--s4);
  max-width: var(--measure);
}

@media (min-width: 769px) {
  .showcase.flip .showcase-art {
    order: -1;
  }
}

@media (max-width: 768px) {
  .showcase {
    grid-template-columns: 1fr;
    gap: var(--s5);
  }

  .showcase .showcase-art {
    order: -1;
  }

  .showcase + .showcase {
    margin-top: var(--s6);
  }
}

/* Numbered "how it works" steps. The number is decorative; the heading carries
 * the meaning for a screen reader. */
.steps {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(var(--grid-min), 1fr));
  gap: var(--s5);
  counter-reset: step;
}

.step {
  display: flex;
  flex-direction: column;
  gap: var(--s2);
  counter-increment: step;
}

.step::before {
  content: counter(step);
  display: grid;
  place-items: center;
  width: var(--s6);
  height: var(--s6);
  border-radius: var(--r-pill);
  background: var(--accent-tint);
  color: var(--accent-hi);
  font-size: var(--fs-lead);
  font-weight: 700;
}

/* ── "What's included" packages (product page) ─────────────────────────────
 * Rendered from pricing-catalog.json so it cannot drift from the pricing page.
 * Three levels across, stacking at 1000 because a package card with six or
 * seven bullets is unreadable in a third of a narrow viewport.
 */
.pkg-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--s4);
  align-items: stretch;
}

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

.pkg-card {
  display: flex;
  flex-direction: column;
  gap: var(--s2);
}

.pkg-card .check-list {
  margin-top: var(--s2);
}

.pkg-card .tier-storage {
  margin-top: var(--s3);
}

.pkg-cta {
  margin-top: auto;
  padding-top: var(--s4);
}

/* ── "We can run it for you" callout ──────────────────────────────────────
 * A managed-service offer that has to stand out mid-page without being a third
 * dark band. An accent-tinted plate does that: the pages already spend their one
 * dark region on the hero and their closing CTA, and stacking another would
 * break the one-dark-band-per-viewport rule the light build is built on.
 */
.managed {
  display: grid;
  grid-template-columns: 1fr minmax(var(--grid-min), 0.8fr);
  gap: var(--s6);
  align-items: center;
  padding: var(--s6);
  border: 1px solid var(--accent);
  border-radius: var(--r-lg);
  background: var(--accent-tint);
}

@media (max-width: 900px) {
  .managed {
    grid-template-columns: 1fr;
    gap: var(--s5);
    padding: var(--s5);
  }

  .managed-art {
    order: -1;
  }
}

.managed-copy {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--s3);
  max-width: var(--measure);
}

.managed-copy h2,
.managed-copy h3 {
  margin: 0;
}

.managed-copy .cta-row {
  margin-top: var(--s2);
}

.managed .illo {
  background: var(--surface-1);
}

/* ── Old-way / our-way contrast ───────────────────────────────────────────
 * Two columns that only work read together, so they share a container rather
 * than living in a generic card grid where a reader might take one alone.
 */
.versus {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--s4);
}

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

.versus-then,
.versus-now {
  display: flex;
  flex-direction: column;
  gap: var(--s3);
  padding: var(--s5);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
}

.versus-then {
  background: var(--surface-2);
}

.versus-now {
  background: var(--surface-1);
  border-color: var(--accent);
  box-shadow: var(--e1);
}

.versus h3 {
  margin: 0;
}

.versus-then h3 {
  color: var(--muted);
}

.versus-now h3 {
  color: var(--accent-hi);
}

.versus ul {
  margin: 0;
  padding-left: var(--s5);
  display: flex;
  flex-direction: column;
  gap: var(--s2);
}

.versus-then ul {
  color: var(--muted);
}

.versus-now ul {
  color: var(--ink-2);
}

/* A trailing note under a card grid or table — the fact that did not earn a card
 * of its own. Sits after the grid, not inside it, so it never orphans a cell. */
.section-foot {
  margin-top: var(--s5);
  max-width: var(--measure);
}
