/*
 * smrprojectflow.com — apex marketing site.
 *
 * Hand-written, no build step, no framework, no external request. The whole
 * reason this site exists separately from the SPA at app./demo. is that those
 * live on a burn box that is deliberately STOPPED between sessions
 * (flow/docs/aws-cost-control.md). A marketing site that goes dark whenever we
 * save credits is not a marketing site, so this one is static files on S3 with
 * nothing to run and nothing to fetch.
 *
 * IDENTITY: Site Tape (projectflow-cloud/src/themes/presets/site-tape.json),
 * the skin the portal's own public marketing page is pinned to
 * (projectflow-cloud commit e595b99 forces data-skin="site-tape" on
 * app./demo.'s "/" route). This site previously copied pf-classic, which
 * e595b99 made stale — the apex and the portal read as two different
 * products until this file was repointed. Source of truth, in order:
 *   1. projectflow-cloud/src/themes/presets/site-tape.json — the "light"
 *      scheme ONLY. The portal marketing route is forced to site-tape/light,
 *      never dark, so light is the one that has to match.
 *   2. projectflow-cloud/src/design-system/skins.generated.css — the built
 *      CSS, [data-skin=site-tape] blocks. This is what actually paints, and
 *      it also carries --accent-fg/--accent-ink, which are DERIVED (contrast-
 *      computed) rather than authored in the preset JSON.
 * Values are duplicated rather than imported because there is no build step
 * here on purpose — if the preset changes, update the :root blocks below to
 * match, and run `node flow/www/check-skin.mjs` to find out whether you did.
 * That script is the gate against exactly the drift that put this site on
 * the wrong skin for a day: it fails the deploy on divergence instead of
 * relying on someone noticing.
 *
 * Fonts: Site Tape uses Inter Tight (body AND display — one family, not two)
 * and JetBrains Mono. Self-hosted as woff2 under www/site/fonts/ (latin
 * subset only, the weights this page actually sets: Inter Tight 500/600/700,
 * JetBrains Mono 400/500/600) — copied from the same @fontsource packages
 * the SPA imports in fonts.css, not fetched from Google Fonts. Deliberately
 * NOT a CDN reference: the SPA avoids Google Fonts for latency and data-
 * residency reasons, and this page's zero-external-request property (see the
 * favicon comment below) is worth more than pulling from a CDN would buy.
 * A system-stack fallback still follows in case a font file 404s.
 */

/* ─────────────────────────── Tokens ─────────────────────────── */
/* Light values are site-tape.json's "light" scheme, literally. See the
   header comment for why they're copied rather than imported. */
:root {
  --bg: #F2F1ED;
  --surface: #FFFFFF;
  --surface-2: #F7F5EF;
  --surface-3: #ECE9E2;
  --border: #E0DDD8;
  --border-strong: #C9C5BD;
  --text: #0A0A0A;
  --text-2: #3F3D38;
  --text-3: #6B6863;
  --text-inv: #F2F1ED;
  --text-3-inv: #908D86;
  --accent: #FFD400;
  /* --accent-fg = text ON an accent FILL (buttons, badges): 13.83:1, fine.
     --accent-ink = accent-hued text on --accent-soft — copied from
     skins.generated.css's site-tape/light block, DERIVED there as
     brandText(brand, brand-soft), not authored in site-tape.json. It is
     NOT safe by default on --accent-soft: --accent-soft is only 12% yellow,
     so the real backdrop is whatever plain surface shows through it, and
     that varies by composite — 4.73:1 over --surface (passes), 3.98:1 over
     --surface-3 (fails). Every --accent-ink use in this file has to be
     measured against its OWN actual composite, not assumed safe because the
     token exists — see the comment on each consumer (.tag-accent is the
     only one left; it's verified against the two surfaces it actually
     renders on). --accent-link is this file's OWN token (no
     site-tape.json/skins.generated.css counterpart — see check-skin.mjs's
     exemption comment) for accent-hued text everywhere else: plain surfaces
     (--bg/--surface/--surface-2/--surface-3) AND --accent-soft composited
     over any of them — 4.91–5.48:1 across all four, comfortable margin
     everywhere. Same hazard-yellow hue (49° vs --accent's 50°), darkened
     until it clears AA, not a reach for the old terracotta. Getting this
     token boundary wrong has shipped two regressions already (PR #115: `a`
     on --bg at 4.39:1; then .eyebrow on --accent-soft/--bg at 4.24:1) —
     when in doubt, use --accent-link and measure, don't reach for
     --accent-ink on the assumption its intended pairing is safe. */
  --accent-fg: #0A0A0A;
  --accent-ink: #856E00;
  --accent-link: #7A6400;
  --accent-soft: rgba(255, 212, 0, 0.12);
  --ok: #0B7F3F;
  --ok-soft: rgba(11, 127, 63, 0.08);
  --info: #0B62A8;
  --info-soft: rgba(11, 98, 168, 0.08);
  --focus: #1958C1;
  --radius-sm: 0px;
  --radius: 0px;
  --radius-lg: 0px;
  --shadow-lg: 0 16px 48px rgba(0, 0, 0, 0.5);
  --font-sans: 'Inter Tight', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif;
  --font-display: var(--font-sans);
  --font-mono: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  --wrap: 1180px;
  color-scheme: light;
}

/*
 * Dark values are site-tape.json's "dark" scheme. The portal's OWN marketing
 * route never renders this — it is forced to site-tape/light — so nothing
 * live verifies this block; it exists because this page had an OS-level dark
 * fallback before this port and leaving it on the old terracotta palette
 * while the light scheme went yellow would read as two different sites for
 * anyone with system dark mode on. Not covered by check-skin.mjs (light
 * only, matching the portal) or by the Playwright screenshot in the PR.
 */
