/* ==========================================================================
   REL Research — site stylesheet
   Shared by all static pages and the /account/ app. Keep component classes
   generic (.btn, .card, .badge, .container, .section, forms, alerts) so the
   account app can reuse them without duplication.
   Design language — sharp editorial: square corners (no border-radius),
   hairline elevation (borders, never box-shadows), self-hosted display
   serif for h1/h2 and wordmarks. Keep new components on this system.
   Strict CSP: this file is the only stylesheet; no inline styles anywhere.
   ========================================================================== */

/* Self-hosted display serif (variable weight 400-600, latin subset).
   The ?v= stamp must stay identical to the preload <link> in every page's
   <head>, or the browser fetches the font twice. */
@font-face {
  font-family: "Source Serif 4";
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url("/assets/fonts/source-serif-4-latin.woff2?v=20260708a") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6,
    U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122,
    U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* Metric-adjusted local fallback: Georgia scaled to Source Serif 4's
   metrics (computed capsize-style from both fonts' hhea/xWidthAvg values),
   so the swap when the webfont arrives causes no visible reflow (CLS). */
@font-face {
  font-family: "Source Serif 4 Fallback";
  src: local("Georgia");
  size-adjust: 107.4471%;
  ascent-override: 96.4195%;
  descent-override: 31.1781%;
  line-gap-override: 0%;
}

/* --------------------------------------------------------------------------
   1. Design tokens
   -------------------------------------------------------------------------- */
:root {
  --color-primary: #2c3e50;
  --color-primary-dark: #233140;
  --color-secondary: #34495e;
  --color-accent: #d4af37;
  --color-bg: #f8f9fa;
  --color-surface: #ffffff;
  --color-border: #e1e4e8;
  --color-border-strong: #cfd6dd;
  --color-text: #1c2733;
  --color-text-muted: #5f6a72; /* AA (>=4.5:1) on both surface and bg tints */
  --color-success: #28a745;
  --color-error: #dc3545;

  /* Derived tokens (readable gold for text on light backgrounds, tints) */
  --color-accent-deep: #8a6d1d;
  --color-on-dark: #ffffff;
  --color-on-dark-muted: #c6d0d9;
  --tint-neutral-bg: #eef1f5;
  --tint-neutral-border: #d7dde5;
  --tint-gold-bg: #faf6e8;
  --tint-gold-border: #e8d9a8;
  --tint-success-bg: #e6f4ea;
  --tint-success-border: #bfe3c8;
  --tint-success-text: #1e7e34;
  --tint-error-bg: #fdecea;
  --tint-error-border: #f4c2c7;
  --tint-error-text: #b02a37; /* AA (>=4.5:1) on --tint-error-bg */

  /* Skeleton fills. A shade darker than --tint-neutral-bg on purpose: a
     placeholder has to be legible on the page tint (--color-bg) as well as on
     a white panel, and at the bottom of its breathe the lighter tint all but
     vanishes against the page. --strong marks the value the eye lands on
     first (a metric figure, a drill title, a table's leading column). */
  --skeleton-fill: #e4e9ef;
  --skeleton-fill-strong: #d7dde5;

  --font-stack: system-ui, -apple-system, "Segoe UI", Roboto, Arial, sans-serif;
  --font-display: "Source Serif 4", "Source Serif 4 Fallback", Georgia,
    "Times New Roman", serif;
  --container-max: 72rem;
}

/* --------------------------------------------------------------------------
   2. Reset and base
   -------------------------------------------------------------------------- */
*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  -webkit-text-size-adjust: 100%;
}

/* Sticky-footer frame: short pages keep the footer at the viewport bottom
   instead of leaving a page-background band beneath it. */
body {
  margin: 0;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  font-family: var(--font-stack);
  font-size: 1rem;
  line-height: 1.6;
  color: var(--color-text);
  background: var(--color-bg);
}

main {
  flex: 1 0 auto;
}

img,
svg {
  max-width: 100%;
  height: auto;
  vertical-align: middle;
}

h1,
h2,
h3,
h4,
p,
ul,
ol,
dl,
figure {
  margin: 0 0 1rem;
}

h1,
h2,
h3,
h4 {
  color: var(--color-primary);
  line-height: 1.2;
  font-weight: 700;
}

/* Display serif for the two top heading levels only; h3 and below stay on
   the sans stack — the serif/sans contrast is the editorial signature. */
h1,
h2 {
  font-family: var(--font-display);
  font-weight: 600;
  letter-spacing: normal;
}

h1 {
  font-size: clamp(2rem, 4.8vw, 3rem);
}

h2 {
  font-size: clamp(1.45rem, 3vw, 1.85rem);
}

h3 {
  font-size: 1.15rem;
}

a {
  color: var(--color-primary);
  text-decoration: underline;
  text-underline-offset: 2px;
}

a:hover {
  color: var(--color-accent-deep);
}

:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
}

hr {
  border: 0;
  border-top: 1px solid var(--color-border);
  margin: 2rem 0;
}

fieldset {
  border: 0;
  padding: 0;
  margin: 0;
  min-width: 0;
}

/* --------------------------------------------------------------------------
   3. Layout
   -------------------------------------------------------------------------- */
.container {
  width: 100%;
  max-width: var(--container-max);
  margin-inline: auto;
  padding-inline: 1.25rem;
}

.container-narrow {
  max-width: 50rem;
}

.section {
  padding-block: clamp(3rem, 6vw, 4.5rem);
}

.section-surface {
  background: var(--color-surface);
  border-top: 1px solid var(--color-border);
  border-bottom: 1px solid var(--color-border);
}

.section-head {
  max-width: 46rem;
  margin-bottom: 2.25rem;
}

.section-head p {
  color: var(--color-text-muted);
}

/* Used on spans and, where the eyebrow is the section's only heading (the
   pricing panel), on an h2 — the font-family and line-height pins keep the
   h2 rendering identical to the spans (no serif, no tighter leading). */
.eyebrow {
  display: block;
  margin-bottom: 0.75rem;
  font-family: var(--font-stack);
  font-size: 0.78rem;
  font-weight: 700;
  line-height: 1.6;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--color-accent-deep);
}

.accent-rule {
  width: 3rem;
  height: 2px;
  margin: 0 0 1.25rem;
  border: 0;
  background: var(--color-accent);
}

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

.note {
  font-size: 0.875rem;
  color: var(--color-text-muted);
}

