/* =========================================================================
   Reviseberg — website styles
   Hand-written, no framework. Tokens first, then layout, then components.
   Target: WCAG 2.2 AA. Body text ≥ 4.5:1, UI ≥ 3:1, targets ≥ 44px.
   ========================================================================= */

:root {
  /* Brand */
  --ink: #291c29;
  --ink-2: #443044;
  --brand: #713653;
  --brand-hover: #57253e;
  --lime: #f1b9d1;
  --lime-deep: #e9a3c2;

  /* Neutrals */
  --bg: #fffaf5;
  --bg-muted: #f4eeea;
  --bg-sunk: #ede3e5;
  --border: #ded3d7;
  /* Decoration only — pills, badges, dividers, the dots on a fake browser. At
     2.26:1 on --bg it is too light to be the edge somebody finds a control by. */
  --border-strong: #b7a4af;
  /* The edge of anything typed into or pressed: inputs, selects, the colour
     picker, outlined buttons and pill links. 1.4.11 asks 3:1 against what is
     beside it when that edge is how the control is found, so it is this dark:
     3.82:1 on --bg, 3.45:1 on --bg-muted, 3.97:1 on white, and 3.16:1 on
     --bg-sunk, the hover fill. */
  --border-control: #98768a;

  /* Text */
  --fg: #291c29;
  --fg-muted: #665461;
  --fg-on-dark: #fff7fb;
  --fg-on-dark-muted: #d8c3d0;

  /* Status */
  --critical: #b3261e;
  --serious: #a2540b;
  --moderate: #7a5b00;
  --ok: #1b6b3a;

  /* Surfaces with a meaning of their own. --bg-ink is the aubergine of the
     closing bands, the dark sections and code; --on-ink is text on an --ink
     or --brand fill, --on-lime text on the rose. */
  --bg-ink: #291c29;
  --bg-raised: #fff;
  --bg-accent: #faedf3;
  --bg-error: #fdf3f2;
  --bg-warning: #fff4d6;
  --on-ink: #fff;
  --on-lime: #291c29;
  --scroll-shadow: rgba(41, 28, 41, .22);

  /* Shape & motion */
  --radius-sm: 10px;
  --radius: 12px;
  --radius-lg: 18px;
  --shadow: 0 1px 2px rgba(41, 28, 41, .06), 0 12px 32px -12px rgba(41, 28, 41, .18);
  --shadow-lg: 0 2px 4px rgba(41, 28, 41, .05), 0 32px 64px -24px rgba(41, 28, 41, .28);
  --tap: 44px;
  --shell: 1180px;
  /* The sticky header's height, in one place because three things need it:
     the mobile menu's top edge, `scroll-padding-top`, and the scroll margin on
     anything focus or an anchor jumps to. Without it every in-page link lands
     with its heading parked underneath the bar. */
  --header-h: 72px;
  --ease: cubic-bezier(.22, .61, .36, 1);

  --font: -apple-system, BlinkMacSystemFont, "Segoe UI", Inter, Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;

  color-scheme: light;
}

/* The dark theme: the same names, other values, for a visitor whose system is
   set to dark. Screen only — a page printed from a dark browser is still
   printed on paper, and Firefox leaves backgrounds out by default, which
   would print light text on white. Every text token is AA on --bg, --bg-muted
   and --bg-sunk alike: --fg 15.7:1 or better, --fg-muted 8.8:1, --brand
   10.2:1, the status colours 7.7:1; --border-control is 4:1. --ink is the
   rose here, so text on it is dark (--on-ink); --bg-ink, the aubergine band,
   becomes a raised dark surface instead. Components with a colour of their
   own get their dark value in "Dark theme" below. */
@media screen and (prefers-color-scheme: dark) {
  :root {
    --ink: #f1b9d1;
    --ink-2: #f8d3e3;
    --brand: #f1b9d1;
    --brand-hover: #f8d3e3;
    --bg: #0c070c;
    --bg-muted: #1a111a;
    --bg-sunk: #251825;
    --border: rgba(255, 226, 240, .14);
    --border-strong: #85707e;
    --border-control: #8a7584;
    --fg: #fbf4f8;
    --fg-muted: #c8b6c1;
    --critical: #ff8f86;
    --serious: #ffb877;
    --moderate: #eed480;
    --ok: #9fe2b6;
    --bg-ink: #1f1320;
    --bg-raised: #170e17;
    --bg-accent: #2b1625;
    --bg-error: #2d1314;
    --bg-warning: #2a230f;
    --on-ink: #2a1529;
    --on-lime: #2a1529;
    --scroll-shadow: rgba(255, 226, 240, .2);
    --shadow: 0 1px 2px rgba(0, 0, 0, .4), 0 12px 32px -12px rgba(0, 0, 0, .7);
    --shadow-lg: 0 2px 4px rgba(0, 0, 0, .35), 0 32px 64px -24px rgba(0, 0, 0, .8);
    color-scheme: dark;
  }
}

/* ----------------------------------------------------------------- reset */

*, *::before, *::after { box-sizing: border-box; }

/* `scroll-padding-top` is what makes a jump link land somewhere readable.
   The header is sticky, so without it the browser scrolls the target to y=0 —
   i.e. exactly behind the bar — and every table of contents, every FAQ anchor
   and every skip link delivers somebody to a heading they cannot see. It is
   also what 2.4.11 asks for, which is a criterion this site publishes a page
   about. */
html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--header-h) + 1rem);
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
  }
}

body {
  margin: 0;
  font-family: var(--font);
  font-size: 1.0625rem;
  line-height: 1.6;
  color: var(--fg);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-wrap: break-word;
}

h1, h2, h3, h4 {
  margin: 0 0 .5em;
  line-height: 1.12;
  letter-spacing: -.02em;
  font-weight: 700;
  text-wrap: balance;
}
/* On a phone a heading word can be wider than the line, and German has many:
   it breaks where the language hyphenates it (`lang` is on <html>), not at the
   last letter that fits. "Barrierefreiheitserkläru / ng" was the first thing on
   the German statement guide, and "Barrierefreiheitsprüfung," left its comma
   to start the next line of the rules page. */
@media (max-width: 40rem) {
  h1, h2, h3, h4 { -webkit-hyphens: auto; hyphens: auto; hyphenate-limit-chars: 10 4 4; }
}

p { margin: 0 0 1em; }
p:last-child { margin-bottom: 0; }

img, svg, video { max-width: 100%; height: auto; }

a { color: var(--brand); text-underline-offset: .18em; text-decoration-thickness: .08em; }
a:hover { color: var(--brand-hover); }

ul, ol { margin: 0 0 1em; padding-left: 1.25em; }
.list-reset { list-style: none; margin: 0; padding: 0; }

code { font-family: var(--font-mono); font-size: .9em; background: var(--bg-sunk); padding: .1em .35em; border-radius: 5px; }

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

:focus-visible {
  outline: 3px solid var(--ink);
  outline-offset: 2px;
  border-radius: 4px;
}
.section--dark :focus-visible, .cta :focus-visible { outline-color: var(--lime); }

::selection { background: var(--lime); color: var(--on-lime); }

main:focus { outline: none; }

/* --------------------------------------------------------------- helpers */

.shell { width: 100%; max-width: var(--shell); margin-inline: auto; padding-inline: clamp(1rem, 4vw, 2rem); }

.skip-link {
  position: absolute; left: 1rem; top: -100%;
  z-index: 100;
  background: var(--ink); color: var(--on-ink);
  padding: .85rem 1.25rem; border-radius: 0 0 var(--radius-sm) var(--radius-sm);
  font-weight: 600; text-decoration: none;
}
.skip-link:focus { top: 0; color: var(--on-ink); }

.icon { width: 1.25em; height: 1.25em; flex: none; }
.icon--sm { width: 1.1em; height: 1.1em; }

.linklike {
  background: none; border: 0; padding: 0; margin: 0;
  font: inherit; color: inherit; text-decoration: underline; cursor: pointer;
  text-underline-offset: .18em;
}

.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;
}

/* A line break that is a layout decision, not a sentence boundary. It splits a
   headline where the designer wants it on a wide screen; on a phone the same
   break lands mid-thought and costs a line, so it stops existing. */
@media (max-width: 48rem) { .br-wide { display: none; } }

.pill {
  display: inline-flex; align-items: center; gap: .5rem;
  margin: 0 0 1.25rem;
  padding: .4rem .85rem;
  border: 1px solid var(--border-strong);
  border-radius: 999px;
  background: var(--bg-muted);
  font-size: .875rem; font-weight: 600; letter-spacing: .01em;
  color: var(--fg-muted);
}

.eyebrow {
  margin: 0 0 .75rem;
  font-size: .8125rem; font-weight: 700; letter-spacing: .1em; text-transform: uppercase;
  color: var(--brand);
}
.section--dark .eyebrow { color: var(--lime); }

.note { font-size: .9375rem; color: var(--fg-muted); }
.note--center { text-align: center; margin-top: 2rem; }

/* ---------------------------------------------------------------- buttons */

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: .5rem;
  min-height: var(--tap); padding: .75rem 1.375rem;
  border: 2px solid transparent; border-radius: 999px;
  font: inherit; font-weight: 650; line-height: 1.2;
  text-decoration: none; cursor: pointer;
  transition: background-color .18s var(--ease), color .18s var(--ease), border-color .18s var(--ease), transform .18s var(--ease);
}
.btn:active { transform: translateY(1px); }

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

.btn--secondary { background: transparent; color: var(--ink); border-color: var(--border-control); }
.btn--secondary:hover { background: var(--bg-muted); color: var(--ink); border-color: var(--ink); }

.btn--ghost { background: transparent; color: var(--fg); padding-inline: .875rem; }
.btn--ghost:hover { background: var(--bg-muted); color: var(--fg); }

.btn--invert { background: var(--lime); color: var(--on-lime); }
.btn--invert:hover { background: var(--lime-deep); color: var(--on-lime); }

.btn--ghost-invert { background: transparent; color: var(--fg-on-dark); border-color: rgba(255,255,255,.4); }
.btn--ghost-invert:hover { background: rgba(255,255,255,.1); color: #fff; border-color: #fff; }

.btn--lg { min-height: 52px; padding: .9rem 1.75rem; font-size: 1.0625rem; }

.link-arrow {
  display: inline-flex; align-items: center; gap: .4rem;
  min-height: 32px;
  font-weight: 650; text-decoration: none;
}
.link-arrow:hover { text-decoration: underline; }
.link-arrow .icon { transition: transform .18s var(--ease); }
.link-arrow:hover .icon { transform: translateX(3px); }

/* ----------------------------------------------------------------- header

   A floating pill: the wordmark, the sections, the language, logging in and
   the free scan. The header itself is a clear strip `--header-h` tall that
   lets clicks through to the page beside the pill; the pill is frosted glass,
   and clear at the very top of the page (`is-top`, set by site.js). Its
   colours are the site's tokens plus five of its own, which the dark theme
   redefines (see "Dark theme"). */

.site-header {
  --chrome-glass: rgba(255, 250, 245, .8);
  --chrome-menu: #fffaf5;
  --chrome-line: rgba(41, 28, 41, .1);
  --chrome-shadow: 0 16px 40px -24px rgba(41, 28, 41, .4);
  --chrome-hover: rgba(41, 28, 41, .07);
  position: sticky; top: 0; z-index: 50;
  display: flex; align-items: center;
  min-height: var(--header-h); padding: 10px 12px;
  pointer-events: none;
}
.site-header__inner {
  position: relative; pointer-events: auto;
  display: flex; align-items: center; gap: .5rem;
  width: min(var(--shell), 100%); min-height: 52px; margin-inline: auto;
  padding: 3px 3px 3px 16px;
  border: 1px solid var(--chrome-line); border-radius: 999px;
  background: var(--chrome-glass);
  backdrop-filter: blur(16px) saturate(140%); -webkit-backdrop-filter: blur(16px) saturate(140%);
  box-shadow: var(--chrome-shadow);
  transition: background-color .4s, border-color .4s, box-shadow .4s;
}
/* Clear at the top of the page — unless the menu is open and hangs from it. */
.site-header.is-top .site-header__inner:not(:has(.site-nav.is-open)) {
  background: transparent; border-color: transparent; box-shadow: none;
  backdrop-filter: none; -webkit-backdrop-filter: none;
}

.site-header__brand { display: inline-flex; align-items: center; min-height: var(--tap); text-decoration: none; color: var(--ink); }

.logo { display: inline-flex; align-items: center; gap: .6rem; font-weight: 750; font-size: 1.1875rem; letter-spacing: -.03em; color: var(--ink); }
/* `flex: none` because the bar it sits in is now three items wide on a phone:
   without it the mark is the thing that gives, and an iceberg squashed to a
   sliver is the logo on every small screen. */
.logo__mark { width: 30px; height: 30px; flex: none; color: var(--brand); }
.logo__berg { color: var(--brand); }
.logo--inverse { color: #fff; }
.logo--inverse .logo__mark { color: var(--lime); }
.logo--inverse .logo__berg { color: var(--lime); }

.nav__toggle {
  display: none;
  align-items: center; gap: .5rem;
  min-height: var(--tap); padding: .5rem .875rem;
  background: transparent; border: 1px solid var(--border-control); border-radius: 999px;
  font: inherit; font-weight: 600; color: var(--fg); cursor: pointer;
}
.nav__toggle:hover { background: var(--chrome-hover); }
.nav__toggle-bars { display: grid; gap: 4px; }
.nav__toggle-bars span { display: block; width: 18px; height: 2px; background: currentColor; border-radius: 2px; }

.site-nav { display: flex; flex: 1; align-items: center; gap: 1rem; margin-left: .75rem; }
.nav__list { display: flex; align-items: center; gap: 2px; list-style: none; margin: 0; padding: 0; }
.nav__link, .nav__lang, .site-header .nav__actions .btn--ghost {
  display: inline-flex; align-items: center; gap: .35rem;
  min-height: var(--tap); padding: 0 .8rem;
  border: 0; border-radius: 999px;
  background: none; color: var(--fg-muted);
  font-size: .9375rem; font-weight: 550; text-decoration: none;
  transition: color .2s, background-color .2s;
}
.nav__link:hover, .nav__lang:hover, .site-header .nav__actions .btn--ghost:hover { background: var(--chrome-hover); color: var(--fg); }
.nav__link.is-current { background: var(--chrome-hover); color: var(--fg); font-weight: 650; }

.nav__actions { display: flex; align-items: center; gap: 2px; margin-left: auto; }

/* The pill's own button: round, and inside the 3px rim. */
.site-header .site-header__cta { min-height: var(--tap); padding: 0 1.125rem; border-radius: 999px; white-space: nowrap; }

/* German labels need room too: collapse before desktop links begin to wrap. */
@media (max-width: 74rem) {
  .nav__toggle { display: inline-flex; }
  /* The menu is a card hanging under the pill, as wide as it. */
  .site-nav {
    position: absolute; top: calc(100% + 8px); left: 0; right: 0;
    display: none;
    flex-direction: column; align-items: stretch; gap: .5rem; margin: 0;
    /* A phone in landscape has ~330px of height: the menu has to scroll rather
       than put its last two items past the bottom of the screen with nothing
       to say so. */
    max-height: calc(100dvh - var(--header-h) - 1rem); overflow-y: auto;
    padding: .75rem;
    border: 1px solid var(--chrome-line); border-radius: 22px;
    background: var(--chrome-menu);
    box-shadow: var(--shadow-lg);
  }
  .site-nav.is-open { display: flex; }
  .nav__list { flex-direction: column; align-items: stretch; }
  .nav__link { min-height: 48px; padding-inline: 1rem; border-radius: 14px; }
  .nav__actions { flex-wrap: wrap; margin-left: 0; padding-top: .5rem; border-top: 1px solid var(--chrome-line); }
  .nav__actions > * { flex: 1 1 auto; justify-content: center; }

  /* The call to action stays in the bar; the menu holds everything else. It
     is pushed right by `margin-left: auto` because the nav beside it is taken
     out of flow while it is closed. */
  .site-header .site-header__cta { margin-left: auto; padding-inline: 1rem; font-size: .9375rem; }
}

/* The call to action never wraps: a two-line button in the bar pushes the
   pill open and the wordmark out of shape. Where the long label will not
   fit, the short one is what ships — same destination, same promise, fewer
   characters (German needs this; English happens not to). */
.site-header__cta-short { display: none; }
@media (max-width: 30rem) {
  .site-header { padding-inline: 8px; }
  .site-header__cta-long { display: none; }
  .site-header__cta-short { display: inline; }
  .site-header__inner { gap: .375rem; padding-left: 12px; }
  .logo { font-size: 1.0625rem; }
}

/* Under ~480px the toggle's word is what pushes the row over the edge, so it
   becomes the button's accessible name instead of its label — the icon and the
   `aria-expanded` state carry the rest, and nothing loses a name. */
@media (max-width: 30rem) {
  .nav__toggle { padding-inline: .75rem; }
  .nav__toggle-label {
    position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
    overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
  }
}
/* At 320px — the width WCAG's reflow is measured at — the German bar was
   wider than the screen and the menu button sat partly off it. The three
   items give up a little padding each instead. */
@media (max-width: 22.5rem) {
  .site-header__inner { gap: .25rem; padding-left: 10px; }
  .logo { gap: .45rem; font-size: 1rem; }
  .site-header .site-header__cta { padding-inline: .75rem; font-size: .875rem; }
  .nav__toggle { padding-inline: .6rem; }
}

/* ------------------------------------------------------------ breadcrumb */

.breadcrumb { padding: 1rem 0 0; font-size: .875rem; }
.breadcrumb__list { display: flex; flex-wrap: wrap; align-items: center; gap: .25rem .5rem; }
.breadcrumb__item { display: inline-flex; align-items: center; gap: .5rem; min-height: 32px; }
.breadcrumb__item + .breadcrumb__item::before { content: "/"; color: var(--border-strong); }
.breadcrumb__item a { color: var(--fg-muted); text-decoration: none; }
.breadcrumb__item a:hover { color: var(--brand); text-decoration: underline; }
.breadcrumb__current { color: var(--fg); font-weight: 600; }
/* The trail plus a hero heading is a lot of chrome on a phone; the current
   page is already the <h1> two lines below it. So a phone gets the one crumb
   that is a way back — the parent, as "← Parent". Dropping only the current
   page used to leave a lone grey "Reviseberg" on most pages, which read as a
   stray label rather than a link. */
@media (max-width: 40rem) {
  .breadcrumb__list > .breadcrumb__item { display: none; }
  .breadcrumb__list > .breadcrumb__item:nth-last-child(2) { display: inline-flex; }
  .breadcrumb__list > .breadcrumb__item:nth-last-child(2)::before {
    content: "←";
    content: "←" / "";
    color: var(--fg-muted);
  }
  .breadcrumb__list > .breadcrumb__item:nth-last-child(2) a { color: var(--fg); text-decoration: underline; text-underline-offset: .18em; }
  /* A trail that is only Home › this page has nothing to add on a phone: the
     wordmark in the header is the way home, and "← Reviseberg" alone above
     the heading read as a stray label. */
  .breadcrumb:has(.breadcrumb__item:first-child:nth-last-child(2)) { display: none; }
}

/* ------------------------------------------------------------------- hero */

.hero { padding: clamp(3rem, 7vw, 5.5rem) 0 clamp(2.5rem, 5vw, 4rem); background: linear-gradient(180deg, var(--bg-muted), var(--bg)); }
.hero__inner { display: grid; gap: clamp(2rem, 5vw, 4rem); grid-template-columns: 1fr; align-items: center; }
@media (min-width: 60rem) { .hero__inner { grid-template-columns: minmax(0, 1.05fr) minmax(0, .95fr); } }

.hero--simple .hero__inner { grid-template-columns: minmax(0, 1fr); }
.hero--simple .hero__copy { max-width: 54rem; }
.hero--simple .hero__title { max-width: 24ch; }
.hero--simple .hero__intro { max-width: 58ch; }

.hero__title { font-size: clamp(2.25rem, 5.2vw, 3.75rem); letter-spacing: -.035em; margin-bottom: .4em; }
.hero__intro { font-size: clamp(1.0625rem, 1.6vw, 1.25rem); color: var(--fg-muted); max-width: 40ch; margin-bottom: 2rem; }
.hero__actions { display: flex; flex-wrap: wrap; gap: .75rem; }
.hero__note { margin-top: 1rem; font-size: .9375rem; color: var(--fg-muted); }
.hero__trust { list-style: none; margin: 2rem 0 0; padding: 0; display: grid; gap: .625rem; }
.hero__trust li { display: flex; align-items: flex-start; gap: .6rem; font-size: .9375rem; color: var(--fg-muted); }
.hero__trust .icon { color: var(--brand); margin-top: .15em; }

/* -------------------------------------------------------- product preview */

.preview {
  margin: 0;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--bg);
  box-shadow: var(--shadow-lg);
  overflow: hidden;
}
.preview__chrome {
  display: flex; align-items: center; gap: .4rem;
  padding: .75rem 1rem;
  background: var(--bg-muted); border-bottom: 1px solid var(--border);
}
.preview__chrome > span:not(.preview__url) { width: 10px; height: 10px; border-radius: 50%; background: var(--border-strong); }
.preview__url { margin-left: .75rem; font-size: .75rem; color: var(--fg-muted); font-family: var(--font-mono); }

.preview__body { padding: 1.5rem; display: grid; gap: 1.25rem; }
.preview__score { display: flex; align-items: center; gap: 1.5rem; flex-wrap: wrap; }

.ring {
  --value: 82;
  position: relative;
  width: 108px; height: 108px; flex: none;
  display: grid; place-content: center; text-align: center;
  border-radius: 50%;
  background:
    conic-gradient(var(--brand) calc(var(--value) * 1%), var(--bg-sunk) 0);
}
.ring::after {
  content: ""; position: absolute; inset: 10px; border-radius: 50%; background: var(--bg);
}
.ring__value { position: relative; z-index: 1; font-size: 2rem; font-weight: 750; letter-spacing: -.04em; line-height: 1; }
.preview__gauge { display: grid; justify-items: center; gap: .5rem; flex: none; }
.ring__label { margin: 0; max-width: 9rem; text-align: center; font-size: .6875rem; text-transform: uppercase; letter-spacing: .06em; color: var(--fg-muted); }

.preview__deltas { list-style: none; margin: 0; padding: 0; display: grid; gap: .5rem; flex: 1 1 180px; }
.preview__deltas li { display: flex; justify-content: space-between; gap: 1rem; font-size: .875rem; border-bottom: 1px dashed var(--border); padding-bottom: .4rem; }
.preview__delta-label { color: var(--fg-muted); }
.preview__delta-value { font-weight: 700; font-variant-numeric: tabular-nums; }
.preview__delta-value.up { color: var(--brand); }
.preview__delta-value.down { color: var(--fg); }

.preview__rows { list-style: none; margin: 0; padding: 0; display: grid; gap: .5rem; }
.preview__row {
  display: grid; grid-template-columns: auto 1fr; gap: .5rem .75rem; align-items: start;
  padding: .75rem; border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--bg-muted);
  font-size: .875rem;
}
.preview__row-meta { grid-column: 2; font-size: .75rem; color: var(--fg-muted); }
.preview__foot { font-size: .8125rem; color: var(--fg-muted); margin: 0; }
.preview__caption { padding: .75rem 1.5rem 1.25rem; font-size: .75rem; color: var(--fg-muted); }

.tag {
  display: inline-block; padding: .1rem .5rem; border-radius: 999px;
  font-size: .6875rem; font-weight: 700; text-transform: uppercase; letter-spacing: .04em;
  border: 1px solid currentColor;
}
.tag--critical, .tag--kritisch { color: var(--critical); }
.tag--serious, .tag--schwer { color: var(--serious); }
.tag--moderate, .tag--mittel { color: var(--moderate); }

/* --------------------------------------------------------------- sections */