@media (prefers-color-scheme: dark) {
  :root {
    --bg: #0A0A0A;
    --surface: #141413;
    --surface-2: #1F1E1C;
    --surface-3: #28261F;
    --border: #2A2826;
    --border-strong: #3A3733;
    --text: #F2F1ED;
    --text-2: #B0AEA8;
    --text-3: #908D86;
    --text-inv: #0A0A0A;
    --text-3-inv: #5E5C58;
    --accent: #FFD400;
    --accent-fg: #0A0A0A;
    --accent-ink: #FFD400;
    /* Same value as --accent-ink here: on a near-black --bg, full-strength
       yellow already clears AA by a wide margin (13.83:1), so there is no
       separate darkened variant needed the way the light scheme has one. */
    --accent-link: #FFD400;
    --accent-soft: rgba(255, 212, 0, 0.10);
    --ok: #00C853;
    --ok-soft: rgba(0, 200, 83, 0.10);
    --info: #6CB6FF;
    --info-soft: rgba(108, 182, 255, 0.10);
    --focus: #5AC8FA;
    --shadow-lg: 0 16px 48px rgba(0, 0, 0, 0.5);
    color-scheme: dark;
  }
}

/* ─────────────────────────── Fonts ──────────────────────────── */
/* Self-hosted, latin subset only (this page ships no non-Latin copy), the
   weights actually used below. Same binaries the SPA ships via
   @fontsource/inter-tight and @fontsource/jetbrains-mono — see the header
   comment. font-display: swap so text paints in the fallback stack rather
   than staying invisible while the woff2 loads. */
@font-face {
  font-family: 'Inter Tight';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('/fonts/inter-tight-latin-500-normal.woff2') format('woff2');
}
@font-face {
  font-family: 'Inter Tight';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('/fonts/inter-tight-latin-600-normal.woff2') format('woff2');
}
@font-face {
  font-family: 'Inter Tight';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('/fonts/inter-tight-latin-700-normal.woff2') format('woff2');
}
@font-face {
  font-family: 'JetBrains Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/fonts/jetbrains-mono-latin-400-normal.woff2') format('woff2');
}
@font-face {
  font-family: 'JetBrains Mono';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('/fonts/jetbrains-mono-latin-500-normal.woff2') format('woff2');
}
@font-face {
  font-family: 'JetBrains Mono';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('/fonts/jetbrains-mono-latin-600-normal.woff2') format('woff2');
}

/* ─────────────────────────── Base ───────────────────────────── */
*, *::before, *::after { box-sizing: border-box; }

html { scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; transition-duration: 0.01ms !important; }
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-sans);
  font-size: 15px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3 { font-family: var(--font-display); letter-spacing: -0.018em; margin: 0; }
p { margin: 0; }
img { max-width: 100%; }
.mono { font-family: var(--font-mono); }

/* --accent-link, not --accent-ink: this is TEXT on a PLAIN surface
   (--bg/--surface), and --accent-ink is scoped to the --accent-soft tint —
   see the token comment. Raw --accent (#FFD400) fails contrast as text
   outright. */
a { color: var(--accent-link); }
:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; border-radius: 4px; }

.skip {
  position: absolute;
  inset-inline-start: -9999px;
  top: 0;
  z-index: 100;
  padding: 10px 16px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
}
.skip:focus { inset-inline-start: 12px; top: 12px; }

.wrap { max-width: var(--wrap); margin-inline: auto; padding-inline: 24px; }

/* ─────────────────────────── Nav ────────────────────────────── */
.nav {
  position: sticky;
  top: 0;
  z-index: 30;
  border-bottom: 1px solid var(--border);
  background: color-mix(in srgb, var(--bg) 85%, transparent);
  backdrop-filter: blur(8px);
}
.nav-inner { display: flex; align-items: center; flex-wrap: wrap; gap: 28px; min-height: 58px; }
/* 899.98px, not 899px, on every max-width breakpoint in this section: at a
   FRACTIONAL viewport width strictly between 899px and 900px (Windows
   125%/150% display scaling and some non-Chromium engines produce these;
   Chromium's own devtools snaps to integers so this gap doesn't reproduce
   there), neither `max-width: 899px` nor `min-width: 900px` would match and
   the nav would fall back to the unqueried base rules — a
   permanently-expanded header with no toggle. `min-width: 900px` doesn't
   need the same fix, since the two just have to not both fail at once, and
   899.98/900 already closes that gap. */
.brand { display: flex; align-items: center; gap: 9px; text-decoration: none; color: var(--text); }
.brand-name { font-family: var(--font-display); font-weight: 700; font-size: 17px; letter-spacing: -0.02em; }
.brand-mark {
  position: relative;
  width: 22px;
  height: 22px;
  border-radius: 5px;
  background: var(--text);
  overflow: hidden;
  flex-shrink: 0;
}
.brand-mark::before {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(135deg, var(--accent) 0%, var(--accent) 50%, transparent 50%);
}
.brand-mark::after {
  content: '';
  position: absolute;
  bottom: 4px;
  inset-inline-start: 4px;
  width: 6px;
  height: 6px;
  border-radius: 1px;
  background: var(--surface-2);
}
/*
 * TWO separate <nav> elements — .nav-links-desktop (plain, always the row,
 * ≥900px) and .nav-disclosure > .nav-links (a native <details>/<summary>
 * mobile menu, <900px) — kept in sync by hand and checked by
 * www/check-nav-links-sync.mjs (same hrefs, same order, on every page).
 * This is NOT the first design tried, and the reason it's two elements
 * instead of one is a real, demonstrated browser limitation worth recording:
 *
 * A single shared <nav> nested inside <details> — closed by default (no
 * `open` attribute, so it never paints open and CLS stays ~0) with CSS
 * forcing it to always render as the desktop row regardless of [open] —
 * measured broken. Chromium does not PAINT a closed <details>'s non-summary
 * content at all, independent of any author `display` override: a minimal
 * isolated repro (`<details><summary>t</summary><div id="d">x</div></details>`
 * with `#d{display:block!important}`) reports completely normal computed
 * style AND correct getBoundingClientRect() geometry, and still paints
 * nothing — confirmed by screenshot and by hit-testing (elementFromPoint
 * lands on the page behind it, not the content). The actual gate is
 * `content-visibility` on the `::details-content` pseudo-element, and IS
 * overridable — `details::details-content { content-visibility: visible
 * !important }` does make it paint — but that pseudo-element is recent
 * enough that an unsupporting browser would silently render a BLANK STRIP
 * between the wordmark and Sign in on this site's primary marketing page,
 * with nothing in any gate to catch it and no second CSS mechanism for
 * `@supports` to fall back to. Not a risk worth taking for the desktop nav
 * of the company's own landing page, so this file doesn't lean on it.
 *
 * Splitting into two plain, independently-styled <nav> elements sidesteps
 * the whole problem: neither one ever needs to be forced visible against a
 * closed <details>'s paint gate, because the desktop copy isn't inside a
 * <details> at all.
 */