/* --------------------------------------------------------------------------
   4. Header and navigation
   -------------------------------------------------------------------------- */

/* Skip link: first focusable element on every page; visually hidden until
   keyboard focus, then a solid navy block above the sticky header. */
.skip-link {
  position: absolute;
  left: -999rem;
  top: 0;
  z-index: 300;
  background: var(--color-primary);
  color: var(--color-on-dark);
  font-weight: 600;
  padding: 0.7rem 1.4rem;
  text-decoration: none;
}

.skip-link:focus {
  left: 0;
}

.site-header {
  background: var(--color-surface);
  border-bottom: 1px solid var(--color-border);
  position: sticky;
  top: 0;
  z-index: 100;
}

/* Stronger hairline once the page has scrolled (site.js toggles .is-scrolled
   on the root element), so the sticky header reads as lifted — no shadow. */
.is-scrolled .site-header {
  border-bottom-color: var(--color-border-strong);
}

/* Anchor targets scroll clear of the sticky header. Default covers the
   two-row wrapped header on narrow viewports; the >=968px block reduces it
   once the header is a single row. */
[id] {
  scroll-margin-top: 7.5rem;
}

.header-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 0.75rem 1.5rem;
  padding-block: 0.9rem;
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  font-family: var(--font-display);
  font-size: 1.15rem;
  font-weight: 600;
  color: var(--color-primary);
  text-decoration: none;
  white-space: nowrap;
}

.brand:hover {
  color: var(--color-primary);
}

.brand-mark {
  width: 0.65rem;
  height: 0.65rem;
  background: var(--color-accent);
  flex: none;
}

.site-nav {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.6rem 1.4rem;
  font-size: 0.92rem;
}

.site-nav a {
  color: var(--color-secondary);
  font-weight: 500;
  text-decoration: none;
}

/* Text links get a >=44px-tall hit area (WCAG 2.2 target size) without
   changing the visual text size; the Sign in button is already large. */
.site-nav a:not(.btn) {
  padding-block: 0.7rem;
}

.site-nav a:hover {
  color: var(--color-accent-deep);
}

.site-nav .btn {
  color: var(--color-on-dark);
}

/* --------------------------------------------------------------------------
   4b. Navigation menu (hamburger disclosure)

   One component, two implementations that must look and behave identically:
   the vanilla build in assets/js/site.js (marketing header) and the Preact
   NavMenu in account/lib/shell.js (account header). A disclosure, not a modal:
   no overlay, no focus trap. Sharp editorial language — zero radius, zero
   shadow, a 1px hairline box with the gold accent as the only decoration.
   -------------------------------------------------------------------------- */
.nav-menu {
  position: relative; /* desktop: the panel anchors to the toggle */
  display: inline-flex;
  align-items: center;
}

/* Hamburger: a >=44px WCAG target with three navy bars. The resting border is
   the strong hairline (not the faint one) so the control reads as a peer of the
   navy "Sign in" button beside it. */
.nav-menu__toggle {
  display: inline-flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  gap: 4px;
  width: 44px;
  height: 44px;
  padding: 0;
  background: none;
  border: 1px solid var(--color-border-strong);
  cursor: pointer;
}

/* Hover only where a pointer can hover, so a tapped toggle does not keep the
   gold border on touch (sticky :hover) after the menu is closed again. */
@media (hover: hover) {
  .nav-menu__toggle:hover {
    border-color: var(--color-accent);
  }
}

.nav-menu__toggle:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
}

/* Open state: the button fills navy and the three bars fold into an X, so the
   open/closed distinction is unmistakable. Both the vanilla and the Preact
   build set aria-expanded, so this one rule serves the marketing and account
   headers alike — no JS branch, no extra markup. */
.nav-menu__toggle[aria-expanded="true"] {
  background: var(--color-primary);
  border-color: var(--color-primary);
}

.nav-menu__toggle[aria-expanded="true"] .nav-menu__bar {
  background: var(--color-on-dark);
}

.nav-menu__toggle[aria-expanded="true"] .nav-menu__bar:nth-child(1) {
  transform: translateY(6px) rotate(45deg);
}

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

.nav-menu__toggle[aria-expanded="true"] .nav-menu__bar:nth-child(3) {
  transform: translateY(-6px) rotate(-45deg);
}

.nav-menu__bar {
  width: 20px;
  height: 2px;
  background: var(--color-primary);
  /* The reduced-motion media query below neutralises these durations. */
  transition: transform 0.2s ease, opacity 0.2s ease, background-color 0.2s ease;
}

/* The panel is hidden via the [hidden] attribute (toggled in JS); when shown
   it is a sharp-cornered surface card bordered with the gold accent rule. */
.nav-menu__panel {
  position: absolute;
  top: calc(100% + 0.35rem);
  right: 0;
  z-index: 150; /* above header content, below the cookie bar */
  min-width: 15rem;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-top: 2px solid var(--color-accent);
  padding: 0.5rem 0;
}

.nav-menu__panel[hidden] {
  display: none;
}

.nav-menu__list {
  list-style: none;
  margin: 0;
  padding: 0;
}

/* The public section links live in two places at once. From 640px up the
   header shows them and this list is hidden; below that the header has no room
   and hides them, so the menu is where they can be reached. Exactly one of the
   two is ever visible. */
.nav-menu__list--site {
  display: none;
}

.nav-menu__item {
  margin: 0;
}

/* Links and the sign-out button share one look so a <button> and an <a> are
   indistinguishable in the list. */
.nav-menu__link {
  position: relative; /* anchors the gold hover rule */
  display: block;
  width: 100%;
  box-sizing: border-box;
  text-align: left;
  /* 1.25rem left inset matches the header gutter (.container /
     .account-header__inner), so on the full-width mobile panel the items line
     up under the wordmark. */
  padding: 0.6rem 1.25rem;
  font: inherit;
  font-size: 0.92rem;
  font-weight: 500;
  color: var(--color-secondary);
  text-decoration: none;
  background: none;
  border: none;
  cursor: pointer;
}

/* Hover/focus is the app's gold left-rule (as on .property-tile::before and
   .engagement-item::before), over a faint gold wash — not the generic gray
   fill this used to have. */
.nav-menu__link::before {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  width: 3px;
  background: var(--color-accent);
  opacity: 0;
  transition: opacity 120ms ease;
}

.nav-menu__link:hover,
.nav-menu__link:focus-visible {
  background: var(--tint-gold-bg);
  color: var(--color-accent-deep);
}