.section { padding: clamp(3rem, 7vw, 5.5rem) 0; }
.section--muted { background: var(--bg-muted); }
.section--tight { padding-top: clamp(2rem, 4vw, 3rem); }
.section--tall { padding-block: clamp(4rem, 12vw, 8rem); }
.section--dark { background: var(--bg-ink); color: var(--fg-on-dark); }
.section--dark h2, .section--dark h3 { color: #fff; }
.section--dark .section-head__intro { color: var(--fg-on-dark-muted); }

.section-head { max-width: 52rem; margin-bottom: clamp(2rem, 4vw, 3rem); }
.section-head--center { margin-inline: auto; text-align: center; }
.section-head__title { font-size: clamp(1.75rem, 3.4vw, 2.625rem); margin-bottom: .35em; }
.section-head__intro { font-size: clamp(1rem, 1.4vw, 1.125rem); color: var(--fg-muted); margin: 0; }

.split { display: grid; gap: clamp(2rem, 5vw, 4rem); align-items: start; }
@media (min-width: 60rem) {
  .split { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
  .split--reverse > :first-child { order: 2; }
}
.split .section-head { margin-bottom: 1.5rem; }
.split__aside { padding: clamp(1.25rem, 3vw, 2rem); border: 1px solid var(--border); border-radius: var(--radius-lg); background: var(--bg); }
.section--muted .split__aside { background: var(--bg); }

/* ------------------------------------------------------------------ cards */

.grid { display: grid; gap: 1.25rem; grid-template-columns: 1fr; }
@media (min-width: 40rem) { .grid--3, .grid--4 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 64rem) {
  .grid--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .grid--4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

.card {
  display: flex; flex-direction: column; gap: .625rem;
  padding: clamp(1.25rem, 2.5vw, 1.75rem);
  border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--bg);
}
.card__icon {
  display: inline-grid; place-content: center;
  width: 44px; height: 44px; margin-bottom: .25rem;
  border-radius: 12px; background: var(--bg-sunk); color: var(--brand);
}
.card__title { font-size: 1.125rem; margin: 0; }
/* A status inside the heading — "In development" on an agent that is not built. */
.card__badge {
  display: inline-block; vertical-align: middle; margin-left: .375rem;
  padding: .125rem .5rem; border-radius: 999px;
  font-size: .75rem; font-weight: 650; line-height: 1.4; white-space: nowrap;
  color: var(--serious); border: 1px solid currentColor;
}
.card__text { margin: 0; color: var(--fg-muted); font-size: .9375rem; }
.card__text a { color: var(--brand); }

/* ------------------------------------------------------------------ steps */

.steps { display: grid; gap: 1.25rem; counter-reset: step; }
@media (min-width: 48rem) { .steps { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 72rem) { .steps { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
.step { display: grid; gap: .75rem; align-content: start; padding: 1.5rem; border-radius: var(--radius); background: var(--bg-muted); border: 1px solid var(--border); }
/* The statement guide's outline has seven parts: four across left a hole in
   the second row, so it is three and four on a wide screen, and the odd one
   out spans the row in two columns. */
@media (min-width: 48rem) and (max-width: 71.99rem) {
  #template .step:last-child:nth-child(odd) { grid-column: 1 / -1; }
}
@media (min-width: 72rem) {
  #template .steps { grid-template-columns: repeat(12, minmax(0, 1fr)); }
  #template .step { grid-column: span 3; }
  #template .step:nth-child(-n + 3) { grid-column: span 4; }
}
.section--muted .step { background: var(--bg); }
.step__num {
  display: grid; place-content: center;
  width: 36px; height: 36px; border-radius: 50%;
  background: var(--ink); color: var(--on-ink); font-weight: 700; font-size: .9375rem;
}
.step__title { font-size: 1.0625rem; margin: 0 0 .25rem; }
.step__text { margin: 0; font-size: .9375rem; color: var(--fg-muted); }

/* ------------------------------------------------------------------ stats */

.stats { display: grid; gap: 1.5rem; margin: 0 0 clamp(2rem, 4vw, 3rem); grid-template-columns: repeat(2, minmax(0, 1fr)); }
@media (min-width: 60rem) { .stats { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
.stat { border-top: 2px solid rgba(255,255,255,.25); padding-top: 1rem; }
.stat__value { margin: 0; font-size: clamp(1.75rem, 3.4vw, 2.5rem); font-weight: 750; letter-spacing: -.035em; color: var(--lime); }
.stat__label { order: 2; font-size: .875rem; color: var(--fg-on-dark-muted); }
.stat { display: flex; flex-direction: column-reverse; gap: .25rem; }

.quote { margin: 0; max-width: 46rem; }
.quote blockquote { margin: 0; font-size: clamp(1.125rem, 2vw, 1.375rem); line-height: 1.45; }
.quote figcaption { margin-top: 1rem; font-weight: 650; color: #fff; }
.quote__role { display: block; font-weight: 400; font-size: .9375rem; color: var(--fg-on-dark-muted); }

/* ----------------------------------------------------------------- checks */

.checks { display: grid; gap: .875rem; }
@media (min-width: 48rem) { .checks--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.checks li { display: flex; align-items: flex-start; gap: .65rem; font-size: .9375rem; }
.checks .icon { color: var(--brand); margin-top: .25em; }
.checks--points .icon { color: var(--fg-muted); }
.section--dark .checks .icon { color: var(--lime); }

.chips { display: flex; flex-wrap: wrap; gap: .625rem; justify-content: center; }
.chip {
  padding: .5rem 1rem; border-radius: 999px;
  border: 1px solid rgba(255,255,255,.28); color: var(--fg-on-dark);
  font-size: .9375rem; font-weight: 550;
}

/* -------------------------------------------------------------------- faq */

.faq { max-width: 52rem; margin-inline: auto; }
.faq .section-head__title { text-align: center; margin-bottom: 2rem; }
.faq__list { display: grid; gap: .75rem; }
.faq__item { border: 1px solid var(--border); border-radius: var(--radius); background: var(--bg); }
.faq__q {
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  min-height: var(--tap); padding: 1rem 1.25rem;
  font-weight: 650; cursor: pointer; list-style: none;
}
.faq__q::-webkit-details-marker { display: none; }
.faq__q::after {
  content: ""; flex: none;
  width: .65em; height: .65em;
  border-right: 2px solid var(--fg-muted); border-bottom: 2px solid var(--fg-muted);
  transform: rotate(45deg) translateY(-.15em);
  transition: transform .2s var(--ease);
}
.faq__item[open] .faq__q::after { transform: rotate(-135deg) translateY(-.15em); }
.faq__q:hover { color: var(--brand); }
.faq__a { padding: 0 1.25rem 1.25rem; color: var(--fg-muted); font-size: .9375rem; }
.faq__a p:not(:last-child) { margin-bottom: .75em; }

/* ------------------------------------------------------------------ table */

.table-wrap { overflow-x: auto; border: 1px solid var(--border); border-radius: var(--radius); background: var(--bg); }
.table { width: 100%; border-collapse: collapse; font-size: .9375rem; min-width: 34rem; }
.table caption { text-align: left; padding: 1rem 1.25rem; font-weight: 650; border-bottom: 1px solid var(--border); }
.table th, .table td { padding: .875rem 1.25rem; text-align: left; vertical-align: top; border-bottom: 1px solid var(--border); }
.table thead th { background: var(--bg-muted); font-size: .8125rem; text-transform: uppercase; letter-spacing: .05em; color: var(--fg-muted); }
.table tbody th { font-weight: 650; }
.table tbody tr:last-child th, .table tbody tr:last-child td { border-bottom: 0; }

/* ------------------------------------------------------------------ plans */

.plans { display: grid; gap: 1.25rem; align-items: start; }
@media (min-width: 56rem) { .plans { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.plan {
  display: flex; flex-direction: column; gap: .75rem;
  padding: clamp(1.5rem, 3vw, 2rem);
  border: 1px solid var(--border); border-radius: var(--radius-lg); background: var(--bg);
}
.plan--featured { border-color: var(--ink); border-width: 2px; box-shadow: var(--shadow); }
.plan__badge {
  align-self: flex-start; margin: 0;
  padding: .25rem .75rem; border-radius: 999px;
  background: var(--lime); color: var(--on-lime);
  font-size: .75rem; font-weight: 700; text-transform: uppercase; letter-spacing: .05em;
}
.plan__name { font-size: 1.25rem; margin: 0; }
.plan__for { margin: 0 0 .5rem; color: var(--fg-muted); font-size: .9375rem; }
.plan .btn { width: 100%; }
.plan__features { display: grid; gap: .625rem; margin-top: .5rem; font-size: .9375rem; }
.plan__features li { display: flex; align-items: flex-start; gap: .6rem; }
.plan__features .icon { color: var(--brand); margin-top: .25em; }
/* The free account across the top of the paid plans: a plan in its own right,
   where somebody arriving from their report is sent, laid out as one row so
   the three paid plans keep their columns. */
.plan--free { background: var(--bg-muted); }
@media (min-width: 56rem) {
  .plan--free {
    grid-column: 1 / -1;
    display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.4fr) minmax(0, .7fr);
    gap: 1rem 2rem; align-items: center;
  }
  .plan--free .plan__features { margin-top: 0; }
}
.plan--free .plan__for { margin-bottom: 0; }

/* -------------------------------------------------------------------- cta */

.cta { background: var(--bg-ink); color: var(--fg-on-dark); padding: clamp(3rem, 6vw, 4.5rem) 0; }
.cta__inner { display: grid; gap: 2rem; align-items: center; }
@media (min-width: 60rem) { .cta__inner { grid-template-columns: minmax(0, 1.2fr) minmax(0, .8fr); } }
.cta__title { font-size: clamp(1.75rem, 3.4vw, 2.5rem); color: #fff; margin-bottom: .35em; }
.cta__text { color: var(--fg-on-dark-muted); margin: 0; max-width: 46ch; }
.cta__actions { display: flex; flex-wrap: wrap; gap: .75rem; align-items: center; }
@media (min-width: 60rem) { .cta__actions { justify-content: flex-end; } }
.cta__note { flex-basis: 100%; margin: 0; font-size: .875rem; color: var(--fg-on-dark-muted); }
@media (min-width: 60rem) { .cta__note { text-align: right; } }

.panel {
  padding: clamp(1.75rem, 4vw, 3rem);
  border: 1px solid var(--border); border-radius: var(--radius-lg);
  background: var(--bg-muted); text-align: center;
  max-width: 48rem; margin-inline: auto;
}
.panel .section-head__intro { margin-bottom: 1.5rem; }

/* ----------------------------------------------------------- lead / forms */

.lead { padding: clamp(2.5rem, 6vw, 4.5rem) 0; background: linear-gradient(180deg, var(--bg-muted), var(--bg)); }

/* Three blocks, and the order matters more on a phone than the columns do.
   Stacked, the pitch used to run pill → headline → paragraph → three trust
   lines before the form began, which put the first field more than a screen
   below the fold: an advertisement clicked on a phone landed on a page whose
   one job was invisible. The reassurance now sits *under* the form, where it
   answers the hesitation rather than delaying it, and the DOM says exactly
   that — no `order`, so reading order and visual order stay the same thing. */
.lead__inner { display: grid; gap: clamp(1.75rem, 5vw, 3.5rem); align-items: start; }
/* The reassurance belongs to the pitch above it, not halfway down the column. */
@media (min-width: 62rem) { .lead__inner { row-gap: 2rem; } }
@media (min-width: 62rem) {
  .lead__inner {
    grid-template-columns: minmax(0, 1fr) minmax(0, 27rem);
    /* `auto 1fr` rather than two auto rows: the form spans both, and two auto
       rows split its extra height between them — which pushed the reassurance
       into the middle of an empty column, a long way from the sentence it is
       reassuring about. */
    grid-template-rows: auto 1fr;
    grid-template-areas: "copy form" "trust form";
    align-content: start;
  }
  .lead__copy { grid-area: copy; }
  .lead__form { grid-area: form; }
  .lead__trust { grid-area: trust; }
}
.lead__copy .hero__title { font-size: clamp(2rem, 4.4vw, 3rem); }
.lead__copy .hero__intro { margin-bottom: 0; }
.lead__trust .hero__trust { margin-top: 0; }
.lead__form {
  padding: clamp(1.5rem, 3vw, 2rem);
  border: 1px solid var(--border); border-radius: var(--radius-lg);
  background: var(--bg); box-shadow: var(--shadow);
}
.form__title { font-size: 1.375rem; margin-bottom: .25rem; }
.form__intro { color: var(--fg-muted); font-size: .9375rem; margin-bottom: 1.5rem; }
/* A form heading with no intro under it sat 10px above the first label and
   read as that field's title, not the form's. */
.lead__form > .form__title + .form { margin-top: 1.25rem; }

/* Beside the demo and contact forms: what happens next, and the addresses for
   anybody who would rather write than fill in a form. They fill the column
   that used to end well short of the tall form beside it. */
.lead__next-title { font-size: 1.125rem; margin: 2rem 0 1rem; }
.lead__trust > .lead__next-title:first-child { margin-top: 0; }
.lead__next { display: grid; gap: 1rem; }
.lead__next li { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: .875rem; align-items: start; }
.lead__next-num {
  display: grid; place-content: center; width: 1.75rem; height: 1.75rem; border-radius: 50%;
  background: var(--ink); color: var(--on-ink); font-size: .8125rem; font-weight: 700;
}
.lead__next h3 { font-size: 1rem; margin: .15rem 0 .2rem; }
.lead__next p { margin: 0; font-size: .9375rem; color: var(--fg-muted); }
.contact-channels { display: grid; gap: 1rem; }
@media (min-width: 40rem) { .contact-channels { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.contact-channels li { padding: 1rem 1.125rem; border: 1px solid var(--border); border-radius: var(--radius); background: var(--bg); }
.contact-channels__title { font-size: 1rem; margin: 0 0 .25rem; }
.contact-channels p { margin: 0; font-size: .9375rem; color: var(--fg-muted); overflow-wrap: anywhere; }
/* The demo form is six fields long, and on a laptop its button sat a hundred
   pixels below the first screen. Tighter here, and the last field is a note,
   not a letter. */
@media (min-width: 62rem) {
  .page-demo .lead { padding-top: 2rem; }
  .page-demo .lead__form { padding-block: 1.5rem; }
  .page-demo .form__intro { margin-bottom: 1rem; }
  .page-demo .form__grid { gap: .75rem; }
  .page-demo textarea.input { height: 4rem; min-height: 4rem; }
  .page-demo .field--consent { margin-top: 1rem; }
  .page-demo .form .btn { margin-top: 1rem; }
}

.form__grid { display: grid; gap: 1rem; }
.field--wide { grid-column: 1 / -1; }
.field { display: grid; gap: .375rem; }
.label { font-weight: 650; font-size: .9375rem; }
.optional { font-weight: 400; color: var(--fg-muted); }
.req { color: var(--critical); }
.hint { margin: 0; font-size: .8125rem; color: var(--fg-muted); }

.input {
  width: 100%; min-height: var(--tap);
  padding: .7rem .875rem;
  font: inherit; font-size: 1rem; color: var(--fg);
  background: var(--bg);
  border: 1px solid var(--border-control); border-radius: var(--radius-sm);
}
.input:hover { border-color: var(--fg-muted); }
.input:focus-visible { outline: 3px solid var(--ink); outline-offset: 1px; border-color: var(--ink); }
textarea.input { min-height: 7rem; resize: vertical; }
select.input { appearance: none; background-image: linear-gradient(45deg, transparent 50%, var(--fg-muted) 50%), linear-gradient(135deg, var(--fg-muted) 50%, transparent 50%); background-position: calc(100% - 20px) 50%, calc(100% - 14px) 50%; background-size: 6px 6px; background-repeat: no-repeat; padding-right: 2.5rem; }

.input[aria-invalid="true"] { border-color: var(--critical); border-width: 2px; }
.field__error { margin: 0; font-size: .875rem; font-weight: 600; color: var(--critical); }

.field--consent { margin-top: 1.25rem; }
.checkbox { display: flex; align-items: flex-start; gap: .65rem; font-size: .875rem; color: var(--fg-muted); cursor: pointer; }
.checkbox input { width: 22px; height: 22px; margin: 0; flex: none; accent-color: var(--ink); }

.hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

.form .btn { width: 100%; margin-top: 1.5rem; }
.form__note { margin-top: 1rem; font-size: .8125rem; color: var(--fg-muted); }

.form__error-summary {
  margin-bottom: 1.5rem; padding: 1rem 1.25rem;
  border: 2px solid var(--critical); border-radius: var(--radius-sm);
  background: var(--bg-error);
}
.form__error-summary h3 { font-size: 1rem; margin-bottom: .5rem; color: var(--critical); }
.form__error-summary ul { margin: 0; padding-left: 1.25rem; font-size: .9375rem; }
.form__error-summary a { color: var(--critical); }

.form__status:not(:empty) {
  margin-top: 1.25rem; padding: 1rem 1.25rem;
  border-radius: var(--radius-sm); font-size: .9375rem;
  border: 2px solid var(--brand); background: var(--bg-accent);
}
.form__status.is-error { border-color: var(--critical); background: var(--bg-error); }
.form__status strong { display: block; }

/* ------------------------------------------------------------- prose /doc */

.doc { max-width: 46rem; margin-inline: auto; }
.prose { font-size: 1.0625rem; }
.prose__head h1 { font-size: clamp(2rem, 4vw, 2.75rem); }
.prose__meta { font-size: .875rem; color: var(--fg-muted); }
.prose__intro { font-size: 1.125rem; color: var(--fg-muted); }
.prose section { margin-top: 2.5rem; }
.prose h2 { font-size: clamp(1.375rem, 2.4vw, 1.75rem); margin-top: 0; }
.prose h3 { font-size: 1.125rem; margin-top: 1.75rem; }
.prose ul, .prose ol { padding-left: 1.35em; }
/* A list that is a component, not running text, keeps its own edge: `.prose ul`
   outranked `.list-reset`, and indented the glossary's jump links and letters
   past the labels above them. */
.prose .list-reset { padding-left: 0; }
.prose li { margin-bottom: .5em; }
.prose .table-wrap { margin: 1.5rem 0; }
.prose .table { min-width: 30rem; }

.toc {
  margin-top: 2rem; padding: 1.25rem 1.5rem;
  background: var(--bg-muted); border: 1px solid var(--border); border-radius: var(--radius);
}
/* The label is the site's eyebrow, whatever element carries it. Inside
   `.prose` the legal pages' label is an <h2>, and `.prose h2` used to win:
   "CONTENTS" in widely spaced capitals at the size of the headings below it. */
.toc .toc__title {
  margin: 0 0 .75rem;
  font-size: .8125rem; font-weight: 700; line-height: 1.4; letter-spacing: .1em; text-transform: uppercase;
  color: var(--brand);
}
.toc ol { margin: 0; padding-left: 1.25em; font-size: .9375rem; }
.toc li { margin-bottom: .35em; }

/* The contents of a page file (pages-content.mjs): a disclosure that ships
   closed. On a phone it is one line between the byline and the answer, where
   it used to be a screen of links before either; beside the article on a wide
   screen `site.js` opens it, and marks the section being read. */
.toc--page { padding: 0; }
.toc__summary {
  display: flex; align-items: center; gap: .5rem;
  min-height: var(--tap); padding: .5rem 1.25rem;
  cursor: pointer; list-style: none;
}
.toc__summary::-webkit-details-marker { display: none; }
.toc__summary::after {
  content: ""; flex: none; margin-left: auto;
  width: .55em; height: .55em;
  border-right: 2px solid var(--fg-muted); border-bottom: 2px solid var(--fg-muted);
  transform: rotate(45deg) translateY(-.15em);
  transition: transform .2s var(--ease);
}
.toc__fold[open] > .toc__summary::after { transform: rotate(-135deg) translateY(-.15em); }
.toc--page .toc__title { margin: 0; }
.toc__count { font-size: .875rem; color: var(--fg-muted); }
.toc--page ol { padding: 0 1.25rem 1rem 2.5rem; font-size: .875rem; line-height: 1.4; }
.toc--page li { margin: 0; }
/* No underline: a numbered list under "On this page" is a list of links by
   context, and an underline under every wrapped line made it harder to scan
   than the headings it points to. Hover, focus and the current section say
   which one is meant. */
.toc--page li a { display: block; padding: .3rem 0; text-decoration: none; }
.toc--page li a:hover { text-decoration: underline; }
.toc--page li a[aria-current] { color: var(--ink); font-weight: 700; text-decoration: underline; text-decoration-thickness: 2px; }
.toc--page li:has(> a[aria-current])::marker { color: var(--brand); font-weight: 700; }

/* ------------------------------------------------------ page-file layout */

/* The layout every page file shares: a heading with its byline, then the body
   beside its table of contents on a wide screen and under it on a narrow one. */
.page-hero .hero__title { max-width: 28ch; }
/* The heading's section ends at the byline. With the hero's own bottom padding
   stacked on the article's top padding, the byline sat above an empty band of
   110–120px that read like something had failed to load, and on a tool page it
   pushed the tool below the fold. */
.page-hero { padding-bottom: 0; }
.byline { margin-top: 1rem; font-size: .9375rem; color: var(--fg-muted); }
.byline a { color: inherit; }
.section--article { padding-top: clamp(1.5rem, 3vw, 2rem); }
.article { display: grid; gap: 1.5rem; }
/* Prose keeps its measure; a table, a tool or an index may use the whole
   column. Capping the body at 46rem squeezed the rule table into two-thirds of
   the page — breaking rule ids mid-word — beside a third of nothing. */
.article__body { min-width: 0; }
.article__body > * { max-width: 46rem; }
.article__body > :is(.table-scroll, .rule-filter, .glossary, .contrast) { max-width: none; }
.article__aside .toc { margin-top: 0; }
@media (min-width: 62rem) {
  .article { gap: 3rem; }
  .article--toc { grid-template-columns: minmax(0, 17rem) minmax(0, 1fr); }
  .article__aside .toc { position: sticky; top: calc(var(--header-h) + 1.5rem); max-height: calc(100vh - var(--header-h) - 3rem); overflow: auto; }
  /* Beside the article the list is open; how long it is needs no saying. */
  .toc__count { display: none; }
}
.prose h2 { margin-top: 2.75rem; }
.prose h2:first-child { margin-top: 0; }
.prose h4 { font-size: 1rem; margin-top: 1.5rem; }
.prose p, .prose ul, .prose ol { margin-bottom: 1em; }
.prose hr { border: 0; border-top: 1px solid var(--border); margin: 2.5rem 0; }
.prose a { overflow-wrap: anywhere; }

/* A wide table scrolls inside itself, and can be reached and scrolled by
   keyboard because the region is focusable and named after its caption. The
   edge that has more to show casts a shadow — the two `local` layers cover it
   once that edge is reached — because a table cut off at the side of a phone
   with no cue reads as a table that ends there. */
.table-scroll {
  overflow-x: auto; margin: 1.5rem 0; border: 1px solid var(--border); border-radius: var(--radius);
  background:
    linear-gradient(to right, var(--bg) 40%, transparent) left center / 2.5rem 100% no-repeat local,
    linear-gradient(to left, var(--bg) 40%, transparent) right center / 2.5rem 100% no-repeat local,
    radial-gradient(farthest-side at 0 50%, var(--scroll-shadow), transparent) left center / .875rem 100% no-repeat scroll,
    radial-gradient(farthest-side at 100% 50%, var(--scroll-shadow), transparent) right center / .875rem 100% no-repeat scroll,
    var(--bg);
}
.table-scroll:focus-visible { outline: 3px solid var(--ink); outline-offset: 2px; }
.table-scroll .table { min-width: 32rem; }
/* A rule id or a token of code is one word: it does not break at its hyphen,
   and a link in a cell breaks where words do. `overflow-wrap: anywhere` (from
   `.prose a`) let a table shrink a column to a few letters — "Relation/ships",
   "Tastaturfall/e" — and `keyboard:focus-invisible`, split at the hyphen, read
   like its neighbour `keyboard:focus-visible`. A table too wide for its words
   scrolls instead, in the region above. */
.table code { white-space: nowrap; }
.table a { overflow-wrap: normal; }
.table .align-center { text-align: center; }
.table .align-right { text-align: right; }

.callout { margin: 1.5rem 0; padding: 1rem 1.25rem; border-left: 4px solid var(--brand); background: var(--bg-muted); border-radius: 0 var(--radius-sm) var(--radius-sm) 0; }
.callout > :last-child { margin-bottom: 0; }
.cta-inline { margin: 2rem 0; display: flex; flex-wrap: wrap; gap: .75rem; }
/* Code keeps its lines: wrapped back to the left edge, a sample about nesting
   shows the nesting wrong. A line too long for the box scrolls — the block is
   focusable, so a keyboard scrolls it too — and the side that has more shows a
   lighter edge, so a cut-off attribute does not pass for the whole of it. */
.code-block {
  margin: 1.25rem 0; padding: 1rem 1.25rem; overflow-x: auto;
  color: var(--fg-on-dark); border-radius: var(--radius-sm); font-size: .875rem; line-height: 1.55;
  background:
    linear-gradient(to right, var(--bg-ink) 40%, transparent) left center / 2.5rem 100% no-repeat local,
    linear-gradient(to left, var(--bg-ink) 40%, transparent) right center / 2.5rem 100% no-repeat local,
    radial-gradient(farthest-side at 0 50%, rgba(255, 247, 251, .5), rgba(255, 247, 251, 0)) left center / 1rem 100% no-repeat scroll,
    radial-gradient(farthest-side at 100% 50%, rgba(255, 247, 251, .5), rgba(255, 247, 251, 0)) right center / 1rem 100% no-repeat scroll,
    var(--bg-ink);
}
.code-block code { background: none; padding: 0; color: inherit; font-size: inherit; }
.code-block:focus-visible { outline-color: var(--lime); }
/* Inline code is a token — `aria-label`, `<a href>` — and a token split over
   two lines reads as two. It does not wrap inside; the few long enough to need
   to are marked by the renderer (`code--long`) and break where they must. */
.prose :not(pre) > code:not(.code--long) { white-space: nowrap; }
.prose code.code--long { overflow-wrap: anywhere; }
sup.ref { font-size: .7em; line-height: 0; }
sup.ref a { text-decoration: none; padding: 0 .1em; }

.sources { max-width: 46rem; margin-inline: auto; }
.sources__title { font-size: 1.125rem; margin-bottom: .75rem; }
.sources__list { padding-left: 1.5em; font-size: .875rem; color: var(--fg-muted); }
.sources__list li { margin-bottom: .5em; overflow-wrap: anywhere; }
.sources__list li:target { background: var(--bg-accent); outline: 2px solid var(--brand); outline-offset: 2px; }

.page-list { display: grid; gap: 1rem; }
@media (min-width: 48rem) { .page-list:not(.page-list--compact) { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.page-list__item { padding: 1.125rem 1.25rem; border: 1px solid var(--border); border-radius: var(--radius); background: var(--bg); }
.page-list__link { font-weight: 650; font-size: 1.0625rem; }
.page-list__text { margin: .35rem 0 0; color: var(--fg-muted); font-size: .9375rem; }
.page-list--compact { gap: .5rem; }
/* A list of illustrated pages: the picture on top, trimmed to the card. */
.page-list--thumbs .page-list__item { overflow: hidden; padding-top: 0; }
.page-list__thumb { display: block; margin: 0 -1.25rem 1rem; }
.page-list__thumb img { display: block; width: 100%; height: auto; aspect-ratio: 1024 / 544; object-fit: cover; background: var(--bg-sunk); }

/* Only ever on a preview build: a draft names what it is waiting for. */
.draft-banner { background: var(--bg-warning); border-bottom: 2px solid var(--moderate); color: var(--fg); padding: 1rem 0; font-size: .9375rem; }
.draft-banner__title { font-weight: 700; margin-bottom: .25rem; }
.draft-banner ul { margin: .5rem 0 0; padding-left: 1.25em; }
.draft-mark { background: var(--bg-warning); color: var(--fg); outline: 1px dashed var(--moderate); padding: 0 .2em; }
.draft-link { text-decoration-style: dashed; }
.pending-widget { margin: 1.5rem 0; padding: 1.25rem; border: 2px dashed var(--border-strong); border-radius: var(--radius); color: var(--fg-muted); }

/* A visitor who arrived from a finding in the app, and wants to go back to it. */
.from-app { background: var(--bg-muted); border-bottom: 1px solid var(--border); font-size: .9375rem; padding: .625rem 0; }
.from-app p { margin: 0; }

/* --------------------------------------------------------------- notfound */

.notfound { max-width: 40rem; margin-inline: auto; text-align: center; }
/* The intro has a max-width of its own; centred text in a box pinned to the
   left sat 70px off the heading's centre line. */
.notfound .hero__intro { margin-inline: auto; }
.notfound__links { display: flex; flex-wrap: wrap; gap: 1rem; justify-content: center; margin-top: 2rem; }
/* The other language, as one line under (or, from site.js, over) the page's own. */
.notfound--other { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: .25rem 1rem; }
.notfound__other-title { margin: 0; font-size: 1rem; letter-spacing: 0; }

/* ----------------------------------------------------------------- footer

   Warm paper with a rose glow at its foot and the name across the bottom.
   Text is AA over the strongest part of the glow: links #4a3947 8:1,
   headings and small print --fg-muted 5.3:1. Its dark values are under
   "Dark theme". */

.site-footer {
  --footer-glow: radial-gradient(70% 90% at 50% 120%, rgba(241, 185, 209, .55), transparent 70%), radial-gradient(40% 60% at 85% 110%, rgba(247, 214, 194, .6), transparent 70%);
  --footer-word: linear-gradient(180deg, rgba(194, 90, 134, .3), rgba(242, 165, 126, .04) 85%);
  --footer-line: rgba(41, 28, 41, .12);
  --footer-link: #4a3947;
  position: relative; overflow: hidden;
  padding-top: clamp(3.5rem, 7vw, 5rem);
  border-top: 1px solid var(--footer-line);
  background: var(--footer-glow), var(--bg);
  color: var(--fg-muted); font-size: .9375rem;
}
.site-footer a { color: var(--footer-link); text-decoration: none; }
.site-footer a:hover { color: var(--fg); text-decoration: underline; }

.footer__top { display: grid; gap: 2.5rem; }
@media (min-width: 60rem) { .footer__top { grid-template-columns: minmax(0, 1fr) minmax(0, 2.75fr); gap: 3.5rem; } }
.footer__pitch { margin: 1rem 0; max-width: 32ch; }
.footer__contact { margin: 0; line-height: 1.7; }
.footer__contact a { color: var(--fg); }

.footer__cols { display: grid; gap: 2rem; grid-template-columns: repeat(auto-fit, minmax(10rem, 1fr)); }
/* Two columns on a phone. One column of every link was more than two screens
   of footer, with the imprint and the privacy policy below all of it. */
@media (max-width: 40rem) { .footer__cols { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 2rem 1.25rem; } }
.footer__heading { margin: 0 0 .625rem; font: 600 .75rem/1.4 var(--font-mono); letter-spacing: .08em; text-transform: uppercase; color: var(--fg-muted); }
.footer__list { list-style: none; margin: 0; padding: 0; display: grid; gap: .1rem; }
.footer__list a { display: inline-flex; align-items: center; min-height: 36px; line-height: 1.3; }
/* Two columns on a phone are narrower than "Barrierefreiheitserklärung". */
@media (max-width: 40rem) { .footer__list a { -webkit-hyphens: auto; hyphens: auto; } }

.footer__bottom {
  display: flex; flex-wrap: wrap; gap: .5rem 1.5rem; justify-content: space-between; align-items: center;
  margin-top: clamp(2.5rem, 5vw, 4rem); padding-top: 1rem; border-top: 1px solid var(--footer-line);
  font-size: .8125rem;
}
.footer__bottom p { margin: 0; }
.footer__legal { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; align-items: center; gap: 0 1.25rem; }
.footer__legal a, .footer__legal .linklike { min-height: var(--tap); display: inline-flex; align-items: center; padding: 0; color: var(--footer-link); font-size: .8125rem; }
/* "Cookie settings" is a button (it opens the consent dialog, it goes nowhere)
   but it sits in a row of links and looks like one of them — `.linklike`'s
   underline made it the only underlined item in the row. */
.footer__legal .linklike { text-decoration: none; }
.footer__legal .linklike:hover { color: var(--fg); text-decoration: underline; }

/* The name, as a picture: the logo at the top already says it. It is cut by
   the footer's bottom edge, and clipped rather than allowed to widen the page. */
.footer__wordmark {
  margin: clamp(1.5rem, 4vw, 2.5rem) 0 -.17em;
  font-size: clamp(4rem, 19.5vw, 19rem); font-weight: 600; line-height: .9; letter-spacing: -.065em;
  text-align: center; white-space: nowrap;
  background: var(--footer-word); -webkit-background-clip: text; background-clip: text; color: transparent;
  user-select: none; pointer-events: none;
}

/* ---------------------------------------------------------------- consent */

/* A small card in the corner, not a strip across the page: it asks about
   advertising cookies, and the page is what somebody came to read. The left
   corner, because the visitor toolbar's launcher holds the right one on every
   page, and a consent card must not cover the accessibility button. */
.consent {
  position: fixed; left: 1rem; bottom: 1rem; z-index: 60;
  width: min(22rem, calc(100% - 2rem));
}
.consent[hidden] { display: none; }
/* Scrolls rather than running off a short screen (400% zoom, a phone on its side). */
.consent__panel {
  max-height: calc(100vh - 2rem); overflow-y: auto;
  padding: 1.125rem 1.25rem 1rem;
  background: var(--bg);
  border: 1px solid var(--border-strong); border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
}
.consent__title { font-size: 1rem; margin-bottom: .375rem; }
.consent__text { font-size: .8125rem; line-height: 1.5; color: var(--fg-muted); margin-bottom: .875rem; }
.consent__actions { display: grid; grid-template-columns: 1fr 1fr; gap: .5rem; }
.consent__actions .btn { min-height: var(--tap); padding: .5rem .75rem; font-size: .875rem; }
.consent__links { margin: .75rem 0 0; font-size: .75rem; line-height: 1.5; color: var(--fg-muted); }

/* ------------------------------------------------------------ dark theme

   What the tokens at the top cannot say on their own: the chrome's and the
   footer's own colours, and the two places the dark theme looks different
   rather than merely darker — the primary button, which takes the home page's
   rose gradient, and the closing band, which glows. */
@media screen and (prefers-color-scheme: dark) {
  /* The wordmark is --ink, so in the header and footer --ink is the light text. */
  .site-header, .site-footer { --ink: #fbf4f8; --ink-2: #fff; --fg-muted: #b8a5b0; }
  .site-header {
    --chrome-glass: rgba(22, 13, 22, .66); --chrome-menu: #160d16; --chrome-line: rgba(255, 236, 246, .16);
    --chrome-shadow: 0 16px 40px -24px rgba(0, 0, 0, .85); --chrome-hover: rgba(255, 236, 246, .09);
  }
  .site-footer {
    --footer-glow: radial-gradient(70% 90% at 50% 120%, rgba(194, 90, 134, .3), transparent 70%), radial-gradient(40% 60% at 85% 110%, rgba(242, 165, 126, .16), transparent 70%);
    --footer-word: linear-gradient(180deg, rgba(241, 185, 209, .32), rgba(242, 165, 126, .04) 85%);
    --footer-line: rgba(255, 236, 246, .12); --footer-link: #d3c3cd;
  }
  .btn--primary { background: linear-gradient(180deg, #f8d3e3, #eca6c5); }
  .btn--primary:hover { background: #f8d3e3; }
  .cta, .section--dark {
    background: radial-gradient(60% 140% at 12% 0%, rgba(194, 90, 134, .22), transparent 70%), var(--bg-ink);
    border-top: 1px solid var(--border);
  }
  /* A dark box on a dark page needs its edge drawn. */
  .code-block, .evidence-stage { box-shadow: inset 0 0 0 1px var(--border); }
}

/* -------------------------------------------------------------- A/B tests */

/* A variant not shown is `hidden`, whatever its class says: `.btn` is
   inline-flex, which beats the attribute's own `display: none`. While site.js
   waits for the assignment (`rb-exp-wait`, added in the head — lib/html.mjs
   says for how long), the elements under test keep their place unseen, so
   neither a flash of the control nor a jump happens when the answer lands. */
[data-experiment][hidden] { display: none !important; }
.rb-exp-wait [data-experiment] { visibility: hidden; }

/* --------------------------------------------------------- print & motion */

@media print {
  .site-header, .site-footer, .consent, .cta, .skip-link { display: none !important; }
  body { font-size: 11pt; }
  a[href^="http"]::after { content: " (" attr(href) ")"; font-size: .85em; }
}

@media (prefers-contrast: more) {
  :root { --border: #6b7c76; --border-strong: #38504a; --border-control: #38504a; --fg-muted: #33443f; }
}
/* The same request on a dark screen: edges and secondary text move towards
   the text colour rather than towards black. */
@media screen and (prefers-contrast: more) and (prefers-color-scheme: dark) {
  :root { --border: #9a8593; --border-strong: #c8b6c1; --border-control: #c8b6c1; --fg-muted: #e6dae1; }
}

/* =========================================================================
   Reference pages — the WCAG catalogue and the BFSG guides
   ========================================================================= */

/* The detection badge.
   Three states, three inks, and never colour alone: each badge carries its own
   icon and its own word, because a page that sells 1.4.1 cannot fail it. The
   inks are the existing status tokens rather than new ones — `--brand` for a
   check that decides, `--serious` for one that only half decides, `--fg-muted`
   for one that decides nothing. All three are AA against `--bg-muted`. */
.badge {
  display: inline-flex;
  align-items: center;
  gap: .375rem;
  padding: .1875rem .5rem;
  border: 1px solid currentColor;
  border-radius: 999px;
  font-size: .8125rem;
  font-weight: 650;
  line-height: 1.35;
  white-space: nowrap;
}
.badge--automated { color: var(--brand); }
.badge--partial { color: var(--serious); }
.badge--manual { color: var(--fg-muted); }

/* The principle jump list on the WCAG hub. */
.jump { display: flex; flex-wrap: wrap; align-items: center; gap: .75rem 1rem; }
.jump__label { margin: 0; font-size: .8125rem; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; color: var(--fg-muted); }
.jump__list { display: flex; flex-wrap: wrap; gap: .5rem; }
.jump__link {
  display: inline-flex; align-items: center; gap: .5rem;
  min-height: var(--tap); padding: .5rem 1rem;
  border: 1px solid var(--border-control); border-radius: 999px;
  color: var(--fg); font-weight: 600; font-size: .9375rem; text-decoration: none;
}
.jump__link:hover { background: var(--bg-muted); color: var(--ink); border-color: var(--ink); }
.jump__count { color: var(--fg-muted); font-variant-numeric: tabular-nums; }

/* A hero the breadcrumb already gave a top margin to. */
.hero--tight { padding-top: clamp(1.5rem, 3vw, 2.5rem); }

/* Facts about a criterion that come from the catalogue rather than the copy. */
.facts { margin: 0; font-size: .9375rem; }
.facts__row {
  display: grid;
  grid-template-columns: minmax(6rem, 34%) 1fr;
  gap: .25rem 1rem;
  padding: .625rem 0;
  border-bottom: 1px solid var(--border);
}
.facts__row:last-child { border-bottom: 0; }
.facts dt { color: var(--fg-muted); }
.facts dd { margin: 0; }

/* "At a glance", on a criterion page and on a rule page alike: one tinted box
   with a title and the facts. The criterion page used to put a tinted card
   inside a bordered card — two frames and two paddings, which on a phone left
   the facts two-thirds of the screen — while the rule page's box had lost its
   frame altogether to a broken line in this file. */
.facts-box, .rule-facts {
  padding: 1.25rem 1.5rem;
  border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--bg-muted);
}
.facts-box__title, .rule-facts .rule-facts__title { margin: 0 0 .5rem; font-size: 1.125rem; }
.facts-box > .note { margin: .75rem 0 0; }
@media (max-width: 40rem) { .facts-box, .rule-facts { padding: 1rem 1.125rem; } }

/* The criterion index: one card per criterion, used on the hub, on every
   criterion page ("related") and on every guide. It is the internal linking
   that makes fifty pages a reference instead of fifty pages. */
.crit-links {
  display: grid;
  gap: .75rem;
  grid-template-columns: repeat(auto-fill, minmax(17rem, 1fr));
}
.crit-link {
  display: grid;
  grid-template-columns: auto 1fr;
  align-content: start;
  gap: .125rem .75rem;
  align-items: baseline;
  height: 100%;
  padding: .875rem 1rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg);
  color: inherit;
  text-decoration: none;
  transition: border-color .15s var(--ease), box-shadow .15s var(--ease);
}
.crit-link:hover { border-color: var(--border-strong); box-shadow: var(--shadow); }
.crit-link__id {
  grid-row: span 2;
  /* The widest id ("1.4.10") sets one width for all, so the names line up. */
  min-width: 3.25rem;
  font-family: var(--font-mono);
  font-size: .8125rem;
  font-weight: 650;
  color: var(--brand);
}
.crit-link__name { font-weight: 650; text-decoration: underline; text-underline-offset: .18em; }
.crit-link:hover .crit-link__name { text-decoration-thickness: 2px; }
.crit-link__meta { display: flex; flex-wrap: wrap; align-items: center; gap: .25rem .5rem; font-size: .8125rem; color: var(--fg-muted); }
.crit-link__meta .badge { padding-block: .0625rem; font-size: .75rem; }

/* The WCAG hub's first screen: the jump list and the key to the badges beside
   the heading, where there was an empty half-page before. */
.hub-key { display: grid; gap: 1.5rem; padding: clamp(1.25rem, 3vw, 1.75rem); border: 1px solid var(--border); border-radius: var(--radius-lg); background: var(--bg); }
.hub-key .jump { align-items: flex-start; flex-direction: column; gap: .5rem; }
.legend__title { margin: 0 0 .5rem; font-size: .8125rem; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; color: var(--fg-muted); }
.legend__list { display: grid; gap: .5rem; font-size: .9375rem; }
.legend__list li { display: flex; flex-wrap: wrap; align-items: baseline; gap: .25rem .6rem; }
.legend__list .badge { flex: none; }
/* The three sentences start at one edge, whatever the width of their badge. */
@supports (grid-template-columns: subgrid) {
  .legend__list { grid-template-columns: max-content minmax(0, 1fr); column-gap: .75rem; }
  .legend__list li { grid-column: 1 / -1; display: grid; grid-template-columns: subgrid; align-items: center; }
  .legend__list .badge { justify-self: start; }
}
.legend__more { margin-top: .75rem; font-size: .9375rem; }
.legend__more summary { display: inline-flex; align-items: center; min-height: var(--tap); cursor: pointer; font-weight: 650; color: var(--brand); text-decoration: underline; text-underline-offset: .18em; }
.legend__more dl { margin: .25rem 0 0; }
.legend__more dt { margin-top: .75rem; font-weight: 650; }
.legend__more dd { margin: .2rem 0 0; color: var(--fg-muted); }

@media (max-width: 40rem) {
  .facts__row { grid-template-columns: 1fr; gap: .125rem; }
}

/* =========================================================================
   The instant free scan
   ========================================================================= */

/* Which half of the checker a visitor gets.
   The scan needs a fetch and a poll, so without JavaScript it cannot work and
   is not shown; the email form that was always there takes its place. The
   inline script in <head> removes `no-js` before anything paints, so neither
   one flashes. Default is the enhanced path, because a page that assumes the
   worse case and corrects it is the one that flickers for everybody. */
.scan-fallback { display: none; }
.no-js .scan { display: none; }
.no-js .scan-fallback { display: block; }
/* Half of what the script shows and hides sets its own display: the bar,
   the pause button, the facts grid. `hidden` has to win over all of them. */
.scan [hidden] { display: none !important; }

/* ---------------------------------------------------------- the stage

   The checker's first screen is a stage of its own: the landing, the scan
   while it runs, and the result. Every control in it (fields, buttons, chips,
   findings) follows the site's tokens, dark theme included, without a rule
   of its own; the stage adds only its cards, glow and chrome. */
.page-scan .lead {
  --stage-card: #fff;
  --stage-line: rgba(41, 28, 41, .1);
  --stage-shadow: 0 30px 90px -40px rgba(41, 28, 41, .42);
  --stage-hot: 194, 90, 134;
  --stage-glow-1: rgba(244, 198, 218, .55);
  --stage-glow-2: rgba(247, 214, 194, .45);
  --stage-glow-3: rgba(231, 201, 230, .45);
  --stage-chrome: #f1eae5;
  --stage-chrome-url: #fffaf5;
  --stage-ok: #1f6b3a;
  --stage-label: #f1b9d1;
  --stage-label-ink: #2a1529;
  position: relative; isolation: isolate;
  /* The glow behind it drifts and grows a little; it must never widen the page. */
  overflow-x: clip;
  padding: clamp(3rem, 8vw, 6rem) 0 clamp(3rem, 6vw, 4.5rem);
  background: var(--bg); color: var(--fg);
}
@media screen and (prefers-color-scheme: dark) {
  .page-scan .lead {
    --stage-card: #170e17;
    --stage-line: rgba(255, 226, 240, .12);
    --stage-shadow: 0 40px 120px -40px rgba(0, 0, 0, .95), 0 0 100px -50px rgba(241, 185, 209, .35);
    --stage-hot: 241, 185, 209;
    --stage-glow-1: rgba(113, 54, 83, .55);
    --stage-glow-2: rgba(194, 90, 134, .32);
    --stage-glow-3: rgba(138, 74, 46, .3);
    --stage-chrome: #201620;
    --stage-chrome-url: rgba(255, 255, 255, .07);
    --stage-ok: #bdf0cf;
  }
  .page-scan .lead .scan-clean { background: var(--bg-muted); }
}

/* Slow light behind the landing, never behind text that needs it. */
.page-scan .lead::before {
  content: '';
  position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background:
    radial-gradient(38% 46% at 30% 34%, var(--stage-glow-1), transparent 70%),
    radial-gradient(34% 40% at 72% 28%, var(--stage-glow-2), transparent 72%),
    radial-gradient(40% 44% at 52% 70%, var(--stage-glow-3), transparent 72%);
  animation: scan-glow 22s ease-in-out infinite alternate;
}
@keyframes scan-glow { to { transform: translate3d(2%, -3%, 0) scale(1.06); } }
.page-scan.is-scanning .lead::before,
.page-scan.has-result .lead::before { opacity: .45; }

/* The landing: one centred column — heading, one line, the field, and the
   reassurances under it. The address field is on the first screen of a phone
   and of a laptop alike. */
.page-scan .lead__inner {
  grid-template-columns: minmax(0, 1fr);
  grid-template-areas: none;
  justify-items: center;
  row-gap: 1.5rem;
  max-width: 52rem;
  text-align: center;
}
/* Every lead names its grid areas; this one is a single column in source
   order, and an item still naming an area that is not there would claim an
   implicit cell — all of them the same one. */
.page-scan .lead__inner > * { grid-area: auto; }
.page-scan .lead__copy .hero__title {
  max-width: 13em; margin: 0 auto;
  font-size: clamp(2.4rem, 1.1rem + 4.4vw, 4.4rem); line-height: 1; letter-spacing: -.055em; font-weight: 600;
}
.page-scan .lead__copy .hero__intro { max-width: 36em; margin: 1.125rem auto 0; font-size: 1.0625rem; color: var(--fg-muted); }
.page-scan .lead__form {
  width: min(100%, 40rem);
  padding: 0; border: 0; background: transparent; box-shadow: none;
  text-align: left;
}
.page-scan .lead__more .byline { margin: 0; font-size: .8125rem; color: var(--fg-muted); }
.page-scan .lead__trust .hero__trust { justify-content: center; margin: 0; color: var(--fg-muted); }

/* The field and its button, in one bar. The bar is the control's visible
   edge (--border-control, 3:1), and the focus ring moves to it. */
.page-scan .scan__start .label { display: block; margin-bottom: .5rem; font-size: .875rem; font-weight: 600; }
.scan__row { display: flex; gap: .625rem; flex-wrap: wrap; }
.scan__row .input { flex: 1 1 14rem; min-width: 0; font-size: 1.0625rem; }
.scan__row .btn { flex: 0 0 auto; }
.page-scan .scan__row {
  flex-wrap: nowrap; gap: .375rem; padding: .375rem;
  border: 1px solid var(--border-control); border-radius: 999px;
  background: var(--stage-card); box-shadow: var(--stage-shadow);
}
.page-scan .scan__row .input {
  min-height: 52px; padding: 0 1.25rem;
  border: 0; border-radius: 999px; background: transparent; color: var(--fg);
}
.page-scan .scan__row .input:focus-visible { outline: none; }
.page-scan .scan__row:focus-within { outline: 3px solid var(--ink); outline-offset: 2px; }
.page-scan .scan__row .btn { border-radius: 999px; gap: .5rem; }
.page-scan .scan__row .btn .icon { transition: transform .3s var(--ease); }
.page-scan .scan__row .btn:hover .icon { transform: translateX(3px); }
@media (max-width: 30rem) {
  .page-scan .scan__row { flex-wrap: wrap; border-radius: 22px; }
  .page-scan .scan__row .btn { width: 100%; }
}
.page-scan .scan__start .hint { margin-top: .75rem; text-align: center; }
.scan__meta { display: flex; flex-wrap: wrap; justify-content: center; gap: .25rem 1rem; margin-top: .5rem; font-size: .8125rem; color: var(--fg-muted); }
.scan__meta li + li::before { content: '·'; margin-right: 1rem; }

/* ---------------------------------------------------------- page states

   The checker is a landing page until somebody uses it, and then it is a
   report. The pitch, the headline and the reassurances have done their job
   the moment a URL is submitted. So the page has three states, set on <body>
   by the script and laid out here: idle (the centred landing), scanning and
   result (one column, the full width of a wider shell). The script owns when;
   CSS owns what it looks like. */
.page-scan.is-scanning .lead__trust,
.page-scan.has-result .lead__trust,
.page-scan.is-scanning .lead__more,
.page-scan.has-result .lead__more { display: none; }

/* The closing band is written for somebody who has not scanned yet. While a
   scan runs it has nothing to offer; with a result, site.js rewrites it. */
.page-scan.is-scanning .cta { display: none; }

/* The pitch is taken off the screen, not out of the page. `display: none` here
   would take the <h1> with it and leave a document whose first heading is an
   <h2> — on the page that sells heading structure. Taken out of the flow it
   keeps the layout single-column (an absolutely positioned grid item claims no
   track) and keeps the heading exactly where a screen reader expects it. */
.page-scan.is-scanning .lead__copy,
.page-scan.has-result .lead__copy {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

.page-scan.is-scanning .lead,
.page-scan.has-result .lead {
  /* Wider than the rest of the site on purpose: the evidence and the offer
     beside it need the room, and nothing here is long-form prose. */
  --shell: 1400px;
  padding-top: clamp(1.75rem, 4vw, 3rem);
}
.page-scan.is-scanning .lead__inner,
.page-scan.has-result .lead__inner { max-width: none; justify-items: stretch; text-align: left; }
@media (min-width: 62rem) {
  .page-scan.is-scanning .lead__inner,
  .page-scan.has-result .lead__inner {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas: "form";
  }
}
.page-scan.is-scanning .lead__form,
.page-scan.has-result .lead__form { width: 100%; }

/* The offer cards repeat what the result's first screen already says. */
.page-scan.is-scanning .funnel-offer,
.page-scan.has-result .funnel-offer { display: none; }

/* Both are scrolled to by the script, and both sit under a sticky header
   unless they are told not to. */
.scan__progress { scroll-margin: calc(var(--header-h) + 1rem) 0 1.5rem; }
.scan__result { scroll-margin-top: calc(var(--header-h) + 1rem); }
.scan__result:focus { outline: none; }

/* ------------------------------------------------------------- the loader

   The words on one side, the page our browser loaded on the other, with a
   beam over it. The beam stops under prefers-reduced-motion — the rule at the
   top of this file — and the status line says the same thing in words. */
.scan-loader { display: grid; gap: clamp(2rem, 4vw, 3.5rem); align-items: start; min-height: min(68svh, 640px); }
@media (min-width: 62rem) { .scan-loader { grid-template-columns: minmax(0, 1fr) minmax(0, 1.25fr); } }
.scan-loader__target { margin: 0 0 .5rem; font-size: .9375rem; font-weight: 500; color: var(--fg-muted); letter-spacing: 0; }
.scan-loader__target strong { color: var(--fg); font-weight: 600; }
.scan__progress-text {
  min-height: 2.2em; margin: 0 0 1.25rem;
  font-size: clamp(1.6rem, 1rem + 1.8vw, 2.4rem); line-height: 1.1; letter-spacing: -.04em; font-weight: 600;
}
.scan__bar { height: 3px; border-radius: 3px; background: var(--stage-line); overflow: hidden; }
.scan__bar span {
  display: block; width: 40%; height: 100%; border-radius: inherit;
  background: linear-gradient(90deg, transparent, rgb(var(--stage-hot)), transparent);
  animation: scan-bar 1.6s var(--ease) infinite;
}
@keyframes scan-bar { from { transform: translateX(-100%); } to { transform: translateX(260%); } }

/* Where it is, as the API says: four small steps, the current one in words. */
.scan-stages { display: flex; flex-wrap: wrap; gap: .25rem 1rem; margin: 1rem 0 0; font-size: .8125rem; color: var(--fg-muted); }
.scan-stage { display: flex; align-items: center; gap: .375rem; }
.scan-stage__mark { display: grid; place-items: center; width: 16px; height: 16px; border-radius: 50%; border: 1px solid var(--border-strong); }
.scan-stage__mark .icon { width: 10px; height: 10px; visibility: hidden; }
.scan-stage.is-done .scan-stage__mark { border-color: var(--stage-ok); color: var(--stage-ok); }
.scan-stage.is-done .scan-stage__mark .icon { visibility: visible; }
.scan-stage.is-current { color: var(--fg); font-weight: 600; }
.scan-stage.is-current .scan-stage__mark { border-color: rgb(var(--stage-hot)); box-shadow: 0 0 0 3px rgba(var(--stage-hot), .25); }
.scan-loader__elapsed { margin: .5rem 0 0; font-size: .8125rem; color: var(--fg-muted); font-variant-numeric: tabular-nums; }

/* The numbers the API publishes while it runs: pages found, the outside
   traffic estimate (labelled as one, every time) and the load time. */
.scan-facts { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 1rem; margin: 1.75rem 0 0; padding-top: 1.25rem; border-top: 1px solid var(--stage-line); }
.scan-facts div { display: flex; flex-direction: column-reverse; justify-content: flex-end; gap: .25rem; min-width: 0; }
.scan-facts dt { font-size: .75rem; color: var(--fg-muted); }
.scan-facts dd { margin: 0; font-size: clamp(1.2rem, 1rem + .8vw, 1.6rem); font-weight: 600; letter-spacing: -.03em; font-variant-numeric: tabular-nums; }
.scan-facts dd .visually-hidden + span, .scan-facts dd [aria-hidden] { white-space: nowrap; }
.scan-fact__note { display: block; margin-top: .25rem; font-size: .6875rem; font-weight: 400; letter-spacing: 0; color: var(--fg-muted); }
@media (max-width: 30rem) { .scan-facts { grid-template-columns: 1fr 1fr; } }

/* The count of pages found, as it grows; the addresses come with the result. */
.scan-found { margin-top: 1.5rem; }
.scan-found__title { margin: 0 0 .5rem; font-size: .875rem; font-weight: 600; }
.scan-found__title b { margin-left: .375rem; color: var(--brand); font-variant-numeric: tabular-nums; }
.scan-found__list li { display: grid; grid-template-columns: 36px 1fr; align-items: center; gap: .75rem; height: 34px; border-top: 1px solid var(--stage-line); }
.scan-found__list li:first-child { color: var(--fg); font-size: .8125rem; }
.scan-found__list .slot { width: 36px; height: 22px; border-radius: 5px; border: 1px dashed var(--border-strong); }
.scan-found__list .bar { width: var(--w, 60%); height: 8px; border-radius: 4px; background: var(--stage-line); }
.scan-found__list .is-new { animation: scan-row .5s var(--ease) both; }
.scan-found__list li:nth-child(n + 4) { opacity: .5; }
@keyframes scan-row { from { opacity: 0; transform: translateY(-6px); } }
.scan-found__note { margin: .5rem 0 0; font-size: .75rem; color: var(--fg-muted); }

/* The email during the scan: the token exists from the first answer, so the
   report can be asked for before the result is in. */
.scan-early { margin-top: 1.75rem; padding: 1.125rem 1.25rem; border: 1px solid var(--border); border-radius: 18px; background: var(--stage-card); box-shadow: var(--stage-shadow); }
.scan-early__title { margin: 0; font-weight: 600; }
.scan-early__text { margin: .25rem 0 .875rem; font-size: .875rem; color: var(--fg-muted); }

/* The page our browser loaded: a skeleton until the picture is in. */
.scan-browser { border: 1px solid var(--stage-line); border-radius: 14px; overflow: hidden; background: var(--stage-chrome); box-shadow: var(--stage-shadow); }
.scan-loader__chrome { display: flex; align-items: center; gap: 6px; height: 34px; padding: 0 12px; }
.scan-loader__chrome span { width: 9px; height: 9px; border-radius: 50%; background: var(--border-strong); opacity: .5; }
.scan-loader__chrome i { flex: 0 1 300px; margin-left: 10px; padding: 3px 12px; border-radius: 999px; background: var(--stage-chrome-url); font: normal .72rem/1.3 var(--font-mono); color: var(--fg-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.scan-loader__page { position: relative; display: grid; gap: 12px; align-content: start; aspect-ratio: 16 / 11; padding: 20px; overflow: hidden; background: var(--bg-muted); }
.scan-loader__block { display: block; height: 14px; border-radius: 6px; background: var(--stage-line); animation: scan-pulse 1.6s ease-in-out infinite; }
.scan-loader__block--head { height: 22px; width: 40%; }
.scan-loader__block--wide { width: 90%; }
.scan-loader__block--mid { width: 64%; }
.scan-loader__block--tall { height: 90px; }
.scan-loader__cols { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; }
@keyframes scan-pulse { 50% { opacity: .55; } }
.scan-loader__shot { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: top; animation: scan-row .6s var(--ease) both; }
.scan-loader__stage.has-shot .scan-loader__block,
.scan-loader__stage.has-shot .scan-loader__cols { display: none; }
.scan-loader__beam {
  position: absolute; left: 0; right: 0; top: -30%; height: 30%; z-index: 2; pointer-events: none;
  background: linear-gradient(180deg, transparent, rgba(var(--stage-hot), .14) 70%, rgba(var(--stage-hot), .45));
  border-bottom: 2px solid rgb(var(--stage-hot));
  box-shadow: 0 6px 24px rgba(var(--stage-hot), .5);
  animation: scan-beam 2.8s var(--ease) infinite;
}
@keyframes scan-beam { to { top: 100%; } }
@media (prefers-reduced-motion: reduce) { .scan-loader__beam { display: none; } }

/* ------------------------------------------------------------- the result */

/* The first screen: the count, the pages, the email field — and the iceberg.
   Nothing to click or scroll to reach the field. */
.scan-first { display: grid; gap: clamp(2rem, 4vw, 4rem); align-items: center; min-height: min(calc(100svh - var(--header-h) - 4rem), 760px); }
@media (min-width: 62rem) { .scan-first { grid-template-columns: minmax(0, 1.05fr) minmax(0, .95fr); } }
.scan-done { display: flex; align-items: center; gap: .5rem; margin: 0; font-size: .875rem; color: var(--stage-ok); }
.scan-done .icon { width: 16px; height: 16px; }
.scan-done strong { font-weight: 600; }
.scan__result-title, .scan-headline {
  margin: .75rem 0 .875rem;
  font-size: clamp(2.6rem, 1.3rem + 4vw, 4.6rem); line-height: .98; letter-spacing: -.055em; font-weight: 600;
}
.scan-headline em { font-style: normal; color: var(--brand); }
.scan-sub { margin: 0; font-size: 1.125rem; color: var(--fg-muted); }
.scan-sub strong { color: var(--fg); font-weight: 600; }

/* The site's own pages: the one that was checked, with its picture, and the
   ones that were not, each with an empty frame where a picture would go. */
.scan-pages-head { margin: 1.75rem 0 .5rem; font-size: 1rem; font-weight: 600; letter-spacing: -.01em; }
.pagelist { border-bottom: 1px solid var(--stage-line); }
.pagelist li { display: grid; grid-template-columns: 40px minmax(0, 1fr) auto; align-items: center; gap: .875rem; min-height: 46px; border-top: 1px solid var(--stage-line); font-size: .9375rem; }
.pagelist .slot { width: 40px; height: 26px; border-radius: 6px; border: 1px dashed var(--border-strong); }
.pagelist__path { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-family: var(--font-mono); font-size: .875rem; }
.pagelist__state { display: flex; align-items: center; gap: .375rem; font-size: .8125rem; color: var(--fg-muted); white-space: nowrap; }
.pagelist__state::before { content: ''; width: 8px; height: 8px; border-radius: 50%; border: 1px solid currentColor; }
.pagelist .is-queued .pagelist__state { color: var(--brand); }
.pagelist .is-queued .pagelist__state::before { background: currentColor; }
.pagelist .is-blur { filter: blur(3px); opacity: .5; }
.pagelist .is-featured { grid-template-columns: 156px minmax(0, 1fr); padding: .75rem 0; }
.pagelist__thumb { width: 156px; aspect-ratio: 16 / 10; border-radius: 10px; overflow: hidden; background: var(--bg-muted); box-shadow: 0 10px 30px -14px rgba(0, 0, 0, .55); }
.pagelist__thumb img { width: 100%; height: 100%; object-fit: cover; object-position: top; }
.pagelist__meta { display: grid; gap: .25rem; min-width: 0; }
.pagelist .is-featured .pagelist__state { color: var(--stage-ok); }
.pagelist .is-featured .pagelist__state::before { background: currentColor; border-color: currentColor; }
.pagelist__failing { font-size: .8125rem; color: var(--fg-muted); }
.pagelist__more { margin: .5rem 0 0; font-size: .8125rem; color: var(--fg-muted); }
@media (max-width: 30rem) {
  .pagelist .is-featured { grid-template-columns: 110px minmax(0, 1fr); }
  .pagelist__thumb { width: 110px; }
}

/* The compact report form, four times on the page: one email field and the
   consent the API asks for. The bar is the field's visible edge. */
.scan-cta { margin-top: 1.5rem; }
.scan-cta__title { margin: 0 0 .625rem; font-weight: 600; }
.scan-cta__row { display: flex; gap: .375rem; padding: .375rem; border: 1px solid var(--border-control); border-radius: 999px; background: var(--stage-card); }
.scan-cta__row .input { flex: 1 1 12rem; min-width: 0; min-height: 46px; padding: 0 1rem; border: 0; border-radius: 999px; background: transparent; color: var(--fg); }
.scan-cta__row .input:focus-visible { outline: none; }
.scan-cta__row:focus-within { outline: 3px solid var(--ink); outline-offset: 2px; }
.scan-cta__row .btn { border-radius: 999px; min-height: 46px; }
.scan-cta__row:has([aria-invalid="true"]) { border-color: var(--critical); border-width: 2px; }
.scan-cta__consent { margin-top: .75rem; font-size: .8125rem; }
.scan-cta__consent a { color: var(--fg); }
.scan-cta .field__error { margin-top: .5rem; }
@media (max-width: 30rem) {
  .scan-cta__row { flex-wrap: wrap; border-radius: 22px; }
  .scan-cta__row .btn { width: 100%; }
}
.scan-choose { margin-top: .5rem; }

/* ------------------------------------------------------------ the iceberg

   One page above the line, the pages found below it: a Blender render in the
   visitor's theme, still or turning, and a dot for each page drawn over it.
   The picture and the dots are decoration; the sentence after them says the
   same in words. The pause button is outside the decoration on purpose. */
.scan-bergcol { position: relative; }
.scan-berg { position: relative; width: min(100%, 480px); aspect-ratio: 1024 / 1168; margin-inline: auto; }
/* The picture and the dots bob together, as two layers: the picture is
   multiplied into the page in the light theme, so the render's own white
   never draws a box on the page's, and white dots in that layer would vanish. */
.scan-berg__float, .scan-berg canvas { position: absolute; inset: 0; animation: berg-bob 9s ease-in-out infinite; }
.scan-berg.is-still .scan-berg__float, .scan-berg.is-still canvas { animation-play-state: paused; }
.scan-berg__float { mix-blend-mode: multiply; }
/* In the dark the same, the other way up: the page's glow shows through the
   render's near-black, and the ice, brighter than either, stays as rendered. */
@media screen and (prefers-color-scheme: dark) { .scan-berg__float { mix-blend-mode: lighten; } }
@keyframes berg-bob { 50% { transform: translateY(-7px); } }
.scan-berg__art {
  position: absolute; inset: 0;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 10%, #000 86%, transparent), linear-gradient(180deg, transparent, #000 7%, #000 95%, transparent);
  -webkit-mask-composite: source-in;
  mask-image: linear-gradient(90deg, transparent, #000 10%, #000 86%, transparent), linear-gradient(180deg, transparent, #000 7%, #000 95%, transparent);
  mask-composite: intersect;
  animation: berg-in 1.3s var(--ease) both;
}
@keyframes berg-in { from { opacity: 0; transform: translateY(26px) scale(.97); } }
.scan-berg__art img, .scan-berg__art video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; }
.scan-berg__art video { opacity: 0; transition: opacity .8s var(--ease); }
.scan-berg.is-turning .scan-berg__art video { opacity: 1; }
.scan-berg canvas { width: 100%; height: 100%; }
.scan-berg__tip, .scan-berg__count, .scan-berg__legend { position: absolute; margin: 0; font-size: .8125rem; color: var(--fg-muted); pointer-events: none; }
.scan-berg b { color: var(--fg); font-weight: 600; }
.scan-berg__tip { left: 68%; top: 14%; padding-left: 28px; }
.scan-berg__tip::before { content: ''; position: absolute; left: 0; top: .75em; width: 22px; height: 1px; background: var(--fg-muted); }
.scan-berg__count { left: 0; top: 67%; width: 12ch; }
.scan-berg__count b { position: relative; display: table; margin-bottom: 4px; font-size: clamp(2.2rem, 1.4rem + 2.6vw, 3.4rem); font-weight: 300; letter-spacing: -.05em; line-height: 1; font-variant-numeric: tabular-nums; }
.scan-berg__count b::after { content: ''; position: absolute; left: calc(100% + 10px); top: 55%; width: 26px; height: 1px; background: var(--fg-muted); }
.scan-berg__legend { left: 4%; bottom: 0; display: flex; align-items: center; gap: 8px; }
.scan-berg__legend i { width: 7px; height: 7px; border-radius: 50%; background: rgb(var(--stage-hot)); box-shadow: 0 0 10px rgb(var(--stage-hot)); }
.scan-berg__tool { position: absolute; z-index: 3; padding: 6px 10px; border-radius: 8px; background: var(--fg); color: var(--bg); font: 500 .75rem/1.35 var(--font); white-space: nowrap; transform: translate(-50%, -125%); pointer-events: none; }
.scan-berg__tool span { display: block; font-weight: 400; opacity: .8; }
.scan-berg__pause { position: absolute; right: calc(50% - min(240px, 50%)); bottom: -6px; display: grid; place-items: center; width: 36px; height: 36px; padding: 0; border: 1px solid var(--border-control); border-radius: 50%; background: var(--stage-card); color: var(--fg-muted); cursor: pointer; }
.scan-berg__pause:hover { color: var(--fg); }
.scan-berg__pause:focus-visible { outline: 3px solid var(--ink); outline-offset: 2px; }
.scan-berg__pause svg { width: 14px; height: 14px; }
.scan-berg__pause .i-play, .scan-berg__pause.is-paused .i-pause { display: none; }
.scan-berg__pause.is-paused .i-play { display: block; }
@media (max-width: 40rem) {
  .scan-berg__tip { left: 62%; }
  .scan-berg__count { top: 70%; }
  .scan-berg__count b { font-size: 2.1rem; }
}

/* After the email: the form becomes the confirmation in the same place. */
.scan-sent { display: flex; gap: 1rem; align-items: flex-start; margin-top: 1.5rem; }
.scan-sent__check { flex: none; display: grid; place-items: center; width: 44px; height: 44px; border-radius: 50%; border: 2px solid var(--stage-ok); color: var(--stage-ok); }
.scan-sent__check .icon { width: 20px; height: 20px; }
.scan-sent strong { display: block; font-size: 1.125rem; }
.scan-sent span { display: block; margin-top: .25rem; font-size: .9375rem; color: var(--fg-muted); }
.scan-sent:focus-visible { outline: 2px solid var(--brand); outline-offset: 3px; }

/* ----------------------------------------------- below the first screen */
.scan-below { display: grid; gap: clamp(2.5rem, 5vw, 4rem); margin-top: clamp(3rem, 6vw, 5rem); }
.scan-onpage { display: grid; gap: clamp(1.5rem, 3vw, 3rem); align-items: start; }
@media (min-width: 62rem) {
  .scan-onpage { grid-template-columns: minmax(0, .95fr) minmax(0, 1.05fr); }
  .scan-onpage__shot { position: sticky; top: calc(var(--header-h) + 1.5rem); }
}
.scan-onpage__shot { margin: 0; }
.scan-onpage__shot img { display: block; width: 100%; height: auto; border: 1px solid var(--stage-line); border-radius: 14px; background: var(--bg-muted); box-shadow: var(--stage-shadow); }
.scan-onpage__shot figcaption { margin-top: .5rem; font-size: .8125rem; color: var(--fg-muted); }

.scan__findings-title {
  margin-bottom: .75rem;
  font-size: .8125rem; font-weight: 700; text-transform: uppercase; letter-spacing: .08em;
  color: var(--fg-muted);
}
.scan-findings { display: grid; gap: .875rem; }
.scan-finding {
  padding: 1rem 1.125rem;
  border: 1px solid var(--border);
  border-left: 4px solid var(--border-strong);
  border-radius: var(--radius-sm);
  background: var(--stage-card);
  transition: transform .2s var(--ease), box-shadow .2s var(--ease);
  /* Staggered in, once. `both` keeps the end state, which is also what the
     reduced-motion rule at the top of this file collapses to. */
  animation: scan-in .45s var(--ease) both;
  animation-delay: calc(var(--i, 0) * 60ms);
}
.scan-finding:hover { transform: translateY(-2px); box-shadow: var(--shadow); }
.scan-finding--critical { border-left-color: var(--critical); }
.scan-finding--serious { border-left-color: var(--serious); }
.scan-finding--moderate { border-left-color: var(--moderate); }
@keyframes scan-in {
  from { opacity: 0; transform: translateY(10px); }
  to { opacity: 1; transform: none; }
}
.scan-finding__head { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem; }
.scan-finding__rule { font-family: var(--font-mono); font-size: .8125rem; }
.scan-finding__count { margin-left: auto; font-size: .8125rem; color: var(--fg-muted); }
.scan-finding__message { margin: .5rem 0 .75rem; font-size: .9375rem; }
.scan-finding__foot { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem; }
.scan-finding__wcag { display: flex; flex-wrap: wrap; gap: .35rem; margin: 0; }
/* The way to the contrast checker: an ordinary link at the finding's own size. */
.scan-finding__tool { flex: 1 1 100%; margin: 0; font-size: .875rem; }
.scan-finding__tool .link-arrow { min-height: 24px; font-weight: 400; text-decoration: underline; }
.scan-finding__selector {
  flex: 1 1 100%;
  display: block;
  padding: .35rem .5rem;
  border-radius: 6px;
  background: var(--bg-sunk);
  font-family: var(--font-mono);
  font-size: .75rem;
  color: var(--fg-muted);
  overflow-wrap: anywhere;
}

/* A criterion link, shaped like a chip rather than underlined prose: it sits in
   a row of its own siblings, not inside a sentence. */
.chip {
  display: inline-flex; align-items: center; gap: .3rem;
  padding: .2rem .6rem;
  border: 1px solid var(--border-strong); border-radius: 999px;
  font-size: .75rem; font-weight: 650;
}
.chip--link { background: var(--bg-muted); color: var(--brand); text-decoration: none; border-color: var(--border-control); }
.chip--link:hover { background: var(--bg-sunk); color: var(--brand-hover); text-decoration: underline; }

/* The rules beyond the ones shown: empty shapes, never the hidden findings
   themselves — nothing that is not shown reaches the browser. */
.scan-locked { margin-top: 1rem; padding: 1.125rem 1.25rem; border: 1px solid var(--border); border-radius: var(--radius); background: var(--bg-muted); }
.scan-locked__rows { display: grid; gap: .5rem; margin-bottom: 1rem; }
.scan-locked__rows span { display: block; height: 12px; border-radius: 6px; background: var(--stage-line); }
.scan-locked__rows span:nth-child(2) { width: 78%; }
.scan-locked__rows span:nth-child(3) { width: 56%; }
.scan-locked__title { margin: 0; font-weight: 600; }
.scan-locked__text { margin: .25rem 0 .75rem; font-size: .875rem; color: var(--fg-muted); }

/* The sentence that keeps a short list of findings honest. Marked as a note
   rather than a warning: it is the result's context, not an apology for it. */
.scan__reach {
  margin: 1.25rem 0 0;
  padding: 1rem 1.125rem;
  border: 1px solid var(--border);
  border-left: 4px solid var(--fg);
  border-radius: var(--radius-sm);
  background: var(--bg-muted);
  font-size: .9375rem;
}

.scan-clean {
  padding: 1.25rem 1.375rem;
  border: 1px solid var(--brand); border-radius: var(--radius);
  background: var(--bg-accent);
}
.scan__clean-title { font-size: 1.125rem; margin-bottom: .375rem; }
.scan__clean-text { margin: 0; font-size: .9375rem; color: var(--fg-muted); }

.scan-failed {
  max-width: 42rem; margin-inline: auto;
  padding: clamp(1.5rem, 3vw, 2rem);
  border: 1px solid var(--border); border-radius: var(--radius-lg);
  background: var(--stage-card); box-shadow: var(--shadow);
}
.scan-failed .btn { margin-top: 1rem; }

/* The page we checked, counted, behind a disclosure: reference, not the reason
   anybody came. */
.scan-about { border-top: 1px solid var(--stage-line); }
.scan-about > summary { display: flex; align-items: center; justify-content: space-between; min-height: 56px; cursor: pointer; font-weight: 600; list-style: none; }
.scan-about > summary::-webkit-details-marker { display: none; }
.scan-about > summary::after { content: '+'; font-size: 1.25rem; color: var(--fg-muted); transition: transform .3s var(--ease); }
.scan-about[open] > summary::after { transform: rotate(45deg); }
.scan-about > summary:focus-visible { outline: 3px solid var(--ink); outline-offset: 2px; }
.scan-page__facts { display: grid; gap: .45rem; margin: 0 0 1rem; font-size: .9375rem; }
.scan-page__facts div {
  display: grid; grid-template-columns: minmax(6rem, min(35%, 11rem)) minmax(0, 1fr); gap: .75rem;
  padding-bottom: .45rem; border-bottom: 1px solid var(--border);
}
.scan-page__facts div:last-child { padding-bottom: 0; border-bottom: 0; }
.scan-page__facts dt { color: var(--fg-muted); }
.scan-page__facts dd { margin: 0; color: var(--fg); overflow-wrap: anywhere; font-variant-numeric: tabular-nums; }
.scan-page__note { margin: .6rem 0 1rem; font-size: .8125rem; color: var(--fg-muted); }

/* The full form, for somebody who wants to choose the pages or say where the
   keyboard walk starts. */
.scan__report { margin-top: 1rem; padding: clamp(1.25rem, 3vw, 1.75rem); border: 1px solid var(--border); border-radius: var(--radius); background: var(--stage-card); scroll-margin-top: calc(var(--header-h) + 1rem); }
.scan__report-title { font-size: 1.125rem; margin-bottom: .375rem; }
.scan__report .form__status:focus-visible { outline: 2px solid var(--brand); outline-offset: 3px; }
/* Which pages the report checks: found for them, or ticked from what the scan found. */
.scan-pages { margin: 1.25rem 0 0; padding: 0; border: 0; min-width: 0; }
.scan-pages legend { padding: 0; margin-bottom: .375rem; }
.scan-pages [hidden] { display: none !important; }
.scan-pages__modes { display: grid; gap: .5rem; margin-top: .5rem; }
.scan-pages__modes .checkbox { color: var(--fg); font-size: .9375rem; }
.scan-pages__chooser { display: grid; gap: .75rem; margin-top: 1rem; }
.scan-pages__tools { display: flex; flex-wrap: wrap; gap: .5rem; }
.form .scan-pages__tools .btn { width: auto; margin-top: 0; min-height: var(--tap); padding: .5rem 1rem; font-size: .875rem; }
.scan-pages__count { margin: 0; font-size: .875rem; font-weight: 600; }
.scan-pages__list {
  max-height: 18rem; overflow: auto;
  padding: .25rem .875rem;
  border: 1px solid var(--border-control); border-radius: var(--radius-sm);
  background: var(--bg);
}
.scan-pages__list:focus-visible { outline: 3px solid var(--ink); outline-offset: 1px; }
.scan-pages__list li { padding: .5rem 0; border-bottom: 1px solid var(--border); }
.scan-pages__list li:last-child { border-bottom: 0; }
.scan-pages__list .checkbox { color: var(--fg); }
.scan-pages__path { overflow-wrap: anywhere; font-family: var(--font-mono); font-size: .8125rem; }
.scan-pages__note { font-family: var(--font); color: var(--fg-muted); }
/* After the email: the next step, offered beside the others rather than instead of them. */
.scan__next { display: grid; gap: .875rem; justify-items: start; margin-top: 1.25rem; }
.scan__next-text { margin: 0; font-size: .9375rem; }
.scan__next-wrong { margin: 0; font-size: .875rem; color: var(--fg-muted); }
.scan__again { margin-top: 1.25rem; font-size: .9375rem; }

/* Once the first screen is behind somebody, its email field follows them. */
.scan-stick {
  position: fixed; left: 50%; bottom: 16px; z-index: 60;
  display: flex; flex-wrap: wrap; align-items: center; gap: .5rem 1rem;
  width: min(820px, calc(100% - 24px)); padding: .625rem .75rem .625rem 1.25rem;
  border: 1px solid var(--border-control); border-radius: 22px;
  background: var(--stage-card); color: var(--fg); box-shadow: var(--stage-shadow);
  transform: translate(-50%, 160%); transition: transform .5s var(--ease);
}
.scan-stick.is-up { transform: translate(-50%, 0); }
.scan-stick__text { margin: 0; font-size: .875rem; color: var(--fg-muted); }
.scan-stick__text b { color: var(--fg); }
.scan-stick .scan-cta__row { flex: 1 1 22rem; }
.scan-stick .scan-cta__consent { flex: 1 1 100%; margin: 0; }
.scan-stick .field__error { flex: 1 1 100%; margin: 0; }
/* On a phone the bar keeps the field and the button on one line, and the
   button says less. The consent stays: the API refuses a report without it. */
@media (max-width: 40rem) {
  .scan-stick { bottom: 8px; padding: .5rem .5rem .5rem .75rem; border-radius: 18px; gap: .25rem; }
  .scan-stick__text { display: none; }
  .scan-stick .scan-cta__row { flex-wrap: nowrap; border-radius: 999px; }
  .scan-stick .scan-cta__row .input { min-width: 0; }
  .scan-stick .scan-cta__row .btn { width: auto; flex: 0 0 auto; padding-inline: 1rem; }
  .scan-stick .scan-cta__consent { font-size: .75rem; }
}

/* Public identity: warm paper, aubergine ink and a restrained rose accent. */
:root { --logo-ice: #f1b9d1; }
.logo--inverse { --logo-ice: #291c29; }
.btn { border-radius: 8px; font-size: .9375rem; min-height: 48px; }
.site-header__cta { min-height: 44px; }
.nav__link { font-size: .9375rem; }
.hero { background: var(--bg); }
.hero__title { letter-spacing: -.055em; }
.section-head__title { letter-spacing: -.045em; }
.card { box-shadow: none; }
.plan--featured { background: var(--bg-accent); }
.evidence-stage { padding: 1.65rem; border-radius: 18px; background: var(--bg-ink); color: var(--fg-on-dark); scroll-margin-top: 6rem; text-align: left; }
.evidence-stage__heading { display: flex; justify-content: space-between; align-items: center; gap: 1rem; margin-bottom: 1.2rem; }
.evidence-stage__heading h2 { font-size: 1.125rem; letter-spacing: -.025em; margin: 0; }
.evidence-stage__heading > span { font-size: .72rem; color: var(--fg-on-dark-muted); }
.evidence-stage__grid { display: grid; grid-template-columns: 1.1fr 1fr; gap: 1rem; }
.sample-shop { background: #f0ddd0; color: #38272d; position: relative; overflow: hidden; border-radius: 9px; padding: 1.5rem 2rem 2.5rem; min-height: 390px; }
.sample-shop__nav { border-bottom: 1px solid #c8afa5; display: flex; justify-content: space-between; padding-bottom: .8rem; font-size: .65rem; letter-spacing: .12em; font-weight: 700; }
.sample-shop__label { font-size: .65rem; text-transform: uppercase; letter-spacing: .1em; margin: 2rem 0 .7rem; }
.sample-shop__headline { font-family: Georgia,serif; font-size: clamp(2.2rem,4vw,3.7rem); line-height: 1; letter-spacing: -.055em; margin-bottom: .8rem; position: relative; z-index: 2; }
.sample-shop > p:not([class]) { font-size: .8rem; max-width: 16rem; position: relative; z-index: 2; }
.sample-shop__button { display: inline-flex; gap: 1.5rem; padding: .7rem 1rem; margin-top: 1rem; font-size: .75rem; background: #38272d; color: #fff7fb; outline: 2px solid #713653; outline-offset: 4px; position: relative; z-index: 2; }
.sample-shop__sculpture { position: absolute; width: 180px; height: 250px; right: -18px; bottom: -28px; transform: rotate(-16deg); }
.sample-shop__sculpture span { display: block; position: absolute; width: 130px; height: 180px; border: 24px solid #b06c82; border-radius: 90px 90px 20px 20px; box-shadow: inset 5px 0 0 #95566b, 7px 9px 0 #cf9aab; }
.sample-shop__sculpture span:nth-child(2) { top: 42px; left: 36px; }
.sample-shop__sculpture span:nth-child(3) { top: 84px; left: 72px; }
.sample-dialog { position: absolute; z-index: 4; inset: 30% 8% auto; padding: 1.5rem; border: 1px solid #b7a4af; border-radius: 10px; background: #fffaf5; box-shadow: 0 15px 70px #291c2966; }
.sample-dialog > span { float: right; }
.sample-dialog strong { font-family: Georgia,serif; font-size: 1.7rem; }
.sample-dialog p { font-size: .875rem; margin-top: .65rem; }
.evidence-panel { background: var(--bg); color: var(--fg); padding: 1.5rem; border-radius: 9px; }
.evidence-panel .eyebrow { display: flex; align-items: center; gap: .5rem; font-size: .65rem; }
.evidence-controls { display: flex; gap: .3rem; margin: 1rem 0 1.5rem; }
.evidence-controls[hidden], [data-evidence-panel][hidden], .sample-dialog[hidden] { display: none; }
.evidence-controls button { flex: 1; border: 1px solid var(--border-control); background: transparent; color: var(--fg-muted); padding: .5rem; min-height: 44px; font: inherit; font-size: .65rem; border-radius: 6px; cursor: pointer; }
.evidence-controls button[aria-pressed=true] { color: var(--on-ink); background: var(--brand); border-color: var(--brand); }
.evidence-key { display: inline-flex; padding: .35rem .75rem; border: 1px solid var(--border-strong); border-bottom-width: 3px; border-radius: 6px; font: 600 .875rem var(--font-mono); margin-bottom: 1rem; background: var(--bg-raised); }
.evidence-panel h3 { font-size: 1.55rem; letter-spacing: -.035em; max-width: 24ch; }
.evidence-panel p { font-size: .875rem; color: var(--fg-muted); }
#evidence-result { min-height: 225px; }
.evidence-verdict { display: flex; gap: .4rem; align-items: center; font-weight: 600; border-top: 1px solid var(--border); padding-top: .9rem; margin-top: 1.2rem; }
.evidence-panel .link-arrow { font-size: .8rem; }
.evidence-caption { font-size: .72rem; color: var(--fg-on-dark-muted); margin: 1rem 0 0; }
@media (max-width: 48rem) {
  .evidence-stage { padding: .9rem; }
  .evidence-stage__heading { display: block; }
  .evidence-stage__heading h2 { margin-bottom: .25rem; }
  .evidence-stage__grid { grid-template-columns: 1fr; }
  .sample-shop { min-height: 330px; padding: 1.2rem 1.5rem 2rem; }
  .sample-shop__headline { font-size: 3.1rem; }
  .evidence-panel { padding: 1.2rem; }
  .evidence-controls { margin-bottom: 1rem; }
  #evidence-result { min-height: 230px; }
}
.page-pricing .hero { text-align: center; padding-bottom: 1.5rem; }
.page-pricing .hero__copy { margin-inline: auto; }
.page-pricing .hero__title, .page-pricing .hero__intro { margin-inline: auto; }
.page-pricing .hero__actions { justify-content: center; }
.page-pricing .hero + .section { padding-top: 2rem; }
.page-pricing .plan { border-radius: 12px; box-shadow: none; }
.page-pricing .plan--featured { border-color: var(--brand); }

.preview__delta-value { white-space: nowrap; }

/* The platform page. Its hero shows the product (the illustration the home
   page uses); each section's heading stays in view beside a list that runs
   longer than it, rather than leaving a block of empty column; and what a
   section leaves out sits under its list, unticked. */
@media (min-width: 60rem) {
  .page-platform .split__head { position: sticky; top: calc(var(--header-h) + 2rem); }
}
.page-platform .hero__aside .preview__body { padding: 1.25rem; }
.limit-notes { display: grid; gap: .5rem; margin-top: 1.25rem; padding-top: 1rem; border-top: 1px solid var(--border); font-size: .9375rem; color: var(--fg-muted); }
.limit-notes__label { font-weight: 650; color: var(--fg); }

/* The toolbar page: each group of settings a card, in a grid a buyer can scan. */
.toolbar-features { display: grid; gap: 1rem; }
@media (min-width: 40rem) { .toolbar-features { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.toolbar-group { padding: 1rem 1.125rem; border: 1px solid var(--border); border-radius: var(--radius); background: var(--bg); }
.prose .toolbar-group__title { margin: 0 0 .625rem; font-size: 1.125rem; }
.toolbar-group__list { display: grid; gap: .5rem; font-size: .9375rem; }
.prose .toolbar-group__list > li { margin: 0; }
.toolbar-try { margin: 1.25rem 0; }
.toolbar-try[hidden] { display: none; }

/* The search phrase at the top of a hero heading — `heroTitle` in lib/ui.mjs.
   It is part of the <h1>, dressed as the line above it: small, tracked
   normally and in the accent colour, so the slogan is still what you read
   first. The heading's own letter-spacing is tuned for display sizes and would
   crush text this small, hence the reset. */
.hero__kicker {
  display: block;
  margin-bottom: .6rem;
  font-size: clamp(1rem, 1.4vw, 1.125rem);
  font-weight: 600;
  line-height: 1.35;
  letter-spacing: -.005em;
  color: var(--brand);
}

/* Annex 3 BFSG on /accessibility-statement/, lettered the way the statute
   letters it. The letter is text, not a list marker: "Annex 3 (c)" is what the
   rest of the page and every lawyer cites, so it has to be read out. */
.annex { display: grid; gap: 1rem; margin-top: 2rem; }
@media (min-width: 48rem) { .annex { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.annex__item {
  display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 1rem;
  padding: 1.35rem 1.5rem;
  border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--bg);
}
.annex__ref { font: 600 1.125rem/1.4 var(--font-mono); color: var(--brand); }
.annex__title { font-size: 1.0625rem; margin: 0 0 .35rem; }
.annex__text { margin: 0; font-size: .9375rem; color: var(--fg-muted); }

/* A criterion page's practical half (pages-learn.mjs): testing by hand, the
   failure and the fix in code, the rules the scan runs and the guides that
   cite the criterion. The code keeps its lines, as `.code-block` does: wrapped
   back to column 0, `Standard</label>` under an indented <label> showed the
   very nesting the sample is about as wrong. Each <pre> is focusable, so a
   keyboard scrolls a long line, and the edge with more to show is shaded. */
.test-steps { margin: 0; padding-left: 1.35em; }
.test-steps li { margin-bottom: .75rem; padding-left: .25rem; }
.test-steps li::marker { font-weight: 700; color: var(--brand); }

.code-sample { margin: 0 0 1rem; border: 1px solid var(--border); border-radius: var(--radius); background: var(--bg); overflow: hidden; }
.code-sample figcaption {
  display: flex; align-items: center; gap: .4rem;
  padding: .55rem .9rem; border-bottom: 1px solid var(--border);
  font-size: .8125rem; font-weight: 700;
}
.code-sample--fail figcaption { color: var(--critical); }
.code-sample--pass figcaption { color: var(--fg); }
.code-sample pre {
  margin: 0; padding: .9rem 1rem; font: .8125rem/1.6 var(--font-mono); white-space: pre; overflow-x: auto;
  background:
    linear-gradient(to right, var(--bg) 40%, transparent) left center / 2.5rem 100% no-repeat local,
    linear-gradient(to left, var(--bg) 40%, transparent) right center / 2.5rem 100% no-repeat local,
    radial-gradient(farthest-side at 0 50%, var(--scroll-shadow), transparent) left center / .875rem 100% no-repeat scroll,
    radial-gradient(farthest-side at 100% 50%, var(--scroll-shadow), transparent) right center / .875rem 100% no-repeat scroll,
    var(--bg);
}
.code-sample pre:focus-visible { outline-offset: -3px; }
.code-sample code { padding: 0; background: none; font-size: inherit; }

.rules__title { margin: 1.75rem 0 .5rem; font-size: 1.0625rem; }
.rule-list { margin-bottom: 1rem; }
.rule-list__item {
  display: grid; grid-template-columns: minmax(0, 15rem) minmax(0, 1fr); gap: .25rem 1rem; align-items: baseline;
  padding: .6rem 0; border-bottom: 1px solid var(--border);
}
@media (max-width: 40rem) { .rule-list__item { grid-template-columns: minmax(0, 1fr); } }
/* An id is never broken, so the id column is as wide as the longest one in
   the list, and every row shares it. */
@supports (grid-template-columns: subgrid) {
  @media (min-width: 40.01rem) {
    .rule-list { display: grid; grid-template-columns: fit-content(24rem) minmax(0, 1fr); column-gap: 1rem; }
    .rule-list__item { grid-column: 1 / -1; grid-template-columns: subgrid; }
  }
}
/* One chip for every rule id, linked or not; a linked one is underlined, as
   on /rules/, and the note under the list says so. They used to come in two
   unexplained styles, and neither looked like a link. */
.rule-list__id { justify-self: start; white-space: nowrap; color: var(--fg); }
.rule-list__link { justify-self: start; }
.rule-list__link .rule-list__id { color: var(--brand); text-decoration: underline; text-underline-offset: .18em; }
.rule-list__link:hover .rule-list__id { color: var(--brand-hover); text-decoration-thickness: 2px; }
.rule-list__help { font-size: .9375rem; color: var(--fg-muted); }
.rule-list__engine {
  display: inline-block; margin-left: .35rem; padding: .05rem .5rem;
  border: 1px solid var(--border-strong); border-radius: 999px;
  font-size: .75rem; font-weight: 600; white-space: nowrap;
}

.guide-refs { display: flex; flex-wrap: wrap; gap: .75rem 1.75rem; margin: 0 0 2.5rem; }
/* The code samples are cards of their own; a card around them is one too many. */
.split--practice .split__aside { padding: 0; border: 0; background: none; }

/* =========================================================================
   Tools: the statement generator (T2) and the BFSG check (T4)
   ========================================================================= */

/* Which half a visitor gets, as on the free scan: the form needs JavaScript,
   so without it the templates (T2) or a pointer to the prose below (T4) take
   its place. The inline script removes `no-js` before anything paints. */
.sg-fallback, .bc-fallback { display: none; }
.no-js .sg-app, .no-js .bc-app { display: none; }
.no-js .sg-fallback, .no-js .bc-fallback { display: block; }

.sg, .bc {
  margin: 2rem 0; padding: clamp(1rem, 3vw, 1.75rem);
  border: 1px solid var(--border); border-radius: var(--radius-lg);
  background: var(--bg); box-shadow: var(--shadow);
  scroll-margin-top: calc(var(--header-h) + 1rem);
}

.sg-head { display: grid; gap: .5rem; margin-bottom: 1.25rem; }
.sg-progress, .bc-progress { margin: 0; font-size: .875rem; font-weight: 650; color: var(--fg-muted); }
.sg-steps { display: flex; flex-wrap: wrap; gap: .5rem; margin: 0; padding: 0; list-style: none; counter-reset: sg-step; }
.prose .sg-steps li { margin: 0; }
.sg-steps__item {
  counter-increment: sg-step;
  padding: .3rem .75rem; border: 1px solid var(--border); border-radius: 999px;
  font-size: .8125rem; color: var(--fg-muted);
}
.sg-steps__item::before { content: counter(sg-step) ". "; }
.sg-steps__item.is-done { color: var(--fg); border-color: var(--border-strong); }
/* The current step is said three ways: aria-current, weight and a filled pill — never colour alone. */
.sg-steps__item.is-current { background: var(--ink); border-color: var(--ink); color: var(--on-ink); font-weight: 650; }

.sg-layout { display: grid; gap: 1.5rem; }
@media (min-width: 64rem) { .sg-layout { grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr); align-items: start; } }
.sg-main { min-width: 0; }
.sg-body { display: grid; gap: 1.25rem; }
.sg-step-title { margin: 0; font-size: 1.25rem; }
.sg-step-title:focus { outline: none; }
.sg-step-title:focus-visible { outline: 3px solid var(--ink); outline-offset: 4px; }

.sg-choices, .sg-repeat, .sg-group, .sg-audit, .sg-item, .bc-question { margin: 0; padding: 0; border: 0; min-width: 0; display: grid; gap: .6rem; }
.sg-choices > legend, .sg-repeat > legend, .sg-group > legend, .sg-audit > legend { margin-bottom: .35rem; padding: 0; }
.sg-item { padding: 1rem; border: 1px solid var(--border); border-radius: var(--radius); }
.sg-item > legend { padding: 0 .35rem; font-weight: 650; font-size: .9375rem; }
.sg-audit { padding: 1rem; border-left: 4px solid var(--border-strong); background: var(--bg-muted); border-radius: 0 var(--radius-sm) var(--radius-sm) 0; }
.sg-nested { display: grid; gap: .75rem; margin-left: clamp(0rem, 3vw, 2rem); }
.sg-choice { display: grid; grid-template-columns: 22px minmax(0, 1fr); gap: .15rem .65rem; align-items: start; }
.sg-choice input { width: 22px; height: 22px; margin: .15rem 0 0; accent-color: var(--ink); }
.sg-choice label { cursor: pointer; }
.sg-choice input:disabled + label { color: var(--fg-muted); cursor: not-allowed; }
.sg-choice .hint { grid-column: 2; }
.sg-why { margin: 0; padding: .6rem .8rem; border-left: 4px solid var(--serious); background: var(--bg-muted); color: var(--fg); }
.req-text { font-weight: 400; color: var(--fg-muted); }
.sg-repeat__row { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: .35rem .5rem; align-items: end; }
.sg-repeat__label { grid-column: 1 / -1; font-size: .875rem; }
.sg-repeat__row .field__error { grid-column: 1 / -1; }
.sg-add, .sg-remove { justify-self: start; min-height: var(--tap); }
.sg-presets { display: flex; flex-wrap: wrap; gap: .5rem; align-items: center; font-size: .875rem; }
.sg-presets .btn { min-height: var(--tap); padding-inline: .75rem; border: 1px solid var(--border-control); }
.sg-authority { font-style: normal; padding: .75rem 1rem; background: var(--bg-muted); border-radius: var(--radius-sm); }
.sg-prefill { display: grid; gap: .6rem; padding-top: 1rem; border-top: 1px solid var(--border); }
.sg-prefill .btn, .sg-actions .btn, .sg-nav .btn, .sg-foot .btn { width: auto; margin: 0; }
.sg-prefill__ok { margin: 0; font-size: .9375rem; }
.sg-nav { display: flex; justify-content: space-between; gap: 1rem; margin-top: 1.5rem; }
.sg-actions { display: flex; flex-wrap: wrap; gap: .75rem; }
.sg-foot { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem 1rem; margin-top: 1.25rem; padding-top: 1rem; border-top: 1px solid var(--border); }
.sg-foot .hint { margin: 0; }
.sg-incomplete ul { margin: .5rem 0 0; }
.link-button { padding: 0; border: 0; background: none; color: var(--brand); font: inherit; text-decoration: underline; cursor: pointer; min-height: 24px; }
.link-button:focus-visible { outline: 3px solid var(--ink); outline-offset: 2px; }

.sg-preview { display: grid; gap: .6rem; min-width: 0; }
@media (min-width: 64rem) { .sg-preview { position: sticky; top: calc(var(--header-h) + 1rem); } }
.sg-preview__title { margin: 0; font-size: 1rem; }
.sg-preview .hint { margin: 0; }
.sg-preview__frame { width: 100%; height: min(70vh, 40rem); border: 1px solid var(--border-strong); border-radius: var(--radius); background: #fff; }
.sg-preview__refresh { justify-self: start; width: auto; }

.sg-sample { margin: 1rem 0; padding: .75rem 1rem; border: 1px solid var(--border); border-radius: var(--radius); }
.sg-sample > summary { cursor: pointer; font-weight: 650; min-height: var(--tap); display: flex; align-items: center; }
.sg-sample .rb-statement h4 { font-size: 1.125rem; }
.sg-sample .rb-statement h5 { font-size: 1rem; margin-top: 1.25rem; }
.sg-sample .rb-statement h6 { font-size: .9375rem; margin-top: 1rem; }
.sg-sample address { font-style: normal; }

/* The BFSG check. */
.bc-form { display: grid; gap: 1rem; }
.bc-legend { font-size: 1.25rem; font-weight: 700; line-height: 1.3; margin-bottom: .5rem; padding: 0; }
.bc-legend:focus { outline: none; }
.bc-legend:focus-visible { outline: 3px solid var(--ink); outline-offset: 4px; }
.bc-help { font-size: .9375rem; }
.bc-help > summary { cursor: pointer; color: var(--brand); text-decoration: underline; min-height: 24px; }
.bc-help p { margin: .5rem 0 0; color: var(--fg-muted); }
.bc-options { display: grid; gap: .75rem; margin-top: .5rem; }
.bc-result { display: grid; gap: .25rem; }
.bc-result h3 { margin-top: 1.25rem; }
.bc-result__label { margin: 0; font-size: .875rem; font-weight: 650; color: var(--fg-muted); text-transform: uppercase; letter-spacing: .04em; }
.bc-verdict { margin: 0 0 .5rem; font-size: clamp(1.375rem, 2.6vw, 1.75rem); padding-left: .9rem; border-left: 6px solid var(--brand); }
.bc-verdict:focus { outline: none; }
.bc-verdict:focus-visible { outline: 3px solid var(--ink); outline-offset: 4px; }
.bc-verdict--grey { border-left-color: var(--serious); }
.bc-grey strong { color: var(--serious); }
.bc-actions { margin-top: 1.25rem; }
.bc-stand { margin-top: 1rem; }

@media print {
  .sg-nav, .sg-foot, .sg-preview, .bc-actions, .bc-help, .bc-progress, .form__error-summary { display: none !important; }
  .sg, .bc { box-shadow: none; border: 0; padding: 0; }
}
/* ======================================================= end of the tools */

/* =========================================================================
   Contrast checker (page T3: components/contrast.mjs, client/contrast.ts)
   ========================================================================= */

/* Without JavaScript nothing can be calculated: the form stays (it says what
   the tool asks for), the empty result goes, and one sentence says why. */
.contrast__nojs { display: none; }
.no-js .contrast__nojs { display: block; }
.no-js .contrast__result,
.no-js .contrast__swap,
.no-js .contrast__presets { display: none; }

.contrast { margin: 2rem 0 2.5rem; }
/* The tool beside its answer. With the article's full width (`.article__body`),
   the form and the result are two columns, so the ratio sits next to the
   colours being changed rather than 650px below them; the form stays in view
   while the longer result scrolls, where the window is tall enough to hold it. */
@media (min-width: 62rem) {
  .contrast { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr); gap: 2rem; align-items: start; }
  .no-js .contrast { display: block; }
  .contrast .contrast__result { margin-top: 0; }
}
@media (min-width: 62rem) and (min-height: 48rem) {
  .contrast__form { position: sticky; top: calc(var(--header-h) + 1rem); }
}
.contrast [hidden] { display: none !important; }
.contrast .list-reset { padding-left: 0; }
.contrast .list-reset > li { margin-bottom: 0; }
.contrast p { margin-bottom: 0; }

.contrast__form {
  display: grid; gap: 1.25rem;
  padding: clamp(1rem, 3vw, 1.75rem);
  border: 1px solid var(--border); border-radius: var(--radius-lg);
  background: var(--bg); box-shadow: var(--shadow);
}
.contrast__nojs { margin: 0; }

/* The two colours one above the other, with "Swap colours" between them —
   plainly about both. Side by side, the swap button sat under the text
   colour's eyedropper, touching it, a few pixels higher than it. */
.contrast__colours { display: grid; gap: .75rem; grid-template-columns: minmax(0, 1fr); }
.contrast__swap { justify-self: start; }
.contrast__colour-row { display: flex; flex-wrap: wrap; gap: .5rem; align-items: stretch; }
.contrast__value { flex: 1 1 9rem; min-width: 0; font-family: var(--font-mono); }
.contrast__picker {
  flex: none; width: var(--tap); height: var(--tap); padding: 3px;
  border: 1px solid var(--border-control); border-radius: var(--radius-sm);
  background: var(--bg); cursor: pointer;
}
.contrast__picker:focus-visible,
.contrast__preset:focus-visible,
.contrast__cvd-summary:focus-visible { outline: 3px solid var(--ink); outline-offset: 2px; }
.contrast__eyedropper { flex: none; padding-inline: .9rem; }
/* The ratio and the verdict under the colours, on a screen where the result
   proper is far below; beside the result on a wide screen it would say
   everything twice. */
.contrast__glance { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem; padding: .6rem .9rem; border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--bg-muted); font-size: 1.125rem; font-weight: 750; font-variant-numeric: tabular-nums; }
@media (min-width: 62rem) { .contrast__glance { display: none; } }
.no-js .contrast__glance { display: none; }

.contrast__type { display: flex; flex-wrap: wrap; gap: 1rem 2rem; align-items: center; }
.contrast__size { flex: 0 1 14rem; }
.contrast__check { color: var(--fg); font-size: .9375rem; align-items: center; min-height: var(--tap); }
.contrast__link-mode { display: grid; gap: .25rem; }
.contrast__link-mode .field { margin-top: .75rem; }

.contrast__presets { display: grid; gap: .5rem; }
.contrast__preset-list { display: flex; flex-wrap: wrap; gap: .5rem; }
.contrast__preset { min-height: var(--tap); border: 1px solid var(--border-control); border-radius: 999px; font-weight: 600; font-size: .875rem; text-align: left; }

.contrast__result { margin-top: 1.5rem; display: grid; gap: 1rem; grid-template-columns: minmax(0, 1fr); }
.contrast__result-title { font-size: clamp(1.25rem, 2.2vw, 1.5rem); margin: 0; }
.prose .contrast__result-title { margin-top: 0; }
.contrast [data-valid] { display: grid; gap: 1rem; grid-template-columns: minmax(0, 1fr); }
.contrast__invalid { font-weight: 600; }

.contrast__head { display: grid; gap: 1rem; grid-template-columns: minmax(0, 1fr); align-items: stretch; }
@media (min-width: 44rem) { .contrast__head { grid-template-columns: auto minmax(0, 1fr); } }
.contrast__ratio {
  display: flex; align-items: center; justify-content: center;
  min-width: 10rem; padding: 1rem 1.5rem;
  border: 1px solid var(--border); border-radius: var(--radius); background: var(--bg-muted);
  font-size: clamp(2rem, 6vw, 2.75rem); font-weight: 750; font-variant-numeric: tabular-nums; line-height: 1.1;
}
.contrast__preview {
  display: grid; align-content: center; min-width: 0;
  border: 1px solid var(--border-strong); border-radius: var(--radius); overflow: hidden;
}
.contrast__canvas { display: block; width: 100%; }

.contrast__summary { font-size: 1.0625rem; font-weight: 650; }
.contrast__applies { color: var(--fg-muted); font-size: .9375rem; }
.contrast__notes { margin: 0; padding-left: 1.25rem; font-size: .9375rem; }

.contrast .table-scroll { margin: 0; }
.contrast .table { min-width: 0; }
.contrast__table th, .contrast__table td { padding: .7rem 1rem; }
@media (max-width: 30rem) {
  .contrast__table th, .contrast__table td { padding: .6rem .5rem; font-size: .875rem; }
  .contrast__table thead th { letter-spacing: 0; font-size: .75rem; }
}
.contrast__table tr.is-applicable th, .contrast__table tr.is-applicable td { background: var(--bg-muted); }
.contrast__yours { font-weight: 500; color: var(--fg-muted); }
.contrast__crit { display: block; font-size: .8125rem; font-weight: 500; color: var(--fg-muted); }
.contrast__status { display: inline-flex; align-items: center; gap: .35rem; font-weight: 700; }
.contrast__status .icon { flex: none; }
.contrast__status--pass { color: var(--ok); }
.contrast__status--fail { color: var(--critical); }

.contrast__subtitle { font-size: 1.125rem; margin: .5rem 0 .25rem; }
.prose .contrast__subtitle { margin-top: .5rem; }
.contrast__adjust { display: flex; flex-wrap: wrap; gap: .25rem 1.5rem; align-items: center; margin: 0 0 .75rem; padding: 0; border: 0; }
.contrast__adjust legend { float: left; margin-right: 1rem; padding: 0; }
.contrast__adjust .checkbox { color: var(--fg); font-size: .9375rem; align-items: center; min-height: var(--tap); }
.contrast__suggestions { display: grid; gap: .75rem; }
.contrast__suggestion {
  display: flex; flex-wrap: wrap; gap: .75rem 1rem; align-items: center;
  padding: .75rem 1rem; border: 1px solid var(--border); border-radius: var(--radius); background: var(--bg);
}
.contrast__suggestion--note { color: var(--fg-muted); font-size: .9375rem; }
.contrast__chip { flex: none; width: 2.5rem; height: 2.5rem; border-radius: 8px; border: 1px solid var(--border-strong); }
.contrast__suggestion-body { flex: 1 1 12rem; min-width: 0; }
.contrast__suggestion-target { font-weight: 650; font-size: .9375rem; }
.contrast__suggestion-actions { display: flex; flex-wrap: wrap; gap: .5rem; }
.contrast__suggestion-actions .btn { min-height: var(--tap); padding: .5rem 1rem; }

.contrast__cvd { border: 1px solid var(--border); border-radius: var(--radius); background: var(--bg); }
.contrast__cvd-summary { padding: .9rem 1.25rem; min-height: var(--tap); font-weight: 650; cursor: pointer; }
.contrast__cvd[open] .contrast__cvd-summary { border-bottom: 1px solid var(--border); }
.contrast__cvd > .note { padding: .9rem 1.25rem 0; }
.contrast .contrast__tiles { display: grid; gap: 1rem; grid-template-columns: repeat(auto-fit, minmax(min(100%, 12rem), 1fr)); padding: 1rem 1.25rem 1.25rem; }
.contrast__tile .contrast__canvas { border: 1px solid var(--border-strong); border-radius: var(--radius-sm); }
.contrast__tile-caption { margin-top: .4rem; font-size: .875rem; }

.contrast__css { display: grid; gap: .5rem; justify-items: start; }
.contrast__code { margin: 0; width: 100%; padding: .8rem 1rem; border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--bg-muted); font: .875rem/1.5 var(--font-mono); white-space: pre-wrap; overflow-wrap: anywhere; }
.contrast__code code { padding: 0; background: none; font-size: inherit; }
.contrast__copied:not(:empty) { font-weight: 600; font-size: .9375rem; }
/* ---------------------------------------------------- end contrast checker */

/* =========================================================================
   BFSG law pages (L2, L4, L6) — the micro-enterprise check, the checklist,
   the clause table and "print or save as PDF". components/{micro-enterprise,
   checklist,clause-report,print-button}.mjs; scripts in client/.
   ========================================================================= */

/* A tool inside an article: the form card the lead forms use, at prose width. */
.tool {
  margin: 2rem 0;
  padding: clamp(1.25rem, 3vw, 1.75rem);
  border: 1px solid var(--border); border-radius: var(--radius-lg);
  background: var(--bg); box-shadow: var(--shadow);
}
.tool .form__title { margin-top: 0; }
.prose .tool ul { margin-bottom: 0; }

/* The micro-enterprise check. The form ships `hidden` and its script shows it;
   the sentence under it stands in when there is no script to calculate with. */
.micro-check__form[hidden], .micro-check__fallback[hidden] { display: none; }
.prose .micro-check__fallback { margin: 0; }
.micro-check__help { font-size: .9375rem; }
.micro-check__help summary {
  display: inline-flex; align-items: center; min-height: var(--tap);
  cursor: pointer; font-weight: 600; color: var(--brand);
  text-decoration: underline; text-underline-offset: .18em;
}
.prose .micro-check__help ul { margin: .25rem 0 0; }
.micro-check__submit { margin-top: 1.5rem; }
.micro-check__result:not(:empty) {
  margin-top: 1.5rem; padding: 1rem 1.25rem;
  border-left: 4px solid var(--fg-muted); border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
  background: var(--bg-muted);
}
.micro-check__result--yes:not(:empty) { border-left-color: var(--brand); }
.prose .micro-check__result p { margin: 0 0 .75rem; }
.prose .micro-check__result p:last-child { margin-bottom: 0; }
.micro-check__verdict { font-weight: 700; }

/* A group of radio buttons: a real fieldset and legend, each choice a 44px row. */
.choice-group { margin: 0; padding: 0; border: 0; display: grid; gap: .25rem; min-width: 0; }
.choice-group legend { padding: 0; margin-bottom: .375rem; }
.choice {
  display: flex; align-items: flex-start; gap: .65rem;
  min-height: var(--tap); padding: .5rem 0;
  font-size: .9375rem; cursor: pointer;
}
.choice input { width: 22px; height: 22px; margin: 0; flex: none; accent-color: var(--ink); }

/* The checklist: one fieldset per phase, a real checkbox per item. */
.checklist { margin: 1rem 0 2rem; padding: 0; border: 0; min-width: 0; }
.prose .checklist__progress { margin: 0 0 .75rem; font-size: .875rem; font-weight: 650; color: var(--fg-muted); }
.prose .checklist__list { margin: 0; padding: 0; list-style: none; }
.checklist__item {
  display: flex; align-items: flex-start; gap: .75rem;
  padding: .625rem 0; border-bottom: 1px solid var(--border);
}
.prose .checklist__item { margin: 0; }
.checklist__item:last-child { border-bottom: 0; }
.checklist__box { width: 24px; height: 24px; margin: .15rem 0 0; flex: none; accent-color: var(--ink); cursor: pointer; }
.checklist__body { min-width: 0; }
.checklist__label { cursor: pointer; }
.prose .checklist__refs { margin: .25rem 0 0; font-size: .875rem; color: var(--fg-muted); }
.checklist__badge {
  display: inline-block; margin-left: .25rem; padding: 0 .45rem;
  border: 1px solid currentColor; border-radius: 999px;
  font-size: .75rem; font-weight: 700; line-height: 1.5; color: var(--brand); white-space: nowrap;
}
.checklist__group { margin: 0 0 1.25rem; padding: 0; border: 0; min-width: 0; }
.checklist__group-title { padding: 0; margin-bottom: .25rem; font-size: 1.0625rem; font-weight: 700; }

.checklist-bar {
  margin: 1.5rem 0 2rem; padding: 1rem 1.25rem;
  border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--bg-muted);
}
.prose .checklist-bar__status { margin: 0 0 .25rem; font-weight: 700; }
.prose .checklist-bar__note { margin: 0 0 .75rem; }
.checklist-bar [hidden] { display: none; }
.checklist-bar__actions { display: flex; flex-wrap: wrap; gap: .5rem; }

/* Print or save as PDF. The button needs its script, so it ships `hidden`. */
.print-action { margin: 1rem 0 1.5rem; }
.print-action [hidden] { display: none; }
.prose .print-action__note { margin: .5rem 0 0; }

/* The EN 301 549 clause table, derived from the catalogue. */
.clause-preview { margin: 1.5rem 0 2rem; }
.clause-preview__intro { color: var(--fg-muted); }
.clause-preview__table td, .clause-preview__table th { vertical-align: middle; }
.clause-preview__notes { font-size: .9375rem; color: var(--fg-muted); }

@media print {
  /* Page furniture a printed guide does not need. */
  .breadcrumb, .article__aside, .further-reading, .cta-inline, .print-action, .checklist-bar__actions,
  .micro-check__form button { display: none !important; }
  .article--toc { display: block; }
  .table-scroll { overflow: visible; border: 0; }
  .tool { box-shadow: none; }
  .checklist__item { break-inside: avoid; }
  /* "Print this section": everything off the marked path is set aside
     (client/print.ts marks the path from <body> down to what is kept). */
  html.print-only body > :not(.print-path) { display: none !important; }
  html.print-only .print-path > :not(.print-path):not(.print-keep) { display: none !important; }
}

/* =========================================================================
   Comparison pages: the matrix, the cards, and the address field that hands
   a visitor to the free checker (components/comparison.mjs,
   components/free-scan-input.mjs).
   ========================================================================= */

/* The matrix is a real table in the same focusable scroll region as the
   Markdown tables. The tool column stays in view while the rest scrolls, so a
   row can be read on a phone without losing whose row it is. */
.comparison .comparison__table { font-size: .875rem; }
.comparison--hub .comparison__table { min-width: 72rem; }
.comparison--pair .comparison__table { min-width: 34rem; }
.comparison__caption { font-size: 1rem; }
.comparison__table th, .comparison__table td { padding: .75rem 1rem; }
.comparison--hub tbody th { position: sticky; left: 0; z-index: 1; background: var(--bg); min-width: 10rem; border-right: 1px solid var(--border); }
.comparison--hub thead th:first-child { position: sticky; left: 0; z-index: 2; }
.comparison--pair tbody th { width: 28%; }
/* Our own row is marked by a border and a tint, never by a badge: the table
   is a comparison, not a verdict. */
.comparison--hub tr.comparison__ours > * { background: var(--bg-muted); }
.comparison--hub tr.comparison__ours > th { box-shadow: inset 4px 0 0 var(--brand); }
.comparison--pair td.comparison__ours { background: var(--bg-muted); }
.comparison__tool { font-weight: 700; }
.comparison__note { display: block; font-weight: 400; font-size: .8125rem; color: var(--fg-muted); }
.comparison__level { font-weight: 700; }
.comparison__sources li { margin: 0 0 .25rem; }
.comparison__sources a { overflow-wrap: anywhere; }
.comparison__legend { margin-top: -.75rem; font-size: .8125rem; color: var(--fg-muted); }

.alt-grid { display: grid; gap: 1rem; margin: 1.5rem 0; }
@media (min-width: 48rem) { .alt-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.alt-card { padding: 1.125rem 1.25rem; border: 1px solid var(--border); border-radius: var(--radius); background: var(--bg); }
.prose .alt-card__title { margin: 0; font-size: 1.0625rem; }
.alt-card__text { margin: .4rem 0 0; font-size: .9375rem; }
.prose .alt-card__meta { margin: .5rem 0 0; font-size: .8125rem; color: var(--fg-muted); }
.alt-card__label { font-weight: 650; }

.free-scan-input { margin: 1.5rem 0 2rem; padding: 1.25rem; border: 1px solid var(--border); border-radius: var(--radius); background: var(--bg-muted); }
.prose .free-scan-input__title { margin: 0 0 .75rem; font-weight: 700; font-size: 1.0625rem; }
.free-scan-input .input { flex: 1 1 16rem; min-width: 0; }
/* ---- Glossary (components/glossary-index.mjs) ------------------------------
   The hub's index: a jump list, one definition list per category, then the
   same terms from A to Z. Letter links are 44px targets like every other
   control on the site; a letter with no entry is not listed. */
.glossary { margin: 1.5rem 0 2.5rem; }
.glossary__nav { margin: 0 0 2.5rem; padding: 1.25rem; border: 1px solid var(--border); border-radius: var(--radius); background: var(--bg-muted); }
.glossary__nav-title { margin: 0 0 .5rem; font-size: .875rem; font-weight: 700; }
.glossary__nav-title + .glossary__cats { margin-bottom: 1.25rem; }
.glossary__cats { display: flex; flex-wrap: wrap; gap: .25rem 1.5rem; }
.glossary__cats li { margin: 0; }
.glossary__cats a { display: inline-block; padding: .6rem 0; font-weight: 650; }
.glossary__count { color: var(--fg-muted); font-size: .875rem; }
.glossary__letters { display: flex; flex-wrap: wrap; gap: .25rem; }
.glossary__letters li { margin: 0; }
.glossary__letters a {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 2.75rem; min-height: 2.75rem; border-radius: var(--radius-sm);
  font-weight: 700;
  background: var(--bg); border: 1px solid var(--border-control); text-decoration: none;
}
.glossary__letters a:hover { background: var(--bg-sunk); text-decoration: underline; }
.glossary__group { margin-top: 2.5rem; }
.glossary__group h2, .glossary__letter { scroll-margin-top: 5rem; }
.glossary__intro { color: var(--fg-muted); }
.glossary__list { display: grid; gap: .75rem; margin: 1rem 0; }
@media (min-width: 48rem) { .glossary__list { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
/* With the article's full width (see `.article__body`), three across, as the
   criteria are on /wcag/. */
@media (min-width: 64rem) { .glossary__list { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.glossary__item { padding: 1rem 1.25rem; border: 1px solid var(--border); border-radius: var(--radius); background: var(--bg); }
.glossary__item dt { margin: 0; }
.glossary__term { font-weight: 650; font-size: 1.0625rem; }
.glossary__def { margin: .35rem 0 0; color: var(--fg-muted); font-size: .9375rem; }
.glossary__az { margin-top: 3rem; }
.glossary__letter { margin: 1.5rem 0 .5rem; font-size: 1.25rem; }
.glossary__compact { display: flex; flex-wrap: wrap; gap: 0 1.5rem; }
.glossary__compact li { margin: 0; }
.glossary__compact a { display: inline-block; padding: .45rem 0; }
/* ---- end glossary ---------------------------------------------------------- */
/* ---------------------------------------------- page-file widgets (P1–P6) */
/* Widgets drawn inside a page file's prose (components/product.mjs): the
   prose list indent and item spacing are for running text, not for a card
   grid or an illustrative demo placed in it. */
.prose .page-widget { margin: 1.75rem 0; }
.prose .page-widget ul.list-reset { padding-left: 0; }
.prose .page-widget ul.list-reset > li { margin-bottom: 0; }

/* ------------------------------------------------------------ rule pages */
/* The fact box on a rule page (components/rule-facts.mjs) and the index of
   rules with its filters (components/rule-index.mjs, client/rule-filter.mjs). */
.rule-facts { margin: 1.5rem 0 2rem; }
.rule-facts .facts code { white-space: nowrap; }
.rule-facts__note { display: block; margin-top: .35rem; font-size: .875rem; color: var(--fg-muted); }
.prose .rule-facts__criteria { display: grid; gap: .35rem; margin: 0; }
.prose .rule-facts__criteria li { display: flex; flex-wrap: wrap; align-items: center; gap: .25rem .5rem; margin: 0; }
.rule-filter:not([hidden]) { display: flex; flex-wrap: wrap; align-items: flex-end; gap: .75rem 1.25rem; margin: 1.5rem 0 0; }
.rule-filter__title { flex-basis: 100%; margin: 0; font-weight: 650; }
.rule-filter__field { display: grid; gap: .35rem; min-width: min(100%, 14rem); }
.rule-filter__count { flex-basis: 100%; margin: 0; font-size: .9375rem; color: var(--fg-muted); }
/* The index scrolls on a phone rather than folding a rule id every four
   letters ("imag/e-/alt"): the id is what somebody came from a report to look
   up. Its caption is printed above the region (rule-index.mjs), because a
   caption inside a scrolling table scrolls off with the columns. */
.table-title { margin: 1.5rem 0 -.75rem; font-weight: 650; }
.table-scroll .rule-index { min-width: 44rem; }
/* end rule pages */

/* sample report (T5) — the frozen crawl of the demo site, components/sample-report.mjs */
.sample-report { margin: 2rem 0 2.5rem; border: 1px solid var(--border); border-radius: var(--radius-lg); background: var(--bg); padding: 1.5rem 1.25rem; }
.sr-head h2 { margin: .5rem 0 .25rem; }
.sr-badge { display: inline-block; margin: 0; padding: .25rem .75rem; border-radius: 999px; background: var(--bg-sunk); color: var(--ink); font-size: .875rem; font-weight: 650; border: 1px dashed var(--border-strong); }
.sr-lede { color: var(--fg-muted); margin: 0 0 1rem; }
.sr-nav ol { list-style: none; margin: 0 0 1.5rem; padding: .75rem 0; display: flex; flex-wrap: wrap; gap: .25rem 1rem; border-top: 1px solid var(--border); border-bottom: 1px solid var(--border); }
.sr-nav a { display: inline-block; min-height: 24px; padding: .25rem 0; }
.sr-section { padding-top: .5rem; scroll-margin-top: calc(var(--header-h) + 1rem); }
.sr-section + .sr-section { border-top: 1px solid var(--border); margin-top: 1.5rem; }
.sr-finding { border: 1px solid var(--border); border-radius: var(--radius); padding: 1rem 1.125rem; margin: 1rem 0; scroll-margin-top: calc(var(--header-h) + 1rem); }
.sr-finding h4 { margin: 0 0 .5rem; }
.sr-sev { display: inline-block; font-size: .75rem; text-transform: uppercase; letter-spacing: .05em; padding: .1rem .5rem; border-radius: 999px; color: var(--on-ink); vertical-align: .15em; }
.sr-sev--critical { background: var(--critical); }
.sr-sev--serious { background: var(--serious); }
.sr-sev--moderate { background: var(--moderate); }
.sr-sev--minor { background: var(--fg-muted); }
.sr-facts { display: flex; flex-wrap: wrap; gap: .5rem 1.5rem; margin: .5rem 0; }
.sr-facts dt { font-size: .8125rem; color: var(--fg-muted); }
.sr-facts dd { margin: 0; }
.sr-label { font-weight: 650; margin: .75rem 0 .25rem; }
.sr-code { background: var(--bg-muted); border: 1px solid var(--border); border-radius: var(--radius-sm); padding: .5rem .75rem; white-space: pre-wrap; overflow-wrap: anywhere; font-size: .8125rem; margin: 0; }
.sr-pages { margin: .25rem 0 .5rem; padding-left: 1.25rem; font-size: .9375rem; }
.sr-pages a { overflow-wrap: anywhere; }
.sr-shots { display: flex; flex-wrap: wrap; gap: .75rem; margin: .75rem 0; }
.sr-shot { margin: .75rem 0; }
.sr-shot img { max-width: 100%; height: auto; border: 1px solid var(--border); border-radius: var(--radius-sm); }
.sr-shot figcaption { font-size: .8125rem; color: var(--fg-muted); }
.sr-walk h4 { margin-bottom: .25rem; overflow-wrap: anywhere; }
.sr-details summary { cursor: pointer; font-weight: 650; min-height: 24px; }
.sr-status { font-weight: 650; }
.sr-status--fail { color: var(--critical); }
.sr-status--partial { color: var(--moderate); }
.sr-status--untested, .sr-status--na { color: var(--fg-muted); }
.sr-note { font-weight: 400; font-size: .8125rem; color: var(--fg-muted); }
@media (max-width: 40rem) { .sample-report { padding: 1rem .75rem; } }
/* end sample report */

/* =========================================================================
   Figures (components/figures.mjs, and the illustration under a page heading)
   ========================================================================= */

/* The illustration under a guide's heading: framed, so the photograph's light
   grey never bleeds into the cream behind it. */
.page-hero--figure .hero__inner { gap: clamp(1.25rem, 3vw, 2rem); }
.page-hero__figure {
  margin: 0;
  max-width: 46rem;
  overflow: hidden;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--bg-sunk);
}
.page-hero__figure img { display: block; width: 100%; height: auto; }

/* A screenshot in the body: the product as it looks, with a caption saying
   the data is an example. */
.figure { margin: 1.75rem 0; }
.figure img { display: block; width: 100%; height: auto; border: 1px solid var(--border); border-radius: var(--radius); box-shadow: var(--shadow); }
.figure__caption { margin-top: .625rem; font-size: .875rem; color: var(--fg-muted); }
.figure__note { font-style: italic; }

/* Charts. Drawn for the eye and hidden from assistive technology; the caption
   says the point and the table under it has the numbers. Each tone is at
   least 3:1 against the page — the pale rose by its plum border — and the
   outlined one differs from the solid ones in shape as well as hue. */
.chart {
  margin: 1.75rem 0;
  padding: clamp(1rem, 2.5vw, 1.5rem);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg);
}
.chart__caption { display: grid; gap: .25rem; margin-bottom: 1rem; }
.chart__title { font-size: 1.0625rem; font-weight: 650; }
.chart__summary { font-size: .9375rem; color: var(--fg-muted); }
.chart__legend { display: flex; flex-wrap: wrap; gap: .5rem 1.25rem; margin: 0 0 1rem; padding: 0; list-style: none; font-size: .875rem; }
.chart__legend li { display: inline-flex; align-items: center; gap: .5rem; margin: 0; }
.chart__swatch { width: 1rem; height: 1rem; flex: none; border-radius: 4px; }
.chart__rows { display: grid; gap: .75rem; }
.chart__row { display: grid; gap: .25rem; }
@media (min-width: 40rem) {
  .chart__row { grid-template-columns: minmax(8rem, 13rem) minmax(0, 1fr); gap: 1rem; align-items: center; }
}
.chart__label { font-size: .9375rem; font-weight: 600; }
.chart__track { display: flex; align-items: center; gap: .625rem; min-width: 0; }
.chart__bar { display: flex; gap: 2px; width: calc(var(--share) * (100% - 3rem)); min-width: min-content; }
.chart__seg {
  flex: var(--n) 1 0;
  display: grid;
  place-items: center;
  min-width: 2rem;
  height: 2rem;
  padding: 0 .25rem;
  border-radius: 4px;
  font-size: .8125rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.chart__total { font-size: .875rem; font-weight: 650; color: var(--fg-muted); font-variant-numeric: tabular-nums; }
.chart__tone--plum { background: var(--brand); color: var(--on-ink); }
.chart__tone--ink { background: var(--ink); color: var(--on-ink); }
.chart__tone--amber { background: var(--serious); color: var(--on-ink); }
.chart__tone--rose { background: var(--lime); color: var(--on-lime); box-shadow: inset 0 0 0 2px var(--brand); }
.chart__tone--outline { background: var(--bg); color: var(--fg); box-shadow: inset 0 0 0 2px var(--fg-muted); }
.chart__note { margin: 1rem 0 0; font-size: .875rem; color: var(--fg-muted); }
.chart__data { margin-top: 1rem; }
.chart__data > summary { padding: .375rem 0; font-size: .9375rem; font-weight: 600; color: var(--brand); cursor: pointer; }
.chart__data .table-scroll { margin: .75rem 0 0; }
.chart__data .table { min-width: 0; }

/* Timelines: a real ordered list of real <time> elements, with a line and dots
   drawn on top. The date the page is about gets the filled dot. */
.timeline-block { margin: 1.75rem 0; }
.timeline__title { font-weight: 650; margin-bottom: .75rem; }
.prose ol.timeline { position: relative; margin: 0; padding: 0 0 0 1.75rem; list-style: none; }
.prose ol.timeline::before {
  content: '';
  position: absolute;
  left: .4375rem; top: .625rem; bottom: .625rem;
  width: 2px;
  background: var(--border-strong);
}
.prose .timeline__item { position: relative; margin: 0; padding-bottom: 1.25rem; }
.prose .timeline__item:last-child { padding-bottom: 0; }
.timeline__item::before {
  content: '';
  position: absolute;
  left: -1.75rem; top: .3rem;
  width: 1rem; height: 1rem;
  border: 2px solid var(--brand);
  border-radius: 50%;
  background: var(--bg);
}
.timeline__item--key::before { background: var(--brand); box-shadow: 0 0 0 4px var(--lime); }
.timeline__date { display: block; font-size: .9375rem; font-weight: 700; color: var(--brand); }
.timeline__text { display: block; }

/* Colour pairs: the background as a tile, the foreground as a bar across it.
   The page sets `--bg` and `--fg` on the tile itself, so they apply to it alone. */
.contrast-sample {
  display: inline-grid;
  place-items: center;
  width: 3.5rem;
  height: 2.25rem;
  border: 1px solid var(--border-strong);
  border-radius: 6px;
  background: var(--bg);
}
.contrast-sample::after { content: ''; width: 60%; height: .5rem; border-radius: 2px; background: var(--fg); }
.verdict { font-weight: 650; white-space: nowrap; }
.verdict--pass { color: var(--brand); }
.verdict--fail { color: var(--critical); }
.verdict--pass::before { content: '✓ '; }
.verdict--fail::before { content: '✕ '; }

/* ===================================================================== The home page

   `homeExperience` in lib/experience.mjs, and its script, client/home.ts.
   The sections follow the visitor's light or dark setting with the rest of
   the site, and add tokens of their own inside `.hm`. Every class here starts `hm-`, so nothing on another page can
   pick it up by accident.

   Text tokens are AA on --bg in both: light --fg 16:1, --hm-fg-2 11:1,
   --hm-fg-3 6.7:1 · dark --fg 18:1, --hm-fg-2 11:1, --hm-fg-3 6.9:1. The edge
   of every control is --hm-control, at 3:1 or better on --bg. */
.hm {
  --hm-bg-rgb: 255, 250, 245; --hm-ink-rgb: 41, 28, 41;
  --hm-fg-2: #4a3947; --hm-fg-3: #665461;
  --hm-surface: rgba(41, 28, 41, .03); --hm-line: rgba(41, 28, 41, .1); --hm-line-2: rgba(41, 28, 41, .16);
  --hm-control: #98768a;
  --hm-glass: rgba(255, 250, 245, .78); --hm-glass-bg: rgba(255, 250, 245, .62); --hm-glass-line: rgba(41, 28, 41, .1);
  --hm-card: #fff; --hm-card-line: rgba(41, 28, 41, .08); --hm-card-shadow: 0 24px 60px -36px rgba(41, 28, 41, .35);
  --hm-accent: #c25a86; --hm-accent-text: #713653; --hm-ok: #1f6b3a; --hm-crit: #b3261e; --hm-hot: 194, 90, 134;
  --hm-focus: #291c29;
  --hm-frame-shadow: 0 40px 100px -40px rgba(41, 28, 41, .45); --hm-panel-shadow: 0 30px 90px -40px rgba(41, 28, 41, .4);
  --hm-chrome: #f1eae5; --hm-chrome-url: #fffaf5; --hm-chrome-text: #665461; --hm-chrome-dot: rgba(41, 28, 41, .18);
  --hm-pic-bg: #e7e6ea;
  --hm-dash-glow: radial-gradient(45% 40% at 18% 40%, rgba(241, 185, 209, .55), transparent 70%), radial-gradient(40% 45% at 86% 66%, rgba(247, 214, 194, .65), transparent 70%);
  /* The hero: still water at dawn with its own iceberg left out, and the 3D
     iceberg as a cut-out — its cream background is too close to the lit
     tip's colour to blend away (assets/home/berg-light-cut.png). */
  --hm-still: url(/assets/home/still-light.jpg); --hm-v-c: .45; --hm-v-e: .45;
  --hm-berg: url(/assets/home/berg-light-cut.png); --hm-berg-blend: normal; --hm-berg-filter: none;
  --hm-berg-mask: radial-gradient(closest-side at 50% 40%, #000 72%, transparent);
  --ease-out: cubic-bezier(.16, 1, .3, 1);
  --bg: #fffaf5; --fg: #291c29;
  position: relative;
  overflow-x: clip;
  background: var(--bg); color: var(--fg);
}
@media screen and (prefers-color-scheme: dark) {
  .hm {
    --hm-bg-rgb: 12, 7, 12; --hm-ink-rgb: 255, 236, 246;
    --hm-fg-2: #d3c3cd; --hm-fg-3: #a8949f;
    --hm-surface: rgba(255, 236, 246, .045); --hm-line: rgba(255, 226, 240, .1); --hm-line-2: rgba(255, 226, 240, .18);
    --hm-control: #8a7584;
    --hm-glass: rgba(22, 13, 22, .66); --hm-glass-bg: rgba(28, 16, 27, .6); --hm-glass-line: rgba(255, 236, 246, .16);
    --hm-card: rgba(255, 236, 246, .045); --hm-card-line: rgba(255, 226, 240, .12); --hm-card-shadow: 0 30px 80px -40px rgba(0, 0, 0, .8);
    --hm-accent: #f1b9d1; --hm-accent-text: #f1b9d1; --hm-ok: #bdf0cf; --hm-crit: #ff8f86; --hm-hot: 241, 185, 209;
    --hm-focus: #f1b9d1;
    --hm-frame-shadow: 0 40px 120px -40px rgba(0, 0, 0, .95);
    --hm-panel-shadow: 0 40px 120px -40px rgba(0, 0, 0, .9), 0 0 100px -50px rgba(241, 185, 209, .45);
    --hm-chrome: #201620; --hm-chrome-url: rgba(255, 255, 255, .07); --hm-chrome-text: #b3a0ab; --hm-chrome-dot: rgba(255, 255, 255, .16);
    --hm-pic-bg: #050305;
    --hm-dash-glow: radial-gradient(45% 40% at 18% 40%, rgba(194, 90, 134, .36), transparent 70%), radial-gradient(40% 45% at 86% 66%, rgba(242, 165, 126, .16), transparent 70%);
    /* Dusk, and the dark render: its off-black is crushed to black and screened away. */
    --hm-still: url(/assets/home/still-dark.jpg);
    --hm-berg: url(/assets/scan/berg-3d-dark.jpg); --hm-berg-blend: screen; --hm-berg-filter: contrast(1.4) brightness(.97);
    --hm-berg-mask: radial-gradient(closest-side at 50% 44%, #000 58%, transparent);
    --bg: #0c070c; --fg: #fbf4f8; --fg-muted: #d3c3cd; --ink: #f1b9d1; --brand: #f1b9d1; --brand-hover: #f8d3e3;
    --border-control: #8a7584; --bg-muted: #1a111a;
    color-scheme: dark;
  }
  .hm .btn--primary { background: linear-gradient(180deg, #f8d3e3, #eca6c5); color: #2a1529; box-shadow: 0 10px 30px -12px rgba(241, 185, 209, .55); }
  .hm .btn--primary:hover { background: #f8d3e3; color: #2a1529; }
}
/* The hero runs under the header, so the still water starts at the top of the window. */
.page-home .site-header { margin-bottom: calc(-1 * var(--header-h)); }

.hm :focus-visible { outline-color: var(--hm-focus); }
.hm .btn { border-radius: 999px; }
.hm .btn--secondary { color: var(--fg); border-color: var(--hm-control); background: var(--hm-surface); }
.hm .btn--secondary:hover { color: var(--fg); border-color: var(--fg); background: rgba(var(--hm-ink-rgb), .08); }
.hm .btn .icon--sm { transition: transform .35s var(--ease-out); }
.hm .btn:hover .icon--sm { transform: translateX(3px); }
.hm .link-arrow { color: var(--hm-accent-text); }
.hm h2 { margin: 10px 0 14px; font-size: clamp(1.8rem, 1.1rem + 2vw, 2.7rem); font-weight: 600; line-height: 1.08; letter-spacing: -.04em; text-wrap: balance; }
.hm h3 { font-weight: 600; }

.hm-eyebrow, .hm-tag { margin: 0; font: 600 .75rem/1.4 var(--font-mono); letter-spacing: .08em; text-transform: uppercase; color: var(--hm-accent-text); }
.hm-lede { margin: 0; max-width: 36em; font-size: 1.0625rem; line-height: 1.6; color: var(--hm-fg-2); }
.hm-note { margin: 0; max-width: 40em; font-size: .8125rem; color: var(--hm-fg-3); }
.hm-small { margin: 12px 0 0; font: .75rem/1.5 var(--font-mono); letter-spacing: .02em; color: var(--hm-fg-3); }
.hm-cta-row { display: flex; flex-wrap: wrap; gap: 10px; margin: 0; }
.hm-head { max-width: 640px; margin-bottom: 44px; }
.hm-head > p:last-child { color: var(--hm-fg-2); }
.hm-glass { background: var(--hm-glass-bg); border: 1px solid var(--hm-glass-line); border-radius: 18px; backdrop-filter: blur(18px) saturate(150%); -webkit-backdrop-filter: blur(18px) saturate(150%); box-shadow: var(--hm-panel-shadow); }
.hm-chip { display: inline-flex; align-items: center; min-height: 24px; padding: 0 9px; border-radius: 999px; font: 500 .72rem var(--font-mono); background: rgba(var(--hm-hot), .16); color: var(--fg); }
.hm-chip--soft { background: rgba(var(--hm-ink-rgb), .07); color: var(--hm-fg-2); }
.hm-dot { display: inline-block; width: 8px; height: 8px; flex: none; border-radius: 50%; background: var(--hm-crit); box-shadow: 0 0 12px var(--hm-crit); }
.hm-live { display: inline-block; width: 8px; height: 8px; flex: none; border-radius: 50%; background: var(--hm-ok); }
/* A pause button, labelled for what it will do next. */
.hm-motion { display: grid; place-items: center; width: 36px; height: 36px; padding: 0; border: 1px solid var(--hm-control); border-radius: 50%; background: var(--hm-glass); color: var(--hm-fg-2); cursor: pointer; }
.hm-motion:hover { color: var(--fg); }
.hm-motion svg { width: 14px; height: 14px; }
.hm-motion .i-play, .hm-motion.is-paused .i-pause { display: none; }
.hm-motion.is-paused .i-play { display: block; }
.hm [hidden] { display: none !important; }

/* ------------------------------------------------------------ the hero

   Still water, with the horizon just above the evidence panel (placed by the
   script; without it, a crop that is close), and the 3D iceberg's tip rising
   above the panel with the rest of it under the frosted glass. */
.hm-hero {
  --hm-px: 0; --hm-py: 0;
  position: relative; isolation: isolate; overflow: hidden;
  min-height: 100svh;
  padding: calc(var(--header-h) + clamp(3.5rem, 9vh, 6.5rem)) 0 4.5rem;
  text-align: center;
}
.hm-hero__img {
  position: absolute; inset: -40px; z-index: -1;
  background: var(--hm-still) var(--hm-photo-pos, center 70%) / var(--hm-photo-size, cover) no-repeat, var(--bg);
  transform: translate(calc(var(--hm-px) * -16px), calc(var(--hm-py) * -12px)) scale(1.06);
  transition: transform 1.2s var(--ease-out);
}
/* The veil keeps the words readable: a pool behind the headline and the edges, and the page colour at the bottom. */
.hm-hero__img::after {
  content: ''; position: absolute; inset: 0;
  background:
    radial-gradient(46% 34% at 50% 40%, rgba(var(--hm-bg-rgb), var(--hm-v-c)), rgba(var(--hm-bg-rgb), calc(var(--hm-v-c) * .5)) 70%, transparent),
    radial-gradient(70% 60% at 50% 40%, rgba(var(--hm-bg-rgb), .15), rgba(var(--hm-bg-rgb), var(--hm-v-e))),
    linear-gradient(180deg, rgba(var(--hm-bg-rgb), .6), transparent 30%, transparent 60%, var(--bg));
}
.hm-hero__copy { display: grid; justify-items: center; gap: 18px; }
.hm-hero__title { max-width: 14em; margin: 0; font-size: clamp(2.5rem, 1.2rem + 4vw, 4.8rem); font-weight: 600; line-height: .98; letter-spacing: -.055em; text-wrap: balance; }
.hm-hero__title .hero__kicker { margin-bottom: 1rem; font-size: clamp(1rem, 1.5vw, 1.2rem); color: var(--hm-accent-text); }
.hm-hero__title em { font-family: Georgia, 'Times New Roman', serif; font-weight: 400; letter-spacing: -.04em; color: var(--hm-accent-text); }
.hm-hero .hm-lede { max-width: 38em; }
.hm-hero .hm-cta-row { justify-content: center; margin-top: 6px; }
.hm-panel-wrap { position: relative; display: flex; justify-content: center; margin-top: 112px; perspective: 1200px; }
/* The iceberg's waterline sits just behind the panel's top edge (30% down the render). */
.hm-berg {
  --bw: min(480px, 76vw);
  position: absolute; left: 50%; top: calc(8px - var(--bw) * .332);
  width: var(--bw); aspect-ratio: 1024 / 1168; transform: translateX(-50%);
  background: var(--hm-berg) center / contain no-repeat;
  mix-blend-mode: var(--hm-berg-blend); filter: var(--hm-berg-filter);
  -webkit-mask-image: var(--hm-berg-mask); mask-image: var(--hm-berg-mask);
  pointer-events: none;
}
.hm-panel {
  position: relative; width: min(100%, 560px); padding: 18px 20px; text-align: left;
  transform: rotateX(calc(var(--hm-ty, 0) * 1deg)) rotateY(calc(var(--hm-tx, 0) * 1deg));
  transition: transform .6s var(--ease-out);
}
.hm-panel__head { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 10px; padding-bottom: 12px; border-bottom: 1px solid var(--hm-glass-line); }
.hm-panel__head b { margin-right: auto; font-weight: 600; }
.hm-trail { margin: 0; padding: 8px 0; list-style: none; }
.hm-trail li { display: flex; align-items: center; gap: 12px; min-height: 34px; font-size: .9rem; color: var(--hm-fg-2); }
.hm-trail kbd { min-width: 70px; font: 500 .72rem var(--font-mono); color: var(--hm-fg-3); background: none; border: 0; padding: 0; }
.hm-trail .icon { width: 15px; height: 15px; margin-left: auto; }
.hm-trail .is-ok { color: var(--hm-ok); }
.hm-trail .is-bad { color: var(--hm-crit); }
.hm-trail li.is-bad { color: var(--fg); }
.hm-panel__foot { margin: 0; padding-top: 8px; border-top: 1px solid var(--hm-glass-line); font-size: .78rem; color: var(--hm-fg-3); }

/* ------------------------------------------------------------ the demo shop

   A picture of a shop, drawn three times (the lens's two layers and the
   agent's browser). Its sizes are in container units, so every copy is the
   same shop at its own width. Its colours are the shop's, not the theme's. */
.hm-shop { position: relative; container-type: inline-size; background: #fbf7f2; color: #2b2420; font-family: Georgia, 'Times New Roman', serif; }
.hm-shop img { display: block; }
.hm-ds-head { display: flex; align-items: center; gap: 4cqw; padding: 2.2cqw 3cqw; font-size: 1.6cqw; }
.hm-ds-head b { font-size: 1.7cqw; letter-spacing: .3em; }
.hm-ds-nav { display: flex; gap: 2.6cqw; margin-left: auto; font-family: system-ui, sans-serif; }
.hm-ds-cart { width: 3cqw; height: 3cqw; }
.hm-ds-cart svg { width: 100%; height: 100%; }
.hm-ds-hero { position: relative; }
.hm-ds-hero img { width: 100%; height: 28cqw; object-fit: cover; }
.hm-ds-hero div { position: absolute; left: 4cqw; top: 6cqw; }
.hm-ds-hero p { margin: 0; font-size: 4.2cqw; line-height: 1.05; color: #fff; text-shadow: 0 .2cqw 2cqw rgba(0, 0, 0, .3); }
.hm-ds-btn { display: inline-block; margin-top: 2cqw; padding: 1.1cqw 2.4cqw; border-radius: .6cqw; background: #2b2420; color: #fbf7f2; font: 500 1.4cqw system-ui, sans-serif; }
.hm-ds-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 2cqw; padding: 3cqw; }
.hm-ds-grid img { width: 100%; height: auto; aspect-ratio: 4 / 3; object-fit: cover; border-radius: .6cqw; }
.hm-ds-cookie { position: absolute; left: 3cqw; right: 3cqw; bottom: 2.4cqw; display: flex; align-items: center; justify-content: space-between; padding: 1.6cqw 2.2cqw; border-radius: 1cqw; background: #fff; box-shadow: 0 1cqw 4cqw rgba(0, 0, 0, .18); font: 400 1.5cqw system-ui, sans-serif; }
.hm-ds-cookie p { margin: 0; }
.hm-ds-cookie .hm-ds-btn { margin: 0; }
/* A finding on the shop: orange for what a scanner reports, pink for what the lens finds. */
.hm-mark { position: absolute; left: var(--l); top: var(--t); width: var(--w); height: var(--h); margin: -4px 0 0 -4px; padding: 4px; box-sizing: content-box; border: 2px solid #ffb877; border-radius: 6px; background: rgba(255, 184, 119, .08); pointer-events: none; }
.hm-mark i { position: absolute; left: -2px; bottom: calc(100% + 4px); padding: 3px 8px; border-radius: 6px; background: #ffb877; color: #2b1a0d; font: 500 .72rem var(--font); font-style: normal; white-space: nowrap; }
.hm-mark.is-end i { left: auto; right: -2px; }
.hm-mark.is-below i { bottom: auto; top: calc(100% + 4px); }
.hm-mark--agent { border-color: #c25a86; background: rgba(194, 90, 134, .1); }

/* ------------------------------------------------------------ the lens */
.hm-lens { padding: clamp(4.5rem, 10vw, 7.5rem) 0 4.5rem; }
.hm-lens__grid { display: grid; grid-template-columns: minmax(0, .7fr) minmax(0, 1.3fr); grid-template-areas: "copy stage" "finds stage"; gap: 30px 56px; align-items: start; }
.hm-lens__copy { grid-area: copy; align-self: end; }
.hm-lens__copy > p:not(.hm-tag) { max-width: 30em; margin: 0; color: var(--hm-fg-2); }
.hm-lens__finds { grid-area: finds; }
.hm-lens__key { display: flex; flex-wrap: wrap; gap: 10px 28px; margin: 22px 0 0; }
.hm-lens__key dt { display: flex; align-items: center; gap: 8px; font: 500 .72rem var(--font-mono); letter-spacing: .06em; text-transform: uppercase; color: var(--hm-fg-3); }
.hm-lens__key dd { margin: 4px 0 0; font-size: 1.0625rem; color: var(--fg); }
.hm-lens__sw { width: 12px; height: 12px; border: 2px solid; border-radius: 4px; }
.hm-lens__sw--scan { border-color: #ffb877; background: rgba(255, 184, 119, .2); }
.hm-lens__sw--agent { border-color: #c25a86; background: rgba(241, 185, 209, .45); border-radius: 50%; }
.hm-lens__head { display: flex; align-items: center; justify-content: space-between; gap: 12px; min-height: 36px; margin-bottom: 10px; }
.hm-lens__head h3 { margin: 0; font: 600 .72rem var(--font-mono); letter-spacing: .08em; text-transform: uppercase; color: var(--hm-fg-3); }
.hm-lens__list { display: grid; gap: 6px; }
.hm-lens__list button {
  position: relative; display: grid; gap: 2px; width: 100%; min-height: 44px;
  padding: 10px 14px 10px 30px; border: 1px solid var(--hm-control); border-radius: 14px;
  background: var(--hm-surface); color: var(--fg); font: inherit; text-align: left; cursor: pointer;
  transition: border-color .3s, background-color .3s;
}
.hm-lens__list button::before { content: ''; position: absolute; left: 12px; top: 17px; width: 8px; height: 8px; border: 1.5px solid var(--hm-control); border-radius: 50%; transition: background-color .3s, border-color .3s, box-shadow .3s; }
.hm-lens__list button:hover { border-color: var(--fg); }
.hm-lens__list button[aria-current="true"] { border-color: var(--hm-accent); background: rgba(var(--hm-hot), .1); }
.hm-lens__list button[aria-current="true"]::before { border-color: #c25a86; background: #f1b9d1; box-shadow: 0 0 10px rgba(241, 185, 209, .8); }
.hm-lens__list b { font-size: .9375rem; font-weight: 600; }
.hm-lens__list span { font-size: .8125rem; color: var(--hm-fg-2); }
.hm-lens__stage {
  --lx: 30%; --ly: 40%; --r: clamp(80px, 10.5vw, 128px); --rim: clamp(7px, .9vw, 12px);
  grid-area: stage; align-self: start; position: sticky; top: calc(var(--header-h) + 24px);
  aspect-ratio: 16 / 11; overflow: hidden; border: 1px solid var(--hm-line); border-radius: 20px;
  background: #fbf7f2; box-shadow: var(--hm-frame-shadow), 0 0 140px -40px rgba(241, 185, 209, .45);
}
.hm-lens__layer { position: absolute; inset: 0; }
.hm-lens__layer .hm-shop { position: absolute; inset: 0; overflow: hidden; }
.hm-lens__layer--deep { clip-path: circle(var(--r) at var(--lx) var(--ly)); transform: scale(1.1); transform-origin: var(--lx) var(--ly); }
.hm-lens__layer--deep .hm-shop { filter: saturate(.8) brightness(1.03); }
.hm-lens__layer--deep .hm-mark i { display: none; }
.hm-lens__stage.is-touring .hm-lens__layer--deep { transition: clip-path .9s var(--ease-out), transform-origin .9s var(--ease-out); }
/* A crystal disc: a frosted rim with a little spectrum in it, over the seam
   between the page and the page magnified. */
.hm-lens__glass {
  --hair: rgba(41, 28, 41, .22);
  position: absolute; left: var(--lx); top: var(--ly); width: calc(var(--r) * 2.2); height: calc(var(--r) * 2.2);
  transform: translate(-50%, -50%); border-radius: 50%; pointer-events: none;
  box-shadow: 0 0 0 1px var(--hair), 0 30px 70px -20px rgba(12, 7, 12, .6), inset 0 0 0 1px rgba(255, 255, 255, .55), inset 5px 0 12px -4px rgba(255, 110, 175, .45), inset -5px 0 12px -4px rgba(140, 150, 255, .4), inset 0 -30px 50px -20px rgba(241, 185, 209, .4);
}
.hm-lens__glass::before {
  content: ''; position: absolute; inset: 0; padding: var(--rim); border-radius: 50%;
  background: conic-gradient(from 215deg, rgba(255, 255, 255, .75), rgba(241, 185, 209, .55), rgba(196, 180, 255, .45), rgba(255, 255, 255, .7), rgba(255, 205, 178, .45), rgba(241, 185, 209, .55), rgba(255, 255, 255, .75));
  backdrop-filter: blur(6px) brightness(1.08); -webkit-backdrop-filter: blur(6px) brightness(1.08);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0); -webkit-mask-composite: xor;
  mask: linear-gradient(#000 0 0) content-box exclude, linear-gradient(#000 0 0);
}
.hm-lens__glass::after { content: ''; position: absolute; left: 17%; top: 11%; width: 36%; height: 17%; border-radius: 50%; background: linear-gradient(180deg, rgba(255, 255, 255, .6), transparent); transform: rotate(-26deg); }
.hm-lens__stage.is-touring .hm-lens__glass { transition: left .9s var(--ease-out), top .9s var(--ease-out); }
.hm-lens__chip { position: absolute; left: 0; top: 0; z-index: 2; max-width: calc(100% - 16px); padding: 5px 11px; border-radius: 999px; background: #f1b9d1; color: #2a1529; font: 500 .75rem var(--font); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; box-shadow: 0 8px 20px -8px rgba(0, 0, 0, .5); pointer-events: none; transition: opacity .3s; }
.hm-lens__stage.is-touring .hm-lens__chip { transition: opacity .3s, left .9s var(--ease-out), top .9s var(--ease-out); }
.hm-lens__chip:empty { opacity: 0; }
@media screen and (prefers-color-scheme: dark) { .hm-lens__glass { --hair: rgba(255, 255, 255, .4); } }

/* ------------------------------------------------------------ the keyboard agent */
.hm-agent { padding: 4.5rem 0; }
.hm-agent__grid { display: grid; grid-template-columns: minmax(0, .85fr) minmax(0, 1.3fr); gap: 56px; align-items: center; }
.hm-agent__copy { display: grid; gap: 14px; justify-items: start; }
.hm-agent__copy h2 { margin: 0; font-size: clamp(2rem, 1.1rem + 2.2vw, 3.2rem); line-height: 1.03; letter-spacing: -.045em; }
.hm-agent__copy p { margin: 0; }
.hm-demo { display: grid; gap: 14px; }
.hm-demo__browser { position: relative; overflow: hidden; border: 1px solid var(--hm-line); border-radius: 14px; background: var(--hm-chrome); box-shadow: var(--hm-frame-shadow); }
.hm-demo__chrome { display: flex; align-items: center; gap: 6px; height: 34px; padding: 0 12px; }
.hm-demo__chrome i { width: 9px; height: 9px; border-radius: 50%; background: var(--hm-chrome-dot); }
.hm-demo__chrome span { flex: 1; max-width: 300px; margin-left: 10px; padding: 3px 12px; border-radius: 999px; background: var(--hm-chrome-url); font: 400 .72rem var(--font-mono); color: var(--hm-chrome-text); }
.hm-demo__ring {
  position: absolute; left: 0; top: 0; width: 0; height: 0; opacity: 0; pointer-events: none;
  border: 2px solid rgb(var(--hm-hot)); border-radius: 8px;
  box-shadow: 0 0 0 4px rgba(var(--hm-hot), .25), 0 0 24px rgba(var(--hm-hot), .6);
  transition: left .45s var(--ease-out), top .45s var(--ease-out), width .45s var(--ease-out), height .45s var(--ease-out), opacity .3s, border-color .3s;
}
.hm-demo__ring.is-bad { border-color: #e5484d; box-shadow: 0 0 0 4px rgba(229, 72, 77, .25), 0 0 24px rgba(229, 72, 77, .6); }
.hm-demo__ring.is-trap { animation: hm-trap .5s ease-in-out 4; }
@keyframes hm-trap { 25% { transform: translateX(-4px); } 75% { transform: translateX(4px); } }
.hm-demo__flag { position: absolute; left: 0; top: 0; max-width: 240px; padding: 8px 12px; border-radius: 10px; background: #291c29; color: #fbf4f8; font-size: .75rem; line-height: 1.35; opacity: 0; transform: translateY(6px); transition: opacity .3s, transform .3s var(--ease-out); pointer-events: none; }
.hm-demo__flag b { display: block; font-size: .8rem; }
.hm-demo__flag.is-on { opacity: 1; transform: none; }
.hm-demo__side { display: grid; grid-template-columns: 1fr auto; align-items: end; gap: 10px 16px; padding: 14px 16px; border: 1px solid var(--hm-card-line); border-radius: 14px; background: var(--hm-card); }
.hm-demo__head { grid-column: 1 / -1; display: flex; align-items: center; gap: 8px; font-size: .8125rem; }
.hm-demo__head span:last-child { color: var(--hm-fg-3); }
.hm-demo:not(.is-paused) .hm-demo__head .hm-live { animation: hm-live 1.8s infinite; }
.hm-demo.is-paused .hm-demo__head .hm-live { background: var(--hm-fg-3); }
@keyframes hm-live { 0% { box-shadow: 0 0 0 0 rgba(31, 107, 58, .5); } 100% { box-shadow: 0 0 0 10px rgba(31, 107, 58, 0); } }
.hm-demo__log { display: flex; flex-direction: column; justify-content: flex-end; gap: 2px; height: 120px; overflow: hidden; -webkit-mask-image: linear-gradient(180deg, transparent, #000 30%); mask-image: linear-gradient(180deg, transparent, #000 30%); }
.hm-demo__log li { display: flex; gap: 10px; font-size: .8125rem; color: var(--hm-fg-3); }
.hm-demo__log li:last-child { color: var(--fg); }
.hm-demo__log kbd { min-width: 46px; padding: 0; border: 0; background: none; font: 500 .72rem var(--font-mono); color: inherit; }
.hm-demo__log li.is-bad em { font-style: normal; color: var(--hm-crit); }
.hm-demo__ctrl { display: flex; align-items: center; gap: 8px; }
.hm-step { min-height: 40px; padding: .5rem 1rem; font-size: .875rem; }

/* ------------------------------------------------------------ the dashboard, in tabs

   Screens of the real dashboard after a real crawl (scripts/home-dashboard.ts),
   in a frosted frame over a soft glow. Until the script runs the tab list is
   hidden and every screen shows, one under another, with its caption. */
.hm-dash { position: relative; isolation: isolate; padding: 4.5rem 0; }
.hm-dash::before {
  content: ''; position: absolute; inset: 0; z-index: -1; pointer-events: none; background: var(--hm-dash-glow);
  -webkit-mask-image: linear-gradient(180deg, transparent, #000 22%, #000 78%, transparent); mask-image: linear-gradient(180deg, transparent, #000 22%, #000 78%, transparent);
}
.hm-dash__head { margin-inline: auto; text-align: center; }
.hm-dash__tabs { display: flex; flex-wrap: wrap; justify-content: center; gap: 4px; width: max-content; max-width: 100%; margin: 0 auto 28px; padding: 5px; border-radius: 24px; box-shadow: none; }
.hm-dash__tabs button { min-height: 40px; padding: 0 16px; border: 0; border-radius: 999px; background: none; color: var(--hm-fg-2); font: 500 .875rem var(--font); cursor: pointer; transition: background-color .25s, color .25s; }
.hm-dash__tabs button:hover { color: var(--fg); background: rgba(var(--hm-ink-rgb), .06); }
.hm-dash__tabs button[aria-selected="true"] { background: var(--fg); color: var(--bg); }
.hm-dash__panel { max-width: 1080px; margin: 0 auto; border-radius: 24px; }
.hm-dash__tabs[hidden] ~ .hm-dash__panel + .hm-dash__panel { margin-top: 48px; }
.hm-dash__panel figure { margin: 0; }
.hm-dash__frame { padding: 8px; border-radius: 22px; }
.hm-dash__frame picture, .hm-dash__frame img { display: block; width: 100%; height: auto; border-radius: 15px; }
.hm-dash__panel:not([hidden]) .hm-dash__frame { animation: hm-panel-in .6s var(--ease-out) both; }
@keyframes hm-panel-in { from { opacity: 0; transform: translateY(14px) scale(.985); } }
/* The ring is the panel's own, around the frame and its caption: a focus shown only on a child is one the keyboard agent cannot see change. */
.hm-dash__panel:focus-visible { outline: 2px solid var(--hm-focus); outline-offset: 6px; }
.hm-dash__panel figcaption { max-width: 38em; margin: 18px auto 0; text-align: center; color: var(--hm-fg-2); }
.hm .hm-dash__note { max-width: 46em; margin: 24px auto 0; text-align: center; }
@media (prefers-reduced-motion: reduce) { .hm-dash__panel:not([hidden]) .hm-dash__frame { animation: none; } }

/* ------------------------------------------------------------ the modules, as crystals */
.hm-feat { padding: 4.5rem 0 3rem; }
.hm-feat__grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 18px; align-items: start; }
.hm-feat__card { padding: 18px 18px 22px; border: 1px solid var(--hm-card-line); border-radius: 22px; background: var(--hm-card); box-shadow: var(--hm-card-shadow); transition: border-color .3s; }
.hm-feat__card:nth-child(3n + 2) { margin-top: 34px; }
.hm-feat__card:nth-child(3n) { margin-top: 68px; }
.hm-feat__grid.is-rising .hm-feat__card { transform: translateY(calc((1 - var(--hm-s, 1)) * 70px)); }
.hm-feat__pic { display: block; aspect-ratio: 5 / 4; margin-bottom: 18px; overflow: hidden; border-radius: 15px; background: var(--hm-pic-bg); }
.hm-feat__pic picture, .hm-feat__pic img { display: block; width: 100%; height: 100%; object-fit: cover; }
.hm-feat__pic img { transition: transform 1s var(--ease-out); }
.hm-feat__card:hover .hm-feat__pic img { transform: scale(1.045); }
.hm-feat__card h3 { margin: 0 0 6px; font-size: 1.2rem; letter-spacing: -.02em; }
.hm-feat__card p { margin: 0; font-size: .9375rem; color: var(--hm-fg-2); }
.hm-feat__more { margin: 32px 0 0; text-align: center; }

/* ------------------------------------------------------------ what is live, the deadline */
.hm-early, .hm-law { padding: 2.5rem 0; }
.hm-early__inner, .hm-law__inner { display: grid; grid-template-columns: 1.1fr 1fr; gap: 56px; align-items: start; padding: 48px; border-radius: 26px; }
.hm-early__inner h2, .hm-law__inner h2 { font-size: clamp(1.7rem, 1.1rem + 1.6vw, 2.4rem); }
.hm-early__inner p, .hm-law__text { color: var(--hm-fg-2); }
.hm-early__inner .hm-cta-row { margin-top: 22px; }
.hm-early__now { display: grid; gap: 14px; }
.hm-early__now > div { padding: 20px 22px; border: 1px solid var(--hm-card-line); border-radius: 16px; background: var(--hm-card); }
.hm-early__now h3 { display: flex; align-items: center; gap: 10px; margin: 0 0 6px; font-size: 1.0625rem; }
.hm-early__now p { margin: 0; }
.hm-law__text { margin: 0 0 22px; }
.hm-law__checks { display: grid; gap: 14px; }
.hm-law__checks li { display: flex; gap: 12px; color: var(--hm-fg-2); }
.hm-law__checks .icon { margin-top: 3px; color: var(--hm-accent-text); }

/* ------------------------------------------------------------ questions */
.hm-faq { padding: 4.5rem 0 5rem; }
.hm-faq__inner { display: grid; grid-template-columns: 1fr 2fr; gap: 48px; align-items: start; }
.hm-faq__inner h2 { margin-top: 0; }
.hm-faq__list { border-top: 1px solid var(--hm-line-2); }
.hm-faq details { border-bottom: 1px solid var(--hm-line-2); }
.hm-faq summary { display: flex; align-items: center; justify-content: space-between; gap: 16px; min-height: 66px; padding: 14px 0; font-size: 1.0625rem; font-weight: 600; list-style: none; cursor: pointer; }
.hm-faq summary::-webkit-details-marker { display: none; }
.hm-faq summary:hover { color: var(--hm-accent-text); }
.hm-faq__icon { width: 18px; height: 18px; flex: none; color: var(--hm-fg-3); transition: transform .35s var(--ease-out); }
.hm-faq details[open] .hm-faq__icon { transform: rotate(45deg); }
.hm-faq__a { max-width: 40em; padding: 0 0 22px; color: var(--hm-fg-2); }
.hm-faq__a p { margin: 0 0 .75em; }
.hm-faq__a a { color: var(--hm-accent-text); }

/* ------------------------------------------------------------ the offer, last

   Dark in both themes: dusk on still water, the iceberg beside the words. */
.hm-final { padding: 2rem 0 6rem; }
.hm-final__inner {
  --fg: #fbf4f8; --hm-focus: #f1b9d1;
  position: relative; isolation: isolate; overflow: hidden;
  display: grid; grid-template-columns: 1fr 1fr; align-items: center; min-height: 380px;
  border-radius: 28px; background: #160c15; color: var(--fg);
}
.hm-final__img { position: absolute; inset: 0 0 0 45%; z-index: -1; background: url(/assets/home/dusk-dark.jpg) 45% 26% / 135% no-repeat, #160c15; -webkit-mask-image: linear-gradient(90deg, transparent, #000 40%); mask-image: linear-gradient(90deg, transparent, #000 40%); }
.hm-final__copy { display: grid; gap: 14px; padding: 48px; }
.hm-final__copy h2 { margin: 0; font-size: clamp(1.8rem, 1.1rem + 1.8vw, 2.6rem); line-height: 1.06; }
.hm-final__copy p { margin: 0; color: #d3c3cd; }
.hm-final .btn--primary { background: linear-gradient(180deg, #f8d3e3, #eca6c5); color: #2a1529; }
.hm-final .btn--primary:hover { background: #f8d3e3; color: #2a1529; }
.hm-final .btn--secondary { color: #fbf4f8; border-color: #8a7584; background: rgba(255, 255, 255, .05); }
.hm-final .btn--secondary:hover { color: #fbf4f8; border-color: #fbf4f8; background: rgba(255, 255, 255, .1); }
.hm-final__bubbles { display: grid; gap: 10px; justify-items: end; padding: 32px 48px; }
.hm-final__bubbles li { display: flex; align-items: center; gap: 10px; max-width: 300px; padding: 11px 14px; border: 1px solid rgba(255, 236, 246, .14); border-radius: 14px; background: rgba(20, 11, 19, .72); font-size: .875rem; backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px); }
.hm-final__bubbles li:nth-child(2) { margin-right: 28px; background: rgba(241, 185, 209, .92); color: #2a1529; }
.hm-final__bubbles .hm-dot { background: #ff8f86; box-shadow: 0 0 12px #ff8f86; }
.hm-final__bubbles li:nth-child(2) .hm-dot { background: #2a1529; box-shadow: none; }
.hm-final__bubbles .icon { width: 16px; height: 16px; color: #bdf0cf; }

/* ------------------------------------------------------------ narrower screens */
@media (max-width: 60rem) {
  .hm-lens__grid { grid-template-columns: minmax(0, 1fr); grid-template-areas: "copy" "stage" "finds"; gap: 28px; }
  .hm-lens__stage { position: relative; top: auto; }
  .hm-agent__grid, .hm-early__inner, .hm-law__inner, .hm-faq__inner { grid-template-columns: minmax(0, 1fr); gap: 32px; }
  .hm-feat__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .hm-feat__card:nth-child(n) { margin-top: 0; }
  .hm-early__inner, .hm-law__inner { padding: 28px; }
  .hm-final__inner { grid-template-columns: minmax(0, 1fr); }
  .hm-final__img { inset: 50% 0 0; -webkit-mask-image: linear-gradient(180deg, transparent, #000 50%); mask-image: linear-gradient(180deg, transparent, #000 50%); }
  .hm-final__bubbles { justify-items: start; padding: 0 24px 32px; }
}
@media (max-width: 40rem) {
  .hm-feat__grid { grid-template-columns: minmax(0, 1fr); }
  .hm-lens__stage { aspect-ratio: 4 / 3.4; }
  .hm-demo__side { grid-template-columns: minmax(0, 1fr); }
  .hm-mark i { font-size: .62rem; }
  .hm-final__copy { padding: 28px 24px; }
  .hm-panel__head b { width: 100%; }
  .hm-hero .hm-cta-row .btn { flex: 1 1 100%; }
}