.nav-links-desktop { display: none; }
@media (min-width: 900px) {
  .nav-links-desktop { display: flex; flex-direction: row; align-items: center; gap: 22px; font-size: 13.5px; }
  .nav-links-desktop a { color: var(--text-2); text-decoration: none; }
  .nav-links-desktop a:hover { color: var(--text); }
}

/*
 * The mobile nav is a native <details>/<summary> disclosure — .nav-disclosure
 * wraps the toggle (<summary class="nav-toggle">) and the panel
 * (<nav class="nav-links" id="nav-panel">). This replaced an earlier
 * JS-button-plus-panel version, and the reason is worth keeping: that
 * version needed THREE separate mechanisms — a synchronous nojs.js just to
 * set an html.js class before paint (so the panel could ship closed without
 * waiting for site.js), a --nav-toggle-ready CSS custom property to detect a
 * stale cached stylesheet before revealing the toggle, and JS-toggled
 * hidden/.is-open state — and even then had a gap neither side of it could
 * close. Gate the toggle's reveal on JS having run, to avoid a visible dead
 * button under stale CSS, and losing JUST site.js (an ad blocker, a flaky
 * network, a stale cached 404 from a bad deploy — all independent of
 * whether the STYLESHEET loaded) left a phone visitor with a closed panel
 * and no way to open it: strictly worse than the original "no mobile nav at
 * all" bug this whole thing exists to fix. Gate the reveal on CSS instead,
 * and a JS failure un-hides a button that does nothing. Those two
 * requirements cannot both hold while opening the menu needs JavaScript AT
 * ALL — so it doesn't, any more. <details>/<summary> open and close natively,
 * with zero script: .nav-disclosure ships without an `open` attribute, so it
 * is closed from the very first rendered frame regardless of network timing
 * (this is what actually fixes the CLS regression the JS-driven version
 * caused — see the historical measurement further down), and <summary>
 * remains a fully working toggle with JavaScript slow, blocked, or off
 * entirely. site.js/legal.js now add ONLY optional conveniences (Escape,
 * outside-click, close-on-link) on top of a menu that already works without
 * them.
 *
 * Hidden entirely at ≥900px — .nav-links-desktop (above) is the desktop row,
 * so nothing here needs to fight <details>'s paint gate to stay visible at
 * that width; see this section's opening comment for why that fight isn't
 * one this file takes on.
 */
@media (min-width: 900px) {
  .nav-disclosure { display: none; }
}
.nav-disclosure summary {
  list-style: none;
  cursor: pointer;
}
.nav-disclosure summary::-webkit-details-marker { display: none; }

.nav-links { gap: 2px; font-size: 13.5px; }
.nav-links a { color: var(--text-2); text-decoration: none; }
.nav-links a:hover { color: var(--text); }
.nav-cta { margin-inline-start: auto; display: flex; gap: 8px; }
/* 404.html only — it has no .nav-disclosure to begin with (see site.js's
   header comment), so its single "Back to the site" button needs to stay
   visible at every width rather than being swept up by
   `.nav-cta { display: none }` in the <900px query below, which would
   otherwise leave a bad-link visitor with a header that's just a wordmark. */
.nav-cta-solo { margin-inline-start: auto; display: flex; gap: 8px; }

.nav-panel-cta { display: flex; flex-direction: column; gap: 8px; margin-top: 10px; padding-top: 12px; border-top: 1px solid var(--border); }

.nav-toggle {
  display: none;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  padding: 0;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--text);
  margin-inline-start: auto;
}
.nav-toggle-bars,
.nav-toggle-bars::before,
.nav-toggle-bars::after {
  display: block;
  width: 16px;
  height: 2px;
  background: currentColor;
}
.nav-toggle-bars { position: relative; }
.nav-toggle-bars::before,
.nav-toggle-bars::after {
  content: '';
  position: absolute;
  inset-inline-start: 0;
}
.nav-toggle-bars::before { top: -5px; }
.nav-toggle-bars::after { top: 5px; }
/* Turns the three bars into an "×" once the panel is open — a stronger
   affordance than swapping the icon for text, and CSS-only so it can't drift
   out of sync: [open] is <details>'s own reflected attribute (not something
   this file or site.js sets), so this can't disagree with what's actually
   showing the way a hand-maintained aria-expanded could. */
.nav-disclosure[open] .nav-toggle-bars { background: transparent; }
.nav-disclosure[open] .nav-toggle-bars::before { top: 0; transform: rotate(45deg); }
.nav-disclosure[open] .nav-toggle-bars::after { top: 0; transform: rotate(-45deg); }

@media (max-width: 899.98px) {
  /* Desktop-only CTA row; below 900px the same links live in .nav-panel-cta
     instead, so this would just be a second, redundant "Start free trial".
     404.html has no .nav-panel-cta (it never had section links to collapse
     in the first place — see site.js's header comment), so its CTA row
     carries .nav-cta-solo instead of .nav-cta and is untouched by this. */
  .nav-cta { display: none; }
  .nav-toggle { display: inline-flex; }
  .nav-links a { padding: 10px 2px; }
  /* Only the OPEN state's layout is styled here — the closed state is
     entirely native (<details> without `open` simply doesn't paint its
     non-summary content — see this section's opening comment).
     Absolutely positioned, not in normal flow: the first version of this
     rule used `flex-basis: 100%` on .nav-disclosure itself to wrap the WHOLE
     details onto its own line when open — which also dragged <summary> down
     with it (it's .nav-disclosure's own flex-basis, and summary is inside),
     visibly moving the toggle out from beside .brand the instant the menu
     opened. Positioning just .nav-links (not the disclosure) means
     .nav-disclosure's own box never has to grow to contain the panel, so it
     stays put next to .brand at its natural (summary-sized) width in both
     states. `top: 100%` is relative to .nav (position: sticky counts as a
     positioned containing block), i.e. flush against the CLOSED header's own
     bottom edge — inset-inline/padding duplicate .wrap's horizontal padding
     because escaping normal flow also escapes .wrap's box.
     Bounded height + its own scroll: on a short LANDSCAPE phone (measured
     667×375, 740×360, 812×375) an earlier unbounded version of this panel
     was 410px tall against a 360-375px viewport, taller than the screen with
     no way to scroll the rest into view. 100dvh, not 100vh: vh on a phone
     includes the address bar's reserved space, so this stays correct as it
     shows/hides. 59px is .nav's own MEASURED closed height (see the
     scroll-margin-top comment further down for how that number was
     verified) — since the panel starts exactly at .nav's bottom edge now,
     that's the only number this calc needs. */
  .nav-disclosure[open] .nav-links {
    position: absolute;
    inset-inline: 0;
    top: 100%;
    z-index: 29;
    display: flex;
    flex-direction: column;
    padding: 14px 24px 20px;
    background: var(--surface);
    border-bottom: 1px solid var(--border);
    box-shadow: var(--shadow-lg);
    max-height: calc(100dvh - 59px);
    overflow-y: auto;
  }
}
/* No `@media (min-width: 900px) { .nav-panel-cta { display: none } }` needed
   here — .nav-disclosure { display: none } (above) already hides the whole
   mobile menu, .nav-panel-cta included, at that width. */