.nav-menu__link:hover::before,
.nav-menu__link:focus-visible::before {
  opacity: 1;
}

.nav-menu__link:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: -2px;
}

/* Gated (signed-out) destinations are visible but not yet reachable — muted so
   the difference reads without hiding the item. */
.nav-menu__link[data-gated] {
  color: var(--color-text-muted);
}

/* A heading, not a button: the section label above the account links. */
.nav-menu__section {
  margin: 0.5rem 0 0.15rem;
  padding: 0.35rem 1.25rem 0;
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-text-muted);
  border-top: 1px solid var(--color-border);
}

/* First section heading has a border-top that would double the panel rule;
   only the Account divider needs it, and it is not the first child, so this is
   safe — kept explicit for clarity. */
.nav-menu__panel nav > .nav-menu__section:first-child {
  border-top: none;
  margin-top: 0;
}

/* Sign out is an action, not a destination: a hairline divider above it lifts
   it off the account links. */
.nav-menu__signout {
  margin-top: 0.35rem;
  border-top: 1px solid var(--color-border);
  color: var(--color-primary);
  font-weight: 600;
}

/* Mobile: keep the panel a right-anchored card hanging from the toggle, exactly
   as on desktop, rather than a full-width sheet. A full-width sheet left a
   full-width strip of page content showing in the gap above it (which read as
   the menu being detached from the header); a card stays visually tied to the
   hamburger. The width is capped to the viewport so a long card can never cause
   horizontal scroll. */
@media (max-width: 639px) {
  .nav-menu__panel {
    max-width: calc(100vw - 1.5rem);
  }

  /* On phones the panel also carries the marketing section links (see the
     .nav-menu__list--site rule further down). A hairline separates that block
     from the account destinations below, so the panel reads as grouped lists
     rather than one long run. */
  .nav-menu__list--site {
    margin-bottom: 0.35rem;
    padding-bottom: 0.35rem;
    border-bottom: 1px solid var(--color-border);
  }
}

/* --------------------------------------------------------------------------
   5. Hero (dark band)
   -------------------------------------------------------------------------- */
.hero {
  background: var(--color-primary);
  color: var(--color-on-dark);
  padding-block: clamp(3.5rem, 8vw, 6rem);
}

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

.hero h1 {
  color: var(--color-on-dark);
  max-width: 24ch;
  line-height: 1.15;
}

.hero-sub {
  max-width: 58ch;
  font-size: 1.08rem;
  color: var(--color-on-dark-muted);
  margin-bottom: 2rem;
}

.hero-cta {
  display: flex;
  flex-wrap: wrap;
  gap: 0.85rem;
}

.hero :focus-visible {
  outline-color: var(--color-accent);
}

/* --------------------------------------------------------------------------
   6. Buttons
   -------------------------------------------------------------------------- */
.btn {
  display: inline-block;
  padding: 0.7rem 1.4rem;
  border: 1px solid transparent;
  font: inherit;
  font-size: 0.95rem;
  font-weight: 600;
  line-height: 1.3;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  transition: background-color 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}

.btn-primary {
  background: var(--color-primary);
  color: var(--color-on-dark);
}

.btn-primary:hover {
  background: var(--color-primary-dark);
  color: var(--color-on-dark);
}

.btn-outline {
  background: transparent;
  border-color: var(--color-primary);
  color: var(--color-primary);
}

.btn-outline:hover {
  background: var(--color-primary);
  color: var(--color-on-dark);
}

.btn-light {
  background: var(--color-surface);
  color: var(--color-primary);
}

.btn-light:hover {
  background: var(--tint-neutral-bg);
  color: var(--color-primary-dark);
}

.btn-outline-light {
  background: transparent;
  border-color: rgba(255, 255, 255, 0.55);
  color: var(--color-on-dark);
}

.btn-outline-light:hover {
  border-color: var(--color-accent);
  color: var(--color-accent);
}

.btn-sm {
  padding: 0.45rem 0.95rem;
  font-size: 0.875rem;
}

.btn-block {
  display: block;
  width: 100%;
}

.btn:disabled,
.btn[aria-disabled="true"] {
  opacity: 0.55;
  cursor: default;
}

/* --------------------------------------------------------------------------
   7. Cards and grids
   -------------------------------------------------------------------------- */
.card {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  padding: 1.75rem;
}

.card-grid {
  display: grid;
  gap: 1.5rem;
  grid-template-columns: 1fr;
}

.product-card {
  display: flex;
  flex-direction: column;
  border-top: 2px solid var(--color-accent);
}

.product-card h3 {
  font-size: 1.25rem;
  margin-bottom: 0.35rem;
}

.product-kicker {
  font-size: 0.8rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--color-text-muted);
  margin-bottom: 0.75rem;
}

.scope-list {
  list-style: none;
  margin: 0.75rem 0 1.5rem;
  padding: 0;
}

.scope-list li {
  position: relative;
  padding-left: 1.4rem;
  margin-bottom: 0.6rem;
  color: var(--color-secondary);
  font-size: 0.96rem;
}

.scope-list li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.65em;
  width: 0.55rem;
  height: 2px;
  background: var(--color-accent);
}

/* Card footer: the commercial line plus the "View full scope" button, pinned
   to the bottom of the card so the three cards align regardless of copy. */
.card-cta {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 0.75rem;
  margin-top: auto;
  padding-top: 1.25rem;
  border-top: 1px solid var(--color-border);
}

.card-cta strong {
  color: var(--color-primary);
  font-size: 1.05rem;
}

/* USP comparison: "a generated answer" versus "a commissioned report".
   Two side-by-side cards on index.html (#why-commissioned). The lesser column
   is recessed with muted dashes; the commissioned column carries the gold
   accent-edge that marks it as the one to choose. Widened to two tracks in
   section 22. */
.usp-compare {
  display: grid;
  gap: 1.5rem;
  grid-template-columns: 1fr;
}

.usp-col {
  display: flex;
  flex-direction: column;
}

.usp-col h3 {
  font-size: 1.25rem;
  margin-bottom: 0.35rem;
}

.usp-col .scope-list {
  margin-bottom: 0;
}

.usp-primary {
  border-top: 2px solid var(--color-accent);
}

.usp-lesser {
  background: var(--color-bg);
}

.usp-lesser h3 {
  color: var(--color-text-muted);
}