/* Sticky-header offset for every in-page anchor target (nav links, footer,
   deep links like /#pricing). Without this the browser scrolls the target
   flush to viewport y=0, which is exactly where the sticky .nav sits, so its
   own top edge (an .eyebrow chip, in every .band section) lands underneath
   the header. 59px is .nav's MEASURED rendered height (58px .nav-inner +
   1px border-bottom — verified with a Playwright getBoundingClientRect() at
   both 1280px and 390px; the mobile toggle row is the same height as the
   desktop one), not a guess. */
main section[id] { scroll-margin-top: 59px; }

/* Hazard-tape divider — Site Tape's own motif (projectflow-cloud's
   MarketingLayout.vue), marking the two seams of the page (below the nav,
   above the footer), not wallpaper. Same --accent/--text vocabulary so it
   repaints with the tokens above. */
.hazard-strip {
  height: 6px;
  /* Second colour is a hard-coded #0A0A0A, not var(--text): hazard tape is
     yellow-on-BLACK regardless of theme. var(--text) happens to equal
     #0A0A0A in the light scheme (so this looked token-driven and correct),
     but --text inverts to #F2F1ED in the dark media query below, which
     paints a washed-out pale-yellow-on-off-white bar instead of tape. The
     portal's own .hazard-strip uses var(--text) too and gets away with it
     only because its marketing route is forced to site-tape/light and never
     renders dark — this file's OS-level dark fallback is the one surface
     that actually hits this. */
  background: repeating-linear-gradient(-45deg, var(--accent) 0 10px, #0A0A0A 10px 20px);
}

/* ─────────────────────────── Buttons ────────────────────────── */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  padding: 8px 15px;
  border: 1px solid transparent;
  border-radius: var(--radius);
  font: inherit;
  font-size: 13.5px;
  font-weight: 500;
  text-decoration: none;
  cursor: pointer;
  white-space: nowrap;
  transition: background-color 150ms ease, border-color 150ms ease, transform 150ms ease;
}
/* `display: inline-flex` above beats the UA `[hidden] { display: none }`
   default (author-origin always wins over user-agent, regardless of
   specificity), so `el.hidden = true` on any .btn was a silent no-op —
   including site.js's app-offline probe hiding the "Sign in" link when
   app.smrprojectflow.com is down. Reproduced: with the app host unreachable
   at 390px, the panel's Sign in reported `display: flex` despite carrying
   `hidden`, still pointing at a dead host. */
.btn[hidden] { display: none; }
.btn-lg { padding: 12px 22px; font-size: 15px; }
.btn-block { display: flex; width: 100%; }
.btn-accent { background: var(--accent); color: var(--accent-fg); }
.btn-accent:hover { filter: brightness(1.08); }
.btn-line { background: transparent; border-color: var(--border-strong); color: var(--text); }
.btn-line:hover { background: var(--surface-2); }
.btn-ghost { background: transparent; color: var(--text-2); }
.btn-ghost:hover { color: var(--text); background: var(--surface-2); }

/* ─────────────────────────── Type ───────────────────────────── */
/* Chip, not plain text — mirrors the portal's PfBadge tone="accent" eyebrow
   (pf-chip / pf-chip-accent in components.css, plus the mono/uppercase
   override MarketingHomePage.vue applies to every chip on that page).
   Renders FULL-WIDTH, not content-sized, on every section head and the
   hero — `display: inline-flex` here is overridden by the parent
   (.head/.hero-copy, both `flex-direction: column`), whose default
   `align-items: stretch` stretches this as the flex item it is. Verified
   deliberate, not a bug: the live portal's OWN section eyebrows ("The
   problem", "How it works", "Day to day", the hero label) are pf-chip at
   the same computed width as their column parent — only chips nested
   inside cards there size to content. Narrowing THIS file's band would
   create the exact apex/portal divergence this whole re-skin exists to
   remove; if it's ever narrowed, narrow the portal's chip layout first and
   port the change here, not the other way round. */