.usp-lesser .scope-list li::before {
  background: var(--color-border-strong);
}

.usp-note {
  max-width: 52rem;
  margin-top: 2rem;
  color: var(--color-text-muted);
}

/* --------------------------------------------------------------------------
   8. Process steps (ordered content only)
   -------------------------------------------------------------------------- */
.steps {
  list-style: none;
  margin: 0;
  padding: 0;
  max-width: 44rem;
  counter-reset: step;
}

.steps li {
  position: relative;
  padding: 0 0 1.9rem 3.5rem;
  counter-increment: step;
}

.steps li:last-child {
  padding-bottom: 0;
}

/* Bare editorial numeral ("01", "02", …) — no circle, no connector line. */
.steps li::before {
  content: counter(step, decimal-leading-zero);
  position: absolute;
  left: 0;
  top: -0.35rem;
  font-family: var(--font-display);
  font-size: 1.5rem;
  font-weight: 600;
  color: var(--color-accent-deep);
}

.steps h3 {
  font-size: 1.05rem;
  margin-bottom: 0.25rem;
}

.steps p {
  color: var(--color-text-muted);
  font-size: 0.95rem;
  margin-bottom: 0;
}

/* --------------------------------------------------------------------------
   9. Standards grid
   -------------------------------------------------------------------------- */
.standards {
  display: grid;
  gap: 1.25rem;
  grid-template-columns: 1fr;
}

.standard {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  padding: 1.5rem;
}

.standard h3 {
  font-size: 1.02rem;
  margin-bottom: 0.45rem;
}

.standard p {
  font-size: 0.94rem;
  color: var(--color-text-muted);
  margin-bottom: 0;
}

/* --------------------------------------------------------------------------
   10. Positioning band ("what this is — and is not")
   -------------------------------------------------------------------------- */
.contrast-band {
  background: var(--color-primary-dark);
  color: var(--color-on-dark);
  padding-block: clamp(3rem, 6vw, 4.5rem);
}

.contrast-band h2 {
  color: var(--color-on-dark);
}

.contrast-band .eyebrow {
  color: var(--color-accent);
}

.contrast-band :focus-visible {
  outline-color: var(--color-accent);
}

.contrast-grid {
  display: grid;
  gap: 2rem;
  grid-template-columns: 1fr;
  margin-top: 2rem;
}

.contrast-col h3 {
  color: var(--color-on-dark);
  font-size: 0.82rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  padding-bottom: 0.6rem;
  border-bottom: 1px solid rgba(255, 255, 255, 0.18);
}

.contrast-col.is h3 {
  color: var(--color-accent);
  border-bottom-color: var(--color-accent);
}

.contrast-col ul {
  list-style: none;
  margin: 1rem 0 0;
  padding: 0;
}

.contrast-col li {
  position: relative;
  padding-left: 1.4rem;
  margin-bottom: 0.7rem;
  color: var(--color-on-dark-muted);
}

.contrast-col li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.7em;
  width: 0.55rem;
  height: 2px;
  background: var(--color-accent);
}

.contrast-col.not li::before {
  background: rgba(255, 255, 255, 0.45);
}

/* --------------------------------------------------------------------------
   11. Pricing
   -------------------------------------------------------------------------- */
.pricing-panel {
  max-width: 38rem;
  margin-inline: auto;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-top: 2px solid var(--color-accent);
  padding: clamp(2rem, 5vw, 3rem);
  text-align: center;
}

.pricing-panel .accent-rule {
  margin-inline: auto;
}

.pricing-lead {
  display: block;
  font-family: var(--font-display);
  font-size: clamp(2.4rem, 6vw, 3rem);
  font-weight: 600;
  color: var(--color-primary);
  line-height: 1.1;
}

.pricing-unit {
  display: block;
  color: var(--color-text-muted);
  margin-bottom: 1.25rem;
}

/* --------------------------------------------------------------------------
   12. FAQ (native details/summary — no script needed)
   -------------------------------------------------------------------------- */
.faq {
  max-width: 46rem;
}

/* Hairline list, not boxes: items divided by rules, flush-left text. */
.faq-item {
  background: transparent;
  border: 0;
  border-bottom: 1px solid var(--color-border);
  margin-bottom: 0;
}

.faq-item:first-child {
  border-top: 1px solid var(--color-border);
}

.faq-item summary {
  list-style: none;
  cursor: pointer;
  padding: 1rem 3rem 1rem 0;
  font-weight: 600;
  color: var(--color-primary);
  position: relative;
}

.faq-item summary::-webkit-details-marker {
  display: none;
}

.faq-item summary::after {
  content: "+";
  position: absolute;
  right: 1.25rem;
  top: 50%;
  transform: translateY(-50%);
  font-size: 1.2rem;
  font-weight: 400;
  color: var(--color-accent-deep);
}

.faq-item[open] summary::after {
  content: "\2212"; /* minus sign */
}

.faq-body {
  padding: 0 1.25rem 1.1rem 0;
  color: var(--color-text-muted);
  font-size: 0.96rem;
}

.faq-body p {
  margin-bottom: 0.5rem;
}

/* --------------------------------------------------------------------------
   13. Forms and alerts
   -------------------------------------------------------------------------- */
.form-field {
  margin-bottom: 1.25rem;
}

.form-field label {
  display: block;
  font-weight: 600;
  font-size: 0.92rem;
  margin-bottom: 0.4rem;
  color: var(--color-primary);
}

input[type="text"],
input[type="email"],
select,
textarea {
  width: 100%;
  padding: 0.65rem 0.75rem;
  font: inherit;
  color: var(--color-text);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
}

input:focus-visible,
select:focus-visible,
textarea:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 1px;
  border-color: var(--color-primary);
}

textarea {
  min-height: 7rem;
  resize: vertical;
}

.form-hint {
  font-size: 0.85rem;
  color: var(--color-text-muted);
  margin-top: 0.45rem;
  margin-bottom: 0;
}

.checkbox-field {
  display: flex;
  gap: 0.6rem;
  align-items: flex-start;
  font-size: 0.92rem;
}

.checkbox-field input {
  margin-top: 0.25rem;
  flex: none;
}

.alert {
  padding: 0.85rem 1rem;
  border: 1px solid;
  font-size: 0.95rem;
  margin-bottom: 1rem;
}

.alert-success {
  background: var(--tint-success-bg);
  border-color: var(--tint-success-border);
  color: var(--tint-success-text);
}