.eyebrow {
  display: inline-flex;
  align-items: center;
  /* min-height, not height: this band is as wide as its column and the text
     inside it is a sentence, so a copy edit, a translation, or a reader's
     larger default font makes it wrap. At a fixed 20px the second line spills
     out of the chip and collides with the h1 17px below — measured with the
     portal's own (14 characters longer) eyebrow string. The portal's
     `.pf-chip`, which this mirrors, carries the same change. */
  min-height: 20px;
  padding: 0 8px;
  border-radius: 4px;
  background: var(--accent-soft);
  /* --accent-link, not --accent-ink: --accent-soft is only 12% yellow, so
     what --accent-ink is actually measured against is the page's plain
     --bg showing through it — 4.24:1 at this size, below AA. --accent-link
     clears it here too (4.91:1). See the --accent-ink token comment above:
     it is NOT safe by default on --accent-soft, only where separately
     verified — this isn't one of those places. */
  color: var(--accent-link);
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.head { display: flex; flex-direction: column; gap: 12px; margin-bottom: 28px; max-width: 800px; }
.head h2 { font-size: clamp(27px, 3.3vw, 39px); font-weight: 700; line-height: 1.12; }
.head .sub { font-size: 15px; color: var(--text-2); line-height: 1.6; }
.band { padding-block: 60px; }
.fine { font-size: 12px; color: var(--text-3); }

/* ─────────────────────────── Hero ───────────────────────────── */
.hero {
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr);
  gap: 48px;
  align-items: center;
  padding-block: 72px 44px;
}
.hero-copy { display: flex; flex-direction: column; gap: 17px; }
.hero h1 {
  font-size: clamp(33px, 4.5vw, 51px);
  font-weight: 700;
  line-height: 1.06;
  letter-spacing: -0.022em;
  max-width: 16ch;
}
.lede { font-size: 16px; color: var(--text-2); line-height: 1.55; max-width: 56ch; }
.hero-actions { display: flex; flex-wrap: wrap; gap: 10px; }
@media (max-width: 980px) {
  .hero { grid-template-columns: 1fr; padding-block: 48px 24px; gap: 32px; }
}

/* Floating illustrative package cards */
.hero-art { position: relative; height: 400px; }
@media (max-width: 980px) { .hero-art { height: 300px; } }
.pkg {
  position: absolute;
  width: 268px;
  padding: 14px 16px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
}
.pkg-1 { top: 10%; inset-inline-end: 34%; animation: bob 5.6s ease-in-out infinite; }
.pkg-2 { top: 0; inset-inline-end: 2%; animation: bob 6.4s ease-in-out infinite reverse; }
.pkg-3 { top: 52%; inset-inline-end: 20%; animation: bob 7.2s ease-in-out infinite; }
@keyframes bob { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-10px); } }
.pkg-top { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-bottom: 9px; font-size: 11px; }
.pkg-title { font-size: 12.5px; font-weight: 600; margin-bottom: 9px; }
.pkg-foot { font-size: 10.5px; color: var(--text-3); margin-top: 7px; }
.pill {
  position: absolute;
  bottom: 10%;
  inset-inline-start: 2%;
  padding: 10px 15px;
  border-radius: 999px;
  background: var(--text);
  color: var(--text-inv);
  font-size: 12.5px;
  font-weight: 500;
  white-space: nowrap;
  box-shadow: var(--shadow-lg);
  animation: bob 5s ease-in-out infinite;
}
@media (max-width: 980px) { .pkg, .pill { animation: none; } }
/* Phones: the cards can't float. `.pkg` is a fixed 268px positioned from the
   container's END edge, so once the hero column drops under ~406px the card's
   start edge goes negative and the viewport slices it — measured at 390px the
   first card sat at -18px with its title cut off mid-word, and at 360px at
   -38px. Below 620 they stop being absolute and become an ordinary stack,
   which also sheds the fixed art height a stack would overflow. */
@media (max-width: 620px) {
  .hero-art { height: auto; display: grid; gap: 12px; }
  .pkg { position: static; width: auto; }
  .pill { position: static; justify-self: start; }
}

.tag {
  display: inline-block;
  padding: 2px 8px;
  border-radius: 99px;
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.02em;
}
/* --accent-ink verified safe HERE specifically, not by default: this tag
   only ever renders inside .pkg or .card (index.html's hero package cards,
   the three-way-BoQ cards), both `background: var(--surface)` — accent-soft
   composited over white is 4.73:1, clears AA. Composited over --surface-3
   (a tinted card background this file also has) the same pairing is
   3.98:1 and fails — if a future edit ever puts a .tag-accent on
   --surface-3, switch this rule to --accent-link and re-measure, don't
   assume the current pass carries over. */
.tag-accent { background: var(--accent-soft); color: var(--accent-ink); }
.tag-info { background: var(--info-soft); color: var(--info); }
.tag-ok { background: var(--ok-soft); color: var(--ok); }

.bar { height: 6px; border-radius: 99px; background: var(--surface-3); overflow: hidden; }
.bar-lg { height: 10px; margin-block: 14px; }
.bar i { display: block; height: 100%; border-radius: 99px; background: var(--accent); }
.fill-accent { background: var(--accent); }
.fill-mid { background: var(--text-2); }
.fill-quiet { background: var(--text-3); }

.sample-note { font-size: 11px; color: var(--text-3); margin-bottom: 6px; }

/* ─────────────────────────── Outcomes ───────────────────────── */
.outcomes {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 24px;
  padding-block: 30px 50px;
  border-top: 1px solid var(--border);
  margin-top: 6px;
  padding-top: 30px;
}
.outcome h3 { font-size: 15px; font-weight: 600; line-height: 1.3; margin-bottom: 6px; }
.outcome p { font-size: 13px; color: var(--text-2); line-height: 1.55; }
@media (max-width: 980px) { .outcomes { grid-template-columns: repeat(2, 1fr); gap: 20px; } }
@media (max-width: 620px) { .outcomes { grid-template-columns: 1fr; } }

/* ─────────────────────────── Cards ──────────────────────────── */
.card {
  padding: 22px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
}
.card-quiet { background: var(--surface-2); }
.card h3 { font-size: 16px; font-weight: 600; line-height: 1.3; margin-bottom: 7px; }
.card p { font-size: 13.5px; color: var(--text-2); line-height: 1.55; }

.cards-3, .cards-4, .boq-grid { display: grid; gap: 12px; }
.cards-3, .boq-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.cards-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
@media (max-width: 1040px) { .cards-4 { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 880px) { .cards-3, .boq-grid { grid-template-columns: 1fr; } }
@media (max-width: 620px) { .cards-4 { grid-template-columns: 1fr; } }

.link-note { text-align: center; font-size: 12.5px; color: var(--text-3); margin-block: 18px 30px; }

/* ─────────────────────────── Beats ──────────────────────────── */
.beats { list-style: none; margin: 0; padding: 0; }
.beats li { position: relative; padding-inline-start: 30px; padding-bottom: 26px; }
.beats li::before {
  content: '';
  position: absolute;
  inset-inline-start: 5px;
  top: 6px;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  border: 1px solid var(--border-strong);
  background: var(--surface);
}
.beats li::after {
  content: '';
  position: absolute;
  inset-inline-start: 9px;
  top: 18px;
  bottom: 0;
  width: 1px;
  background: var(--border);
}
.beats li:last-child { padding-bottom: 0; }
.beats li:last-child::after { display: none; }
/* accent-link, not --accent: a solid #FFD400 dot on --surface is barely
   visible (the "you are here" marker would disappear), and --surface is a
   plain surface, not the --accent-soft tint --accent-ink is scoped to. */
.beat-last::before { background: var(--accent-link); border-color: var(--accent-link); }
.beat-time { font-size: 10.5px; font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase; color: var(--text-3); }
.beats h3 { font-size: 17px; font-weight: 600; margin: 4px 0 5px; }
.beats p { font-size: 14px; color: var(--text-2); line-height: 1.6; max-width: 64ch; }

/* ─────────────────────────── Comparison ─────────────────────── */
.table-scroll {
  overflow-x: auto;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface);
}
.cmp { width: 100%; min-width: 900px; border-collapse: collapse; font-size: 12.5px; }
.cmp thead th {
  text-align: start;
  vertical-align: bottom;
  padding: 14px;
  font-size: 11.5px;
  font-weight: 600;
  color: var(--text-3);
  background: var(--surface-2);
  border-bottom: 1px solid var(--border);
}
.cmp tbody th, .cmp tbody td {
  padding: 13px 14px;
  vertical-align: top;
  border-bottom: 1px solid var(--border);
  color: var(--text-2);
  line-height: 1.45;
}
.cmp tbody tr:last-child th, .cmp tbody tr:last-child td { border-bottom: 0; }
.cmp .crit { text-align: start; font-weight: 600; color: var(--text); min-width: 225px; }
.cmp .ours { background: var(--accent-soft); color: var(--text); font-weight: 600; min-width: 195px; }
.cmp thead th.ours { color: var(--text); }

.fair {
  margin-top: 16px;
  padding: 18px 20px;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface-2);
}
.fair h3 { font-size: 15px; font-weight: 600; margin-bottom: 5px; }
.fair p { font-size: 13.5px; color: var(--text-2); line-height: 1.6; max-width: 80ch; }

/* ─────────────────────────── Getting started ────────────────── */
.start-layout { display: grid; grid-template-columns: minmax(0, 1.35fr) minmax(0, 0.65fr); gap: 32px; align-items: start; }
@media (max-width: 900px) { .start-layout { grid-template-columns: 1fr; gap: 24px; } }
.steps { list-style: none; margin: 0; padding: 0; counter-reset: step; display: flex; flex-direction: column; gap: 22px; }
.steps li { counter-increment: step; padding-inline-start: 42px; position: relative; }
.steps li::before {
  content: counter(step);
  position: absolute;
  inset-inline-start: 0;
  top: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  border-radius: 6px;
  background: var(--surface-3);
  color: var(--text-2);
  font-family: var(--font-mono);
  font-size: 12px;
  font-weight: 600;
}
.step-tag { font-size: 10.5px; font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase; color: var(--accent-link); }
.steps h3 { font-size: 16.5px; font-weight: 600; margin: 4px 0 5px; }
.steps p { font-size: 13.5px; color: var(--text-2); line-height: 1.6; max-width: 60ch; }

.nots ul { list-style: none; margin: 12px 0 0; padding: 0; display: flex; flex-direction: column; gap: 10px; }
.nots li { position: relative; padding-inline-start: 22px; font-size: 13px; color: var(--text-2); line-height: 1.45; }
.nots li::before { content: '✓'; position: absolute; inset-inline-start: 0; color: var(--ok); font-weight: 700; }

/* ─────────────────────────── Pricing ────────────────────────── */
.cycle {
  display: inline-flex;
  gap: 3px;
  padding: 3px;
  border-radius: var(--radius);
  background: var(--surface-3);
  margin-bottom: 22px;
}
.cycle-btn {
  border: 0;
  background: transparent;
  padding: 7px 17px;
  border-radius: 6px;
  font: inherit;
  font-size: 13px;
  font-weight: 500;
  color: var(--text-2);
  cursor: pointer;
}
/* Flat, not shadowed — site-tape's own active-toggle affordance has no
   shadow (skins.generated.css's site-tape/light --shadow-sm is `none`). */
.cycle-btn.on { background: var(--surface); color: var(--text); font-weight: 600; box-shadow: none; }
.save { color: var(--accent-link); font-weight: 600; font-size: 11.5px; margin-inline-start: 5px; }

.tiers { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; align-items: start; }
@media (max-width: 900px) { .tiers { grid-template-columns: 1fr; } }
.tier {
  position: relative;
  padding: 26px 22px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.tier-featured {
  background: var(--text);
  color: var(--text-inv);
  border-color: var(--text);
  --text-3: var(--text-3-inv);
}
.tier-featured h3, .tier-featured .price { color: var(--text-inv); }
.tier-featured .tier-blurb, .tier-featured .feats li { color: var(--text-3-inv); }
.tier-badge {
  position: absolute;
  top: -10px;
  inset-inline-start: 22px;
  padding: 3px 10px;
  border-radius: 99px;
  background: var(--accent);
  color: var(--accent-fg);
  font-size: 10.5px;
  font-weight: 600;
}
.tier h3 { font-size: 18px; font-weight: 700; }
.tier-blurb { font-size: 13px; color: var(--text-2); line-height: 1.45; min-height: 2.9em; }
.price { font-family: var(--font-display); font-size: 32px; font-weight: 700; letter-spacing: -0.02em; }
.price small { font-size: 13px; font-weight: 500; color: var(--text-3); margin-inline-start: 3px; }
.tier-meta { font-size: 11px; color: var(--text-3); }
.feats { list-style: none; margin: 8px 0 14px; padding: 0; display: flex; flex-direction: column; gap: 9px; flex: 1; }
.feats li { position: relative; padding-inline-start: 20px; font-size: 13px; color: var(--text-2); line-height: 1.45; }
.feats li::before { content: '✓'; position: absolute; inset-inline-start: 0; color: var(--accent-link); font-weight: 700; }
/* Raw --accent here, not --accent-link: this card's background is --text
   (near-black), and #FFD400 reads fine directly on it — --accent-link
   exists for plain LIGHT surfaces, this isn't one. */
.tier-featured .feats li::before { color: var(--accent); }
.addon-note { margin-top: 16px; max-width: 88ch; }

/* ─────────────────────────── ROI ────────────────────────────── */
.roi-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; align-items: start; }
@media (max-width: 900px) { .roi-grid { grid-template-columns: 1fr; } }
.roi-inputs { display: flex; flex-direction: column; gap: 20px; }
.field { display: flex; flex-direction: column; gap: 8px; }
.field-label { font-size: 12.5px; font-weight: 500; color: var(--text-2); line-height: 1.4; }
.field .cycle { margin-bottom: 0; align-self: flex-start; }
.field-row { display: flex; align-items: center; gap: 14px; }
.field-row input[type='range'] { flex: 1; min-width: 0; accent-color: var(--accent); }
.field-out { min-width: 54px; text-align: end; font-size: 15px; font-weight: 600; color: var(--text); }