.alert-error {
  background: var(--tint-error-bg);
  border-color: var(--tint-error-border);
  color: var(--tint-error-text);
}

/* --------------------------------------------------------------------------
   14. Badges (status indicators — reused by the account app)
   -------------------------------------------------------------------------- */
.badge {
  display: inline-block;
  padding: 0.25em 0.6em;
  border: 1px solid transparent;
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  white-space: nowrap;
}

.badge-neutral {
  background: var(--tint-neutral-bg);
  border-color: var(--tint-neutral-border);
  color: var(--color-secondary);
}

.badge-accent {
  background: var(--tint-gold-bg);
  border-color: var(--tint-gold-border);
  color: var(--color-accent-deep);
}

.badge-success {
  background: var(--tint-success-bg);
  border-color: var(--tint-success-border);
  color: var(--tint-success-text);
}

.badge-muted {
  background: var(--color-bg);
  border-color: var(--color-border);
  color: var(--color-text-muted);
}

.badge-error {
  background: var(--tint-error-bg);
  border-color: var(--tint-error-border);
  color: var(--color-error);
}

/* --------------------------------------------------------------------------
   15. Tables (degrade to horizontal scroll inside .table-wrap)
   -------------------------------------------------------------------------- */
.table-wrap {
  overflow-x: auto;
}

.table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.95rem;
}

.table th,
.table td {
  padding: 0.6rem 0.75rem;
  text-align: left;
  border-bottom: 1px solid var(--color-border);
  vertical-align: top;
}

.table th {
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-text-muted);
  border-bottom: 2px solid var(--color-primary);
}

/* --------------------------------------------------------------------------
   16. Page head (interior pages) and prose (legal / product detail)
   -------------------------------------------------------------------------- */
.page-head {
  background: var(--color-surface);
  border-bottom: 1px solid var(--color-border);
  padding-block: clamp(2.5rem, 5vw, 3.5rem);
}

.page-head p {
  max-width: 56ch;
  color: var(--color-text-muted);
  margin-bottom: 0;
}

.page-head .lede {
  font-size: 1.05rem;
}

.prose {
  /* The ch unit measures the "0" glyph, wider than the average letter, so
     58ch yields a real measure of ~70-75 characters per line. */
  max-width: 58ch;
}

.prose h2 {
  font-size: 1.3rem;
  margin: 2.25rem 0 0.75rem;
}

.prose h3 {
  font-size: 1.05rem;
  margin: 1.5rem 0 0.5rem;
}

.prose ul,
.prose ol {
  padding-left: 1.35rem;
}

.prose li {
  margin-bottom: 0.4rem;
}

/* Gold-dash bullets for prose lists that sit beside dash-marked components
   (product-page methodology sections); legal prose keeps plain markers. */
.prose ul.dash-list {
  list-style: none;
  padding-left: 0;
}

.prose ul.dash-list li {
  position: relative;
  padding-left: 1.4rem;
  margin-bottom: 0.6rem;
}

.prose ul.dash-list li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.7em;
  width: 0.55rem;
  height: 2px;
  background: var(--color-accent);
}

.version-tag {
  font-size: 0.85rem;
  color: var(--color-text-muted);
}

/* Numbered deliverable outline (mirrors the report's actual sections) */
.toc {
  list-style: none;
  margin: 0;
  padding: 0;
  counter-reset: toc;
}

.toc > li {
  counter-increment: toc;
  position: relative;
  padding: 1.5rem 1.5rem 1.5rem 4.25rem;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  margin-bottom: 0.85rem;
}

.toc > li::before {
  content: counter(toc, decimal-leading-zero);
  position: absolute;
  left: 1.4rem;
  top: 1.55rem;
  font-family: var(--font-display);
  font-size: 1.15rem;
  font-weight: 600;
  line-height: 1; /* aligns the serif numeral baseline with the h3 title */
  color: var(--color-accent-deep);
}

.toc h3 {
  font-size: 1.08rem;
  margin-bottom: 0.4rem;
}

.toc p {
  color: var(--color-text-muted);
  font-size: 0.95rem;
  margin-bottom: 0;
}

/* Nested lists share the gold-dash marker language of .scope-list. */
.toc ul {
  list-style: none;
  margin: 0.5rem 0 0;
  padding-left: 0;
  color: var(--color-text-muted);
  font-size: 0.95rem;
}

.toc ul li {
  position: relative;
  padding-left: 1.4rem;
  margin-bottom: 0.3rem;
}

.toc ul li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.65em;
  width: 0.55rem;
  height: 2px;
  background: var(--color-accent);
}

/* --------------------------------------------------------------------------
   17. Auth pages (sign-in / verify)
   -------------------------------------------------------------------------- */
.auth-main {
  display: flex;
  justify-content: center;
  align-items: flex-start; /* keep the card its natural height when main grows */
  padding: clamp(3rem, 8vw, 5.5rem) 1.25rem;
}

.auth-card {
  width: 100%;
  max-width: 27rem;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-top: 2px solid var(--color-accent);
  padding: 2.25rem;
}

.auth-card h1 {
  font-size: 1.45rem;
  margin-bottom: 0.5rem;
}

.auth-card > p {
  color: var(--color-text-muted);
  font-size: 0.95rem;
}

/* One step of the sign-in flow: address, code, or profile. */
.auth-step {
  margin-top: 1.5rem;
}

@media (max-width: 419px) {
  .auth-card {
    padding: 1.75rem 1.25rem;
  }
}

/* Inline text buttons ("Send a new code" / "Use a different address"). */
.link-button {
  appearance: none;
  background: none;
  border: none;
  padding: 0;
  font: inherit;
  color: var(--color-primary);
  font-weight: 600;
  text-decoration: underline;
  cursor: pointer;
}

.link-button:hover {
  color: var(--color-accent-deep);
}

.link-button:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
}

/* Field-level validation error, shown beneath the offending input. */
.field-error {
  color: var(--color-error);
  font-size: 0.85rem;
  margin-top: 0.4rem;
  margin-bottom: 0;
}

input[aria-invalid="true"] {
  border-color: var(--color-error);
}

input[aria-invalid="true"]:focus-visible {
  outline-color: var(--color-error);
  border-color: var(--color-error);
}

/* The emailed six-digit code, typed back in. Monospaced and widely tracked so
   a transcription error is visible before it is submitted. */
.otp-input {
  font-family: ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace;
  font-size: 1.5rem;
  letter-spacing: 0.28em;
  text-align: center;
}

.optional-mark {
  font-weight: 400;
  color: var(--color-text-muted);
  font-size: 0.85em;
}

/* --------------------------------------------------------------------------
   18. CTA panel (product pages)
   -------------------------------------------------------------------------- */
.cta-panel {
  background: var(--color-primary);
  color: var(--color-on-dark);
  padding: clamp(2rem, 5vw, 2.75rem);
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 1.25rem;
}

.cta-panel h2 {
  color: var(--color-on-dark);
  margin-bottom: 0.35rem;
}

.cta-panel p {
  color: var(--color-on-dark-muted);
  margin-bottom: 0;
  max-width: 48ch;
}

.cta-panel :focus-visible {
  outline-color: var(--color-accent);
}

/* --------------------------------------------------------------------------
   19. Footer
   -------------------------------------------------------------------------- */
.site-footer {
  background: var(--color-primary-dark);
  color: var(--color-on-dark-muted);
  padding: 3.25rem 0 2rem;
  font-size: 0.92rem;
}

.site-footer a {
  color: #d5dbe1;
  text-decoration: none;
}

.site-footer a:hover {
  color: var(--color-accent);
}

.site-footer :focus-visible {
  outline-color: var(--color-accent);
}

.footer-grid {
  display: grid;
  gap: 2rem;
  grid-template-columns: 1fr;
}

.footer-brand p {
  max-width: 34rem;
  color: #9aa6b1;
}

.footer-wordmark {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  color: var(--color-on-dark);
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 1.15rem;
  margin-bottom: 0.75rem;
}

.footer-heading {
  color: var(--color-on-dark);
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  margin-bottom: 0.9rem;
}

.footer-col ul {
  list-style: none;
  margin: 0;
  padding: 0;
}

.footer-col li {
  margin-bottom: 0.55rem;
}

/* Keep the contact address on one line — no mid-domain wrap. */
a[href^="mailto:"] {
  white-space: nowrap;
}

.footer-legal {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 0.5rem 2rem;
  margin-top: 2.5rem;
  padding-top: 1.5rem;
  border-top: 1px solid rgba(255, 255, 255, 0.14);
  font-size: 0.85rem;
  color: #9aa6b1;
}

.footer-legal p {
  margin: 0;
}

/* --------------------------------------------------------------------------
   20. Error pages
   -------------------------------------------------------------------------- */
.error-main {
  display: flex;
  justify-content: center;
  padding: clamp(4rem, 12vw, 7rem) 1.25rem;
  text-align: center;
}

.error-card {
  max-width: 30rem;
}

.error-code {
  display: block;
  font-size: 0.85rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--color-accent-deep);
  margin-bottom: 0.75rem;
}

/* --------------------------------------------------------------------------
   21. Utilities
   -------------------------------------------------------------------------- */
.hidden {
  display: none !important;
}

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

.mt-1 {
  margin-top: 1rem;
}

.mt-2 {
  margin-top: 2rem;
}

.mb-0 {
  margin-bottom: 0;
}

/* --------------------------------------------------------------------------
   22. Loading and pending feedback

   Two vocabularies, one rhythm.
   - SKELETON: the shape of content that does not exist yet. Square corners,
     hairline borders, --tint-neutral-bg fills. No gradient sweep: a diagonal
     shimmer is the most recognisable generic-template tell, and there is not
     one gradient anywhere else in this codebase. Liveness comes from a
     synchronised opacity breathe on the GROUP -- the same idiom, and the same
     1.4s ease-in-out, as the shipped .order-status__pulse.
   - PENDING: a 2px gold rule on a control that is working. Same gold-rule
     grammar as .accent-rule, .product-card's gold top border and
     .property-tile::before, so a working button reads as this design system
     rather than as a bootstrapped spinner.

   These live in site.css because it is the only stylesheet loaded by all
   three contexts that need them: the marketing/sign-in pages, the account app
   (account.css) and the report viewer (report.css, which does not load
   account.css). Both animations are infinite, so both carry an explicit
   prefers-reduced-motion override in section 25 -- a static resting state, NOT
   a shortened duration, which the global kill-switch would turn into a strobe.
   -------------------------------------------------------------------------- */

/* 22.1 Skeleton group ----------------------------------------------------- */
.skeleton {
  animation: skeleton-breathe 1.4s ease-in-out infinite;
  pointer-events: none;
  user-select: none;
}

/* "A surface is being prepared here" -- the gold top rule borrowed from
   .product-card / .auth-card. Use on a whole <main> or panel body; omit when
   the skeleton sits inside a surface that already carries its own rule. */
.skeleton-region {
  border-top: 2px solid var(--color-accent);
  padding-top: 1.25rem;
}

/* 22.2 Bars and boxes ----------------------------------------------------- */
/* The box is exactly one line box (1.6em at the house body line-height); the
   0.3em padding leaves a 1em painted bar centred inside it, so the bar reads
   as text and the swap to real text moves nothing. em, not rem, so a bar
   inherits the size of whatever it stands in for. */
.skeleton-line {
  display: block;
  height: 1.6em;
  padding-block: 0.3em;
  background-color: var(--skeleton-fill);
  background-clip: content-box;
}

/* For h1/h2 and anywhere line-height is 1.2. */
.skeleton-line-tight {
  height: 1.2em;
  padding-block: 0.1em;
}

/* A heavier bar for a value the eye lands on first (metric-tile values, a
   drill-head title, a table's first column). */
.skeleton-line-strong {
  background-color: var(--skeleton-fill-strong);
}

/* Separate runs of text need breathing room between them. Two cases do not,
   and opt out with .skeleton-row on their container: bars sitting side by side
   in a flex row (where the margin pushes the second one out of line with the
   first), and bars standing in for the successive lines of ONE wrapped run of
   text, which have no gap between them either. */
.skeleton-line + .skeleton-line {
  margin-top: 0.2rem;
}

.skeleton-row .skeleton-line + .skeleton-line {
  margin-top: 0;
}

.skeleton-block {
  display: block;
  background-color: var(--skeleton-fill);
}

.skeleton-block-sm {
  height: 2.4rem; /* an .input (0.55rem 0.7rem padding) or a .btn */
}

.skeleton-block-md {
  height: 7rem; /* a textarea, a meter list */
}

.skeleton-block-lg {
  height: 12rem;
}