.roi-out { display: flex; flex-direction: column; gap: 12px; }
.res-cap { display: block; font-size: 11.5px; color: var(--text-3); line-height: 1.4; }
.res-num { font-family: var(--font-display); font-size: clamp(23px, 3vw, 31px); font-weight: 700; letter-spacing: -0.02em; margin-top: 4px; }
.res-note { font-size: 11px; color: var(--text-3); }
.delta { padding: 18px 20px; border-radius: var(--radius-lg); border: 1px solid var(--border); background: var(--surface-2); }
.delta.good { background: var(--text); border-color: var(--text); color: var(--text-inv); --text-3: var(--text-3-inv); }
.delta-top { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
.delta .res-num { font-size: clamp(21px, 2.6vw, 27px); }
.delta p { font-size: 12.5px; line-height: 1.55; margin-top: 8px; opacity: 0.85; }
.caveat { margin-top: 16px; max-width: 86ch; line-height: 1.6; }

.incl { margin-top: 30px; padding-top: 24px; border-top: 1px solid var(--border); }
.incl h3 { font-size: 15px; font-weight: 600; margin-bottom: 14px; }
.incl ul { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px 20px; }
@media (max-width: 880px) { .incl ul { grid-template-columns: 1fr; } }
.incl li { position: relative; padding-inline-start: 20px; font-size: 13px; color: var(--text-2); line-height: 1.45; }
.incl li::before { content: '✓'; position: absolute; inset-inline-start: 0; color: var(--accent-link); font-weight: 700; }

/* ─────────────────────────── FAQ ────────────────────────────── */
.faq { border: 1px solid var(--border); border-radius: var(--radius-lg); background: var(--surface); overflow: hidden; }
.faq details + details { border-top: 1px solid var(--border); }
.faq summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 16px 20px;
  cursor: pointer;
  font-family: var(--font-display);
  font-size: 15px;
  font-weight: 600;
  list-style: none;
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after { content: '⌄'; color: var(--text-3); font-size: 16px; line-height: 1; transition: transform 180ms ease; }
.faq details[open] summary::after { transform: rotate(180deg); }
.faq summary:hover { background: var(--surface-2); }
.faq p { padding: 0 20px 18px; font-size: 14px; color: var(--text-2); line-height: 1.65; max-width: 84ch; }

/* ─────────────────────────── Trust ──────────────────────────── */
.trust {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 14px;
  padding: 20px 24px;
  margin-block: 40px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
}
@media (max-width: 880px) { .trust { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 520px) { .trust { grid-template-columns: 1fr; } }
.trust div { display: flex; flex-direction: column; gap: 3px; }
.trust strong { font-size: 12.5px; font-weight: 600; }
.trust span { font-size: 11px; color: var(--text-3); }

/* ─────────────────────────── Closing ────────────────────────── */
.closing {
  display: grid;
  grid-template-columns: minmax(0, 1.2fr) minmax(0, 0.8fr);
  gap: 32px;
  align-items: center;
  padding: 46px;
  margin-block: 50px;
  background: var(--text);
  color: var(--text-inv);
  border-radius: var(--radius-lg);
}
@media (max-width: 880px) { .closing { grid-template-columns: 1fr; padding: 30px; gap: 18px; } }
.closing h2 { font-size: clamp(26px, 3.2vw, 37px); font-weight: 700; line-height: 1.12; }
.closing p { margin-top: 12px; font-size: 15px; color: var(--text-3-inv); line-height: 1.55; }
.closing-actions { display: flex; gap: 10px; flex-wrap: wrap; justify-content: flex-end; }
@media (max-width: 880px) { .closing-actions { justify-content: flex-start; } }
.closing .btn-line { border-color: var(--text-3-inv); color: var(--text-inv); }
.closing .btn-line:hover { background: rgba(255, 255, 255, 0.08); }

/* ─────────────────────────── Footer ─────────────────────────── */
.foot { border-top: 1px solid var(--border); padding-block: 28px; font-size: 12px; color: var(--text-3); }
.foot-inner { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 12px; }

/* ─────────────────── App-availability notice ────────────────── */
/*
 * Rendered by site.js only when app.smrprojectflow.com fails its reachability
 * probe. The app box is stopped between sessions on purpose, so the trial CTA
 * is periodically a dead link — and a prospect who clicks it and gets a
 * timeout concludes the company is not real, not that the server is saving
 * money. Hidden and zero-cost when the app is up.
 */
.offline-bar {
  padding: 10px 24px;
  background: var(--accent-soft);
  border-bottom: 1px solid var(--border);
  color: var(--text);
  font-size: 13px;
  text-align: center;
  line-height: 1.5;
}
.offline-bar[hidden] { display: none; }

/* ─────────────────── Breakeven calculator extras ────────────── */
.roi-pair { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
@media (max-width: 520px) { .roi-pair { grid-template-columns: 1fr; } }

.roi-hours {
  margin-top: 16px;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface);
}
.roi-hours summary {
  padding: 14px 18px;
  cursor: pointer;
  font-size: 13.5px;
  font-weight: 600;
  color: var(--text-2);
  list-style: none;
}
.roi-hours summary::-webkit-details-marker { display: none; }
.roi-hours summary::after { content: ' ⌄'; color: var(--text-3); }
.roi-hours[open] summary::after { content: ' ⌃'; }
.roi-hours-body {
  display: flex;
  flex-direction: column;
  gap: 18px;
  padding: 18px;
  border-top: 1px solid var(--border);
}
.roi-hours-out { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.roi-hours-out strong { font-family: var(--font-display); font-size: 20px; font-weight: 700; color: var(--text); }
.roi-hours-out span { font-size: 11.5px; color: var(--text-3); }

/* ══════════════════════ Legal documents ═══════════════════════ */
/*
 * Long-form prose, not marketing. Narrower measure, larger line-height,
 * numbered headings, and a sticky table of contents on wide screens — these
 * pages get read in anger, usually by somebody's lawyer looking for one
 * clause, so navigation matters more than atmosphere.
 */
.legal-wrap {
  display: grid;
  grid-template-columns: 220px minmax(0, 1fr);
  gap: 48px;
  align-items: start;
  padding-block: 48px 72px;
}
@media (max-width: 900px) {
  /* minmax(0, 1fr), not 1fr — the desktop rule above already knows this. A
     bare `1fr` takes min-content as its automatic minimum, and this track's
     min-content is set by `.legal-table`'s own `min-width: 620px`, so every
     legal page carrying a table laid itself out 646px wide inside a 390px
     phone: the document scrolled sideways and the table of contents was
     stretched to match. Measured on /legal/privacy/, /legal/dpa/ and
     /legal/subprocessors/ at 320, 390 and 414px. */
  .legal-wrap { grid-template-columns: minmax(0, 1fr); gap: 24px; }
}

.legal-toc { position: sticky; top: 78px; font-size: 12.5px; }
@media (max-width: 900px) {
  .legal-toc {
    position: static;
    padding: 16px 18px;
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    background: var(--surface-2);
  }
}
.legal-toc h2 {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--text-3);
  margin-bottom: 10px;
}
.legal-toc ol { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 7px; }
.legal-toc a { color: var(--text-2); text-decoration: none; line-height: 1.35; display: block; }
.legal-toc a:hover { color: var(--accent-link); }

.legal-doc { max-width: 74ch; }
.legal-doc h1 {
  font-size: clamp(28px, 3.4vw, 40px);
  font-weight: 700;
  line-height: 1.1;
  margin-bottom: 12px;
}
.legal-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 18px;
  font-size: 12px;
  color: var(--text-3);
  padding-bottom: 20px;
  margin-bottom: 28px;
  border-bottom: 1px solid var(--border);
}
.legal-lede { font-size: 16px; color: var(--text-2); line-height: 1.6; margin-bottom: 32px; }

.legal-doc h2 {
  font-size: 19px;
  font-weight: 700;
  line-height: 1.3;
  margin: 40px 0 12px;
  scroll-margin-top: 78px;
}
.legal-doc h3 {
  font-size: 15px;
  font-weight: 600;
  margin: 24px 0 8px;
}
.legal-doc p { font-size: 14.5px; line-height: 1.7; color: var(--text-2); margin-bottom: 14px; }
.legal-doc ul, .legal-doc ol.legal-list { margin: 0 0 16px; padding-inline-start: 22px; }
.legal-doc li { font-size: 14.5px; line-height: 1.65; color: var(--text-2); margin-bottom: 7px; }
.legal-doc strong { color: var(--text); font-weight: 600; }
.legal-doc a { color: var(--accent-link); }

/* A statement of fact the reader must not skim past — used where the honest
   answer differs from what a buyer might assume (hosting region, billing
   status, what is not yet built). */
.legal-note {
  padding: 16px 18px;
  margin: 20px 0 24px;
  border: 1px solid var(--border-strong);
  border-inline-start: 3px solid var(--accent-link);
  border-radius: var(--radius);
  background: var(--surface-2);
}
.legal-note p { margin-bottom: 0; font-size: 13.5px; }
.legal-note p + p { margin-top: 10px; }

.legal-table-wrap {
  overflow-x: auto;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface);
  margin-bottom: 20px;
}
.legal-table { width: 100%; min-width: 620px; border-collapse: collapse; font-size: 13px; }
.legal-table th, .legal-table td {
  text-align: start;
  vertical-align: top;
  padding: 12px 14px;
  border-bottom: 1px solid var(--border);
  line-height: 1.5;
}
.legal-table thead th {
  font-size: 11.5px;
  font-weight: 600;
  color: var(--text-3);
  background: var(--surface-2);
}
.legal-table tbody td { color: var(--text-2); }
.legal-table tbody th { font-weight: 600; color: var(--text); }
.legal-table tr:last-child th, .legal-table tr:last-child td { border-bottom: 0; }