/* Character-width utilities, for bars inside a table cell. A percentage width
   contributes nothing to a column's intrinsic width, so an auto-layout table
   sizes its columns one way for the placeholder and another way for the data,
   and every column shifts sideways when the rows land. A ch width does count,
   so a bar set to roughly the real content's length holds the column steady.
   Pick per column from what that column actually holds. */
.skeleton-ch6 {
  width: 6ch;
}

.skeleton-ch10 {
  width: 10ch;
}

.skeleton-ch14 {
  width: 14ch;
}

.skeleton-ch20 {
  width: 20ch;
}

.skeleton-ch28 {
  width: 28ch;
}

.skeleton-ch32 {
  width: 32ch;
}

/* A bar standing in for a cell whose real content wraps to two lines: the BOX
   is two line boxes tall, the painted bar stays one line. Without it the
   placeholder rows are a line short and the whole table shifts up when the
   data lands. */
.skeleton-line-2line {
  height: 3.2em;
  padding-block: 1.1em;
}

/* Width utilities, in the manner of section 21's .mt-1 / .mb-0. */
.skeleton-w25 {
  width: 25%;
}

.skeleton-w40 {
  width: 40%;
}

.skeleton-w60 {
  width: 60%;
}

.skeleton-w75 {
  width: 75%;
}

.skeleton-w90 {
  width: 90%;
}

/* 22.3 Shaped skeletons --------------------------------------------------- */
/* Mirrors .property-tile: same border, same padding, same 0.5rem gap.
   min-height is the MODAL real height, measured against a rendered grid: a
   two-line address plus a status badge lands at ~13.2rem, and that is the
   common case. Deliberately not the minimum -- a skeleton that is a little too
   tall settles once; one that is too short pushes the whole page down when the
   tiles arrive. */
.skeleton-tile {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  min-height: 13.2rem;
  padding: 1.25rem;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
}

/* A generic bordered panel body placeholder (conditions summary, profile dl,
   share list). */
.skeleton-panel-body {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
}

/* 22.4 Pending controls --------------------------------------------------- */
/* Works for both button dialects: .btn-primary (marketing) and .btn--primary
   (account). Only the base .btn class is targeted. */
/* Full opacity deliberately overrides the .btn[aria-disabled] / :disabled dim
   from section 6: "pending" is its own state with its own vocabulary (the
   gerund label, the gold rule, cursor: progress). Dimming it as well would
   fade out the very mark that says the button is working. */
.btn.is-pending {
  position: relative;
  cursor: progress;
  opacity: 1;
}

.btn.is-pending::after {
  content: "";
  position: absolute;
  left: -1px;
  right: -1px;
  bottom: -1px;
  height: 2px;
  background: var(--color-accent);
  animation: pending-pulse 1.4s ease-in-out infinite;
}

/* Inline text buttons ("Send a new code", "Use a different address") had no
   disabled styling at all -- this is the missing rule. */
.link-button:disabled,
.link-button[aria-disabled="true"] {
  opacity: 0.55;
  cursor: default;
  text-decoration: none;
}

/* Field-level pending stamp, for rows with no button to carry the state.
   Typography is the house uppercase micro-label; the leading mark is the
   house gold dash. */
.field-pending {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-text-muted);
}

.field-pending::before {
  content: "";
  width: 0.55rem;
  height: 2px;
  background: var(--color-accent);
  animation: pending-pulse 1.4s ease-in-out infinite;
}

/* Settled variant: same stamp, no pulse. For a state that has finished
   ("Saved") or is merely waiting on the clock (a resend cooldown). A pulsing
   mark on a finished action reads as still working, which is a lie. */
.field-pending--settled::before {
  animation: none;
  opacity: 0.55;
}

/* 22.5 Stale content being replaced (re-sort, re-filter, search) ----------- */
/* Never blank a loaded list. Dim it, freeze it, and let the view's status line
   say "Updating...". Headers stay at full contrast so the sort arrow and the
   column labels remain readable. */
.is-busy {
  opacity: 0.5;
  transition: opacity 120ms ease;
  pointer-events: none;
}

/* 22.6 Navigation acknowledgement ----------------------------------------- */
/* Every intra-app navigation in /account/ is a real document load. This is the
   sub-100ms "your click landed" mark on the element that was clicked; the
   destination's boot skeleton takes over from there. */
.is-navigating {
  border-color: var(--color-accent);
}

/* 22.7 Keyframes ---------------------------------------------------------- */
/* Narrow range: a skeleton that dropped to 0.35 opacity would read as
   disappearing rather than as loading. */
@keyframes skeleton-breathe {
  0%,
  100% {
    opacity: 0.55;
  }

  50% {
    opacity: 1;
  }
}

/* Same stops as the existing order-status-pulse. Deliberately not unified with
   it: .order-status__pulse is load-bearing in a shipped panel and stays as is. */
@keyframes pending-pulse {
  0%,
  100% {
    opacity: 0.35;
  }

  50% {
    opacity: 1;
  }
}

/* --------------------------------------------------------------------------
   23. Responsive breakpoints (~640px, ~968px)
   -------------------------------------------------------------------------- */