/* Legal index cards */
.legal-index { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
@media (max-width: 760px) { .legal-index { grid-template-columns: 1fr; } }
.legal-index a {
  display: block;
  padding: 22px;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface);
  text-decoration: none;
  color: inherit;
  transition: border-color 150ms ease;
}
.legal-index a:hover { border-color: var(--border-strong); }
.legal-index h3 { font-size: 16px; font-weight: 600; margin-bottom: 6px; color: var(--text); }
.legal-index p { font-size: 13.5px; line-height: 1.55; color: var(--text-2); }

/* ───────────────────────── 404 page ─────────────────────────── */
/* Lived in an inline <style> until the CloudFront CSP (style-src 'self')
   made that a blocked resource and rendered the page unstyled. */
.nf { min-height: 70vh; display: flex; flex-direction: column; justify-content: center; gap: 18px; padding-block: 80px; }
.nf h1 { font-size: clamp(30px, 4vw, 44px); font-weight: 700; letter-spacing: -0.022em; }
.nf p { font-size: 16px; color: var(--text-2); max-width: 52ch; }

/* Progress-bar widths. Utility classes rather than style="width:N%"
   attributes, which `style-src 'self'` blocks — every bar rendered at zero
   width under the policy. */
.w-100 { width: 100%; }
.w-88 { width: 88%; }
.w-78 { width: 78%; }
.w-72 { width: 72%; }
.w-70 { width: 70%; }
.w-45 { width: 45%; }

/* Sub-processor entity line, previously a style attribute. */
.legal-entity-line { font-size: 11px; font-weight: 400; color: var(--text-3); }

.legal-index-contact { margin-top: 24px; }