@media (min-width: 640px) {
  .card-grid {
    grid-template-columns: repeat(2, 1fr);
  }

  /* A third card would leave an empty cell on two tracks — let it span both. */
  .card-grid .product-card:nth-child(3):last-child {
    grid-column: span 2;
  }

  .standards {
    grid-template-columns: repeat(2, 1fr);
  }

  .contrast-grid {
    grid-template-columns: repeat(2, 1fr);
    gap: 3rem;
  }

  .usp-compare {
    grid-template-columns: repeat(2, 1fr);
  }

  .footer-grid {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (min-width: 968px) {
  /* Single-row header: less anchor clearance needed. */
  [id] {
    scroll-margin-top: 6rem;
  }

  /* Wide enough for the three products side by side. */
  .card-grid {
    grid-template-columns: repeat(3, 1fr);
  }

  .card-grid .product-card:nth-child(3):last-child {
    grid-column: auto;
  }

  /* Six-track grid so a five-card set lays out 3 + 2 with no empty cell. */
  .standards {
    grid-template-columns: repeat(6, 1fr);
  }

  .standard {
    grid-column: span 2;
  }

  .standard:nth-child(4):nth-last-child(2),
  .standard:nth-child(5):last-child {
    grid-column: span 3;
  }

  .footer-grid {
    grid-template-columns: 2fr 1fr 1fr 1fr;
    gap: 3rem;
  }
}

/* Phones: the header keeps to a single row — brand, "Sign in", hamburger.
   Wrapping instead (the old `justify-content: center`) stacked those three onto
   three centred rows and left a 168px sticky header eating a fifth of the
   viewport, with the sign-in card pushed beneath it. The section links have no
   room here, so they move into the menu panel (see .nav-menu__list--site). */
@media (max-width: 639px) {
  .header-inner {
    flex-wrap: nowrap;
    gap: 0.75rem;
  }

  .site-nav {
    flex-wrap: nowrap;
    gap: 0.5rem;
    font-size: 0.88rem;
  }

  /* Direct children only: the menu panel is mounted inside .site-nav, so a
     descendant selector here would blank out every link in the panel too. */
  .site-nav > a:not(.btn) {
    display: none;
  }

  .nav-menu__list--site {
    display: block;
  }
}

/* --------------------------------------------------------------------------
   24. Cookie consent banner (rendered by assets/js/site.js)
   Slim, non-blocking bottom bar. Collapsed it offers Reject / Only necessary
   plus a "More options" disclosure; expanded it reveals a per-category panel
   and Save / Accept all.
   -------------------------------------------------------------------------- */
.cookie-consent {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 200; /* above the sticky header */
  background: var(--color-surface);
  border-top: 2px solid var(--color-accent); /* gold system-bar line, no shadow */
  animation: cookie-rise 0.25s ease;
}

@keyframes cookie-rise {
  from {
    transform: translateY(100%);
  }
  to {
    transform: translateY(0);
  }
}

.cookie-consent__inner {
  max-width: var(--container-max);
  margin-inline: auto;
  padding: 1rem 1.25rem;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.75rem 1.5rem;
}

.cookie-consent__body {
  flex: 1 1 20rem;
  min-width: 0;
}

.cookie-consent__text {
  margin: 0;
  font-size: 0.9rem;
  line-height: 1.5;
  color: var(--color-text-muted);
}

.cookie-consent__text a {
  color: var(--color-primary);
  font-weight: 600;
  white-space: nowrap;
}

.cookie-consent__panel {
  display: none;
  margin-top: 0.85rem;
  padding-top: 0.6rem;
  border-top: 1px solid var(--color-border);
}

.cookie-consent.is-expanded .cookie-consent__panel {
  display: block;
}

.cookie-consent__row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  max-width: 26rem;
  padding: 0.4rem 0;
  font-size: 0.9rem;
}

.cookie-consent__row-label {
  color: var(--color-text);
  font-weight: 500;
}

.cookie-consent__always {
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--color-text-muted);
}

.cookie-consent__toggle {
  width: 1.05rem;
  height: 1.05rem;
  flex: none;
  accent-color: var(--color-primary);
}

.cookie-consent__actions {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.5rem;
  flex: none;
}

/* Compact chevron toggle: sits to the right of the quick-choice buttons in
   both states and shares their height. Icon-only ("More options" is on the
   aria-label / title). */
.cookie-consent__expand {
  appearance: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  align-self: stretch;
  background: none;
  border: 1px solid var(--color-primary);
  padding: 0 0.6rem;
  font: inherit;
  color: var(--color-primary);
  cursor: pointer;
  transition: background-color 0.15s ease, color 0.15s ease;
}

.cookie-consent__expand::after {
  content: "\25be"; /* down triangle */
  font-size: 0.8rem;
  line-height: 1;
}

.cookie-consent.is-expanded .cookie-consent__expand::after {
  content: "\25b4"; /* up triangle */
}

/* Invert only on real pointer devices. On touch, :hover sticks after a tap
   until the next tap elsewhere, so a plain :hover rule would leave the chevron
   navy after it was tapped to expand and then again to collapse. */
@media (hover: hover) {
  .cookie-consent__expand:hover {
    background: var(--color-primary);
    color: var(--color-on-dark);
  }
}

/* Reject and the chevron toggle stay put in both states. Collapsed shows
   Only necessary; expanded swaps it for Save choices + Accept all and
   reveals the per-category panel. The selectors are scoped to the component
   (`.cookie-consent .cookie-consent__save`) so the display:none sits at
   two-class specificity: the account app's base `.btn` rule (loaded later)
   can no longer beat it and re-show these buttons on /account/. */
.cookie-consent .cookie-consent__save,
.cookie-consent .cookie-consent__acceptall {
  display: none;
}

.cookie-consent.is-expanded .cookie-consent__save,
.cookie-consent.is-expanded .cookie-consent__acceptall {
  display: inline-block;
}

.cookie-consent.is-expanded .cookie-consent__only {
  display: none;
}

@media (max-width: 639px) {
  .cookie-consent__inner {
    padding: 0.75rem 1rem;
    gap: 0.6rem 1rem;
  }

  .cookie-consent__text {
    font-size: 0.82rem;
  }

  .cookie-consent__actions {
    width: 100%;
  }

  /* Quick-choice buttons share the row; the chevron stays compact on the right. */
  .cookie-consent__actions .btn {
    flex: 1 1 auto;
  }

  /* Collapsed the chevron trails the two buttons; expanded it wraps to a
     second row, where margin-left:auto keeps it aligned under Accept all. */
  .cookie-consent__expand {
    flex: 0 0 auto;
    margin-left: auto;
  }
}

/* --------------------------------------------------------------------------
   25. Motion and print
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    transition-duration: 0.01ms !important;
    animation-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }

  /* Infinite animations need a resting state, not a shortened duration: the
     kill-switch above compresses them to 0.01ms, which strobes. Each of these
     stays an unambiguous "in progress" mark with zero motion. */
  .skeleton {
    animation: none;
    opacity: 0.8;
  }

  .btn.is-pending::after,
  .field-pending::before {
    animation: none;
    opacity: 0.7;
  }
}

@media print {
  body {
    background: #fff;
    color: #000;
  }

  .site-header,
  .site-nav,
  .btn,
  .hero-cta,
  .footer-grid,
  .cta-panel {
    display: none !important;
  }

  .hero,
  .contrast-band,
  .site-footer {
    background: none;
    color: #000;
    padding-block: 1rem;
  }

  .hero h1,
  .contrast-band h2,
  .contrast-col h3,
  .contrast-col li {
    color: #000;
  }

  .section {
    padding-block: 1.25rem;
  }

  a {
    color: #000;
  }

  .faq-item {
    border: 0;
  }
}
