/* === pattern-tokens:font-import:start (generated) === */
/*
   The After Dark faces. A stack NAMES a family; it never
   fetches one - so without this the headings below render in
   the metric-matched fallback and look deliberate.

   A <link rel="stylesheet"> in the document head is faster:
   the browser finds it while parsing the head, where this is
   not discovered until global.css has itself arrived and been
   parsed - an extra round trip on the critical path. Write the
   <link> as well; this is the backstop that makes a forgotten
   one slow rather than wrong.

   Quoted, not a bare url() token: these URLs carry a semicolon
   inside the weight axis, and only a string ends where the URL
   ends.

   At the top of the file because @import is valid only before
   any other rule. Regenerated in place; edits here are lost. */
@import url("https://fonts.googleapis.com/css2?family=Archivo:ital,wght@0,400..700;1,400..700&family=Big+Shoulders:opsz,wght@10..72,400..700&display=swap");
/* === pattern-tokens:font-import:end === */

/* F-Buddy UK -- site stylesheet. Seeded by page_brief.py --seed; the palette
   below was derived from the logo's inks and is a starting point to correct,
   never a decision already made. Everything else on this site builds on it. */

/* ---- reset ---- */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body { margin: 0; }
img, picture, svg, video { display: block; max-width: 100%; }
button, input, select, textarea { font: inherit; color: inherit; }
h1, h2, h3, h4, h5, h6, p, figure, blockquote, dl, dd { margin: 0; }
ul[class], ol[class] { list-style: none; margin: 0; padding: 0; }

/* ---- tokens ---- */
:root {
  --color-bg: #f8f8f8;
  --color-surface: #ffffff;
  --color-surface-soft: #f0efef;
  --color-text: #211f23;
  --color-text-soft: #6f6d70;
  --color-heading: #161618;
  --color-primary: #d81c24;
  --color-primary-dark: #a8141b;
  --color-scrim: #181719;
  --color-rule: #e0e0e0;
  --color-focus: #a8141b; /* the brand's deep red, 7.6:1 on the page (was green #1d876c; partner 2026-10-04: "more on brand") */
  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --space-4: 1rem;
  --space-5: 1.5rem;
  --space-6: 2rem;
  --space-7: 2.5rem;
  --space-8: 3rem;
  --space-9: 4rem;
  --space-10: 5rem;
  --space-11: 6.5rem;
  --space-12: 8rem;
  --container-max: 75rem;

  /* The dials are the brand's character: decide them, do not keep them. */
  --btn-radius: 8px;
  --card-radius: 14px;
  --card-shadow: 0 1px 2px rgba(0, 0, 0, .05), 0 10px 28px -12px rgba(0, 0, 0, .18);
  --card-border: 1px solid var(--color-rule);
  --chip-radius: 999px;
  --logo-height: 50px;

  --transition-fast: 120ms ease;
  --transition-slow: 320ms ease;

  --type-scale: 1;
}

/* ---- base type ---- */
body {
  background: var(--color-bg);
  color: var(--color-text);
  font-family: var(--font-body);
  font-size: 1rem;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4 {
  font-family: var(--font-heading);
  font-weight: var(--weight-display, 700);
  color: var(--color-heading);
  line-height: calc(1.15 * var(--heading-leading, 1));
  letter-spacing: calc(-0.02em + var(--heading-tracking, 0) * 1em);
}

a { color: var(--color-primary); }

:where(a, button, summary, input, select, textarea):focus-visible {
  outline: 2px solid var(--color-focus);
  outline-offset: 3px;
  border-radius: 4px;
}

/* ---- motion ---- */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
}

/* === pattern-tokens:start (generated - edit outside these markers) === */
/*
   Role tokens the design patterns require. A var() this
   sheet does not define is discarded at compute time, so
   the rule is lost rather than falling back to anything.
   Regenerated in place; anything you add here is replaced.
*/
/* Metric-matched fallback for Big Shoulders, on the heading. Arial,
   resized to match Big Shoulders, so the line boxes are already the size
   they will be once the webfont arrives and the page does not reflow
   under the reader when it does.

   One face PER WEIGHT. A real face gets wider at 700; a local one
   thickened synthetically does not, so a single face solved at 400
   leaves anything set at 700 too narrow and this block causes the
   shift it exists to stop. The descriptor is what picks the right
   solved number instead of synthesising a bold from the 400 face.

   The local() chain is ordered. The numbers are solved against Arial
   specifically, so a stand-in is a degradation rather than a match -
   but Linux and Android have no Arial, and there a face with nothing
   to load defines no family at all and the stack falls through in
   silence, which measured 34.7% off.

   BESIDE the :root rule, never inside it: an at-rule in a declaration
   block is dropped by the parser, and the stack would have survived
   naming a family nothing defines. */
@font-face {
  font-family: 'BigShouldersFallback';
  src: local('Arial'), local('Liberation Sans'), local('Helvetica Neue'),
       local('Helvetica'), local('Roboto');
  font-weight: 400;
  size-adjust: 69.2%;
  ascent-override: 98.6%;
  descent-override: 21.4%;
  line-gap-override: 0%;
}
@font-face {
  font-family: 'BigShouldersFallback';
  src: local('Arial'), local('Liberation Sans'), local('Helvetica Neue'),
       local('Helvetica'), local('Roboto');
  font-weight: 700;
  size-adjust: 83.1%;
  ascent-override: 98.6%;
  descent-override: 21.4%;
  line-gap-override: 0%;
}

/* Metric-matched fallback for Archivo, on the body. Arial,
   resized to match Archivo, so the line boxes are already the size
   they will be once the webfont arrives and the page does not reflow
   under the reader when it does.

   One face PER WEIGHT. A real face gets wider at 700; a local one
   thickened synthetically does not, so a single face solved at 400
   leaves anything set at 700 too narrow and this block causes the
   shift it exists to stop. The descriptor is what picks the right
   solved number instead of synthesising a bold from the 400 face.

   The local() chain is ordered. The numbers are solved against Arial
   specifically, so a stand-in is a degradation rather than a match -
   but Linux and Android have no Arial, and there a face with nothing
   to load defines no family at all and the stack falls through in
   silence, which measured 34.7% off.

   BESIDE the :root rule, never inside it: an at-rule in a declaration
   block is dropped by the parser, and the stack would have survived
   naming a family nothing defines. */
@font-face {
  font-family: 'ArchivoFallback';
  src: local('Arial'), local('Liberation Sans'), local('Helvetica Neue'),
       local('Helvetica'), local('Roboto');
  font-weight: 400;
  size-adjust: 98.3%;
  ascent-override: 87.8%;
  descent-override: 21%;
  line-gap-override: 0%;
}
@font-face {
  font-family: 'ArchivoFallback';
  src: local('Arial'), local('Liberation Sans'), local('Helvetica Neue'),
       local('Helvetica'), local('Roboto');
  font-weight: 700;
  size-adjust: 105.7%;
  ascent-override: 87.8%;
  descent-override: 21%;
  line-gap-override: 0%;
}

:root {
  /* Inks. The ratios are measured, not intended. */
  /* on this brand's own --color-scrim: 17.87:1 */
  --color-on-scrim: #ffffff;
  /* white 5.11:1, the brand's own text 3.20:1 on --color-primary */
  --color-on-primary: #ffffff;

  /* Type: the After Dark pairing. Chosen, not derived. */
  --font-heading: 'Big Shoulders', 'BigShouldersFallback', 'Arial Narrow', 'Helvetica Neue Condensed', sans-serif;
  --font-body: 'Archivo', 'ArchivoFallback', 'Segoe UI', system-ui, -apple-system, sans-serif;
  --heading-leading: 0.95;
  --heading-tracking: 0.01;
}
/* === pattern-tokens:end === */


/* === pattern cta-assurance@2 (library v148; appended by page_assemble.py -- adopt a newer version by replacing this block, never by adding a second) === */
/* cta-assurance v1 - tokens only, selectors prefixed */
/* Sets no colour: it inherits the ink above it. See the README. */
.cta-assurance {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--space-2) var(--space-3);
  list-style: none;
  margin: var(--space-4) 0 0;
  padding: 0;
  font-size: 0.875rem;
  line-height: 1.5;
}
.cta-assurance-item + .cta-assurance-item::before {
  content: "";
  display: inline-block;
  width: 0.25rem;
  height: 0.25rem;
  margin-inline-end: var(--space-3);
  border-radius: 50%;
  background: currentColor;
  vertical-align: middle;
}
/* === /pattern cta-assurance@2 === */






/* === pattern faq-details@6 (library v148; appended by page_assemble.py -- adopt a newer version by replacing this block, never by adding a second) === */
/* faq-details v3 - tokens only, selectors prefixed.
   No script anywhere: <details>/<summary> gives keyboard operation, the
   expanded/collapsed announcement and find-in-page for free. */
.faq-details {
  padding-block: var(--space-8);
}
/* Keep the measure: answers read badly at full width. */
.faq-details-inner {
  width: min(100% - 2 * var(--space-4), 48rem);
  margin-inline: auto;
}
.faq-details-title {
  font-family: var(--font-heading);
  color: var(--color-heading);
  font-size: calc(clamp(1.75rem, 1rem + 2vw, 2.25rem) * var(--type-scale, 1));
  margin: 0 0 var(--space-6);
}
/* A rule under every item, plus one above the first. */
.faq-details-item {
  border-block-end: 1px solid var(--color-rule);
}
.faq-details-item:first-of-type {
  border-block-start: 1px solid var(--color-rule);
}
.faq-details-summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  padding-block: var(--space-4);
  cursor: pointer;
  font-family: var(--font-heading);
  /* --color-text: this is not large text. */
  color: var(--color-text);
  /* Both lines are needed to drop the default triangle. */
  list-style: none;
}
.faq-details-summary::-webkit-details-marker {
  display: none;
}
/* Required: removing the marker above removes the focus affordance some
   browsers hang off it. */
.faq-details-summary:focus-visible {
  outline: 2px solid var(--color-focus);
  outline-offset: -2px;
}
.faq-details-question {
  font-size: 1.0625rem;
  font-weight: 700;
  line-height: 1.4;
}
/* The indicator is a shape, not a glyph and never colour alone. */
.faq-details-icon {
  position: relative;
  flex: 0 0 auto;
  width: var(--space-5);
  height: var(--space-5);
}
.faq-details-icon::before,
.faq-details-icon::after {
  content: "";
  position: absolute;
  inset-inline: 0;
  top: 50%;
  height: 2px;
  margin-block-start: -1px;
  background: var(--color-text-soft);
}
.faq-details-icon::after {
  transform: rotate(90deg);
}
/* A state change, not an animation: it applies under reduced motion too. */
.faq-details-item[open] .faq-details-icon {
  transform: rotate(45deg);
}
.faq-details-answer {
  padding-block-end: var(--space-4);
  padding-inline-end: var(--space-6);
  color: var(--color-text-soft);
}
.faq-details-answer p {
  margin: 0 0 var(--space-3);
  line-height: 1.65;
}
.faq-details-answer p:last-child {
  margin-block-end: 0;
}
/* Motion is opt-in and only ever eases a state the page already reached. */
@media (prefers-reduced-motion: no-preference) {
  .faq-details-icon {
    transition: transform var(--transition-fast) ease-out;
  }
  .faq-details-item[open] .faq-details-answer {
    animation: faq-details-open var(--transition-fast) ease-out;
  }
}
@keyframes faq-details-open {
  from {
    opacity: 0;
    transform: translateY(-0.25rem);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}
/* Belt and braces if a brand reintroduces a transition on these. */
@media (prefers-reduced-motion: reduce) {
  .faq-details-icon {
    transition: none;
  }
  .faq-details-answer {
    animation: none;
  }
}
/* === /pattern faq-details@6 === */


/* === pattern colophon@2 (library v148; appended by page_assemble.py -- adopt a newer version by replacing this block, never by adding a second) === */
/* colophon v2 - tokens only, selectors prefixed */
.colophon {
  border-top: 1px solid var(--color-rule);
  padding-block: var(--space-8) var(--space-6);
  font-size: 0.875rem;
  color: var(--color-text-soft);
}
.colophon--plain {
  background: var(--color-bg);
}
.colophon--soft {
  background: var(--color-surface);
}
.colophon-inner {
  width: 92%;
  max-width: var(--container-max);
  margin-inline: auto;
  display: grid;
  gap: var(--space-4);
}
/* layout: --line is the centred stack at every width; --columns spreads the
   three groups across the row from 60rem up and is the same stack below. */
.colophon--line .colophon-inner,
.colophon--columns .colophon-inner {
  justify-items: center;
  text-align: center;
}
/* mark: the brand mark above everything else, or nothing at all. */
.colophon--none .colophon-mark {
  display: none;
}
.colophon--logo .colophon-mark {
  display: inline-flex;
  margin-block-end: var(--space-2);
}
/* The set height is the floor: `height: auto` under a `max-height` alone
   resolves a viewBox-only SVG to 0x0. A tenth over the header's height, so
   the footer mark reads as a signature and not a repeat of the bar. */
.colophon-logo {
  display: block;
  width: auto;
  height: calc(var(--logo-height, 2.75rem) * 1.1);
  max-width: 100%;
  object-fit: contain;
}
/* The platform decides the menu's own markup, so its rules reach it by
   descent rather than by a generated class name. */
.colophon-menu ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-2) var(--space-6);
}
.colophon-legal {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-2) var(--space-6);
}
.colophon-menu a,
.colophon-legal a {
  color: var(--color-text-soft);
  text-decoration: none;
}
.colophon-menu a:hover,
.colophon-legal a:hover {
  color: var(--color-text);
  text-decoration: underline;
  text-underline-offset: 0.2em;
}
.colophon a:focus-visible {
  outline: 2px solid var(--color-focus);
  outline-offset: 2px;
}
.colophon-copyright {
  margin: 0;
}
@media (min-width: 60rem) {
  .colophon--columns .colophon-inner {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    justify-items: start;
    align-items: start;
    text-align: start;
    gap: var(--space-6) var(--space-8);
  }
  /* A brand with no managed footer menu deletes the nav: two columns then,
     not two columns and a hole. */
  .colophon--columns .colophon-inner:not(:has(.colophon-menu)) {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
  .colophon--columns .colophon-mark {
    grid-column: 1 / -1;
  }
  .colophon--columns .colophon-menu ul,
  .colophon--columns .colophon-legal {
    flex-direction: column;
    justify-content: flex-start;
    gap: var(--space-2);
  }
  .colophon--columns .colophon-copyright {
    justify-self: end;
    text-align: end;
  }
}
/* === /pattern colophon@2 === */

/* === pattern cta-sticky@7 (library v148; appended by page_assemble.py -- adopt a newer version by replacing this block, never by adding a second) === */
/* cta-sticky v6 - tokens only, selectors prefixed. */
@media (max-width: 59.99rem) {
  .cta-sticky {
    position: fixed;
    inset-inline: 0;
    bottom: 0;
    z-index: 50;
    box-sizing: border-box;
    padding: var(--space-2) var(--space-4);
    padding-bottom: calc(var(--space-2) + env(safe-area-inset-bottom, 0px));
    background: var(--color-surface);
    /* Two separations: --color-rule may be set to nothing. */
    border-top: 1px solid var(--color-rule);
    box-shadow: 0 -1px 0 color-mix(in srgb, var(--color-text) 14%, transparent),
                0 -8px 24px color-mix(in srgb, var(--color-text) 10%, transparent);
  }
  .cta-sticky-btn {
    display: block;
    box-sizing: border-box;
    text-align: center;
    background: var(--color-primary);
    color: var(--color-on-primary);
    font-weight: 700;
    text-decoration: none;
    padding: var(--space-3) var(--space-4);
    border-radius: var(--btn-radius);
    /* The bar's height and the body clearance below must stay in step. */
    /* Fallback required: declared inside body:has(). */
    min-height: var(--cta-sticky-target, 48px);
    line-height: 1.5;
  }
  .cta-sticky-btn:hover {
    background: var(--color-primary-dark);
  }
  /* Focus needs its own indicator, not the hover fill. */
  .cta-sticky-btn:focus-visible {
    outline: 3px solid var(--color-focus);
    outline-offset: 3px;
  }
  /* Clearance, derived from the same tokens as the bar. */
  body:has(.cta-sticky) {
    /* On body so both this rule and the bar read it. */
    --cta-sticky-target: 48px;
    padding-bottom: calc(
      max(var(--cta-sticky-target), 1.5em + 2 * var(--space-3))
      + 2 * var(--space-2) + 1px + env(safe-area-inset-bottom, 0px)
    );
  }
}
@media (min-width: 60rem) {
  .cta-sticky {
    display: none;
  }
}
/* === /pattern cta-sticky@7 === */

/* === pattern crumb-trail@1 (library v148; appended by page_assemble.py -- adopt a newer version by replacing this block, never by adding a second) === */
/* crumb-trail v1 - tokens only, selectors prefixed */
.crumb-trail {
  box-sizing: border-box;
  margin-inline: auto;
  padding-block: var(--space-3) var(--space-2);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  font-size: 0.875rem;
  line-height: 1.5;
  color: var(--color-text-soft);
}
.crumb-trail--page {
  width: min(100% - 2 * var(--space-4), var(--container-max));
}
/* 52rem is the article column, held by the article masthead, the contents
   list and the author block. Any other number puts a second left edge on
   the page. */
.crumb-trail--column {
  width: min(100% - 2 * var(--space-4), 52rem);
}
.crumb-trail-link {
  color: var(--color-text-soft);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.18em;
}
.crumb-trail-link:hover {
  color: var(--color-text);
}
.crumb-trail-link:focus-visible {
  outline: 2px solid var(--color-focus);
  outline-offset: 2px;
}
.crumb-trail-separator {
  color: var(--color-text-soft);
}
.crumb-trail-current {
  color: var(--color-text);
  font-weight: 600;
}
/* === /pattern crumb-trail@1 === */



/* === page /new/blog/best-fuck-buddy-sites-uk: its own styles (page_assemble.py; rewritten on every assemble of this page) === */
.fb-article-split {
  width: min(100% - 2 * var(--space-4), var(--container-max));
  margin-inline: auto;
  display: grid;
  gap: var(--space-8);
}
.fb-article-split .prose-column { width: 100%; margin-inline: 0; }
.fb-article-aside-panel {
  background: var(--color-scrim);
  color: var(--color-on-scrim);
  border-radius: var(--card-radius);
  padding: var(--space-6);
  margin-block: var(--space-6);
}
.fb-article-aside-title {
  font-family: var(--font-heading);
  font-weight: var(--weight-display, 700);
  font-size: calc(1.75rem * var(--type-scale, 1));
  line-height: calc(1.1 * var(--heading-leading, 1));
  color: var(--color-on-scrim);
  margin: 0 0 var(--space-3);
}
.fb-article-aside-text { margin: 0 0 var(--space-5); color: var(--color-on-scrim); }
.fb-article-aside-btn {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 48px; padding: var(--space-3) var(--space-6);
  background: var(--color-primary); color: var(--color-on-primary);
  border-radius: var(--btn-radius); font-weight: 700; text-decoration: none;
  width: 100%;
}
.fb-article-aside-btn:hover { background: var(--color-primary-dark); }
.fb-article-aside-btn:focus-visible { outline: 2px solid var(--color-on-scrim); outline-offset: 3px; }
.fb-article-aside-list {
  list-style: none; margin: var(--space-4) 0 0; padding: 0;
  font-size: 0.875rem; color: var(--color-on-scrim);
}
.fb-article-aside-list li + li { margin-top: var(--space-1); }
@media (min-width: 960px) {
  .fb-article-split { grid-template-columns: minmax(0, 68ch) minmax(16rem, 1fr); align-items: start; }
  .fb-article-aside { position: sticky; top: calc(var(--page-header-height, 5rem) + var(--space-4)); }
}
/* === /page /new/blog/best-fuck-buddy-sites-uk === */

/* === brand: F-Buddy dark furniture (hand-written, outside every pattern block) ===
   The F-Buddy logo is a sticker mark - white outline, pale "No strings attached"
   line - drawn for a dark ground; on the page colour its tagline measures 1.05:1.
   So this brand's header and footer sit on the logo's own charcoal (--color-scrim).
   Two-class selectors so they outrank the patterns' single-class grounds and
   survive any re-append of those blocks. Partner asked 2026-09-25. */
.masthead-nav.masthead-nav--plain {
  --masthead-nav-ground: var(--color-scrim);
  --masthead-nav-ink: var(--color-on-scrim);
  --masthead-nav-edge: color-mix(in srgb, var(--color-on-scrim) 16%, transparent);
  --masthead-nav-cta-face: var(--color-primary);
  --masthead-nav-cta-ink: var(--color-on-primary);
  --masthead-nav-panel-face: var(--color-scrim);
  --masthead-nav-panel-ink: var(--color-on-scrim);
  --masthead-nav-ring: var(--color-on-scrim);
}
.colophon.colophon--plain {
  background: var(--color-scrim);
  color: color-mix(in srgb, var(--color-on-scrim) 78%, var(--color-scrim));
  border-top-color: transparent;
}
.colophon.colophon--plain a {
  color: var(--color-on-scrim);
}
.colophon.colophon--plain a:focus-visible {
  outline-color: var(--color-on-scrim);
}
/* Live member photos blurred as a join teaser (partner, 2026-09-25: "soft" -
   colours and shapes, no recognisable faces; blurred everywhere, no hover
   reveal). Visual only: the image the page loads is still the sharp one.
   clip-path keeps the blur inside the photo's rounded box, no halo. */
.member-grid .mem-card img {
  filter: blur(10px);
  clip-path: inset(0 round var(--card-radius));
}
/* === /brand: F-Buddy dark furniture === */





/* === pattern signup-steps@2 (library v166; appended by page_assemble.py -- adopt a newer version by replacing this block, never by adding a second) === */
/* signup-steps v2 - tokens only, selectors prefixed */
.signup-steps {
  /* Answer rows: over the 44px floor, sized for a thumb. */
  --signup-steps-target: 56px;
  padding-block: var(--space-5) var(--space-8);
}
.signup-steps-inner {
  width: min(100% - 2 * var(--space-4), var(--container-max));
  margin-inline: auto;
  display: grid;
  gap: var(--space-5);
}
.signup-steps-copy {
  min-width: 0;
}
.signup-steps-title {
  margin: 0;
  font-family: var(--font-heading);
  font-weight: var(--weight-display, 700);
  font-size: calc(clamp(1.75rem, 1.3rem + 2.2vw, 3.25rem) * var(--type-scale, 1));
  line-height: calc(1.1 * var(--heading-leading, 1));
  letter-spacing: calc(-0.01em + var(--heading-tracking, 0) * 1em);
  color: var(--color-heading);
  text-wrap: balance;
}
.signup-steps-sub {
  margin: var(--space-3) 0 0;
  max-width: 34rem;
  font-size: 1rem;
  color: var(--color-text-soft);
}

.signup-steps-card {
  min-width: 0;
  margin: 0;
  padding: var(--space-4) var(--space-4) var(--space-5);
  background: var(--color-surface);
  color: var(--color-text);
  border: var(--card-border);
  border-radius: var(--card-radius);
  box-shadow: var(--card-shadow);
}
/* --color-text, not --color-heading: a heading on a card is not on the page ground. */
.signup-steps-card-title,
.signup-steps-q {
  margin: 0;
  padding: 0;
  font-family: var(--font-heading);
  font-weight: var(--weight-display, 700);
  line-height: calc(1.2 * var(--heading-leading, 1));
  letter-spacing: calc(-0.005em + var(--heading-tracking, 0) * 1em);
  color: var(--color-text);
}
.signup-steps-card-title {
  font-size: calc(clamp(1.375rem, 1.2rem + .8vw, 1.75rem) * var(--type-scale, 1));
}
.signup-steps-q {
  margin-bottom: var(--space-3);
  font-size: calc(1.1875rem * var(--type-scale, 1));
}
.signup-steps-step {
  min-width: 0;
  margin: var(--space-6) 0 0;
  padding: 0;
  border: 0;
}
.signup-steps-card-title + .signup-steps-step {
  margin-top: var(--space-4);
}
.signup-steps-help {
  margin: calc(-1 * var(--space-2)) 0 var(--space-3);
  font-size: .9375rem;
  color: var(--color-text-soft);
}

/* Answers: the input is inside its label, so the whole row is the target. */
.signup-steps-opts {
  display: grid;
  gap: var(--space-3);
  margin: 0;
  padding: 0;
  list-style: none;
}
.signup-steps-opts--two {
  grid-template-columns: 1fr 1fr;
}
.signup-steps-opt {
  min-width: 0;
}
.signup-steps-opt label {
  position: relative;
  display: block;
  cursor: pointer;
}
/* Off-screen but focusable, so the row takes the keyboard and the group is
   still announced. display: none would remove both. */
.signup-steps-opt input,
.signup-steps-other input {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  border: 0;
  overflow: hidden;
  white-space: nowrap;
  clip-path: inset(50%);
}
.signup-steps-opt-face {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  min-height: var(--signup-steps-target);
  padding: var(--space-3) var(--space-4);
  background: var(--color-surface);
  /* The border is the only thing marking this as a control. */
  border: 2px solid color-mix(in srgb, var(--color-text) 22%, var(--color-surface));
  border-radius: var(--btn-radius);
  font-weight: 700;
  line-height: 1.25;
}
.signup-steps-opt:hover .signup-steps-opt-face {
  border-color: color-mix(in srgb, var(--color-primary) 70%, var(--color-surface));
}
.signup-steps-opt input:checked + .signup-steps-opt-face {
  border-color: var(--color-primary);
  background: color-mix(in srgb, var(--color-primary) 9%, var(--color-surface));
}
.signup-steps-tick {
  flex: none;
  display: grid;
  place-items: center;
  width: 22px;
  height: 22px;
  border: 2px solid color-mix(in srgb, var(--color-text) 35%, var(--color-surface));
  border-radius: 50%;
}
.signup-steps-opt input:checked + .signup-steps-opt-face .signup-steps-tick {
  background: var(--color-primary);
  border-color: var(--color-primary);
  color: var(--color-on-primary);
}
.signup-steps-opt input:checked + .signup-steps-opt-face .signup-steps-tick::before,
.signup-steps-other input:checked + span .signup-steps-tick::before {
  content: "";
  width: 5px;
  height: 10px;
  margin-top: -2px;
  border: solid currentColor;
  border-width: 0 2.5px 2.5px 0;
  transform: rotate(45deg);
}

/* The third answer to "who are you": a real choice, drawn small. */
.signup-steps-other {
  position: relative;
  display: inline-flex;
  margin-top: var(--space-2);
  cursor: pointer;
}
.signup-steps-other > span {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  min-height: 44px;
  padding: 0 var(--space-1);
  font-weight: 600;
  text-decoration: underline;
  text-underline-offset: 3px;
}
.signup-steps-other .signup-steps-tick {
  display: none;
}
.signup-steps-other input:checked + span {
  text-decoration: none;
}
.signup-steps-other input:checked + span .signup-steps-tick {
  display: grid;
  background: var(--color-primary);
  border-color: var(--color-primary);
  color: var(--color-on-primary);
}

/* Fields. 16px text, or iOS zooms the page on focus. */
.signup-steps-dob {
  display: grid;
  grid-template-columns: 1fr 1fr 1.4fr;
  gap: var(--space-2);
  /* A label that wraps must not push its box out of line with the others. */
  align-items: end;
}
.signup-steps-field {
  display: grid;
  gap: var(--space-1);
  min-width: 0;
}
.signup-steps-field > span {
  font-size: .9375rem;
  font-weight: 700;
}
.signup-steps-field input {
  box-sizing: border-box;
  width: 100%;
  min-height: 52px;
  padding: 0 var(--space-3);
  font: inherit;
  font-size: 1rem;
  color: var(--color-text);
  background: var(--color-surface);
  border: 2px solid color-mix(in srgb, var(--color-text) 30%, var(--color-surface));
  border-radius: var(--btn-radius);
}
.signup-steps-consent {
  display: grid;
  grid-template-columns: 24px 1fr;
  gap: var(--space-3);
  align-items: start;
  margin-top: var(--space-4);
  font-size: .875rem;
}
.signup-steps-consent input {
  width: 22px;
  height: 22px;
  margin: 2px 0 0;
  accent-color: var(--color-primary);
}
.signup-steps-consent a,
.signup-steps-foot a {
  color: var(--color-text);
  font-weight: 700;
  text-underline-offset: 2px;
}

.signup-steps-actions {
  display: grid;
  gap: var(--space-3);
  margin-top: var(--space-6);
}
.signup-steps-submit {
  width: 100%;
  min-height: var(--signup-steps-target);
  padding: 0 var(--space-5);
  border: 0;
  border-radius: var(--btn-radius);
  background: var(--color-primary);
  color: var(--color-on-primary);
  font-family: var(--font-body);
  font-size: 1.0625rem;
  font-weight: 700;
  cursor: pointer;
}
.signup-steps-submit:hover {
  background: var(--color-primary-dark);
}
.signup-steps-note {
  margin: 0;
  text-align: center;
  font-size: .875rem;
  color: var(--color-text-soft);
}
.signup-steps-foot {
  margin: var(--space-4) 0 0;
  padding-top: var(--space-4);
  border-top: 1px solid var(--color-rule);
  text-align: center;
  font-size: .9375rem;
  color: var(--color-text-soft);
}

.signup-steps-opt input:focus-visible + .signup-steps-opt-face,
.signup-steps-other input:focus-visible + span,
.signup-steps-field input:focus-visible,
.signup-steps-consent input:focus-visible,
.signup-steps-submit:focus-visible,
.signup-steps-consent a:focus-visible,
.signup-steps-foot a:focus-visible {
  outline: 3px solid var(--color-focus);
  outline-offset: 2px;
}

/* Built by the behaviour. Nothing below is in the authored page; the
   behaviour adds it, and these rules draw it. */
.signup-steps-card {
  scroll-margin-top: var(--space-2);
}
.signup-steps-top {
  display: grid;
  grid-template-columns: 44px 1fr auto;
  align-items: center;
  gap: var(--space-3);
  min-height: 44px;
}
.signup-steps-back {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  margin-left: calc(-1 * var(--space-2));
  padding: 0;
  background: none;
  border: 0;
  border-radius: var(--btn-radius);
  color: var(--color-text);
  cursor: pointer;
}
.signup-steps-back::before {
  content: "";
  width: 10px;
  height: 10px;
  margin-left: 4px;
  border: solid currentColor;
  border-width: 0 0 2.5px 2.5px;
  transform: rotate(45deg);
}
.signup-steps-bar {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  gap: var(--space-1);
}
.signup-steps-seg {
  position: relative;
  height: 6px;
  overflow: hidden;
  border-radius: var(--chip-radius);
  background: color-mix(in srgb, var(--color-text) 14%, var(--color-surface));
}
.signup-steps-seg::before {
  content: "";
  position: absolute;
  inset: 0 auto 0 0;
  width: 0;
  background: var(--color-primary);
}
.signup-steps-seg[data-hub-signup-done]::before {
  width: 100%;
}
.signup-steps-seg[data-hub-signup-now]::before {
  width: 35%;
}
.signup-steps-seg::after {
  content: "";
  position: absolute;
  inset: 0;
  transform: translateX(-100%);
  background: linear-gradient(90deg, transparent, color-mix(in srgb, var(--color-surface) 70%, transparent), transparent);
}
.signup-steps-count {
  font-size: .875rem;
  color: var(--color-text-soft);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* The members: faces in the card on a phone, a row beside it when wide. */
.signup-steps-members {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-height: 52px;
  margin-top: var(--space-3);
  padding: var(--space-2) var(--space-3);
  border-radius: var(--chip-radius);
  background: color-mix(in srgb, var(--color-primary) 7%, var(--color-surface));
}
.signup-steps-faces {
  display: flex;
  flex: none;
  padding-left: var(--space-2);
}
.signup-steps-face {
  width: 2.25rem;
  height: 2.25rem;
  margin-left: calc(-1 * var(--space-2));
  overflow: hidden;
  border: 2px solid var(--color-surface);
  border-radius: 50%;
  background: var(--color-surface-soft);
}
.signup-steps-face img,
.signup-steps-wall img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 1;
  object-fit: cover;
}
.signup-steps-members p {
  margin: 0;
  font-size: .875rem;
  font-weight: 700;
  line-height: 1.35;
}
.signup-steps-wall {
  margin-top: var(--space-6);
}
.signup-steps-wall-title {
  margin: 0 0 var(--space-3);
  font-size: calc(.9375rem * var(--type-scale, 1));
  font-weight: 700;
}
.signup-steps-wall ul {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--space-3);
  margin: 0;
  padding: 0;
  list-style: none;
}
.signup-steps-wall img {
  border-radius: var(--card-radius);
  background: var(--color-surface-soft);
}
.signup-steps-wall b {
  display: block;
  margin-top: var(--space-2);
  font-size: .9375rem;
}
.signup-steps-wall span {
  display: block;
  font-size: .875rem;
  color: var(--color-text-soft);
}

/* Several answers to "looking for": a square tick, not a round one. */
.signup-steps-opt input[type="checkbox"] + .signup-steps-opt-face .signup-steps-tick {
  border-radius: min(var(--btn-radius), 6px);
}

/* Interests. */
.signup-steps-chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin: 0;
  padding: 0;
  list-style: none;
}
.signup-steps-chip label {
  position: relative;
  display: block;
  cursor: pointer;
}
.signup-steps-chip input {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  border: 0;
  overflow: hidden;
  white-space: nowrap;
  clip-path: inset(50%);
}
.signup-steps-chip span {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  min-height: 44px;
  padding: 0 var(--space-4);
  background: var(--color-surface);
  border: 2px solid color-mix(in srgb, var(--color-text) 22%, var(--color-surface));
  border-radius: var(--chip-radius);
  font-size: .9375rem;
  font-weight: 600;
}
.signup-steps-chip span::before {
  content: "+";
  font-weight: 400;
  color: var(--color-text-soft);
}
.signup-steps-chip input:checked + span {
  background: var(--color-primary);
  border-color: var(--color-primary);
  color: var(--color-on-primary);
}
.signup-steps-chip input:checked + span::before {
  content: "";
  width: 5px;
  height: 9px;
  margin-right: 2px;
  border: solid currentColor;
  border-width: 0 2px 2px 0;
  transform: rotate(45deg) translateY(-1px);
}
.signup-steps-chip input:disabled + span {
  cursor: not-allowed;
  border-style: dashed;
  color: var(--color-text-soft);
}
.signup-steps-more {
  min-height: 44px;
  margin-top: var(--space-2);
  padding: 0 var(--space-1);
  background: none;
  border: 0;
  color: var(--color-text);
  font: inherit;
  font-weight: 600;
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}
.signup-steps-tally {
  margin: var(--space-3) 0 0;
  font-size: .875rem;
  color: var(--color-text-soft);
}

/* The date of birth: the reward, and the wheel where a page asks for one. */
.signup-steps-reward {
  display: inline-flex;
  margin: var(--space-3) 0 0;
  padding: var(--space-1) var(--space-3);
  border-radius: var(--chip-radius);
  background: color-mix(in srgb, var(--color-primary) 10%, var(--color-surface));
  font-size: .9375rem;
  font-weight: 700;
}
.signup-steps-wheels {
  display: grid;
  grid-template-columns: 1fr 1.4fr 1.3fr;
  gap: var(--space-2);
}
.signup-steps-wheel-col {
  display: grid;
  gap: var(--space-1);
  min-width: 0;
}
.signup-steps-wheel-label {
  font-size: .9375rem;
  font-weight: 700;
  text-align: center;
}
/* The band is the background, so it stays put while the rows scroll. Five
   44px rows show, two of them spacers above and below: keep the band's 88px
   and 132px in step with that. */
.signup-steps-wheel {
  height: 220px;
  margin: 0;
  padding: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  scroll-snap-type: y mandatory;
  scrollbar-width: none;
  list-style: none;
  border-radius: var(--btn-radius);
  background: linear-gradient(transparent 88px, color-mix(in srgb, var(--color-primary) 12%, var(--color-surface)) 88px 132px, transparent 132px);
  mask-image: linear-gradient(to bottom, transparent, var(--color-text) 30%, var(--color-text) 70%, transparent);
}
.signup-steps-wheel::-webkit-scrollbar {
  width: 0;
  height: 0;
}
.signup-steps-wheel li {
  display: grid;
  place-items: center;
  height: 44px;
  scroll-snap-align: center;
  font-size: 1.0625rem;
  font-variant-numeric: tabular-nums;
  color: var(--color-text-soft);
  cursor: pointer;
}
.signup-steps-wheel li[aria-selected="true"] {
  color: var(--color-text);
  font-weight: 700;
}

/* Errors say what is missing; a dashed edge marks where, never colour alone. */
.signup-steps-error {
  margin: var(--space-3) 0 0;
  padding: var(--space-2) var(--space-3);
  border-left: 4px solid var(--color-text);
  background: var(--color-surface-soft);
  font-size: .9375rem;
  font-weight: 600;
}
.signup-steps-opt input[aria-invalid] + .signup-steps-opt-face,
.signup-steps-field input[aria-invalid] {
  border-style: dashed;
  border-color: var(--color-text);
}

.signup-steps-next {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  width: 100%;
  min-height: var(--signup-steps-target);
  padding: 0 var(--space-5);
  border: 0;
  border-radius: var(--btn-radius);
  background: var(--color-primary);
  color: var(--color-on-primary);
  font-family: var(--font-body);
  font-size: 1.0625rem;
  font-weight: 700;
  cursor: pointer;
}
.signup-steps-next::after {
  content: "";
  width: 8px;
  height: 8px;
  border: solid currentColor;
  border-width: 2.5px 2.5px 0 0;
  transform: rotate(45deg);
}
.signup-steps-next:hover {
  background: var(--color-primary-dark);
}
.signup-steps-skip {
  justify-self: center;
  min-height: 44px;
  padding: 0 var(--space-3);
  background: none;
  border: 0;
  color: var(--color-text);
  font: inherit;
  font-weight: 600;
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}
.signup-steps-finish {
  padding: var(--space-8) var(--space-2);
  text-align: center;
}
.signup-steps-finish svg {
  display: block;
  margin: 0 auto;
  color: var(--color-primary);
}
.signup-steps-finish p {
  margin: var(--space-4) 0 0;
  font-size: 1.125rem;
  font-weight: 700;
}
.signup-steps-finish small {
  display: block;
  margin-top: var(--space-2);
  font-size: .9375rem;
  color: var(--color-text-soft);
}
.signup-steps-back:focus-visible,
.signup-steps-next:focus-visible,
.signup-steps-skip:focus-visible,
.signup-steps-more:focus-visible,
.signup-steps-wheel:focus-visible,
.signup-steps-chip input:focus-visible + span {
  outline: 3px solid var(--color-focus);
  outline-offset: 2px;
}

/* A short phone: the same card, tighter, so Next stays in view. */
@media (max-width: 59.99rem) and (max-height: 760px) {
  .signup-steps {
    --signup-steps-target: 48px;
  }
  .signup-steps-card {
    padding-top: var(--space-3);
  }
  .signup-steps-step {
    margin-top: var(--space-4);
  }
  .signup-steps-opts {
    gap: var(--space-2);
  }
  .signup-steps-actions {
    margin-top: var(--space-4);
  }
}

@media (prefers-reduced-motion: no-preference) {
  .signup-steps-opt-face,
  .signup-steps-field input,
  .signup-steps-chip span {
    transition: border-color var(--transition-fast) ease-out, background-color var(--transition-fast) ease-out, transform var(--transition-fast) ease-out;
  }
  .signup-steps-opt:active .signup-steps-opt-face,
  .signup-steps-chip:active span {
    transform: scale(.97);
  }
  .signup-steps-opt input:checked + .signup-steps-opt-face .signup-steps-tick,
  .signup-steps-chip input:checked + span {
    animation: signup-steps-pop .34s cubic-bezier(.3, 1.6, .5, 1);
  }
  .signup-steps-seg::before {
    transition: width .5s cubic-bezier(.2, .8, .2, 1);
  }
  @keyframes signup-steps-pop {
    from { transform: scale(.6); }
  }
}

/* Wide: the headline and its sentence beside the card. */
@media (min-width: 60rem) {
  .signup-steps {
    padding-block: var(--space-8) var(--space-12);
  }
  .signup-steps-inner {
    grid-template-columns: minmax(0, 1fr) minmax(0, 27rem);
    gap: var(--space-8);
    align-items: start;
  }
  .signup-steps-sub {
    margin-top: var(--space-4);
    font-size: 1.125rem;
  }
  .signup-steps-card {
    padding: var(--space-5) var(--space-6) var(--space-6);
  }
}
/* === /pattern signup-steps@2 === */

/* === pattern masthead-nav@12 (library v229; appended by page_assemble.py -- adopt a newer version by replacing this block, never by adding a second) === */
/* masthead-nav - tokens only, selectors prefixed. The menu inside
   .masthead-nav-links is styled by structure - ul, li, a - so the list the
   platform generates for {{menu.navigation}} and a list written by hand take
   the same rules. */

/* Each ground names its own inks, and every rule below reads the pair rather
   than a token, so nothing here knows which ground it is on. */
.masthead-nav--plain {
  --masthead-nav-ground: var(--color-bg);
  --masthead-nav-ink: var(--color-text);
  --masthead-nav-edge: var(--color-rule);
  --masthead-nav-cta-face: var(--color-primary);
  --masthead-nav-cta-ink: var(--color-on-primary);
  --masthead-nav-panel-face: var(--color-surface);
  --masthead-nav-panel-ink: var(--color-text);
  --masthead-nav-ring: var(--color-focus);
}
.masthead-nav--soft {
  --masthead-nav-ground: var(--color-surface-soft);
  --masthead-nav-ink: var(--color-text);
  --masthead-nav-edge: var(--color-rule);
  --masthead-nav-cta-face: var(--color-primary);
  --masthead-nav-cta-ink: var(--color-on-primary);
  --masthead-nav-panel-face: var(--color-surface);
  --masthead-nav-panel-ink: var(--color-text);
  --masthead-nav-ring: var(--color-focus);
}
.masthead-nav--brand {
  --masthead-nav-ground: var(--color-primary);
  --masthead-nav-ink: var(--color-on-primary);
  --masthead-nav-edge: color-mix(in srgb, var(--color-on-primary) 35%, transparent);
  --masthead-nav-cta-face: var(--color-on-primary);
  --masthead-nav-cta-ink: var(--color-primary);
  --masthead-nav-panel-face: var(--color-primary);
  --masthead-nav-panel-ink: var(--color-on-primary);
  --masthead-nav-ring: var(--color-on-primary);
}

/* ---- the bar ---- */
/* One number for every tap target here, and for the room the drawer keeps.
   Clipped sideways, never scrolled: a faded submenu is laid out where it
   will open, and one past the edge would otherwise widen the page. */
.masthead-nav {
  --masthead-nav-tap: 2.75rem;
  background: var(--masthead-nav-ground);
  color: var(--masthead-nav-ink);
  border-block-end: 1px solid var(--masthead-nav-edge);
  overflow-x: clip;
}
/* edge: every rung keeps the 1px border and changes only what paints it, so
   the bar is the same height on all three and --page-header-height holds. */
.masthead-nav--rule {
  border-block-end-color: var(--masthead-nav-edge);
}
.masthead-nav--shadow {
  border-block-end-color: transparent;
  box-shadow: var(--card-shadow);
}
.masthead-nav--flush {
  border-block-end-color: transparent;
}
.masthead-nav--static {
  position: static;
}
/* The z-index orders the drawer's scrim, panel and button against each other
   rather than against the page. `sticky` is no containing block for a fixed
   child, so the drawer still pins to the viewport. */
.masthead-nav--pinned,
.masthead-nav--compact {
  position: sticky;
  inset-block-start: 0;
  z-index: 40;
}
/* The containing block for the small-screen menu and for the controls when
   they are parked in the corner on --centred. */
.masthead-nav-inner {
  position: relative;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3);
  max-width: var(--container-max);
  margin-inline: auto;
  padding: var(--space-3) var(--space-4);
}
.masthead-nav-mark {
  display: flex;
  align-items: center;
  flex: 0 1 auto;
  min-width: 0;
  margin-inline-end: auto;
}
/* The set height is the floor: `height: auto` under a `max-height` alone
   resolves a viewBox-only SVG to 0x0. object-fit stops the cap distorting it. */
.masthead-nav-logo {
  display: block;
  width: auto;
  height: var(--logo-height, 2.75rem);
  max-width: 100%;
  object-fit: contain;
}
/* mark: how the brand mark meets the ground behind it. */
.masthead-nav--direct .masthead-nav-mark {
  padding: 0;
}
.masthead-nav--plate .masthead-nav-mark {
  padding: var(--space-2) var(--space-3);
  border-radius: var(--card-radius);
  background: var(--color-bg);
}
.masthead-nav--mono .masthead-nav-logo {
  filter: brightness(0) invert(1);
}

/* ---- the small-screen disclosure ---- */
.masthead-nav-disclosure {
  flex: 0 0 auto;
}
.masthead-nav-toggle {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  min-height: var(--masthead-nav-tap);
  padding-inline: var(--space-3);
  border: 1px solid var(--masthead-nav-edge);
  border-radius: var(--btn-radius);
  color: var(--masthead-nav-ink);
  font-family: var(--font-heading);
  font-size: calc(0.9375rem * var(--type-scale, 1));
  font-weight: var(--weight-display, 700);
  cursor: pointer;
  /* Both lines are needed to drop the default triangle. */
  list-style: none;
}
.masthead-nav-toggle::-webkit-details-marker {
  display: none;
}
/* Three bars: the element is the middle one, the pseudo-elements the others.
   The fold into a cross is a state change, so reduced motion keeps it. */
.masthead-nav-toggle-icon {
  position: relative;
  flex: 0 0 auto;
  width: var(--masthead-nav-bar-width, 1rem);
  height: var(--masthead-nav-bar, 2px);
  background: currentColor;
}
.masthead-nav-toggle-icon::before,
.masthead-nav-toggle-icon::after {
  content: "";
  position: absolute;
  inset-inline: 0;
  height: var(--masthead-nav-bar, 2px);
  background: currentColor;
}
.masthead-nav-toggle-icon::before {
  top: calc(-1 * var(--masthead-nav-bar-gap, 5px));
}
.masthead-nav-toggle-icon::after {
  top: var(--masthead-nav-bar-gap, 5px);
}
.masthead-nav-disclosure[open] .masthead-nav-toggle-icon {
  background: transparent;
}
.masthead-nav-disclosure[open] .masthead-nav-toggle-icon::before {
  top: 0;
  transform: rotate(45deg);
}
.masthead-nav-disclosure[open] .masthead-nav-toggle-icon::after {
  top: 0;
  transform: rotate(-45deg);
}
/* burger: how the bars are drawn. Every rung folds into the same cross. */
.masthead-nav--three {
  --masthead-nav-bar: 2px;
  --masthead-nav-bar-gap: 5px;
}
.masthead-nav--two {
  --masthead-nav-bar-gap: 4px;
}
.masthead-nav--two .masthead-nav-toggle-icon {
  background: transparent;
}
.masthead-nav--bold {
  --masthead-nav-bar: 3px;
  --masthead-nav-bar-gap: 6px;
  --masthead-nav-bar-width: 1.25rem;
}
/* boxed: the element is the shape, a tap target square in the join
   control's own pair, and draws the middle bar as a centred gradient. */
.masthead-nav--boxed .masthead-nav-toggle {
  border: 0;
}
.masthead-nav--boxed.masthead-nav--icon .masthead-nav-toggle {
  padding-inline: 0;
}
.masthead-nav--boxed .masthead-nav-toggle-icon {
  width: var(--masthead-nav-tap);
  height: var(--masthead-nav-tap);
  border-radius: var(--btn-radius);
  color: var(--masthead-nav-cta-ink);
  background: linear-gradient(currentColor, currentColor) center / 1rem 2px no-repeat,
              var(--masthead-nav-cta-face);
}
.masthead-nav--boxed .masthead-nav-toggle-icon::before,
.masthead-nav--boxed .masthead-nav-toggle-icon::after {
  inset-inline: calc(50% - 0.5rem);
}
.masthead-nav--boxed .masthead-nav-toggle-icon::before {
  top: calc(50% - 6px);
}
.masthead-nav--boxed .masthead-nav-toggle-icon::after {
  top: calc(50% + 4px);
}
.masthead-nav--boxed .masthead-nav-disclosure[open] .masthead-nav-toggle-icon {
  background: var(--masthead-nav-cta-face);
}
.masthead-nav--boxed .masthead-nav-disclosure[open] .masthead-nav-toggle-icon::before,
.masthead-nav--boxed .masthead-nav-disclosure[open] .masthead-nav-toggle-icon::after {
  top: calc(50% - 1px);
}
/* toggle=icon: the word leaves the box, never the accessibility tree - never
   display: none. With no word in it the box needs a square floor, and the
   bars stand bare: no frame, the tap area and the focus ring kept. */
.masthead-nav--icon .masthead-nav-toggle {
  justify-content: center;
  min-width: var(--masthead-nav-tap);
  border: 0;
}
.masthead-nav--icon .masthead-nav-toggle-text {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  clip-path: inset(50%);
  white-space: nowrap;
}

/* ---- the menu: whatever list sits inside the nav landmark ---- */
.masthead-nav-links ul {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  margin: 0;
  padding: 0;
  list-style: none;
}
.masthead-nav-links li {
  margin: 0;
}
.masthead-nav-links a,
.masthead-nav-links button {
  display: flex;
  align-items: center;
  min-height: var(--masthead-nav-tap);
  margin: 0;
  padding: var(--space-2) 0;
  border: 0;
  background: none;
  color: inherit;
  font-family: var(--font-heading);
  font-size: calc(1rem * var(--type-scale, 1));
  font-weight: var(--weight-display, 700);
  text-align: start;
  text-decoration: none;
  cursor: pointer;
}
.masthead-nav-links a[href]:hover,
.masthead-nav-links button:hover {
  text-decoration: underline;
  text-underline-offset: 0.3em;
}
/* A parent with children and no URL of its own arrives as an <a> with no
   href. It is a label, not a link, so it must not offer a pointer. */
.masthead-nav-links li:has(> ul) > a:not([href]) {
  cursor: default;
}
.masthead-nav-links ul ul {
  padding-inline-start: var(--space-4);
  border-inline-start: 1px solid var(--masthead-nav-edge);
}
.masthead-nav-links ul ul a,
.masthead-nav-links ul ul button {
  font-size: calc(0.9375rem * var(--type-scale, 1));
  font-weight: 500;
}

/* ---- the tray: the menu and the controls, both inside the disclosure ---- */
/* No `display` here: one would force the tray open on --panel, which opens
   and shuts natively. Each rung turns it on where it wants it laid out. */
.masthead-nav-tray {
  flex-direction: column;
  gap: var(--space-4);
}

/* ---- login and join ---- */
.masthead-nav-controls {
  display: flex;
  align-items: center;
  gap: var(--space-4);
}
.masthead-nav-login {
  display: flex;
  align-items: center;
  color: inherit;
  font-family: var(--font-heading);
  font-size: calc(0.9375rem * var(--type-scale, 1));
  font-weight: var(--weight-display, 700);
  text-decoration: none;
  padding-block: var(--space-2);
}
.masthead-nav-login:hover {
  text-decoration: underline;
  text-underline-offset: 0.3em;
}
.masthead-nav-join {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 1 1 auto;
  min-height: var(--masthead-nav-tap);
  padding-inline: var(--space-5);
  border-radius: var(--btn-radius);
  background: var(--masthead-nav-cta-face);
  color: var(--masthead-nav-cta-ink);
  font-family: var(--font-heading);
  font-size: calc(0.9375rem * var(--type-scale, 1));
  font-weight: var(--weight-display, 700);
  text-decoration: none;
}
.masthead-nav-join:hover {
  text-decoration: underline;
  text-underline-offset: 0.2em;
}
/* The ring is the ground's own, so one rule is right on all three. */
.masthead-nav a:focus-visible,
.masthead-nav button:focus-visible,
.masthead-nav summary:focus-visible {
  outline: 3px solid var(--masthead-nav-ring);
  outline-offset: 2px;
}

/* ---- small screens ---- */
@media (max-width: 59.99rem) {
  /* A wide wordmark at --logo-height is most of a phone across. Without this
     cap it takes the whole row and pushes the menu button onto a second one. */
  .masthead-nav-mark {
    max-width: 45%;
    min-width: var(--masthead-nav-tap);
    min-height: var(--masthead-nav-tap);
  }
  /* A wordless button is one tap wide, so the mark may take the rest of the
     row. --row has no button and --minimal a wider join control: both 45%. */
  .masthead-nav--drawer.masthead-nav--icon:not(.masthead-nav--minimal) .masthead-nav-mark,
  .masthead-nav--panel.masthead-nav--icon:not(.masthead-nav--minimal) .masthead-nav-mark {
    max-width: calc(100% - var(--masthead-nav-tap) - var(--space-3));
  }
  /* A long label ellipsises; border-box holds the padding inside the cap. */
  .masthead-nav-toggle {
    box-sizing: border-box;
    max-width: 100%;
  }
  .masthead-nav--labelled .masthead-nav-toggle-text {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  /* One button, two words, and only ever one of them in the box. */
  .masthead-nav-toggle-text--close {
    display: none;
  }
  .masthead-nav-disclosure[open] .masthead-nav-toggle-text {
    display: none;
  }
  .masthead-nav-disclosure[open] .masthead-nav-toggle-text--close {
    display: inline;
  }
  /* The controls lead the sheet, and follow the menu in the markup so the
     bar is read in the order it is drawn. --row has no sheet and is left. */
  .masthead-nav--drawer .masthead-nav-controls,
  .masthead-nav--panel .masthead-nav-controls {
    order: -1;
    flex-direction: column;
    align-items: stretch;
    gap: var(--space-3);
  }
  /* A row in a menu here, not a word in the bar: it takes a menu target. */
  .masthead-nav-login {
    min-height: var(--masthead-nav-tap);
  }
  /* menu-side moves the button, and the drawer it opens, to the same edge.
     Scoped to the rungs that HAVE a button: on --row the disclosure is the
     whole menu, so ordering it puts the navigation above the brand. */
  .masthead-nav--drawer.masthead-nav--side-end .masthead-nav-disclosure,
  .masthead-nav--panel.masthead-nav--side-end .masthead-nav-disclosure {
    order: 0;
  }
  .masthead-nav--drawer.masthead-nav--side-start .masthead-nav-disclosure,
  .masthead-nav--panel.masthead-nav--side-start .masthead-nav-disclosure {
    order: -1;
  }
  /* No start margin: 45% and 55% add up exactly, so anything added breaks
     the line and drops the mark to a second row. */
  .masthead-nav--side-start .masthead-nav-mark {
    margin-inline-end: auto;
  }
  /* A join control stretched over a tablet is a bar, not a button. */
  /* Definite, not max-width: an auto margin here cancels the stretch. */
  .masthead-nav--panel .masthead-nav-controls {
    width: min(20rem, 100%);
  }
  .masthead-nav--panel.masthead-nav--menu-end .masthead-nav-controls {
    align-self: flex-end;
  }
}

/* menu=drawer: a panel fixed to the inline-end edge, over a dimmed page. */
@media (max-width: 59.99rem) {
  /* The drawer is fixed to the viewport and the button that shuts it is not,
     so a scroll parts them and leaves an open menu with no way out. Pinned on
     both sticky rungs: this is not the sticky axis and does not fold into it. */
  .masthead-nav--drawer:has(.masthead-nav-disclosure[open]) {
    position: sticky;
    inset-block-start: 0;
    z-index: 40;
  }
  /* 45% for the mark and the rest for the button, gap included, so the two
     share one row: flexbox breaks lines before it shrinks anything. */
  .masthead-nav--drawer .masthead-nav-disclosure,
  .masthead-nav--panel .masthead-nav-disclosure {
    max-width: calc(55% - var(--space-3));
  }
  /* Laid out open or shut, so it has somewhere to slide FROM. Engines hide a
     closed <details> two ways, one unreachable from the child, so both are
     needed. `visibility` keeps it out of the tab order - never use opacity. */
  .masthead-nav--drawer .masthead-nav-tray {
    display: flex;
  }
  .masthead-nav--drawer .masthead-nav-disclosure::details-content {
    content-visibility: visible;
    block-size: auto;
  }
  .masthead-nav--drawer .masthead-nav-tray {
    position: fixed;
    inset-block: 0;
    z-index: 41;
    width: min(20rem, 82vw);
    overflow-y: auto;
    overscroll-behavior: contain;
    /* Block-start padding is the header's first row, computed - the button
       sits on the drawer, so anything less puts it over the first item. */
    padding: calc(var(--space-3)
                  + max(var(--masthead-nav-tap), var(--logo-height, 2.75rem))
                  + var(--space-4))
             var(--space-4) var(--space-6);
    background: var(--masthead-nav-panel-face);
    color: var(--masthead-nav-panel-ink);
    box-shadow: var(--card-shadow);
    visibility: hidden;
  }
  /* `translate` is the one place a logical property cannot carry the meaning,
     so each side states its own, and its own :dir(rtl). */
  .masthead-nav--drawer.masthead-nav--side-end .masthead-nav-tray {
    inset-inline-end: 0;
    border-inline-start: 1px solid var(--masthead-nav-edge);
    translate: 100% 0;
  }
  .masthead-nav--drawer.masthead-nav--side-end .masthead-nav-tray:dir(rtl) {
    translate: -100% 0;
  }
  .masthead-nav--drawer.masthead-nav--side-start .masthead-nav-tray {
    inset-inline-start: 0;
    border-inline-end: 1px solid var(--masthead-nav-edge);
    translate: -100% 0;
  }
  .masthead-nav--drawer.masthead-nav--side-start .masthead-nav-tray:dir(rtl) {
    translate: 100% 0;
  }
  .masthead-nav--drawer .masthead-nav-disclosure[open] .masthead-nav-tray {
    visibility: visible;
    translate: none;
  }
  /* The backdrop belongs to the disclosure: in the panel it would be inside
     the box it has to sit behind. */
  .masthead-nav--drawer .masthead-nav-disclosure::before {
    content: "";
    position: fixed;
    inset: 0;
    z-index: 40;
    background: color-mix(in srgb, var(--color-scrim) 62%, transparent);
    visibility: hidden;
    opacity: 0;
  }
  .masthead-nav--drawer .masthead-nav-disclosure[open]::before {
    visibility: visible;
    opacity: 1;
  }
  /* The button stays where it was pressed, above both the backdrop and the
     panel. The panel's block-start padding keeps the first item out of it. */
  .masthead-nav--drawer .masthead-nav-disclosure[open] .masthead-nav-toggle {
    position: relative;
    z-index: 42;
  }
}

/* menu=panel: the menu drops out of the button, over what is below. */
@media (max-width: 59.99rem) {
  /* A shut <details> contains its own layout, so this sheet is laid out
     against the button until it opens - `visibility` keeps that box out. */
  .masthead-nav--panel .masthead-nav-tray {
    position: absolute;
    inset-inline: 0;
    top: 100%;
    z-index: 20;
    max-height: 70vh; /* vh twin */
    max-height: 70svh;
    overflow-y: auto;
    padding: var(--space-4);
    background: var(--masthead-nav-ground);
    border-block-end: 1px solid var(--masthead-nav-edge);
    box-shadow: var(--card-shadow);
    visibility: hidden;
  }
  /* Scoped to [open], unlike the drawer's: this sheet does not slide, and a
     `display` that applied while shut would hold it open. */
  .masthead-nav--panel .masthead-nav-disclosure[open] .masthead-nav-tray {
    display: flex;
    visibility: visible;
  }
}

/* ---- menu=row: no button, the menu is a scrolling row beside the mark ---- */
@media (max-width: 59.99rem) {
  .masthead-nav--row .masthead-nav-toggle {
    display: none;
  }
  /* Both declarations open the panel: engines hide a closed <details> in two
     different ways, and one of them cannot be reached from the child. */
  .masthead-nav--row .masthead-nav-tray {
    display: flex;
  }
  .masthead-nav--row .masthead-nav-disclosure::details-content {
    content-visibility: visible;
    block-size: auto;
  }
  .masthead-nav--row .masthead-nav-mark {
    margin-inline-end: 0;
  }
  .masthead-nav--row .masthead-nav-disclosure {
    flex: 1 1 auto;
    min-width: 0;
  }
  .masthead-nav--row .masthead-nav-tray {
    gap: var(--space-2);
  }
  .masthead-nav--row .masthead-nav-links {
    min-width: 0;
  }
  .masthead-nav--row .masthead-nav-join {
    flex: 0 1 auto;
  }
  .masthead-nav--row .masthead-nav-links > ul {
    flex-direction: row;
    flex-wrap: nowrap;
    align-items: center;
    gap: var(--space-4);
    overflow-x: auto;
    scrollbar-width: none;
  }
  .masthead-nav--row .masthead-nav-links > ul::-webkit-scrollbar {
    display: none;
  }
  .masthead-nav--row .masthead-nav-links > ul > li {
    flex: 0 0 auto;
  }
  /* One row, so a submenu cannot nest under its parent; its children run on
     beside it instead. */
  .masthead-nav--row .masthead-nav-links li:has(> ul) {
    display: flex;
    align-items: center;
    gap: var(--space-4);
  }
  .masthead-nav--row .masthead-nav-links ul ul {
    flex-direction: row;
    gap: var(--space-4);
    padding-inline-start: var(--space-4);
  }
}

/* ---- wide screens: the menu is always open and sits in the bar ---- */
@media (min-width: 60rem) {
  .masthead-nav-toggle {
    display: none;
  }
  /* Both declarations open the panel: engines hide a closed <details> in two
     different ways, and one of them cannot be reached from the child. */
  .masthead-nav-tray {
    display: flex;
  }
  .masthead-nav-disclosure::details-content {
    content-visibility: visible;
    block-size: auto;
  }
  .masthead-nav-tray {
    flex-direction: row;
    align-items: center;
    gap: var(--space-6);
  }
  .masthead-nav-links {
    flex: 1 1 auto;
    min-width: 0;
  }
  .masthead-nav-inner {
    flex-wrap: nowrap;
    gap: var(--space-6);
    padding-block: var(--space-4);
  }
  /* The mark must not shrink here: the logo is sized from its height at this
     width, so a shrinking box would let the image spill over the first menu
     item instead of taking room from it. */
  .masthead-nav-mark {
    flex: 0 0 auto;
  }
  .masthead-nav-logo {
    max-width: none;
  }
  .masthead-nav-disclosure {
    flex: 1 1 auto;
    min-width: 0;
  }
  .masthead-nav-controls {
    flex: 0 0 auto;
  }
  .masthead-nav-join {
    flex: 0 0 auto;
  }
  .masthead-nav-links > ul {
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-2) var(--space-5);
  }
  .masthead-nav-links > ul > li {
    position: relative;
  }
  .masthead-nav-links > ul > li > a,
  .masthead-nav-links > ul > li > button {
    white-space: nowrap;
  }
  /* The tap floor holds here too: 1024 is a tablet held sideways. Padding
     inside it, so a one-row bar keeps the join control's height. */
  .masthead-nav-mark,
  .masthead-nav-login,
  .masthead-nav-links > ul > li > a,
  .masthead-nav-links > ul > li > button {
    box-sizing: border-box;
    min-width: var(--masthead-nav-tap);
    min-height: var(--masthead-nav-tap);
  }
  /* Faded rather than removed: a submenu taken out of the layout cannot be
     focused, so a keyboard could never open it. */
  .masthead-nav-links ul ul {
    position: absolute;
    top: 100%;
    inset-inline-start: 0;
    z-index: 30;
    min-width: 12rem;
    padding: var(--space-2);
    border: var(--card-border);
    border-inline-start: var(--card-border);
    border-radius: var(--card-radius);
    background: var(--masthead-nav-panel-face);
    color: var(--masthead-nav-panel-ink);
    box-shadow: var(--card-shadow);
    opacity: 0;
    pointer-events: none;
  }
  .masthead-nav-links > ul > li:hover > ul,
  .masthead-nav-links > ul > li:focus-within > ul {
    opacity: 1;
    pointer-events: auto;
  }
  /* The last two items sit nearest the edge, so their panels hang from
     their end edge instead. */
  .masthead-nav-links > ul > li:nth-last-child(-n + 2) > ul {
    inset-inline-start: auto;
    inset-inline-end: 0;
  }
  .masthead-nav-links ul ul a,
  .masthead-nav-links ul ul button {
    min-height: var(--masthead-nav-tap);
    padding-inline: var(--space-2);
  }
  /* A third level sits inside its parent's panel rather than beside it. */
  .masthead-nav-links ul ul ul {
    position: static;
    min-width: 0;
    padding: 0 0 0 var(--space-3);
    border: 0;
    border-inline-start: 1px solid var(--masthead-nav-edge);
    border-radius: 0;
    box-shadow: none;
    opacity: 1;
    pointer-events: auto;
  }
  /* A chevron marks the items that carry children. */
  .masthead-nav-links > ul > li:has(> ul) > a::after,
  .masthead-nav-links > ul > li:has(> ul) > button::after {
    content: "";
    display: inline-block;
    width: 0.4em;
    height: 0.4em;
    margin-inline-start: var(--space-2);
    border-inline-end: 2px solid currentColor;
    border-block-end: 2px solid currentColor;
    transform: translateY(-0.15em) rotate(45deg);
  }

  /* overflow: what happens to items that do not fit the row. */
  .masthead-nav--wrap .masthead-nav-links > ul {
    flex-wrap: wrap;
  }
  /* --more folds the items past the room into a last item the behaviour
     library builds. Without the library this rung is --wrap, so the property
     below is the whole switch. */
  .masthead-nav--more .masthead-nav-links > ul {
    --hub-overflow: more;
  }
  .masthead-nav--scroll .masthead-nav-links > ul {
    flex-wrap: nowrap;
    overflow-x: auto;
    scrollbar-width: none;
    padding: var(--space-2) var(--space-3);
    mask-image: linear-gradient(to right, transparent, currentColor var(--space-3),
                                currentColor calc(100% - var(--space-3)), transparent);
  }
  .masthead-nav--scroll .masthead-nav-links > ul::-webkit-scrollbar {
    display: none;
  }
  .masthead-nav--scroll .masthead-nav-links > ul > li {
    flex: 0 0 auto;
  }
  /* A scrolling row clips anything that pops out of it, so its submenus run
     on beside their parent instead. */
  .masthead-nav--scroll .masthead-nav-links > ul > li:has(> ul) {
    display: flex;
    align-items: center;
    gap: var(--space-4);
  }
  .masthead-nav--scroll .masthead-nav-links ul ul {
    position: static;
    flex-direction: row;
    min-width: 0;
    padding: 0 0 0 var(--space-3);
    border: 0;
    border-inline-start: 1px solid var(--masthead-nav-edge);
    border-radius: 0;
    background: none;
    color: inherit;
    box-shadow: none;
    opacity: 1;
    pointer-events: auto;
  }
  .masthead-nav--scroll .masthead-nav-links > ul > li:has(> ul) > a::after,
  .masthead-nav--scroll .masthead-nav-links > ul > li:has(> ul) > button::after {
    content: none;
  }

  /* submenu: --dropdown is the panel under its own item, above. --mega is one
     panel the width of the bar, its items in columns. */
  .masthead-nav--dropdown .masthead-nav-links > ul > li {
    position: relative;
  }
  .masthead-nav--mega .masthead-nav-links > ul > li {
    position: static;
  }
  .masthead-nav--mega .masthead-nav-links > ul > li > ul {
    display: block;
    inset-inline: 0;
    min-width: 0;
    padding: var(--space-5) var(--space-6);
    border-radius: 0 0 var(--card-radius) var(--card-radius);
    columns: 12rem;
    column-gap: var(--space-6);
  }
  .masthead-nav--mega .masthead-nav-links > ul > li > ul > li {
    break-inside: avoid;
  }
  .masthead-nav--mega .masthead-nav-links > ul > li > ul a,
  .masthead-nav--mega .masthead-nav-links > ul > li > ul button {
    padding-inline: 0;
  }

  /* layout=inline - mark, menu, controls, one row. */
  .masthead-nav--inline .masthead-nav-inner {
    justify-content: space-between;
  }
  .masthead-nav--inline .masthead-nav-links > ul {
    justify-content: flex-start;
  }

  /* layout=centred - mark on its own line, menu centred under it, controls
     parked in the corner so the mark stays optically centred. */
  .masthead-nav--centred .masthead-nav-inner {
    flex-wrap: wrap;
    gap: var(--space-3);
    padding-block: var(--space-5);
  }
  .masthead-nav--centred .masthead-nav-mark {
    margin-inline: auto;
  }
  .masthead-nav--centred .masthead-nav-disclosure {
    flex: 1 0 100%;
  }
  /* Centred by auto margins on the end items, not justify-content: a row
     wider than its box centres by pushing its first items off the left edge,
     where no scroll can reach them. */
  .masthead-nav--centred .masthead-nav-links > ul > li:first-child {
    margin-inline-start: auto;
  }
  .masthead-nav--centred .masthead-nav-links > ul > li:last-child {
    margin-inline-end: auto;
  }
  .masthead-nav--centred .masthead-nav-controls {
    position: absolute;
    inset-block-start: var(--space-5);
    inset-inline-end: var(--space-4);
  }

  /* Last in the block on purpose: it has to outrank --centred's taller
     padding, and the two selectors weigh the same. */
  .masthead-nav--pinned .masthead-nav-inner,
  .masthead-nav--compact .masthead-nav-inner {
    padding-block: var(--space-3);
  }
  .masthead-nav--pinned.masthead-nav--centred .masthead-nav-controls,
  .masthead-nav--compact.masthead-nav--centred .masthead-nav-controls {
    inset-block-start: var(--space-3);
  }
}

/* sticky=compact: once the page has scrolled, the bar tightens and the mark
   comes down a fifth. The behaviour library sets the attribute. */
.masthead-nav--compact[data-hub-shrink="scrolled"] .masthead-nav-inner {
  padding-block: var(--space-2);
}
.masthead-nav--compact[data-hub-shrink="scrolled"] .masthead-nav-logo {
  height: calc(var(--logo-height, 2.75rem) * 0.8);
}

/* ---- nav=minimal: no menu, the mark and the controls at every width ---- */
.masthead-nav--full .masthead-nav-links {
  display: block;
}
.masthead-nav--minimal .masthead-nav-links {
  display: none;
}
.masthead-nav--minimal .masthead-nav-tray {
  justify-content: flex-end;
}
/* These outweigh the menu rungs' rules, which name two classes and the
   tray: this rung has no sheet to slide, drop or scroll. */
@media (max-width: 59.99rem) {
  .masthead-nav--minimal .masthead-nav-toggle {
    display: none;
  }
  /* The join control does not shorten as a menu button's word does, so the
     row never breaks here: the mark gives way instead. */
  .masthead-nav--minimal .masthead-nav-inner {
    flex-wrap: nowrap;
  }
  .masthead-nav--minimal .masthead-nav-inner .masthead-nav-disclosure {
    order: 0;
    flex: 0 0 auto;
    max-width: none;
  }
  .masthead-nav--minimal .masthead-nav-inner .masthead-nav-disclosure::details-content {
    content-visibility: visible;
    block-size: auto;
  }
  .masthead-nav--minimal .masthead-nav-inner .masthead-nav-disclosure::before {
    content: none;
  }
  .masthead-nav--minimal .masthead-nav-disclosure .masthead-nav-tray {
    display: flex;
    position: static;
    width: auto;
    max-height: none;
    padding: 0;
    border: 0;
    background: none;
    box-shadow: none;
    visibility: visible;
    translate: none;
  }
  .masthead-nav--minimal .masthead-nav-controls {
    order: 0;
    width: auto;
    flex-direction: row;
    align-items: center;
  }
  /* The join control is the point of a page with no menu; the login link
     returns above 60rem. */
  .masthead-nav--minimal .masthead-nav-login {
    display: none;
  }
}

/* ---- menu-align: which edge the small-screen menu is set against ----
   Below 60rem only: above it `layout` already decides where the menu sits. */
@media (max-width: 59.99rem) {
  .masthead-nav--menu-start .masthead-nav-tray {
    text-align: start;
  }
  .masthead-nav--menu-start .masthead-nav-links a,
  .masthead-nav--menu-start .masthead-nav-links button,
  .masthead-nav--menu-start .masthead-nav-login {
    justify-content: flex-start;
  }
  .masthead-nav--menu-centre .masthead-nav-tray {
    text-align: center;
  }
  .masthead-nav--menu-centre .masthead-nav-links a,
  .masthead-nav--menu-centre .masthead-nav-links button,
  .masthead-nav--menu-centre .masthead-nav-login {
    justify-content: center;
  }
  .masthead-nav--menu-centre .masthead-nav-links ul ul {
    align-items: center;
    padding-inline: 0;
    border-inline: none;
  }
  .masthead-nav--menu-end .masthead-nav-tray {
    text-align: end;
  }
  .masthead-nav--menu-end .masthead-nav-links a,
  .masthead-nav--menu-end .masthead-nav-links button,
  .masthead-nav--menu-end .masthead-nav-login {
    justify-content: flex-end;
  }
  /* The rule moves with the items, or it is left down the empty side. */
  .masthead-nav--menu-end .masthead-nav-links ul ul {
    align-items: flex-end;
    padding-inline: 0 var(--space-4);
    border-inline: none;
    border-inline-end: 1px solid var(--masthead-nav-edge);
  }
}

/* No easing keyword follows --transition-fast below: brands ship that token
   with an easing in it, and a second keyword makes the declaration invalid. */
@media (prefers-reduced-motion: no-preference) {
  .masthead-nav-toggle-icon,
  .masthead-nav-toggle-icon::before,
  .masthead-nav-toggle-icon::after {
    transition: transform var(--transition-fast),
                background var(--transition-fast),
                top var(--transition-fast);
  }
  .masthead-nav-links ul ul {
    transition: opacity var(--transition-fast);
  }
  /* `visibility` is in the list so the panel stays on screen while it leaves. */
  .masthead-nav--drawer .masthead-nav-tray {
    transition: translate var(--transition-fast),
                visibility var(--transition-fast);
  }
  .masthead-nav--drawer .masthead-nav-disclosure::before {
    transition: opacity var(--transition-fast),
                visibility var(--transition-fast);
  }
  .masthead-nav--compact .masthead-nav-inner {
    transition: padding var(--transition-fast);
  }
  .masthead-nav--compact .masthead-nav-logo {
    transition: height var(--transition-fast);
  }
}
/* Belt and braces if a brand reintroduces a transition on these. */
@media (prefers-reduced-motion: reduce) {
  .masthead-nav-toggle-icon,
  .masthead-nav-toggle-icon::before,
  .masthead-nav-toggle-icon::after {
    transition: none;
  }
  .masthead-nav-links ul ul {
    transition: none;
  }
  .masthead-nav--drawer .masthead-nav-tray,
  .masthead-nav--drawer .masthead-nav-disclosure::before,
  .masthead-nav--compact .masthead-nav-inner,
  .masthead-nav--compact .masthead-nav-logo {
    transition: none;
  }
}
/* === /pattern masthead-nav@12 === */

/* === pattern signup-card@8 (library v295; appended by page_assemble.py -- adopt a newer version by replacing this block, never by adding a second) === */
/* signup-card v8 - tokens only, selectors prefixed */
/* The card sits in an opener's call-to-action place: it takes a width of its
   own and leaves the page's layout to the opener. */
.signup-card {
  /* Answer rows: over the 44px floor, sized for a thumb. */
  --signup-card-target: 56px;
  width: 100%;
  max-width: 24rem;
  text-align: left;
}
.signup-card-form {
  min-width: 0;
  margin: 0;
  padding: var(--space-4) var(--space-4) var(--space-5);
  background: var(--color-surface);
  color: var(--color-text);
  border: var(--card-border);
  border-radius: var(--card-radius);
  box-shadow: var(--card-shadow);
}
/* --color-text, not --color-heading: a heading on a card is not on the page ground. */
.signup-card-title,
.signup-card-q {
  margin: 0;
  padding: 0;
  font-family: var(--font-heading);
  font-weight: var(--weight-display, 700);
  line-height: calc(1.2 * var(--heading-leading, 1));
  letter-spacing: calc(-0.005em + var(--heading-tracking, 0) * 1em);
  color: var(--color-text);
}
@supports (line-height: 1cap) {
  .signup-card-title,
  .signup-card-q {
    line-height: calc(max(1.2em, 1.45cap) * var(--heading-leading, 1));
  }
}
.signup-card-title {
  font-size: calc(clamp(1.375rem, 1.2rem + .8vw, 1.75rem) * var(--type-scale, 1));
}
.signup-card-q {
  margin-bottom: var(--space-3);
  font-size: calc(1.1875rem * var(--type-scale, 1));
}
/* A new step's question takes focus for screen readers; it is not a control,
so it draws no ring. */
.signup-card-q:focus {
  outline: none;
}
.signup-card-step {
  min-width: 0;
  margin: var(--space-6) 0 0;
  padding: 0;
  border: 0;
}
.signup-card-title + .signup-card-step {
  margin-top: var(--space-4);
}
.signup-card-help {
  margin: calc(-1 * var(--space-2)) 0 var(--space-3);
  font-size: .9375rem;
  color: var(--color-text-soft);
}
/* Answers: the input is inside its label, so the whole row is the target. */
.signup-card-opts {
  display: grid;
  gap: var(--space-3);
  margin: 0;
  padding: 0;
  list-style: none;
}
/* Two "I am" answers side by side while both fit; an answer whose longest
   word is wider than half the card takes the whole row, and so does the
   other. width: 100% is not the width: it caps the automatic minimum at the
   row, so a word wider than the row breaks inside its tile. Each half gives
   up half the gap and 1px, or two halves rounded up wrap. */
.signup-card-opts--two {
  display: flex;
  flex-wrap: wrap;
}
.signup-card-opt {
  min-width: 0;
}
.signup-card-opts--two > .signup-card-opt {
  flex: 1 1 calc(50% - var(--space-3) / 2 - 1px);
  width: 100%;
  min-width: auto;
}
.signup-card-opts--two .signup-card-opt-face {
  gap: var(--space-2);
}
.signup-card-opt label {
  position: relative;
  display: block;
  cursor: pointer;
}
/* Off-screen but focusable, so the row takes the keyboard and the group is
still announced. display: none would remove both. */
.signup-card-opt input,
.signup-card-other input {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  border: 0;
  overflow: hidden;
  white-space: nowrap;
  clip-path: inset(50%);
}
.signup-card-opt-face {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  min-height: var(--signup-card-target);
  padding: var(--space-3) var(--space-4);
  background: var(--color-surface);
  /* The border is the only thing marking this as a control. */
  border: 2px solid color-mix(in srgb, var(--color-text) 22%, var(--color-surface));
  border-radius: var(--btn-radius);
  font-weight: 700;
  line-height: 1.25;
}
/* A word wider than a whole row breaks rather than leave its tile. */
.signup-card-opt-face > span:first-child {
  min-width: 0;
  overflow-wrap: break-word;
}
.signup-card-opt:hover .signup-card-opt-face {
  border-color: color-mix(in srgb, var(--color-primary) 70%, var(--color-surface));
}
.signup-card-opt input:checked + .signup-card-opt-face {
  border-color: var(--color-primary);
  background: color-mix(in srgb, var(--color-primary) 9%, var(--color-surface));
}
.signup-card-tick {
  flex: none;
  display: grid;
  place-items: center;
  width: 22px;
  height: 22px;
  border: 2px solid color-mix(in srgb, var(--color-text) 35%, var(--color-surface));
  border-radius: 50%;
}
.signup-card-opt input:checked + .signup-card-opt-face .signup-card-tick {
  background: var(--color-primary);
  border-color: var(--color-primary);
  color: var(--color-on-primary);
}
.signup-card-opt input:checked + .signup-card-opt-face .signup-card-tick::before,
.signup-card-other input:checked + span .signup-card-tick::before {
  content: "";
  width: 5px;
  height: 10px;
  margin-top: -2px;
  border: solid currentColor;
  border-width: 0 2.5px 2.5px 0;
  transform: rotate(45deg);
}
/* The third answer to "who are you": a real choice, drawn small. */
.signup-card-other {
  position: relative;
  display: inline-flex;
  margin-top: var(--space-2);
  cursor: pointer;
}
.signup-card-other > span {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  min-height: 44px;
  padding: 0 var(--space-1);
  font-weight: 600;
  text-decoration: underline;
  text-underline-offset: 3px;
}
.signup-card-other .signup-card-tick {
  display: none;
}
.signup-card-other input:checked + span {
  text-decoration: none;
}
.signup-card-other input:checked + span .signup-card-tick {
  display: grid;
  background: var(--color-primary);
  border-color: var(--color-primary);
  color: var(--color-on-primary);
}
/* Fields. 16px text, or iOS zooms the page on focus. */
.signup-card-dob {
  display: grid;
  grid-template-columns: 1fr 1fr 1.4fr;
  gap: var(--space-2);
  /* A label that wraps must not push its box out of line with the others. */
  align-items: end;
}
.signup-card-field {
  display: grid;
  gap: var(--space-1);
  min-width: 0;
}
.signup-card-field > span {
  font-size: .9375rem;
  font-weight: 700;
}
.signup-card-field input,
.signup-card-field select {
  box-sizing: border-box;
  width: 100%;
  min-height: 52px;
  padding: 0 var(--space-3);
  font: inherit;
  font-size: 1rem;
  color: var(--color-text);
  background: var(--color-surface);
  border: 2px solid color-mix(in srgb, var(--color-text) 30%, var(--color-surface));
  border-radius: var(--btn-radius);
}
.signup-card-consent {
  display: grid;
  grid-template-columns: 24px 1fr;
  gap: var(--space-3);
  align-items: start;
  margin-top: var(--space-4);
  font-size: .875rem;
}
.signup-card-consent input {
  width: 22px;
  height: 22px;
  margin: 2px 0 0;
  accent-color: var(--color-primary);
}
.signup-card-consent a,
.signup-card-foot a {
  color: var(--color-text);
  font-weight: 700;
  text-underline-offset: 2px;
}
.signup-card-actions {
  display: grid;
  gap: var(--space-3);
  margin-top: var(--space-6);
}
.signup-card-submit {
  width: 100%;
  min-height: var(--signup-card-target);
  padding: 0 var(--space-5);
  border: 0;
  border-radius: var(--btn-radius);
  background: var(--color-primary);
  color: var(--color-on-primary);
  font-family: var(--font-body);
  font-size: 1.0625rem;
  font-weight: 700;
  cursor: pointer;
}
.signup-card-submit:hover {
  background: var(--color-primary-dark);
}
.signup-card-note {
  margin: 0;
  text-align: center;
  font-size: .875rem;
  color: var(--color-text-soft);
}
.signup-card-foot {
  margin: var(--space-4) 0 0;
  padding-top: var(--space-4);
  border-top: 1px solid var(--color-rule);
  text-align: center;
  font-size: .9375rem;
  color: var(--color-text-soft);
}
.signup-card-opt input:focus-visible + .signup-card-opt-face,
.signup-card-other input:focus-visible + span,
.signup-card-field input:focus-visible,
.signup-card-field select:focus-visible,
.signup-card-consent input:focus-visible,
.signup-card-submit:focus-visible,
.signup-card-consent a:focus-visible,
.signup-card-foot a:focus-visible {
  outline: 3px solid var(--color-focus);
  outline-offset: 2px;
}
/* Built by the behaviour. Nothing below is in the authored page; the
behaviour adds it, and these rules draw it. */
.signup-card-form {
  scroll-margin-top: var(--space-2);
}
.signup-card-top {
  display: grid;
  grid-template-columns: 44px 1fr auto;
  align-items: center;
  gap: var(--space-3);
  min-height: 44px;
}
.signup-card-back {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  margin-left: calc(-1 * var(--space-2));
  padding: 0;
  background: none;
  border: 0;
  border-radius: var(--btn-radius);
  color: var(--color-text);
  cursor: pointer;
}
.signup-card-back::before {
  content: "";
  width: 10px;
  height: 10px;
  margin-left: 4px;
  border: solid currentColor;
  border-width: 0 0 2.5px 2.5px;
  transform: rotate(45deg);
}
.signup-card-bar {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  gap: var(--space-1);
}
.signup-card-seg {
  position: relative;
  height: 6px;
  overflow: hidden;
  border-radius: var(--chip-radius);
  background: color-mix(in srgb, var(--color-text) 14%, var(--color-surface));
}
.signup-card-seg::before {
  content: "";
  position: absolute;
  inset: 0 auto 0 0;
  width: 0;
  background: var(--color-primary);
}
.signup-card-seg[data-hub-signup-done]::before {
  width: 100%;
}
.signup-card-seg[data-hub-signup-now]::before {
  width: 35%;
}
.signup-card-seg::after {
  content: "";
  position: absolute;
  inset: 0;
  transform: translateX(-100%);
  background: linear-gradient(90deg, transparent, color-mix(in srgb, var(--color-surface) 70%, transparent), transparent);
}
.signup-card-count {
  font-size: .875rem;
  color: var(--color-text-soft);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
/* The members: faces in the card on a phone, a row beside it when wide. */
.signup-card-members {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-height: 52px;
  margin-top: var(--space-3);
  padding: var(--space-2) var(--space-3);
  border-radius: var(--chip-radius);
  background: color-mix(in srgb, var(--color-primary) 7%, var(--color-surface));
}
.signup-card-faces {
  display: flex;
  flex: none;
  padding-left: var(--space-2);
}
.signup-card-face {
  width: 2.25rem;
  height: 2.25rem;
  margin-left: calc(-1 * var(--space-2));
  overflow: hidden;
  border: 2px solid var(--color-surface);
  border-radius: 50%;
  background: var(--color-surface-soft);
}
.signup-card-face img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 1;
  object-fit: cover;
}
.signup-card-members p {
  margin: 0;
  font-size: .875rem;
  font-weight: 700;
  line-height: 1.35;
}
.signup-card-summary {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin: var(--space-2) 0 0;
  font-size: .875rem;
  color: var(--color-text-soft);
}
.signup-card-summary::before {
  content: "";
  flex: none;
  width: 5px;
  height: 9px;
  margin: 0 var(--space-1) 2px;
  border: solid var(--color-primary);
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}
/* Several answers to "looking for": a square tick, not a round one. */
.signup-card-opt input[type="checkbox"] + .signup-card-opt-face .signup-card-tick {
  border-radius: min(var(--btn-radius), 6px);
}
/* Interests. */
.signup-card-chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin: 0;
  padding: 0;
  list-style: none;
}
.signup-card-chip label {
  position: relative;
  display: block;
  cursor: pointer;
}
.signup-card-chip input {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  border: 0;
  overflow: hidden;
  white-space: nowrap;
  clip-path: inset(50%);
}
.signup-card-chip span {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  min-height: 44px;
  padding: 0 var(--space-4);
  background: var(--color-surface);
  border: 2px solid color-mix(in srgb, var(--color-text) 22%, var(--color-surface));
  border-radius: var(--chip-radius);
  font-size: .9375rem;
  font-weight: 600;
}
.signup-card-chip span::before {
  content: "+";
  font-weight: 400;
  color: var(--color-text-soft);
}
.signup-card-chip input:checked + span {
  background: var(--color-primary);
  border-color: var(--color-primary);
  color: var(--color-on-primary);
}
.signup-card-chip input:checked + span::before {
  content: "";
  width: 5px;
  height: 9px;
  margin-right: 2px;
  border: solid currentColor;
  border-width: 0 2px 2px 0;
  transform: rotate(45deg) translateY(-1px);
}
.signup-card-chip input:disabled + span {
  cursor: not-allowed;
  border-style: dashed;
  color: var(--color-text-soft);
}
.signup-card-more {
  min-height: 44px;
  margin-top: var(--space-2);
  padding: 0 var(--space-1);
  background: none;
  border: 0;
  color: var(--color-text);
  font: inherit;
  font-weight: 600;
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}
.signup-card-tally {
  margin: var(--space-3) 0 0;
  font-size: .875rem;
  color: var(--color-text-soft);
}
/* The date of birth: the reward, and the wheel where a page asks for one. */
.signup-card-reward {
  display: inline-flex;
  margin: var(--space-3) 0 0;
  padding: var(--space-1) var(--space-3);
  border-radius: var(--chip-radius);
  background: color-mix(in srgb, var(--color-primary) 10%, var(--color-surface));
  font-size: .9375rem;
  font-weight: 700;
}
.signup-card-wheels {
  display: grid;
  grid-template-columns: 1fr 1.4fr 1.3fr;
  gap: var(--space-2);
}
.signup-card-wheel-col {
  display: grid;
  gap: var(--space-1);
  min-width: 0;
}
.signup-card-wheel-label {
  font-size: .9375rem;
  font-weight: 700;
  text-align: center;
}
/* The band is the background, so it stays put while the rows scroll. Five
44px rows show, two of them spacers above and below: keep the band's 88px
and 132px in step with that. */
.signup-card-wheel {
  height: 220px;
  margin: 0;
  padding: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  scroll-snap-type: y mandatory;
  scrollbar-width: none;
  list-style: none;
  border-radius: var(--btn-radius);
  background: linear-gradient(transparent 88px, color-mix(in srgb, var(--color-primary) 12%, var(--color-surface)) 88px 132px, transparent 132px);
  mask-image: linear-gradient(to bottom, transparent, var(--color-text) 30%, var(--color-text) 70%, transparent);
}
.signup-card-wheel::-webkit-scrollbar {
  width: 0;
  height: 0;
}
.signup-card-wheel li {
  display: grid;
  place-items: center;
  height: 44px;
  scroll-snap-align: center;
  font-size: 1.0625rem;
  font-variant-numeric: tabular-nums;
  color: var(--color-text-soft);
  cursor: pointer;
}
.signup-card-wheel li[aria-selected="true"] {
  color: var(--color-text);
  font-weight: 700;
}
/* Errors say what is missing; a dashed edge marks where, never colour alone. */
.signup-card-error {
  margin: var(--space-3) 0 0;
  padding: var(--space-2) var(--space-3);
  border-left: 4px solid var(--color-text);
  background: var(--color-surface-soft);
  font-size: .9375rem;
  font-weight: 600;
}
.signup-card-opt input[aria-invalid] + .signup-card-opt-face,
/* Where the visitor lives: country, postal code or region, town. One rhythm
   between them, wide enough that a focus ring never meets the next label. */
.signup-card-lists {
  display: grid;
  gap: var(--space-4);
}
.signup-card-step > .signup-card-field + .signup-card-field,
.signup-card-step > .signup-card-field + .signup-card-postal,
.signup-card-step > .signup-card-field + .signup-card-lists,
.signup-card-step > .signup-card-postal + .signup-card-lists {
  margin-top: var(--space-4);
}
/* The towns offered as the visitor types: a raised list over the card, under
   the field, so the card keeps its height. */
.signup-card-place {
  position: relative;
}
.signup-card-places {
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  z-index: 3;
  margin: var(--space-1) 0 0;
  padding: var(--space-1);
  background: var(--color-surface);
  border: 1px solid var(--color-rule);
  border-radius: var(--btn-radius);
  box-shadow: var(--card-shadow);
}
/* How many towns there are, and that the list goes on. */
.signup-card-places-count {
  margin: 0;
  padding: var(--space-1) var(--space-3);
  font-size: .8125rem;
  color: var(--color-text-soft);
}
/* Four and a half rows: the cut row says the list scrolls. */
.signup-card-places-list {
  max-height: calc(4.5 * 44px);
  margin: 0;
  padding: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  list-style: none;
}
.signup-card-places li {
  display: flex;
  align-items: center;
  min-height: 44px;
  padding: 0 var(--space-3);
  border-radius: var(--btn-radius);
  cursor: pointer;
}
.signup-card-places li:hover,
.signup-card-places li[aria-selected="true"] {
  background: var(--color-surface-soft);
  box-shadow: inset 3px 0 0 var(--color-primary);
}
.signup-card-field input[aria-invalid],
.signup-card-field select[aria-invalid] {
  border-style: dashed;
  border-color: var(--color-text);
}
.signup-card-next {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  width: 100%;
  min-height: var(--signup-card-target);
  padding: 0 var(--space-5);
  border: 0;
  border-radius: var(--btn-radius);
  background: var(--color-primary);
  color: var(--color-on-primary);
  font-family: var(--font-body);
  font-size: 1.0625rem;
  font-weight: 700;
  cursor: pointer;
}
.signup-card-next::after {
  content: "";
  width: 8px;
  height: 8px;
  border: solid currentColor;
  border-width: 2.5px 2.5px 0 0;
  transform: rotate(45deg);
}
.signup-card-next:hover {
  background: var(--color-primary-dark);
}
/* The encouraging line after an answer, under the summary of answers so far. */
.signup-card-cheer {
  margin: var(--space-2) 0 0;
  font-size: .9375rem;
  font-weight: 600;
  color: var(--color-text);
}
/* A line under a location field: the place a postal code was read as, or a
   warning, set apart from the field rather than tucked under it. */
.signup-card-place-note {
  margin: var(--space-2) 0 0;
  font-size: .9375rem;
  color: var(--color-text-soft);
}
.signup-card-lists > .signup-card-place-note {
  margin-top: calc(-1 * var(--space-2));
}
.signup-card-place-note[data-hub-signup-warn] {
  color: var(--color-text);
  font-weight: 600;
}
/* The link between a postal code and the region and town lists. */
.signup-card-switch {
  display: block;
  min-height: 44px;
  margin-top: var(--space-2);
  padding: 0;
  background: none;
  border: 0;
  color: var(--color-text);
  font: inherit;
  font-size: .9375rem;
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}
.signup-card-skip {
  justify-self: center;
  min-height: 44px;
  padding: 0 var(--space-3);
  background: none;
  border: 0;
  color: var(--color-text);
  font: inherit;
  font-weight: 600;
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}
.signup-card-finish {
  padding: var(--space-8) var(--space-2);
  text-align: center;
}
.signup-card-finish svg {
  display: block;
  margin: 0 auto;
  color: var(--color-primary);
}
.signup-card-finish p {
  margin: var(--space-4) 0 0;
  font-size: 1.125rem;
  font-weight: 700;
}
.signup-card-finish small {
  display: block;
  margin-top: var(--space-2);
  font-size: .9375rem;
  color: var(--color-text-soft);
}
.signup-card-back:focus-visible,
.signup-card-next:focus-visible,
.signup-card-skip:focus-visible,
.signup-card-switch:focus-visible,
.signup-card-more:focus-visible,
.signup-card-wheel:focus-visible,
.signup-card-chip input:focus-visible + span {
  outline: 3px solid var(--color-focus);
  outline-offset: 2px;
}
/* A short phone: the same card, tighter, so Next stays in view. */
@media (max-width: 59.99rem) and (max-height: 760px) {
  .signup-card {
    --signup-card-target: 48px;
  }
  .signup-card-form {
    padding-top: var(--space-3);
  }
  .signup-card-step {
    margin-top: var(--space-4);
  }
  .signup-card-opts {
    gap: var(--space-2);
  }
  .signup-card-actions {
    margin-top: var(--space-4);
  }
}
@media (prefers-reduced-motion: no-preference) {
  .signup-card-opt-face,
  .signup-card-field input,
  .signup-card-chip span {
    transition: border-color var(--transition-fast) ease-out, background-color var(--transition-fast) ease-out, transform var(--transition-fast) ease-out;
  }
  .signup-card-opt:active .signup-card-opt-face,
  .signup-card-chip:active span {
    transform: scale(.97);
  }
  .signup-card-opt input:checked + .signup-card-opt-face .signup-card-tick,
  .signup-card-chip input:checked + span {
    animation: signup-card-pop .34s cubic-bezier(.3, 1.6, .5, 1);
  }
  .signup-card-seg::before {
    transition: width .5s cubic-bezier(.2, .8, .2, 1);
  }
  @keyframes signup-card-pop {
    from {
      transform: scale(.6);
    }
  }
}
/* Wide: a tighter card, so a first step and its button sit above the fold. */
@media (min-width: 60rem) {
  .signup-card {
    --signup-card-target: 48px;
  }
  .signup-card-form {
    padding: var(--space-5);
  }
  .signup-card-q {
    font-size: calc(1.125rem * var(--type-scale, 1));
  }
  .signup-card-opts {
    grid-template-columns: 1fr 1fr;
    gap: var(--space-2);
  }
  .signup-card-opt-face {
    padding: var(--space-2) var(--space-3);
    font-size: .9375rem;
  }
  /* A tighter card beside the words, so a first step and its button sit above
  the fold on a laptop. */
  .signup-card-top {
    min-height: 36px;
  }
  .signup-card-members {
    min-height: 44px;
    margin-top: var(--space-2);
    padding-block: var(--space-1);
  }
  .signup-card-step {
    margin-top: var(--space-4);
  }
  .signup-card-step[data-hub-signup-part="seeking"] {
    margin-top: var(--space-4);
  }
  .signup-card-q {
    margin-bottom: var(--space-2);
  }
  .signup-card-help {
    margin-bottom: var(--space-2);
  }
  .signup-card-other {
    margin-top: 0;
  }
  .signup-card-actions {
    margin-top: var(--space-4);
  }
  .signup-card-foot {
    margin-top: var(--space-3);
    padding-top: var(--space-3);
  }
}
/* Before the behaviour library takes the card over, the card is drawn at
   its first step where scripts run, so the page does not jump when it does.
   The animations move nothing: each holds a state for 3s, and if the library
   has not come by then every question shows. */
@media (scripting: enabled) {
  .signup-card:not(.hub-signup-live) :is(.signup-card-title, .signup-card-note, fieldset.signup-card-step:not(:first-of-type)) {
    animation: signup-card-wait 0s 3s backwards;
  }
  /* The row the progress bar takes. */
  .signup-card:not(.hub-signup-live) .signup-card-form::before {
    content: "";
    display: block;
    animation: signup-card-bar 0s 3s backwards;
  }
  /* "Looking for" first: its help line, and no summed answer. */
  .signup-card:not(.hub-signup-live) [data-hub-signup-part="seeking"]:first-of-type::before {
    content: "";
    display: block;
    font-size: .9375rem;
    animation: signup-card-help 0s 3s backwards;
  }
  .signup-card:not(.hub-signup-live) [data-hub-signup-part="seeking"]:first-of-type .signup-card-opt:has(input[name="lf"]:is([value="3"], [value="5"], [value="6"], [value="7"], [value="17"], [value="18"], [value="19"], [value="20"], [value="21"], [value="22"], [value="23"])) {
    animation: signup-card-wait 0s 3s backwards;
  }
}
/* From 60rem "I am" and "looking for" are the first step together. */
@media (scripting: enabled) and (min-width: 60rem) {
  .signup-card:not(.hub-signup-live) [data-hub-signup-part="iam"]:first-of-type + [data-hub-signup-part="seeking"] {
    animation: none;
  }
  .signup-card:not(.hub-signup-live) :is([data-hub-signup-part="seeking"]:first-of-type, [data-hub-signup-part="iam"]:first-of-type + [data-hub-signup-part="seeking"])::before {
    content: "";
    display: block;
    font-size: .9375rem;
    animation: signup-card-help-wide 0s 3s backwards;
  }
  .signup-card:not(.hub-signup-live) [data-hub-signup-part="iam"]:first-of-type + [data-hub-signup-part="seeking"] .signup-card-opt:has(input[name="lf"]:is([value="3"], [value="5"], [value="6"], [value="7"], [value="17"], [value="18"], [value="19"], [value="20"], [value="21"], [value="22"], [value="23"])) {
    animation: signup-card-wait 0s 3s backwards;
  }
}
@keyframes signup-card-wait {
  from {
    display: none;
  }
}
@keyframes signup-card-bar {
  from {
    min-height: 44px;
  }
}
@keyframes signup-card-help {
  from {
    content: "\a0";
    margin: calc(-1 * var(--space-2)) 0 var(--space-3);
  }
}
@keyframes signup-card-help-wide {
  from {
    content: "\a0";
    margin: calc(-1 * var(--space-2)) 0 var(--space-2);
  }
}
/* === /pattern signup-card@8 === */

/* === pattern hero-split@14 (library v229; appended by page_assemble.py -- adopt a newer version by replacing this block, never by adding a second) === */
/* hero-split v3 - tokens only, selectors prefixed */
.hero-split {
  padding-block: var(--space-8);
}
.hero-split-inner {
  width: min(100% - 2 * var(--space-4), var(--container-max));
  margin-inline: auto;
  display: grid;
  gap: var(--space-6);
  align-items: center;
}
.hero-split-visual {
  order: -1; /* image leads on phones; the copy leads from 48rem up */
}
.hero-split-visual img {
  width: 100%;
  height: auto;
  object-fit: cover;
  border-radius: var(--card-radius);
  box-shadow: var(--card-shadow);
}
.hero-split-title {
  font-family: var(--font-heading);
  font-size: calc(clamp(2rem, 1.2rem + 3.5vw, 3.4rem) * var(--type-scale, 1));
  line-height: calc(1.15 * var(--heading-leading, 1));
  color: var(--color-heading);
  margin: 0 0 var(--space-4);
  text-wrap: balance;
}
@supports (line-height: 1cap) {
  .hero-split-title {
    line-height: calc(max(1.15em, 1.45cap) * var(--heading-leading, 1));
  }
}
.hero-split-sub {
  color: var(--color-text-soft);
  font-size: 1.125rem;
  max-width: 46ch;
  margin: 0 0 var(--space-6);
}
.hero-split-cta {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
}
.hero-split-btn {
  box-sizing: border-box;
  display: inline-block;
  background: var(--color-primary);
  color: var(--color-on-primary);
  font-weight: 700;
  text-decoration: none;
  padding: var(--space-3) var(--space-6);
  border-radius: var(--btn-radius);
  min-height: 48px;
  line-height: 1.5;
}
.hero-split-btn:hover {
  background: var(--color-primary-dark);
}
/* Focus needs its own indicator, not the hover fill. */
.hero-split-btn:focus-visible {
  outline: 3px solid var(--color-focus);
  outline-offset: 3px;
}
@media (min-width: 48rem) {
  .hero-split {
    padding-block: var(--space-12);
  }
  .hero-split-inner {
    grid-template-columns: 1.1fr 0.9fr;
    gap: var(--space-8);
  }
  .hero-split-visual {
    order: 0;
  }
  .hero-split--end .hero-split-visual {
    order: 1;
  }
  .hero-split--start .hero-split-inner {
    grid-template-columns: 0.9fr 1.1fr;
  }
  .hero-split--start .hero-split-visual {
    order: -1;
  }
}

.hero-split img[data-hub-placeholder] {
  background: color-mix(in srgb, var(--color-primary) 18%, var(--color-surface));
}

/* Holding a signup-card in place of the join button: on a phone the card
   follows the headline and the photograph comes after it. */
@media (max-width: 47.99rem) {
  .hero-split-inner:has(.signup-card) .hero-split-visual {
    order: 1;
  }
}
/* Wide: the photograph fills its half and the card overlaps its inner edge,
   so the two read as layered rather than boxed. */
@media (min-width: 60rem) {
  .hero-split:has(.signup-card) {
    padding-block: var(--space-6) var(--space-8);
  }
  .hero-split-inner:has(.signup-card) {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr);
    grid-template-areas: ". visual" "title visual" "sub visual" ". visual";
    grid-template-rows: 1fr auto auto 1fr;
    row-gap: var(--space-3);
    /* The card reaches --space-12 out of the photograph's column toward the
       headline, so the gap has to clear that reach, on either side. */
    column-gap: calc(var(--space-12) + var(--space-6));
    align-items: stretch;
  }
  .hero-split-inner:has(.signup-card) .hero-split-copy {
    display: contents;
  }
  .hero-split-inner:has(.signup-card) .hero-split-title {
    grid-area: title;
    max-width: 10em;
    margin: 0;
  }
  .hero-split-inner:has(.signup-card) .hero-split-sub {
    grid-area: sub;
    margin: 0;
  }
  .hero-split-inner:has(.signup-card) .hero-split-visual {
    grid-area: visual;
    /* A height, not a minimum, anchored at the top: a taller step must not
       stretch the picture or move it. */
    height: 38rem;
    align-self: start;
    margin-inline-start: var(--space-12);
  }
  .hero-split-inner:has(.signup-card) .hero-split-visual img {
    height: 100%;
  }
  .hero-split-inner:has(.signup-card) .hero-split-cta {
    grid-area: visual;
    z-index: 2;
    align-self: center;
    justify-self: start;
    margin-inline-start: calc(-1 * var(--space-12));
  }
  /* The same layering mirrored. */
  .hero-split--start .hero-split-inner:has(.signup-card) {
    grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr);
    grid-template-areas: "visual ." "visual title" "visual sub" "visual .";
  }
  .hero-split--start .hero-split-inner:has(.signup-card) .hero-split-visual {
    margin-inline: 0 var(--space-12);
  }
  .hero-split--start .hero-split-inner:has(.signup-card) .hero-split-cta {
    justify-self: end;
    margin-inline: 0 calc(-1 * var(--space-12));
  }
}
/* === /pattern hero-split@14 === */

/* === pattern heading-block@9 (library v229; appended by page_assemble.py -- adopt a newer version by replacing this block, never by adding a second) === */
/* heading-block v4 - tokens only, selectors prefixed */
.heading-block {
  /* Same gutter idiom as every other pattern. */
  width: min(100% - 2 * var(--space-4), 45rem);
  margin-inline: auto;
  margin-block-end: var(--space-8);
  text-align: start;
}
.heading-block-eyebrow {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  margin: 0 0 var(--space-4);
  /* --color-text: --color-primary carries no stated ratio. */
  color: var(--color-text);
  font-size: 0.8125rem;
  line-height: 1;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
/* Hairline rules either side of the label. Decorative only - the label's own
   words carry the meaning. */
.heading-block-eyebrow::before,
.heading-block-eyebrow::after {
  content: "";
  display: block;
  width: var(--space-5);
  height: 2px;
  border-radius: var(--chip-radius);
  background: color-mix(in srgb, var(--color-primary) 45%, transparent);
}
.heading-block-title {
  margin: 0;
  font-family: var(--font-heading);
  font-size: calc(clamp(2rem, 1.4rem + 2.6vw, 3.6rem) * var(--type-scale, 1));
  line-height: calc(1.02 * var(--heading-leading, 1));
  letter-spacing: calc(-0.035em + var(--heading-tracking, 0) * 1em);
  font-weight: var(--weight-display, 700);
  color: var(--color-heading);
  text-wrap: balance;
}
@supports (line-height: 1cap) {
  .heading-block-title {
    line-height: calc(max(1.02em, 1.45cap) * var(--heading-leading, 1));
  }
}
.heading-block-intro {
  max-width: 42rem;
  margin: var(--space-4) 0 0;
  font-size: 1.0625rem;
  line-height: 1.65;
  color: var(--color-text-soft);
}
/* Tablet up: centred. Phones keep it left. */
@media (min-width: 48rem) {
  .heading-block {
    text-align: center;
  }
  .heading-block-intro {
    margin-inline: auto;
  }
}
/* === /pattern heading-block@9 === */

/* === pattern member-grid@6 (library v229; appended by page_assemble.py -- adopt a newer version by replacing this block, never by adding a second) === */
/* member-grid v1 - tokens only, selectors prefixed.
   Everything below .member-grid is markup the PLATFORM writes, so these class
   names are a contract with it, not ours to rename. */
.member-grid {
  display: block;
  padding-inline: var(--space-4);
}
.member-grid .lp-grid,
.member-grid .lp-members__empty {
  max-width: var(--container-max);
  margin-inline: auto;
}
.member-grid .lp-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(9rem, 1fr));
  gap: var(--space-4);
  list-style: none;
  margin-block: 0;
  padding: 0;
}
.member-grid .mem-card {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  min-width: 0;
  position: relative;
}
.member-grid .mem-card img,
.member-grid .mem-card__initial {
  display: block;
  width: 100%;
  aspect-ratio: 1 / 1;
  object-fit: cover;
  border-radius: var(--card-radius);
  background: var(--color-surface);
}
.member-grid .mem-card__initial {
  display: grid;
  place-items: center;
  font-family: var(--font-heading);
  font-size: calc(2rem * var(--type-scale, 1));
  color: var(--color-primary);
  background: color-mix(in srgb, var(--color-primary) 12%, var(--color-surface));
}
.member-grid .mem-card .badge {
  position: absolute;
  top: var(--space-2);
  inset-inline-start: var(--space-2);
  padding: 0.15rem var(--space-2);
  border-radius: var(--chip-radius);
  background: var(--color-primary);
  color: var(--color-on-primary);
  font-size: 0.8rem;
  font-weight: 700;
  line-height: 1.4;
}
.member-grid .mem-card__name {
  margin: var(--space-2) 0 0;
  font-family: var(--font-heading);
  font-size: calc(1rem * var(--type-scale, 1));
  font-weight: 700;
  color: var(--color-text);
  overflow-wrap: anywhere;
}
.member-grid .mem-card__where,
.member-grid .mem-card__line {
  margin: 0;
  font-size: 0.85rem;
  line-height: 1.5;
  color: var(--color-text-soft);
  overflow-wrap: anywhere;
}
/* Two lines and no more. A blurb is member-written and has no length limit,
   so without this one card sets the height of the whole row. */
.member-grid .mem-card__line {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  overflow: hidden;
}
/* 44px, not the 24px WCAG floor: on a phone this is the card's only control
   and it sits between two photographs. */
.member-grid .mem-card__cta {
  display: flex;
  align-items: center;
  min-height: 44px;
  margin-top: auto;
  color: var(--color-primary);
  font-size: 0.85rem;
  font-weight: 700;
  text-decoration: none;
}
.member-grid .mem-card__cta:hover {
  text-decoration: underline;
}
.member-grid .mem-card__cta:focus-visible {
  outline: 2px solid var(--color-focus);
  outline-offset: 2px;
  border-radius: var(--chip-radius);
}
/* The join tile is the platform's last li and carries no photograph, so it
   needs a body of its own or it collapses to a link on the baseline. A grid
   item stretches to its row, so the floor is for the row it lands in ALONE -
   it is the last of an unknown number, so it wraps by itself often. */
.member-grid .mem-card--join {
  display: grid;
  place-items: center;
  min-height: 9rem;
  padding: var(--space-4);
  border: var(--card-border);
  border-radius: var(--card-radius);
  background: color-mix(in srgb, var(--color-primary) 8%, var(--color-surface));
  text-align: center;
}
.member-grid .mem-card--join .mem-card__cta {
  justify-content: center;
  margin: 0;
}
.member-grid .lp-members__empty {
  margin-block: 0;
  padding: var(--space-5) var(--space-4);
  border: 1px dashed color-mix(in srgb, var(--color-primary) 30%, transparent);
  border-radius: var(--card-radius);
  background: var(--color-surface);
  color: var(--color-text-soft);
  font-size: 0.9rem;
  line-height: 1.6;
}

/* card: how much furniture sits around the photograph */
.member-grid--plain .mem-card {
  padding: 0;
}
.member-grid--framed .mem-card {
  padding: var(--space-3);
  border: var(--card-border);
  border-radius: var(--card-radius);
  background: var(--color-surface);
  box-shadow: var(--card-shadow);
}
.member-grid--framed .mem-card .badge {
  top: var(--space-4);
  inset-inline-start: var(--space-4);
}
.member-grid--portrait .mem-card img,
.member-grid--portrait .mem-card__initial {
  aspect-ratio: 3 / 4;
}

/* flow: a wrapping grid, or one row the reader swipes. The rail never moves
   on its own - the visitor drives it, the same bargain gallery-scroll makes. */
.member-grid--grid .lp-grid {
  grid-template-columns: repeat(auto-fill, minmax(9rem, 1fr));
}
/* marquee is the rail plus a behaviour. With no behaviour library it IS the
   rail, so it takes every rail rule and adds nothing of its own. */
.member-grid--rail,
.member-grid--marquee {
  padding-inline: 0;
}
.member-grid--rail .lp-grid,
.member-grid--marquee .lp-grid {
  display: flex;
  padding-inline: var(--space-4);
  gap: var(--space-4);
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory;
  scroll-padding-inline: var(--space-4);
  scrollbar-width: none;
  padding-block: var(--space-2);
  max-width: none;
}
.member-grid--rail .lp-grid::-webkit-scrollbar,
.member-grid--marquee .lp-grid::-webkit-scrollbar {
  display: none;
}
.member-grid--rail .mem-card,
.member-grid--marquee .mem-card {
  flex: 0 0 auto;
  width: min(42vw, 11rem);
  scroll-snap-align: start;
}
.member-grid--rail .lp-grid:focus-visible,
.member-grid--marquee .lp-grid:focus-visible {
  outline: 2px solid var(--color-focus);
  outline-offset: 2px;
}
/* The carousel's controls stay hidden while the marquee moves the row, and
   show once its stop control is pressed. */
.member-grid--marquee:has(.hub-marquee-running):not(:has(.hub-marquee-control[aria-pressed="true"])) .hub-carousel-controls {
  display: none;
}

/* controls: where the previous and next arrows sit, read by the behaviour
   library from these properties. phone: whether a phone shows them. */
.member-grid--top {
  --hub-carousel-controls: top;
  --hub-carousel-look: round;
}
.member-grid--edges {
  --hub-carousel-controls: edges;
  --hub-carousel-look: round;
}
.member-grid--arrows {
  --hub-carousel-phone: show;
}
.member-grid--swipe {
  --hub-carousel-phone: hide;
}
.member-grid--marquee {
  --hub-marquee-look: round;
}
/* The pair keeps to the column the heading above it sits in. */
.member-grid .hub-carousel-controls--top {
  max-width: var(--container-max);
  margin-inline: auto;
  padding-inline: var(--space-4);
}
/* Over a photograph the arrows need a ground of their own. */
.member-grid .hub-carousel-controls--edges .hub-carousel-control {
  border: 0;
  background: var(--color-bg);
  color: var(--color-text);
  box-shadow: var(--card-shadow);
}
/* The marquee's stop control shares the arrows' row, at its end. */
.member-grid--marquee {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  align-items: center;
}
.member-grid--marquee .lp-grid,
.member-grid--marquee .lp-members__empty {
  flex: 0 0 100%;
}
.member-grid--marquee .hub-carousel-controls--top {
  margin-inline: 0;
  padding-inline: 0 var(--space-2);
}
.member-grid--marquee .hub-marquee-control {
  margin: 0 var(--space-4) var(--space-3) 0;
}

@media (min-width: 48rem) {
  .member-grid .lp-grid {
    gap: var(--space-5);
  }
  .member-grid--grid .lp-grid {
    grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr));
  }
  .member-grid--rail .mem-card,
  .member-grid--marquee .mem-card {
    width: 13rem;
  }
  .member-grid .mem-card--join {
    min-height: 11rem;
  }
}

@media (prefers-reduced-motion: no-preference) {
  .member-grid--rail .lp-grid,
  .member-grid--marquee .lp-grid {
    scroll-behavior: smooth;
  }
  .member-grid .mem-card__cta {
    transition: color var(--transition-fast);
  }
}

/* With scripting off nothing can build the previous and next controls, and
   the hidden scroll bar would leave a mouse no way along the row, so both
   rows wrap like the grid rung. */
@media (scripting: none) {
  .member-grid--rail .lp-grid,
  .member-grid--marquee .lp-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(9rem, 1fr));
    overflow-x: visible;
    max-width: var(--container-max);
  }
  .member-grid--rail .mem-card,
  .member-grid--marquee .mem-card {
    width: auto;
  }
}
@media (scripting: none) and (min-width: 48rem) {
  .member-grid--rail .lp-grid,
  .member-grid--marquee .lp-grid {
    grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr));
  }
}
.member-grid:not(.member-grid--moving):not(.member-grid--marquee) {
  --hub-motion: none;
}
/* === /pattern member-grid@6 === */

/* === pattern photo-band@2 (library v229; appended by page_assemble.py -- adopt a newer version by replacing this block, never by adding a second) === */
/* photo-band v1 - tokens only, selectors prefixed */
.photo-band {
  display: block;
  width: 100%;
  background: var(--color-surface-soft);
}
/* Rem against the viewport width, never viewport height: see the README. */
.photo-band--short {
  --photo-band-height: clamp(10rem, 28vw, 18rem);
}
.photo-band--standard {
  --photo-band-height: clamp(14rem, 40vw, 28rem);
}
.photo-band--tall {
  --photo-band-height: clamp(18rem, 56vw, 40rem);
}
.photo-band-image {
  display: block;
  width: 100%;
  height: var(--photo-band-height);
  object-fit: cover;
}

.photo-band img[data-hub-placeholder] {
  background: color-mix(in srgb, var(--color-primary) 18%, var(--color-surface));
}
/* === /pattern photo-band@2 === */

/* === pattern cta-band@6 (library v229; appended by page_assemble.py -- adopt a newer version by replacing this block, never by adding a second) === */
/* cta-band - tokens only, selectors prefixed */

/* Each rung names its own ground, ink, control pair and ring, and every rule
   below reads those rather than a token, so nothing here knows which ground it
   is on. The ring is per rung and not --color-focus everywhere: on --brand and
   --deep that token is a brand colour landing on a brand colour, and it
   disappears into the band on every sample brand. See the README. */
.cta-band--plain {
  --cta-band-ground: var(--color-bg);
  --cta-band-ink: var(--color-text);
  --cta-band-btn-face: var(--color-primary);
  --cta-band-btn-ink: var(--color-on-primary);
  --cta-band-ring: var(--color-focus);
}
.cta-band--soft {
  --cta-band-ground: var(--color-surface-soft);
  --cta-band-ink: var(--color-text);
  --cta-band-btn-face: var(--color-primary);
  --cta-band-btn-ink: var(--color-on-primary);
  --cta-band-ring: var(--color-focus);
}
.cta-band--brand {
  --cta-band-ground: var(--color-primary);
  --cta-band-ink: var(--color-on-primary);
  --cta-band-btn-face: var(--color-on-primary);
  --cta-band-btn-ink: var(--color-primary);
  --cta-band-ring: var(--color-on-primary);
}
.cta-band--deep {
  --cta-band-ground: var(--color-scrim);
  --cta-band-ink: var(--color-on-scrim);
  --cta-band-btn-face: var(--color-on-scrim);
  --cta-band-btn-ink: var(--color-scrim);
  --cta-band-ring: var(--color-on-scrim);
}
.cta-band {
  padding-block: var(--space-12);
  padding-inline: var(--space-4);
  background: var(--cta-band-ground);
  color: var(--cta-band-ink);
  text-align: center;
}
.cta-band-inner {
  max-width: var(--container-max);
  margin-inline: auto;
}
.cta-band-eyebrow {
  font-size: 0.8125rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  margin: 0 0 var(--space-4);
}
/* Not --color-heading: that token is promised against --color-bg, and three of
   the four rungs paint a ground of their own. */
.cta-band-title {
  font-family: var(--font-heading);
  color: var(--cta-band-ink);
  font-size: calc(clamp(2rem, 4.5vw, 3.25rem) * var(--type-scale, 1));
  font-weight: var(--weight-display, 700);
  letter-spacing: calc(-0.02em + var(--heading-tracking, 0) * 1em);
  line-height: calc(1.1 * var(--heading-leading, 1));
  margin: 0 0 var(--space-4);
  text-wrap: balance;
}
@supports (line-height: 1cap) {
  .cta-band-title {
    line-height: calc(max(1.1em, 1.45cap) * var(--heading-leading, 1));
  }
}
.cta-band-lead {
  font-size: 1.0625rem;
  line-height: 1.6;
  max-width: 46ch;
  margin: 0 auto var(--space-6);
}
.cta-band-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  /* 48px target, above the 44px AAA floor. */
  min-height: 48px;
  padding: var(--space-3) var(--space-6);
  border-radius: var(--btn-radius);
  background: var(--cta-band-btn-face);
  color: var(--cta-band-btn-ink);
  font-weight: 700;
  line-height: 1.5;
  text-decoration: none;
}
.cta-band-btn:hover {
  text-decoration: underline;
  text-underline-offset: 0.2em;
}
/* The offset leaves a band-coloured gap, putting the guaranteed pair either
   side of the ring. */
.cta-band-btn:focus-visible {
  outline: 3px solid var(--cta-band-ring);
  outline-offset: 4px;
}
/* === /pattern cta-band@6 === */

/* === pattern hero-portrait@1 (library v229; appended by page_assemble.py -- adopt a newer version by replacing this block, never by adding a second) === */
/* hero-portrait v1 - tokens only, selectors prefixed */
/* Each ground names its own ink; every rule below reads the pair. */
.hero-portrait--plain {
  --hero-portrait-ground: var(--color-bg);
  --hero-portrait-ink: var(--color-text-soft);
  --hero-portrait-title-ink: var(--color-heading);
  --hero-portrait-btn-face: var(--color-primary);
  --hero-portrait-btn-ink: var(--color-on-primary);
  --hero-portrait-ring: var(--color-focus);
}
.hero-portrait--soft {
  --hero-portrait-ground: var(--color-surface-soft);
  --hero-portrait-ink: var(--color-text);
  --hero-portrait-title-ink: var(--color-text);
  --hero-portrait-btn-face: var(--color-primary);
  --hero-portrait-btn-ink: var(--color-on-primary);
  --hero-portrait-ring: var(--color-focus);
}
.hero-portrait--brand {
  --hero-portrait-ground: var(--color-primary);
  --hero-portrait-ink: var(--color-on-primary);
  --hero-portrait-title-ink: var(--color-on-primary);
  --hero-portrait-btn-face: var(--color-on-primary);
  --hero-portrait-btn-ink: var(--color-primary);
  --hero-portrait-ring: var(--color-on-primary);
}
.hero-portrait--deep {
  --hero-portrait-ground: var(--color-scrim);
  --hero-portrait-ink: var(--color-on-scrim);
  --hero-portrait-title-ink: var(--color-on-scrim);
  --hero-portrait-btn-face: var(--color-primary);
  --hero-portrait-btn-ink: var(--color-on-primary);
  --hero-portrait-ring: var(--color-on-scrim);
}
.hero-portrait {
  background: var(--hero-portrait-ground);
  color: var(--hero-portrait-ink);
  padding-block: var(--space-5) var(--space-8);
}
.hero-portrait-inner {
  width: min(100% - 2 * var(--space-4), var(--container-max));
  margin-inline: auto;
  display: grid;
  gap: var(--space-5);
  align-items: center;
}
/* The portrait leads on a phone; from 48rem the side rung places it. */
.hero-portrait-visual {
  order: -1;
}
.hero-portrait-img {
  display: block;
  width: 100%;
  height: clamp(13rem, 64vw, 20rem);
  object-fit: cover;
  /* A face sits high in a portrait; a short crop keeps it. */
  object-position: 50% 25%;
}
.hero-portrait--rounded .hero-portrait-img {
  border-radius: calc(2 * var(--card-radius));
}
/* The arch is a shape, not the brand's corner: a half circle on every brand. */
.hero-portrait--arch .hero-portrait-img {
  border-start-start-radius: 9999px;
  border-start-end-radius: 9999px;
  border-end-start-radius: var(--card-radius);
  border-end-end-radius: var(--card-radius);
}
.hero-portrait--half-bleed {
  padding-block-start: 0;
}
.hero-portrait--half-bleed .hero-portrait-visual {
  margin-inline: calc(-1 * var(--space-4));
}
.hero-portrait-title {
  font-family: var(--font-heading);
  color: var(--hero-portrait-title-ink);
  font-size: calc(clamp(2rem, 1.2rem + 3.2vw, 3.5rem) * var(--type-scale, 1));
  font-weight: var(--weight-display, 700);
  letter-spacing: calc(-0.02em + var(--heading-tracking, 0) * 1em);
  line-height: calc(1.08 * var(--heading-leading, 1));
  max-width: 12em;
  margin: 0 0 var(--space-4);
  text-wrap: balance;
}
@supports (line-height: 1cap) {
  .hero-portrait-title {
    line-height: calc(max(1.08em, 1.45cap) * var(--heading-leading, 1));
  }
}
.hero-portrait-sub {
  font-size: 1.0625rem;
  line-height: 1.55;
  max-width: 42ch;
  margin: 0 0 var(--space-5);
}
.hero-portrait-btn {
  box-sizing: border-box;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 48px;
  padding: var(--space-3) var(--space-6);
  border-radius: var(--btn-radius);
  background: var(--hero-portrait-btn-face);
  color: var(--hero-portrait-btn-ink);
  font-weight: 700;
  line-height: 1.5;
  text-decoration: none;
}
.hero-portrait-btn:hover {
  text-decoration: underline;
  text-underline-offset: 0.2em;
}
.hero-portrait-btn:focus-visible {
  outline: 3px solid var(--hero-portrait-ring);
  outline-offset: 3px;
}
@media (min-width: 48rem) {
  .hero-portrait {
    padding-block: var(--space-8);
  }
  .hero-portrait-inner {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    column-gap: var(--space-8);
  }
  .hero-portrait--start .hero-portrait-visual {
    order: -1;
  }
  .hero-portrait--end .hero-portrait-visual {
    order: 0;
  }
  /* A height, not a minimum: a taller card step never stretches it. */
  .hero-portrait-img {
    height: clamp(30rem, 52vw, 44rem);
  }
  .hero-portrait--half-bleed {
    padding-block: 0;
  }
  .hero-portrait--half-bleed .hero-portrait-inner {
    width: 100%;
    column-gap: 0;
  }
  .hero-portrait--half-bleed .hero-portrait-visual {
    margin-inline: 0;
  }
  .hero-portrait--half-bleed .hero-portrait-copy {
    padding-block: var(--space-8);
    padding-inline: var(--space-8) max(var(--space-4), calc(100% - var(--container-max) / 2));
  }
  .hero-portrait--half-bleed.hero-portrait--end .hero-portrait-copy {
    padding-inline: max(var(--space-4), calc(100% - var(--container-max) / 2)) var(--space-8);
  }
}

.hero-portrait img[data-hub-placeholder] {
  background: color-mix(in srgb, var(--color-primary) 18%, var(--color-surface));
  object-fit: contain;
}

/* Holding a signup-card: on a phone the portrait shrinks to a strip so the
   first question is on the first screen; wide, it is anchored at the top. */
@media (max-width: 47.99rem) {
  .hero-portrait-inner:has(.signup-card) .hero-portrait-img {
    height: clamp(8rem, 36vw, 10rem);
  }
}
@media (min-width: 48rem) {
  .hero-portrait-inner:has(.signup-card) {
    align-items: start;
  }
  /* Keep in step with the card's first step: the two end together. */
  .hero-portrait-inner:has(.signup-card) .hero-portrait-img {
    height: clamp(38rem, 66vw, 50rem);
  }
  .hero-portrait--half-bleed .hero-portrait-inner:has(.signup-card) .hero-portrait-img {
    height: calc(clamp(38rem, 66vw, 50rem) + 2 * var(--space-8));
  }
}
/* === /pattern hero-portrait@1 === */

/* === pattern steps-plain@6 (library v229; appended by page_assemble.py -- adopt a newer version by replacing this block, never by adding a second) === */
/* steps-plain v1 - tokens only, selectors prefixed */
.steps-plain {
  --steps-plain-cell-min: 15rem;
  --steps-plain-badge-size: 2.75rem;
  padding-block: var(--space-8);
  padding-inline: var(--space-4);
  counter-reset: steps-plain;
}
.steps-plain-inner {
  max-width: var(--container-max);
  margin-inline: auto;
}
.steps-plain-eyebrow {
  color: var(--color-text-soft);
  font-size: 0.8125rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  margin: 0 0 var(--space-3);
}
.steps-plain-title {
  font-family: var(--font-heading);
  /* Page ground and a clamp floor above 24px: both halves of the heading
   token's contract. Keep both if you edit it. */
  color: var(--color-heading);
  font-size: calc(clamp(1.75rem, 3.4vw, 2.75rem) * var(--type-scale, 1));
  font-weight: var(--weight-display, 700);
  letter-spacing: calc(-0.02em + var(--heading-tracking, 0) * 1em);
  line-height: calc(1.15 * var(--heading-leading, 1));
  margin: 0 0 var(--space-4);
  text-wrap: balance;
}
@supports (line-height: 1cap) {
  .steps-plain-title {
    line-height: calc(max(1.15em, 1.45cap) * var(--heading-leading, 1));
  }
}
.steps-plain-intro {
  color: var(--color-text-soft);
  font-size: 1rem;
  line-height: 1.6;
  max-width: 46ch;
  margin: 0 0 var(--space-6);
}
/* Phones: a divided list, the numeral in its own gutter. */
.steps-plain-list {
  display: grid;
  gap: 0;
  list-style: none;
  margin: 0;
  padding: 0;
}
.steps-plain-item {
  counter-increment: steps-plain;
  display: grid;
  grid-template-columns: var(--steps-plain-badge-size) 1fr;
  column-gap: var(--space-4);
  align-items: start;
  padding-block: var(--space-5);
  border-top: 1px solid var(--color-rule);
}
.steps-plain-item:last-child {
  border-bottom: 1px solid var(--color-rule);
}
.steps-plain-item::before {
  content: counter(steps-plain, decimal-leading-zero);
  grid-row: 1 / span 2;
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--steps-plain-badge-size);
  height: var(--steps-plain-badge-size);
  border-radius: var(--chip-radius);
  /* --color-text on --color-surface-soft: the one ink promised against every
   page ground, on the one tinted fill that is one. */
  background: var(--color-surface-soft);
  color: var(--color-text);
  font-family: var(--font-heading);
  font-size: calc(0.9375rem * var(--type-scale, 1));
  font-weight: var(--weight-display, 700);
  font-variant-numeric: tabular-nums;
}
.steps-plain-heading {
  font-family: var(--font-heading);
  color: var(--color-text);
  font-size: calc(1.125rem * var(--type-scale, 1));
  font-weight: var(--weight-display, 700);
  line-height: calc(1.3 * var(--heading-leading, 1));
  margin: 0 0 var(--space-2);
  text-wrap: balance;
}
@supports (line-height: 1cap) {
  .steps-plain-heading {
    line-height: calc(max(1.3em, 1.45cap) * var(--heading-leading, 1));
  }
}
.steps-plain-body {
  color: var(--color-text-soft);
  font-size: 0.9375rem;
  line-height: 1.6;
  margin: 0;
}
.steps-plain-note {
  color: var(--color-text-soft);
  font-size: 0.875rem;
  line-height: 1.6;
  margin: var(--space-5) 0 0;
}
/* From the tablet band the list becomes one bordered box whose cells are
   separated by the grid gap showing the ground through - not by cell borders,
   which double up wherever two cells meet. */
@media (min-width: 48rem) {
  .steps-plain {
    padding-inline: var(--space-6);
  }
  .steps-plain-list {
    grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
    gap: 1px;
    /* The hairline is drawn per cell, not by painting the container and
     letting the cells mask it: a wrapped final row leaves grid areas no cell
     covers, and those would show as a slab of rule colour. */
    background: var(--color-surface);
    border-radius: var(--card-radius);
    overflow: hidden;
  }
  .steps-plain-item {
    display: flex;
    flex-direction: column;
    min-height: var(--steps-plain-cell-min);
    padding: var(--space-5);
    background: var(--color-surface);
    border: 0;
    box-shadow: 0 0 0 1px var(--color-rule);
  }
  .steps-plain-item:last-child {
    border: 0;
  }
  .steps-plain-item::before {
    margin-bottom: var(--space-6);
  }
  /* margin-top:auto drives the copy to the cell floor, so cells carrying
   unequal amounts of it still line up as a set. */
  .steps-plain-body {
    margin-top: auto;
  }
}
.steps-plain:not(.steps-plain--moving) {
  --hub-motion: none;
}
/* === /pattern steps-plain@6 === */

/* === pattern hero-centred@8 (library v229; appended by page_assemble.py -- adopt a newer version by replacing this block, never by adding a second) === */
/* hero-centred v1 - tokens only, selectors prefixed */
.hero-centred {
  --hero-centred-title-measure: 9.4em;
  --hero-centred-sub-measure: 50ch;
  /* Portrait on phones, letterbox from the tablet band: a landscape crop
   shown at a fixed height on a narrow screen is a sliver. */
  --hero-centred-ratio: 4 / 5;
  padding-block: var(--space-8);
  padding-inline: var(--space-4);
}
.hero-centred-copy {
  max-width: var(--container-max);
  margin: 0 auto var(--space-6);
  text-align: center;
}
.hero-centred-title {
  font-family: var(--font-heading);
  /* Page ground and a clamp floor above 24px: both halves of the heading
   token's contract. Keep both if you edit it. */
  color: var(--color-heading);
  font-size: calc(clamp(2.125rem, 6vw, 4rem) * var(--type-scale, 1));
  font-weight: var(--weight-display, 700);
  letter-spacing: calc(-0.03em + var(--heading-tracking, 0) * 1em);
  line-height: calc(1.05 * var(--heading-leading, 1));
  max-width: var(--hero-centred-title-measure);
  margin: 0 auto var(--space-5);
  text-wrap: balance;
}
@supports (line-height: 1cap) {
  .hero-centred-title {
    line-height: calc(max(1.05em, 1.45cap) * var(--heading-leading, 1));
  }
}
.hero-centred-sub {
  color: var(--color-text-soft);
  font-size: clamp(1rem, 1.4vw, 1.1875rem);
  line-height: 1.6;
  max-width: var(--hero-centred-sub-measure);
  margin: 0 auto var(--space-6);
}
.hero-centred-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  /* 48px target, above the 44px AAA floor. */
  min-height: 48px;
  padding: var(--space-3) var(--space-6);
  border-radius: var(--btn-radius);
  background: var(--color-primary);
  color: var(--color-on-primary);
  font-weight: 700;
  line-height: 1.5;
  text-decoration: none;
}
.hero-centred-btn:hover {
  text-decoration: underline;
  text-underline-offset: 0.2em;
}
/* The ring lands on the page ground, where --color-focus is contracted. */
.hero-centred-btn:focus-visible {
  outline: 3px solid var(--color-focus);
  outline-offset: 3px;
}
.hero-centred-media {
  max-width: var(--container-max);
  margin-inline: auto;
  overflow: hidden;
  border-radius: var(--card-radius);
  /* A ground behind a slow or failed image, so the band keeps its shape. */
  background: var(--color-surface-soft);
}
.hero-centred-img {
  display: block;
  width: 100%;
  height: 100%;
  aspect-ratio: var(--hero-centred-ratio);
  object-fit: cover;
}
@media (min-width: 48rem) {
  .hero-centred {
    --hero-centred-ratio: 16 / 7;
    padding-inline: var(--space-6);
  }
}

.hero-centred img[data-hub-placeholder] {
  background: color-mix(in srgb, var(--color-primary) 18%, var(--color-surface));
}
/* === /pattern hero-centred@8 === */

/* === pattern zigzag-rows@12 (library v229; appended by page_assemble.py -- adopt a newer version by replacing this block, never by adding a second) === */
/* zigzag-rows v4 - tokens only, selectors prefixed */
.zigzag-rows {
  /* One ratio for every media box, set once: equal-height rows are what hold
   the rhythm down the page. */
  --zigzag-rows-media-ratio: 1 / 1;
  padding-block: var(--space-8);
}
.zigzag-rows-inner {
  width: min(100% - 2 * var(--space-4), var(--container-max));
  margin-inline: auto;
  display: grid;
  gap: var(--space-8);
}
/* Same title setting as the library's other list sections. */
.zigzag-rows-title {
  font-family: var(--font-heading);
  color: var(--color-heading);
  font-size: calc(clamp(1.75rem, 1.2rem + 2.2vw, 2.75rem) * var(--type-scale, 1));
  line-height: calc(1.1 * var(--heading-leading, 1));
  letter-spacing: calc(-0.02em + var(--heading-tracking, 0) * 1em);
  margin: 0;
  text-wrap: balance;
}
@supports (line-height: 1cap) {
  .zigzag-rows-title {
    line-height: calc(max(1.1em, 1.45cap) * var(--heading-leading, 1));
  }
}
/* Phones: one column and no order property - source order already puts the
   image first, so there is nothing to undo. */
.zigzag-rows-row {
  display: grid;
  gap: var(--space-5);
  align-items: center;
}
.zigzag-rows-media {
  aspect-ratio: var(--zigzag-rows-media-ratio);
  overflow: hidden;
  border-radius: var(--card-radius);
  box-shadow: var(--card-shadow);
  background: var(--color-surface-soft);
}
.zigzag-rows-img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.zigzag-rows-heading {
  font-family: var(--font-heading);
  color: var(--color-heading);
  font-size: calc(clamp(1.75rem, 1.2rem + 1.2vw, 2rem) * var(--type-scale, 1));
  line-height: calc(1.2 * var(--heading-leading, 1));
  letter-spacing: calc(-0.015em + var(--heading-tracking, 0) * 1em);
  margin: 0 0 var(--space-3);
  text-wrap: balance;
}
@supports (line-height: 1cap) {
  .zigzag-rows-heading {
    line-height: calc(max(1.2em, 1.45cap) * var(--heading-leading, 1));
  }
}
/* Body copy is body copy: it starts at 16px and grows. The source this came
   from set it clamp(13px, 0.9vw, 14px), which is caption size. */
.zigzag-rows-body {
  color: var(--color-text-soft);
  font-size: clamp(1rem, 0.95rem + 0.2vw, 1.125rem);
  line-height: 1.6;
  max-width: 46ch;
  margin: 0;
}
.zigzag-rows-action {
  margin: var(--space-5) 0 0;
}
/* Underlined, body size, 44px target. */
.zigzag-rows-link {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  /* --color-text: --color-primary-dark is for light grounds only. */
  color: var(--color-text);
  font-size: 1rem;
  font-weight: 700;
  line-height: 1.4;
  text-decoration: underline;
  text-decoration-thickness: from-font;
  text-underline-offset: 0.2em;
}
.zigzag-rows-link:hover {
  color: var(--color-primary-dark);
}
.zigzag-rows-link:focus-visible {
  outline: 2px solid var(--color-focus);
  outline-offset: 3px;
}
@media (min-width: 48rem) {
  .zigzag-rows {
    padding-block: var(--space-12);
  }
  .zigzag-rows-inner {
    gap: var(--space-12);
  }
  .zigzag-rows-row {
    grid-template-columns: 1fr 1fr;
    gap: var(--space-8);
  }
  /* Both halves are placed explicitly, so the alternation is a stated
     property of the row and not a side effect of auto-placement. */
  .zigzag-rows-media {
    grid-column: 1;
    grid-row: 1;
  }
  .zigzag-rows-copy {
    grid-column: 2;
    grid-row: 1;
  }
  .zigzag-rows-row--mirrored .zigzag-rows-media {
    grid-column: 2;
    grid-row: 1;
  }
  .zigzag-rows-row--mirrored .zigzag-rows-copy {
    grid-column: 1;
    grid-row: 1;
  }
  /* Guard: a mirrored row whose media holds a link, button or anything
   tabbable renders unmirrored, because flipping it would send focus
   right-then-left. A safety net where :has() is supported, not a licence. */
  .zigzag-rows-row--mirrored:has(.zigzag-rows-media :is(a, button, [tabindex])) .zigzag-rows-media {
    grid-column: 1;
  }
  .zigzag-rows-row--mirrored:has(.zigzag-rows-media :is(a, button, [tabindex])) .zigzag-rows-copy {
    grid-column: 2;
  }
}

.zigzag-rows img[data-hub-placeholder] {
  background: color-mix(in srgb, var(--color-primary) 18%, var(--color-surface));
}
.zigzag-rows:not(.zigzag-rows--moving) {
  --hub-motion: none;
}
/* === /pattern zigzag-rows@12 === */

/* === pattern cta-image@7 (library v229; appended by page_assemble.py -- adopt a newer version by replacing this block, never by adding a second) === */
/* cta-image v1 - tokens only, selectors prefixed */
.cta-image {
  /* Contrast floor: the words sit on a photograph, so the scrim carries the
   contrast and clamp() holds it whatever the dial is set to. */
  --cta-image-scrim-floor: clamp(0.92, var(--cta-image-scrim-strength, 0.92), 1);
  position: relative;
  isolation: isolate;
  display: grid;
  place-items: center;
  min-height: clamp(28rem, 60vh, 40rem);
  padding: var(--space-12) var(--space-4);
  /* Solid ground under the image, so a failed or slow image leaves the copy
   on the scrim rather than on nothing. See the README. */
  background: var(--color-scrim);
}
.cta-image-img {
  position: absolute;
  inset: 0;
  z-index: -2;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
/* Floor across the middle band where the copy sits, falling away top and
   bottom so the photograph is still a photograph. See the README. */
.cta-image::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(
    to bottom,
    color-mix(in srgb, var(--color-scrim) calc(var(--cta-image-scrim-floor) * 34%), transparent) 0%,
    color-mix(in srgb, var(--color-scrim) calc(var(--cta-image-scrim-floor) * 100%), transparent) 22%,
    color-mix(in srgb, var(--color-scrim) calc(var(--cta-image-scrim-floor) * 100%), transparent) 78%,
    color-mix(in srgb, var(--color-scrim) calc(var(--cta-image-scrim-floor) * 34%), transparent) 100%
  );
}
.cta-image-inner {
  max-width: var(--container-max);
  color: var(--color-on-scrim);
  text-align: center;
}
.cta-image-eyebrow {
  font-size: 0.8125rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  margin: 0 0 var(--space-4);
}
.cta-image-title {
  font-family: var(--font-heading);
  /* --color-heading is barred over a photograph however heavy the scrim. */
  color: var(--color-on-scrim);
  font-size: calc(clamp(2rem, 5vw, 3.5rem) * var(--type-scale, 1));
  font-weight: var(--weight-display, 700);
  letter-spacing: calc(-0.02em + var(--heading-tracking, 0) * 1em);
  line-height: calc(1.1 * var(--heading-leading, 1));
  margin: 0 0 var(--space-4);
  text-wrap: balance;
}
@supports (line-height: 1cap) {
  .cta-image-title {
    line-height: calc(max(1.1em, 1.45cap) * var(--heading-leading, 1));
  }
}
.cta-image-lead {
  font-size: 1.0625rem;
  line-height: 1.6;
  max-width: 46ch;
  margin: 0 auto var(--space-6);
}
.cta-image-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-4);
  justify-content: center;
}
.cta-image-btn,
.cta-image-ghost {
  box-sizing: border-box;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  /* 48px target, above the 44px AAA floor. */
  min-height: 48px;
  padding: var(--space-3) var(--space-6);
  border-radius: var(--btn-radius);
  font-weight: 700;
  line-height: 1.5;
  text-decoration: none;
}
.cta-image-btn {
  /* The edge identifies the control, not the fill: no token promises
   --color-primary against --color-scrim. See the README. */
  border: 2px solid var(--color-on-scrim);
  background: var(--color-primary);
  color: var(--color-on-primary);
}
.cta-image-ghost {
  border: 2px solid var(--color-on-scrim);
  background: color-mix(in srgb, var(--color-scrim) 80%, transparent);
  color: var(--color-on-scrim);
}
.cta-image-btn:hover,
.cta-image-ghost:hover {
  text-decoration: underline;
  text-underline-offset: 0.2em;
}
/* Two bands rather than one ring: what sits behind a control here is a
   photograph, which no token describes, so the indicator brings its own
   ground. See the README. */
.cta-image-btn:focus-visible,
.cta-image-ghost:focus-visible {
  outline: 3px solid var(--color-on-scrim);
  outline-offset: 3px;
  box-shadow: 0 0 0 7px var(--color-scrim);
}

/* Lighter only over a placeholder; a photograph keeps the floor above. */
.cta-image img[data-hub-placeholder] {
  background: color-mix(in srgb, var(--color-primary) 24%, var(--color-scrim));
}
.cta-image:has(> .cta-image-img[data-hub-placeholder]) {
  --cta-image-scrim-floor: 0.4;
}
/* === /pattern cta-image@7 === */

/* === pattern hero-stated@6 (library v229; appended by page_assemble.py -- adopt a newer version by replacing this block, never by adding a second) === */
/* hero-stated v1 - tokens only, selectors prefixed */
/* Each ground names its own ink, and every rule below reads the pair rather
   than a token, so nothing here knows which ground it is on. */
.hero-stated--plain {
  --hero-stated-ground: var(--color-bg);
  --hero-stated-ink: var(--color-text-soft);
  --hero-stated-title-ink: var(--color-heading);
  --hero-stated-btn-face: var(--color-primary);
  --hero-stated-btn-ink: var(--color-on-primary);
  --hero-stated-ring: var(--color-focus);
}
.hero-stated--brand {
  --hero-stated-ground: var(--color-primary);
  --hero-stated-ink: var(--color-on-primary);
  --hero-stated-title-ink: var(--color-on-primary);
  --hero-stated-btn-face: var(--color-on-primary);
  --hero-stated-btn-ink: var(--color-primary);
  --hero-stated-ring: var(--color-on-primary);
}
.hero-stated--deep {
  --hero-stated-ground: var(--color-scrim);
  --hero-stated-ink: var(--color-on-scrim);
  --hero-stated-title-ink: var(--color-on-scrim);
  --hero-stated-btn-face: var(--color-primary);
  --hero-stated-btn-ink: var(--color-on-primary);
  --hero-stated-ring: var(--color-on-scrim);
}
.hero-stated {
  padding-block: var(--space-12);
  padding-inline: var(--space-4);
  background: var(--hero-stated-ground);
  color: var(--hero-stated-ink);
}
.hero-stated-inner {
  max-width: var(--container-max);
  margin-inline: auto;
}
.hero-stated-eyebrow {
  font-size: 0.8125rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  margin: 0 0 var(--space-4);
}
.hero-stated-title {
  font-family: var(--font-heading);
  /* On the plain ground this is --color-heading, which the contract promises
   at the large-text bar against --color-bg; the clamp floor is 40px. On the
   other two grounds it is that ground's own ink. */
  color: var(--hero-stated-title-ink);
  font-size: calc(clamp(2.5rem, 7vw, 4.5rem) * var(--type-scale, 1));
  font-weight: var(--weight-display, 700);
  letter-spacing: calc(-0.03em + var(--heading-tracking, 0) * 1em);
  line-height: calc(1.02 * var(--heading-leading, 1));
  max-width: 10.75em;
  margin: 0 0 var(--space-5);
  text-wrap: balance;
}
@supports (line-height: 1cap) {
  .hero-stated-title {
    line-height: calc(max(1.02em, 1.45cap) * var(--heading-leading, 1));
  }
}
.hero-stated-sub {
  font-size: clamp(1.0625rem, 1.7vw, 1.25rem);
  line-height: 1.55;
  max-width: 46ch;
  margin: 0 0 var(--space-6);
}
.hero-stated-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  /* 52px: on a page whose opener carries no image, this is what the eye
   lands on after the words. */
  min-height: 52px;
  padding: var(--space-3) var(--space-6);
  border-radius: var(--btn-radius);
  background: var(--hero-stated-btn-face);
  color: var(--hero-stated-btn-ink);
  font-size: 1.0625rem;
  font-weight: 700;
  line-height: 1.5;
  text-decoration: none;
}
.hero-stated-btn:hover {
  text-decoration: underline;
  text-underline-offset: 0.2em;
}
/* The ring is the ground's own, so one rule is right on all three. */
.hero-stated-btn:focus-visible {
  outline: 3px solid var(--hero-stated-ring);
  outline-offset: 4px;
}
.hero-stated--centred .hero-stated-inner {
  text-align: center;
}
.hero-stated--centred .hero-stated-title,
.hero-stated--centred .hero-stated-sub {
  margin-inline: auto;
}
@media (min-width: 48rem) {
  .hero-stated {
    padding-inline: var(--space-8);
  }
}

/* Holding a signup-card in place of the join button. */
.hero-stated--centred .signup-card {
  margin-inline: auto;
}
/* Wide: the words on the left, the card on the right, and the first step
   above the fold. */
@media (min-width: 60rem) {
  .hero-stated:has(.signup-card) {
    padding-block: var(--space-6) var(--space-8);
  }
  .hero-stated-inner:has(.signup-card) {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 24rem;
    column-gap: var(--space-8);
    align-items: start;
  }
  .hero-stated-inner:has(.signup-card) > :not(.hero-stated-cta) {
    grid-column: 1;
  }
  .hero-stated-inner:has(.signup-card) > .hero-stated-cta {
    grid-column: 2;
    grid-row: 1 / span 6;
  }
}
/* === /pattern hero-stated@6 === */

/* === pattern feature-panels@6 (library v229; appended by page_assemble.py -- adopt a newer version by replacing this block, never by adding a second) === */
/* feature-panels v1 - tokens only, selectors prefixed */
.feature-panels {
  --feature-panels-min: 20rem;
  --feature-panels-height: clamp(24rem, 46vh, 34rem);
  padding-block: var(--space-8) 0;
}
.feature-panels-head {
  max-width: var(--container-max);
  margin: 0 auto var(--space-6);
  padding-inline: var(--space-4);
}
.feature-panels-eyebrow {
  color: var(--color-text-soft);
  font-size: 0.8125rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  margin: 0 0 var(--space-3);
}
.feature-panels-title {
  font-family: var(--font-heading);
  /* Page ground and a clamp floor above 24px: both halves of the heading
   token's contract. Keep both if you edit it. */
  color: var(--color-heading);
  font-size: calc(clamp(1.75rem, 3.4vw, 2.75rem) * var(--type-scale, 1));
  font-weight: var(--weight-display, 700);
  letter-spacing: calc(-0.02em + var(--heading-tracking, 0) * 1em);
  line-height: calc(1.15 * var(--heading-leading, 1));
  margin: 0 0 var(--space-4);
  text-wrap: balance;
}
@supports (line-height: 1cap) {
  .feature-panels-title {
    line-height: calc(max(1.15em, 1.45cap) * var(--heading-leading, 1));
  }
}
.feature-panels-intro {
  color: var(--color-text-soft);
  font-size: 1rem;
  line-height: 1.6;
  max-width: 46ch;
  margin: 0;
}
/* Edge to edge, no gutters and no radius: the panels are the section. */
.feature-panels-list {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(var(--feature-panels-min), 1fr));
  gap: 0;
  list-style: none;
  margin: 0;
  padding: 0;
}
/* Each panel names a ground, and its ink is the one the contract states
   against that ground. Everything below reads both through these two
   properties, which is why nothing here needs to know which panel it is. */
.feature-panels-item--light {
  --feature-panels-ground: var(--color-surface-soft);
  --feature-panels-ink: var(--color-text);
}
.feature-panels-item--brand {
  --feature-panels-ground: var(--color-primary);
  --feature-panels-ink: var(--color-on-primary);
}
.feature-panels-item--deep {
  --feature-panels-ground: var(--color-scrim);
  --feature-panels-ink: var(--color-on-scrim);
}
.feature-panels-item {
  display: flex;
  flex-direction: column;
  min-height: var(--feature-panels-height);
  padding: var(--space-6);
  background: var(--feature-panels-ground);
  color: var(--feature-panels-ink);
}
.feature-panels-mark {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  font-size: 0.8125rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  margin: 0 0 var(--space-8);
}
.feature-panels-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  width: 2rem;
  height: 2rem;
  border-radius: var(--chip-radius);
  /* The mark's own ground is the panel ink at low strength, so it reads on
   every one of the three without needing a fourth pair. */
  background: color-mix(in srgb, var(--feature-panels-ink) 16%, transparent);
}
.feature-panels-icon svg {
  display: block;
  width: 1.125rem;
  height: 1.125rem;
}
.feature-panels-claim {
  font-family: var(--font-heading);
  /* The panel ink, never --color-heading: every panel paints its own ground
   and that token is promised against --color-bg alone. */
  color: var(--feature-panels-ink);
  font-size: calc(clamp(1.5rem, 2.6vw, 2.125rem) * var(--type-scale, 1));
  font-weight: var(--weight-display, 700);
  letter-spacing: calc(-0.02em + var(--heading-tracking, 0) * 1em);
  line-height: calc(1.15 * var(--heading-leading, 1));
  margin: 0;
  text-wrap: balance;
}
@supports (line-height: 1cap) {
  .feature-panels-claim {
    line-height: calc(max(1.15em, 1.45cap) * var(--heading-leading, 1));
  }
}
/* margin-top:auto pins the link to the panel floor, so panels holding claims
   of unequal length still line their links up across the row. */
.feature-panels-action {
  margin: auto 0 0;
  padding-top: var(--space-6);
}
.feature-panels-link {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  /* 44px target on a link that carries no padding of its own. */
  min-height: 44px;
  color: var(--feature-panels-ink);
  font-weight: 700;
  /* Underlined, not tinted: colour is never the only thing marking a link,
   and on three different grounds a tint could not be either. */
  text-decoration: underline;
  text-underline-offset: 0.2em;
}
.feature-panels-arrow {
  transition: translate var(--transition-fast) ease-out;
}
.feature-panels-link:hover .feature-panels-arrow,
.feature-panels-link:focus-visible .feature-panels-arrow {
  translate: 0.25rem 0;
}
/* The ring is the panel's own ink, which is by definition the one colour the
   contract promises against that panel's ground - so one rule is guaranteed
   on all three, where --color-focus would not be. See the README. */
.feature-panels-link:focus-visible {
  outline: 3px solid var(--feature-panels-ink);
  outline-offset: 3px;
}
@media (prefers-reduced-motion: reduce) {
  .feature-panels-arrow {
    transition: none;
  }
}
@media (min-width: 48rem) {
  .feature-panels-head {
    padding-inline: var(--space-6);
  }
  .feature-panels-item {
    padding: var(--space-8);
  }
}
/* === /pattern feature-panels@6 === */


/* === pattern prose-column@6 (library v229; appended by page_assemble.py -- adopt a newer version by replacing this block, never by adding a second) === */
/* prose-column v1 - tokens only, selectors prefixed */
.prose-column {
  --prose-column-measure: 68ch;
  width: min(100% - 2 * var(--space-4), var(--prose-column-measure));
  margin-inline: auto;
  padding-block: var(--space-6);
  color: var(--color-text);
  font-size: 1.0625rem;
  line-height: 1.7;
}
.prose-column > :first-child {
  margin-top: 0;
}
.prose-column > :last-child {
  margin-bottom: 0;
}
.prose-column p {
  margin: 0 0 var(--space-5);
}
.prose-column h2,
.prose-column h3 {
  font-family: var(--font-heading);
  letter-spacing: calc(-0.02em + var(--heading-tracking, 0) * 1em);
  line-height: calc(1.2 * var(--heading-leading, 1));
  text-wrap: balance;
}
@supports (line-height: 1cap) {
  .prose-column h2,
  .prose-column h3 {
    line-height: calc(max(1.2em, 1.45cap) * var(--heading-leading, 1));
  }
}
/* --color-heading on an h2 only: the clamp floor is 28px, above the size the
   token is promised at, and the column paints no ground of its own. */
.prose-column h2 {
  color: var(--color-heading);
  font-size: calc(clamp(1.75rem, 3vw, 2.25rem) * var(--type-scale, 1));
  font-weight: var(--weight-display, 700);
  margin: var(--space-8) 0 var(--space-4);
}
/* h3 is under the size the heading token covers, so it takes the body ink. */
.prose-column h3 {
  color: var(--color-text);
  font-size: calc(1.25rem * var(--type-scale, 1));
  font-weight: var(--weight-display, 700);
  margin: var(--space-6) 0 var(--space-3);
}
.prose-column ul,
.prose-column ol {
  margin: 0 0 var(--space-5);
  padding-inline-start: var(--space-6);
}
.prose-column li {
  margin-bottom: var(--space-2);
}
.prose-column li::marker {
  color: var(--color-text-soft);
}
.prose-column a {
  /* Inherit: the underline carries the affordance, on every ground and in
   every ink. See the README. */
  color: inherit;
  text-decoration: underline;
  text-underline-offset: 0.18em;
}
.prose-column a:hover {
  text-decoration-thickness: 2px;
}
.prose-column a:focus-visible {
  outline: 3px solid var(--color-focus);
  outline-offset: 2px;
}
.prose-column blockquote {
  margin: var(--space-6) 0;
  padding-inline-start: var(--space-5);
  /* The rule is decoration beside a quote the <blockquote> already marks up,
   so a brand may set it as soft as it likes. */
  border-inline-start: 3px solid var(--color-rule);
}
.prose-column blockquote p {
  font-size: 1.1875rem;
  line-height: 1.55;
  margin-bottom: var(--space-3);
}
.prose-column cite {
  color: var(--color-text-soft);
  font-size: 0.9375rem;
  font-style: normal;
}
/* A table is wider than a phone and says so: it scrolls inside its own box
   rather than making the page scroll sideways. */
.prose-column figure {
  margin: var(--space-6) 0;
  overflow-x: auto;
}
.prose-column table {
  border-collapse: collapse;
  width: 100%;
  min-width: 28rem;
  font-size: 0.9375rem;
}
.prose-column caption {
  color: var(--color-text-soft);
  font-size: 0.875rem;
  text-align: start;
  margin-bottom: var(--space-3);
}
.prose-column th,
.prose-column td {
  text-align: start;
  padding: var(--space-3);
  border-bottom: 1px solid var(--color-rule);
  vertical-align: top;
}
.prose-column thead th {
  background: var(--color-surface-soft);
  border-bottom-width: 2px;
}
.prose-column tbody th {
  font-weight: 700;
}
.prose-column td {
  color: var(--color-text-soft);
}
.prose-column thead th:first-child {
  border-start-start-radius: var(--card-radius);
}
.prose-column thead th:last-child {
  border-start-end-radius: var(--card-radius);
}
/* === /pattern prose-column@6 === */

/* === pattern member-filter@1 (library v229; appended by page_assemble.py -- adopt a newer version by replacing this block, never by adding a second) === */
/* member-filter v1 - tokens only, selectors prefixed.
   The panels below are filled by member-grid, which owns their look. */
.member-filter {
  min-inline-size: 0;
  margin: 0;
  padding: 0;
  border: 0;
}
.member-filter-legend {
  padding: 0;
  margin-bottom: var(--space-3);
  color: var(--color-text-soft);
  font-size: 0.8rem;
  font-weight: 700;
}
/* Off-screen but focusable, so the pill still takes the keyboard and the
   radio group is still announced. display:none would remove both. */
.member-filter-radio {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  border: 0;
  overflow: hidden;
  white-space: nowrap;
  clip-path: inset(50%);
}
.member-filter-tab {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  margin: 0 var(--space-2) var(--space-5) 0;
  padding: var(--space-2) var(--space-5);
  border: 1.5px solid color-mix(in srgb, var(--color-primary) 28%, transparent);
  border-radius: var(--chip-radius);
  background: var(--color-surface);
  color: var(--color-primary);
  font-size: 0.85rem;
  font-weight: 700;
  cursor: pointer;
}
.member-filter-tab:hover {
  background: color-mix(in srgb, var(--color-primary) 10%, var(--color-surface));
}
.member-filter-radio:checked + .member-filter-tab {
  border-color: var(--color-primary);
  background: var(--color-primary);
  color: var(--color-on-primary);
}
.member-filter-radio:focus-visible + .member-filter-tab {
  outline: 3px solid var(--color-focus);
  outline-offset: 2px;
  border-radius: var(--chip-radius);
}
/* The switch. Later-sibling only, which is why the radios sit above the
   panels and why nothing may be wrapped around either. */
.member-filter-panel {
  display: none;
}
/* A panel holds whatever the page puts in it, so it may never be the reason
   the viewport scrolls sideways. */
.member-filter-panel img {
  max-width: 100%;
  height: auto;
}
.member-filter-radio--one:checked ~ .member-filter-panel--one,
.member-filter-radio--two:checked ~ .member-filter-panel--two,
.member-filter-radio--three:checked ~ .member-filter-panel--three {
  display: block;
}

@media (prefers-reduced-motion: no-preference) {
  .member-filter-tab {
    transition: background var(--transition-fast),
                color var(--transition-fast),
                border-color var(--transition-fast);
  }
}
/* === /pattern member-filter@1 === */

/* === pattern link-cluster@7 (library v229; appended by page_assemble.py -- adopt a newer version by replacing this block, never by adding a second) === */
/* link-cluster v1 - tokens only, selectors prefixed */
/* Each ground names its own ink and pill face; every rule reads the pair. */
.link-cluster--plain {
  --link-cluster-ground: var(--color-bg);
  --link-cluster-ink: var(--color-text);
  --link-cluster-quiet: var(--color-text-soft);
  --link-cluster-title-ink: var(--color-heading);
  --link-cluster-face: var(--color-surface);
  --link-cluster-ring: var(--color-focus);
  --link-cluster-edge: var(--color-rule);
}
.link-cluster--soft {
  --link-cluster-ground: var(--color-surface-soft);
  --link-cluster-ink: var(--color-text);
  --link-cluster-quiet: var(--color-text-soft);
  --link-cluster-title-ink: var(--color-text);
  --link-cluster-face: var(--color-surface);
  --link-cluster-ring: var(--color-focus);
  --link-cluster-edge: var(--color-rule);
}
.link-cluster--brand {
  --link-cluster-ground: var(--color-primary);
  --link-cluster-ink: var(--color-primary);
  --link-cluster-quiet: var(--color-on-primary);
  --link-cluster-title-ink: var(--color-on-primary);
  --link-cluster-face: var(--color-on-primary);
  --link-cluster-ring: var(--color-on-primary);
  --link-cluster-edge: transparent;
}
.link-cluster {
  padding-block: var(--space-8);
  padding-inline: var(--space-4);
  background: var(--link-cluster-ground);
}
.link-cluster-inner {
  max-width: var(--container-max);
  margin-inline: auto;
  text-align: center;
}
.link-cluster-title {
  font-family: var(--font-heading);
  color: var(--link-cluster-title-ink);
  font-size: calc(clamp(1.75rem, 2.8vw, 2.25rem) * var(--type-scale, 1));
  font-weight: var(--weight-display, 700);
  letter-spacing: calc(-0.02em + var(--heading-tracking, 0) * 1em);
  line-height: calc(1.2 * var(--heading-leading, 1));
  margin: 0 0 var(--space-3);
  text-wrap: balance;
}
@supports (line-height: 1cap) {
  .link-cluster-title {
    line-height: calc(max(1.2em, 1.45cap) * var(--heading-leading, 1));
  }
}
.link-cluster-intro {
  color: var(--link-cluster-quiet);
  font-size: 1rem;
  line-height: 1.6;
  max-width: 46ch;
  margin: 0 auto var(--space-5);
}
.link-cluster-list {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-2);
  list-style: none;
  margin: 0;
  padding: 0;
}
/* The pill is a target before it is a shape: 44px is the floor, and the
   horizontal padding is what keeps two short place names apart. */
.link-cluster-link {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: var(--space-2) var(--space-4);
  border: 1px solid var(--link-cluster-edge);
  border-radius: var(--chip-radius);
  /* The face alone does not separate a pill from the ground on a brand whose
   surface and surface-soft are nearly the same colour, so the edge is drawn
   on the two grounds where that can happen. */
  background: var(--link-cluster-face);
  color: var(--link-cluster-ink);
  font-size: 0.9375rem;
  font-weight: 700;
  line-height: 1.3;
  text-decoration: none;
}
.link-cluster-link:hover {
  text-decoration: underline;
  text-underline-offset: 0.2em;
}
.link-cluster-link:focus-visible {
  outline: 3px solid var(--link-cluster-ring);
  outline-offset: 3px;
}
/* === /pattern link-cluster@7 === */

/* === pattern anchored-split@4 (library v229; appended by page_assemble.py -- adopt a newer version by replacing this block, never by adding a second) === */
/* anchored-split v2 - tokens only, selectors prefixed */
/* Both sides share one ground; every rule reads this set. The base carries the
   plain ground's values, so a copy that loses its modifier still renders. */
.anchored-split,
.anchored-split--plain {
  --anchored-split-ground: var(--color-bg);
  --anchored-split-ink: var(--color-text);
  --anchored-split-quiet: var(--color-text-soft);
  --anchored-split-title-ink: var(--color-heading, var(--color-text));
  --anchored-split-edge: var(--color-rule, color-mix(in srgb, var(--color-text) 18%, transparent));
}
.anchored-split--soft {
  --anchored-split-ground: var(--color-surface-soft);
  --anchored-split-ink: var(--color-text);
  --anchored-split-quiet: var(--color-text-soft);
  --anchored-split-title-ink: var(--color-text);
  --anchored-split-edge: var(--color-rule, color-mix(in srgb, var(--color-text) 18%, transparent));
}
.anchored-split {
  padding-block: var(--space-8);
  padding-inline: var(--space-4);
  background: var(--anchored-split-ground);
  color: var(--anchored-split-ink);
}
.anchored-split-inner {
  max-width: var(--container-max, 72rem);
  margin-inline: auto;
  display: grid;
  gap: var(--space-6);
}
.anchored-split-eyebrow {
  color: var(--anchored-split-quiet);
  font-size: 0.8125rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  margin: 0 0 var(--space-3);
}
.anchored-split-title {
  font-family: var(--font-heading);
  color: var(--anchored-split-title-ink);
  font-size: calc(clamp(1.75rem, 3vw, 2.75rem) * var(--type-scale, 1));
  line-height: calc(1.12 * var(--heading-leading, 1));
  letter-spacing: calc(-0.02em + var(--heading-tracking, 0) * 1em);
  margin: 0 0 var(--space-4);
  max-width: 11.25em;
  text-wrap: balance;
}
@supports (line-height: 1cap) {
  .anchored-split-title {
    line-height: calc(max(1.12em, 1.45cap) * var(--heading-leading, 1));
  }
}
.anchored-split-lede {
  color: var(--anchored-split-quiet);
  font-size: 1.0625rem;
  line-height: 1.55;
  max-width: 40ch;
  margin: 0;
}
.anchored-split-entry {
  padding-block: var(--space-5);
  border-block-start: 1px solid var(--anchored-split-edge);
}
.anchored-split-entry:first-child {
  border-block-start: 0;
  padding-block-start: 0;
}
.anchored-split-entry-title {
  font-family: var(--font-heading);
  color: var(--anchored-split-ink);
  font-size: calc(1.25rem * var(--type-scale, 1));
  font-weight: var(--weight-display, 700);
  line-height: calc(1.25 * var(--heading-leading, 1));
  margin: 0 0 var(--space-3);
}
@supports (line-height: 1cap) {
  .anchored-split-entry-title {
    line-height: calc(max(1.25em, 1.45cap) * var(--heading-leading, 1));
  }
}
.anchored-split-entry-body {
  color: var(--anchored-split-ink);
  font-size: 1rem;
  line-height: 1.6;
  max-width: 62ch;
  margin: 0;
}
/* The asymmetry is the point - 40/60, never 50/50, which reads as
   indecision. Below this width the two stack and nothing sticks, which is
   the correct behaviour rather than a fallback: on a phone there is no
   second column for the anchor to stay beside. */
@media (min-width: 60rem) {
  .anchored-split {
    padding-inline: var(--space-8);
  }
  .anchored-split-inner {
    grid-template-columns: 4fr 6fr;
    gap: var(--space-8);
    align-items: start;
  }
  /* align-self is what keeps the panel its own height. Without it the grid
     stretches it to the row and it sticks with nothing above it to hold. */
  .anchored-split-anchor {
    position: sticky;
    inset-block-start: var(--space-6);
    align-self: start;
  }
}
/* === /pattern anchored-split@4 === */

/* === pattern listing-rows@4 (library v229; appended by page_assemble.py -- adopt a newer version by replacing this block, never by adding a second) === */
/* listing-rows v2 - tokens only, selectors prefixed */
/* Each ground names its own ink set, and every rule below reads that set. The
   base carries the plain ground's values, so a copy that loses its modifier
   still has a ground, a hairline and a focus ring. */
.listing-rows,
.listing-rows--plain {
  --listing-rows-ground: var(--color-bg);
  --listing-rows-ink: var(--color-text);
  --listing-rows-quiet: var(--color-text-soft);
  --listing-rows-title-ink: var(--color-heading, var(--color-text));
  --listing-rows-edge: var(--color-rule, color-mix(in srgb, var(--color-text) 18%, transparent));
  --listing-rows-ring: var(--color-focus, var(--color-primary));
}
.listing-rows--soft {
  --listing-rows-ground: var(--color-surface-soft);
  --listing-rows-ink: var(--color-text);
  --listing-rows-quiet: var(--color-text-soft);
  --listing-rows-title-ink: var(--color-text);
  --listing-rows-edge: var(--color-rule, color-mix(in srgb, var(--color-text) 18%, transparent));
  --listing-rows-ring: var(--color-focus, var(--color-primary));
}
/* The fallback ink here is --color-surface, not --color-bg. Do not "tidy" it
   to match the other grounds: on some brands the page ground fails against
   the primary and the surface does not. See the README. */
.listing-rows--brand {
  --listing-rows-ground: var(--color-primary);
  --listing-rows-ink: var(--color-on-primary, var(--color-surface));
  --listing-rows-quiet: var(--color-on-primary, var(--color-surface));
  --listing-rows-title-ink: var(--color-on-primary, var(--color-surface));
  --listing-rows-edge: color-mix(in srgb, var(--color-on-primary, var(--color-surface)) 35%, transparent);
  --listing-rows-ring: var(--color-on-primary, var(--color-surface));
}
.listing-rows {
  padding-block: var(--space-8);
  padding-inline: var(--space-4);
  background: var(--listing-rows-ground);
  color: var(--listing-rows-ink);
}
.listing-rows-inner {
  max-width: var(--container-max, 72rem);
  margin-inline: auto;
}
.listing-rows-title {
  font-family: var(--font-heading);
  color: var(--listing-rows-title-ink);
  font-size: calc(clamp(1.75rem, 3vw, 2.5rem) * var(--type-scale, 1));
  line-height: calc(1.15 * var(--heading-leading, 1));
  letter-spacing: calc(-0.02em + var(--heading-tracking, 0) * 1em);
  margin: 0 0 var(--space-3);
  text-wrap: balance;
}
@supports (line-height: 1cap) {
  .listing-rows-title {
    line-height: calc(max(1.15em, 1.45cap) * var(--heading-leading, 1));
  }
}
.listing-rows-intro {
  color: var(--listing-rows-quiet);
  font-size: 1.0625rem;
  line-height: 1.55;
  max-width: 52ch;
  margin: 0 0 var(--space-6);
}
.listing-rows-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  border-block-start: 1px solid var(--listing-rows-edge);
}
.listing-rows-item {
  display: grid;
  grid-column: 1 / -1;
  gap: var(--space-2) var(--space-5);
  padding-block: var(--space-5);
  border-block-end: 1px solid var(--listing-rows-edge);
}
.listing-rows-link {
  font-family: var(--font-heading);
  color: var(--listing-rows-ink);
  font-size: calc(1.1875rem * var(--type-scale, 1));
  font-weight: var(--weight-display, 700);
  line-height: calc(1.3 * var(--heading-leading, 1));
  text-decoration: none;
  /* 24px, held independently of the type scale: at --type-scale 0.9 the line
     box alone is 22.2px and this is the only tap target in the row. */
  min-block-size: 1.5rem;
}
@supports (line-height: 1cap) {
  .listing-rows-link {
    line-height: calc(max(1.3em, 1.45cap) * var(--heading-leading, 1));
  }
}
.listing-rows-link:hover {
  text-decoration: underline;
  text-underline-offset: 0.2em;
}
.listing-rows-link:focus-visible {
  outline: 3px solid var(--listing-rows-ring);
  outline-offset: 3px;
}
.listing-rows-summary {
  color: var(--listing-rows-quiet);
  font-size: 1rem;
  line-height: 1.5;
  max-width: 64ch;
  margin: 0;
}
.listing-rows-meta,
.listing-rows-when {
  color: var(--listing-rows-quiet);
  font-size: 0.875rem;
  line-height: 1.4;
}
@media (min-width: 48rem) {
  .listing-rows {
    padding-inline: var(--space-8);
  }
  /* Change the column count here and in the markup together. */
  .listing-rows-list {
    grid-template-columns: 1fr auto auto;
  }
  .listing-rows-item {
    grid-template-columns: subgrid;
  }
  .listing-rows-link {
    grid-column: 1;
    grid-row: 1;
  }
  .listing-rows-meta {
    grid-column: 2;
    grid-row: 1;
    text-align: right;
  }
  .listing-rows-when {
    grid-column: 3;
    grid-row: 1;
    text-align: right;
  }
  .listing-rows-summary {
    grid-column: 1 / -1;
    grid-row: 2;
  }
}
/* === /pattern listing-rows@4 === */

/* === pattern media-card-grid@14 (library v229; appended by page_assemble.py -- adopt a newer version by replacing this block, never by adding a second) === */
/* media-card-grid v5 - tokens only, selectors prefixed */
.media-card-grid {
  /* Contrast floor. The words sit on a photograph, so the scrim carries the
   contrast; clamp() holds it whatever the dial is set to. */
  --media-card-grid-scrim-floor: clamp(0.92, var(--media-card-grid-scrim-strength, 0.92), 1);
  --media-card-grid-ratio: 5 / 6;
  padding-block: var(--space-8);
}
.media-card-grid-inner {
  width: min(100% - 2 * var(--space-4), var(--container-max));
  margin-inline: auto;
}
.media-card-grid-title {
  font-family: var(--font-heading);
  color: var(--color-heading);
  font-size: calc(clamp(1.75rem, 1.2rem + 2.2vw, 2.75rem) * var(--type-scale, 1));
  line-height: calc(1.1 * var(--heading-leading, 1));
  letter-spacing: calc(-0.02em + var(--heading-tracking, 0) * 1em);
  margin: 0 0 var(--space-6);
  text-wrap: balance;
}
@supports (line-height: 1cap) {
  .media-card-grid-title {
    line-height: calc(max(1.1em, 1.45cap) * var(--heading-leading, 1));
  }
}
.media-card-grid-list {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(17rem, 100%), 1fr));
  gap: var(--space-5);
  align-items: stretch;
  list-style: none;
  margin: 0;
  padding: 0;
}
/* One grid cell, two stacked layers: photograph and scrim. */
.media-card-grid-item {
  position: relative;
  display: grid;
  grid-template-areas: "media";
  aspect-ratio: var(--media-card-grid-ratio);
  overflow: hidden;
  border-radius: var(--card-radius);
  box-shadow: var(--card-shadow);
  background: var(--color-surface-soft);
  isolation: isolate;
}
.media-card-grid-img,
.media-card-grid-scrim {
  grid-area: media;
}
.media-card-grid-img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
/* The full level is held to the top of the text band, then fades. */
.media-card-grid-scrim {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  padding: var(--space-5);
  color: var(--color-on-scrim);
  background-image: linear-gradient(
    to top,
    color-mix(in srgb, var(--color-scrim) calc(var(--media-card-grid-scrim-floor) * 100%), transparent) 0%,
    color-mix(in srgb, var(--color-scrim) calc(var(--media-card-grid-scrim-floor) * 100%), transparent) 45%,
    color-mix(in srgb, var(--color-scrim) calc(var(--media-card-grid-scrim-floor) * 58%), transparent) 70%,
    transparent 100%
  );
}
/* The chip stays in flow, so a wrapping label pushes rather than covers. */
.media-card-grid-chip {
  margin: 0;
  background: var(--color-surface);
  color: var(--color-text);
  font-size: 0.8125rem;
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: 0.03em;
  padding: var(--space-2) var(--space-3);
  border-radius: var(--chip-radius);
}
/* margin-top:auto keeps the cue on the floor of every card. */
.media-card-grid-text {
  margin-top: auto;
  padding-top: var(--space-6);
}
.media-card-grid-heading {
  /* Set, not inherited: a brand's own h3 { color } beats inheritance. */
  color: var(--color-on-scrim);
  font-family: var(--font-heading);
  font-size: calc(clamp(1.125rem, 0.95rem + 0.7vw, 1.4375rem) * var(--type-scale, 1));
  line-height: calc(1.2 * var(--heading-leading, 1));
  letter-spacing: calc(-0.015em + var(--heading-tracking, 0) * 1em);
  margin: 0 0 var(--space-2);
  text-wrap: balance;
}
@supports (line-height: 1cap) {
  .media-card-grid-heading {
    line-height: calc(max(1.2em, 1.45cap) * var(--heading-leading, 1));
  }
}
/* One link per card, and it is the heading. ::after makes the whole card
   the target without nesting anything inside the link. */
.media-card-grid-link {
  color: inherit;
  text-decoration: none;
}
.media-card-grid-link::after {
  content: "";
  position: absolute;
  inset: 0;
}
.media-card-grid-link:hover {
  text-decoration: underline;
  text-underline-offset: 0.2em;
}
/* Drawn inside the card's edge, which clips overflow. Three bands, so one
   of them contrasts against any photograph. */
.media-card-grid-link:focus-visible::after {
  outline: 2px solid var(--color-focus);
  outline-offset: calc(-1 * var(--space-1));
  /* Name the radius: border-radius is not inherited, so `inherit` would take
   the parent's, which is none. */
  border-radius: var(--card-radius);
  box-shadow: 0 0 0 2px var(--color-on-scrim) inset,
              0 0 0 6px var(--color-scrim) inset;
}
.media-card-grid-copy {
  margin: 0;
  font-size: clamp(0.875rem, 0.82rem + 0.25vw, 0.9375rem);
  line-height: 1.45;
}
.media-card-grid-cue {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  margin: var(--space-4) 0 0;
  font-size: 0.875rem;
  font-weight: 700;
}
.media-card-grid-cue::after {
  content: "\2192";
}
/* On hover the gap widens, so the arrow steps away from its words. */
@media (prefers-reduced-motion: no-preference) {
  .media-card-grid-cue {
    transition: gap var(--transition-fast) ease-out;
  }
  .media-card-grid-img {
    transition: scale var(--transition-slow) ease-out;
  }
  .media-card-grid-item:hover .media-card-grid-cue,
  .media-card-grid-item:focus-within .media-card-grid-cue {
    gap: var(--space-4);
  }
  .media-card-grid--moving .media-card-grid-item:hover .media-card-grid-img,
  .media-card-grid--moving .media-card-grid-item:focus-within .media-card-grid-img {
    scale: 1.03;
  }
}
/* Narrow cards cannot carry the full inset and still leave the copy room. */
@media (max-width: 29.99rem) {
  .media-card-grid-scrim {
    padding: var(--space-4);
  }
  .media-card-grid-text {
    padding-top: var(--space-5);
  }
}
.media-card-grid:not(.media-card-grid--moving) {
  --hub-motion: none;
}
/* === /pattern media-card-grid@14 === */

/* === pattern photo-cards@8 (library v229; appended by page_assemble.py -- adopt a newer version by replacing this block, never by adding a second) === */
/* photo-cards v1 - tokens only, selectors prefixed */
.photo-cards {
  --photo-cards-min: 17rem;
  --photo-cards-ratio: 3 / 2;
  padding-block: var(--space-8);
  padding-inline: var(--space-4);
}
.photo-cards-inner {
  max-width: var(--container-max);
  margin-inline: auto;
}
.photo-cards-title {
  font-family: var(--font-heading);
  /* Page ground and a clamp floor above 24px: both halves of the heading
   token's contract. Keep both if you edit it. */
  color: var(--color-heading);
  font-size: calc(clamp(1.75rem, 3.4vw, 2.75rem) * var(--type-scale, 1));
  font-weight: var(--weight-display, 700);
  letter-spacing: calc(-0.02em + var(--heading-tracking, 0) * 1em);
  line-height: calc(1.15 * var(--heading-leading, 1));
  margin: 0 0 var(--space-6);
  text-wrap: balance;
}
@supports (line-height: 1cap) {
  .photo-cards-title {
    line-height: calc(max(1.15em, 1.45cap) * var(--heading-leading, 1));
  }
}
.photo-cards-list {
  display: grid;
  gap: var(--space-5);
  grid-template-columns: repeat(auto-fit, minmax(var(--photo-cards-min), 1fr));
  list-style: none;
  margin: 0;
  padding: 0;
}
.photo-cards-item {
  position: relative;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  background: var(--color-surface);
  border: var(--card-border);
  border-radius: var(--card-radius);
  box-shadow: var(--card-shadow);
}
.photo-cards-img {
  display: block;
  width: 100%;
  aspect-ratio: var(--photo-cards-ratio);
  object-fit: cover;
  /* A ground behind a slow or failed image, so the card keeps its shape. */
  background: var(--color-surface-soft);
}
.photo-cards-text {
  display: flex;
  flex-direction: column;
  flex: 1;
  padding: var(--space-5);
}
.photo-cards-chip {
  align-self: flex-start;
  padding: 0.15rem var(--space-3);
  border-radius: var(--chip-radius);
  background: var(--color-surface-soft);
  color: var(--color-text);
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  margin: 0 0 var(--space-3);
}
.photo-cards-heading {
  font-family: var(--font-heading);
  /* A card is not --color-bg, so the heading token promises nothing here. */
  color: var(--color-text);
  font-size: calc(1.1875rem * var(--type-scale, 1));
  font-weight: var(--weight-display, 700);
  line-height: calc(1.3 * var(--heading-leading, 1));
  margin: 0 0 var(--space-2);
  text-wrap: balance;
}
@supports (line-height: 1cap) {
  .photo-cards-heading {
    line-height: calc(max(1.3em, 1.45cap) * var(--heading-leading, 1));
  }
}
.photo-cards-link {
  color: inherit;
  text-decoration: none;
}
/* The card is the target, drawn out of the heading's own link so there is
   still exactly one focus stop and one accessible name. */
.photo-cards-link::after {
  content: "";
  position: absolute;
  inset: 0;
}
.photo-cards-link:hover {
  text-decoration: underline;
  text-underline-offset: 0.2em;
}
.photo-cards-link:focus-visible {
  outline: 3px solid var(--color-focus);
  outline-offset: 2px;
}
.photo-cards-copy {
  /* margin-top:auto sets the copy on the card floor, so cards holding
   unequal amounts of it still end level as a set. */
  margin: auto 0 0;
  color: var(--color-text-soft);
  font-size: 0.9375rem;
  line-height: 1.55;
}
@media (min-width: 48rem) {
  .photo-cards {
    padding-inline: var(--space-6);
  }
}

.photo-cards img[data-hub-placeholder] {
  background: color-mix(in srgb, var(--color-primary) 18%, var(--color-surface));
}
.photo-cards:not(.photo-cards--moving) {
  --hub-motion: none;
}
/* === /pattern photo-cards@8 === */

/* === pattern article-masthead@13 (library v229; appended by page_assemble.py -- adopt a newer version by replacing this block, never by adding a second) === */
/* article-masthead v2 - tokens only, selectors prefixed */
.article-masthead {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  width: min(100% - 2 * var(--space-4), 52rem);
  margin-inline: auto;
  margin-block-end: var(--space-8);
  padding-block-start: var(--space-8);
  /* The title below is set in --color-heading, which the contract guarantees
     against --color-bg and against nothing else. Keep this ground. */
  background: var(--color-bg);
}
/* align-items: flex-start above keeps the text left, so the two rule-bearing
   rows need width: 100% to reach the full measure. Dropping either one pulls
   its hairline in to the width of its own words. */
.article-masthead-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-1) var(--space-2);
  width: 100%;
  margin: 0 0 var(--space-5);
  padding-block-end: var(--space-4);
  border-block-end: 1px solid var(--color-rule);
}
.article-masthead-item {
  margin: 0;
  color: var(--color-text-soft);
  font-size: 0.8125rem;
  font-weight: 500;
  letter-spacing: 0.04em;
  line-height: 1.4;
  text-transform: uppercase;
}
.article-masthead-tag {
  color: var(--color-text);
  font-weight: 700;
}
.article-masthead-sep {
  color: var(--color-text-soft);
  line-height: 1;
  user-select: none;
}
.article-masthead-title {
  margin: 0 0 var(--space-4);
  font-family: var(--font-heading);
  font-size: calc(clamp(2rem, 4vw, 3.5rem) * var(--type-scale, 1));
  font-weight: var(--weight-display, 700);
  letter-spacing: calc(-0.02em + var(--heading-tracking, 0) * 1em);
  line-height: calc(1.08 * var(--heading-leading, 1));
  color: var(--color-heading);
  text-wrap: balance;
}
@supports (line-height: 1cap) {
  .article-masthead-title {
    line-height: calc(max(1.08em, 1.45cap) * var(--heading-leading, 1));
  }
}
/* The lede is held to a shorter measure than the title on purpose. The two
   are not meant to match, and matching them flattens the block. */
.article-masthead-lede {
  max-width: 42ch;
  margin: 0 0 var(--space-6);
  color: var(--color-text-soft);
  font-size: clamp(1rem, 1.2vw, 1.1875rem);
  font-weight: 500;
  line-height: 1.55;
}
.article-masthead-author {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  width: 100%;
  margin-block-start: var(--space-2);
  padding-block-start: var(--space-5);
  border-block-start: 1px solid var(--color-rule);
}
/* Nothing to show, nothing to frame: the row's rule and padding go with it. */
.article-masthead-author:not(:has(img, .article-masthead-byline:not(:empty), .article-masthead-role:not(:empty))) {
  margin-block-start: 0;
  padding-block-start: 0;
  border-block-start: 0;
}
.article-masthead-avatar {
  flex: 0 0 auto;
  display: block;
  width: 2.75rem;
  height: 2.75rem;
  border-radius: 50%;
  object-fit: cover;
}
.article-masthead-author-meta {
  min-width: 0;
}
.article-masthead-byline,
.article-masthead-role {
  margin: 0;
  line-height: 1.3;
}
.article-masthead-byline {
  color: var(--color-text);
  font-size: 0.9375rem;
  font-weight: 700;
}
.article-masthead-role {
  color: var(--color-text-soft);
  font-size: 0.8125rem;
  font-weight: 500;
}
@media (min-width: 48rem) {
  .article-masthead-title {
    letter-spacing: calc(-0.025em + var(--heading-tracking, 0) * 1em);
  }
}
/* === /pattern article-masthead@13 === */

/* === pattern key-takeaways@2 (library v229; appended by page_assemble.py -- adopt a newer version by replacing this block, never by adding a second) === */
/* key-takeaways v1 - tokens only, selectors prefixed */
.key-takeaways {
  --key-takeaways-measure: 68ch;
  box-sizing: border-box;
  width: min(100% - 2 * var(--space-4), var(--key-takeaways-measure));
  margin-block: var(--space-6);
  margin-inline: auto;
  padding: var(--space-5);
  background: var(--color-surface-soft);
  border: var(--card-border);
  border-radius: var(--card-radius);
  color: var(--color-text);
  /* The body size the article column is set in: the measure above is in ch,
     so it resolves against this and lands on the same column. */
  font-size: 1.0625rem;
  line-height: 1.6;
}
.key-takeaways-heading {
  margin: 0 0 var(--space-4);
  font-family: var(--font-heading);
  font-size: calc(1rem * var(--type-scale, 1));
  font-weight: var(--weight-display, 700);
  letter-spacing: calc(0.06em + var(--heading-tracking, 0) * 1em);
  line-height: calc(1.3 * var(--heading-leading, 1));
  text-transform: uppercase;
  /* --color-text: the block paints a surface, and the label is small. */
  color: var(--color-text);
}
@supports (line-height: 1cap) {
  .key-takeaways-heading {
    line-height: calc(max(1.3em, 1.45cap) * var(--heading-leading, 1));
  }
}
.key-takeaways-list {
  margin: 0;
  padding-inline-start: var(--space-5);
}
.key-takeaways-point {
  margin: 0 0 var(--space-3);
}
.key-takeaways-point:last-child {
  margin-bottom: 0;
}
.key-takeaways-point::marker {
  color: var(--color-text-soft);
}
/* === /pattern key-takeaways@2 === */

/* === pattern article-figure@2 (library v229; appended by page_assemble.py -- adopt a newer version by replacing this block, never by adding a second) === */
/* article-figure v1 - tokens only, selectors prefixed */
.article-figure {
  box-sizing: border-box;
  /* 52rem is the article shell, held by the masthead, the contents list and
     the author block. Any other number puts a third left edge on the page. */
  width: min(100% - 2 * var(--space-4), 52rem);
  margin-block: var(--space-6);
  margin-inline: auto;
}
.article-figure-image {
  display: block;
  width: 100%;
  height: auto;
  border-radius: var(--card-radius);
}
.article-figure-caption {
  max-width: 60ch;
  margin-block-start: var(--space-3);
  color: var(--color-text-soft);
  font-size: 0.875rem;
  line-height: 1.5;
  text-wrap: pretty;
}
.article-figure-credit {
  font-style: italic;
}

.article-figure img[data-hub-placeholder] {
  background: color-mix(in srgb, var(--color-primary) 18%, var(--color-surface));
}
/* === /pattern article-figure@2 === */

/* === pattern source-note@1 (library v229; appended by page_assemble.py -- adopt a newer version by replacing this block, never by adding a second) === */
/* source-note v1 - tokens only, selectors prefixed */
.source-note {
  margin: var(--space-2) 0 var(--space-4);
  font-size: 0.75rem;
  font-weight: 400;
  line-height: 1.45;
  max-width: 60ch;
  text-wrap: pretty;
}
/* === /pattern source-note@1 === */

/* === pattern article-toc@3 (library v229; appended by page_assemble.py -- adopt a newer version by replacing this block, never by adding a second) === */
/* article-toc v2 - tokens only, selectors prefixed */
.article-toc {
  width: min(100% - 2 * var(--space-4), 52rem);
  margin-inline: auto;
  margin-block: var(--space-6);
  border-block: 1px solid var(--color-rule);
}
.article-toc-summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  min-height: 44px;
  padding-block: var(--space-3);
  cursor: pointer;
  color: var(--color-text);
  /* Both lines are needed to drop the default triangle. */
  list-style: none;
}
.article-toc-summary::-webkit-details-marker {
  display: none;
}
/* Required: removing the marker above removes the focus affordance some
   browsers hang off it. */
.article-toc-summary:focus-visible {
  outline: 2px solid var(--color-focus);
  outline-offset: -2px;
}
.article-toc-label {
  font-family: var(--font-heading);
  /* Not 0.8125rem: this rides --type-scale and would drop under the text floor. */
  font-size: calc(0.875rem * var(--type-scale, 1));
  font-weight: 700;
  letter-spacing: calc(0.06em + var(--heading-tracking, 0) * 1em);
  line-height: calc(1.3 * var(--heading-leading, 1));
  text-transform: uppercase;
}
@supports (line-height: 1cap) {
  .article-toc-label {
    line-height: calc(max(1.3em, 1.45cap) * var(--heading-leading, 1));
  }
}
/* The indicator is a shape, not a glyph and never colour alone. */
.article-toc-icon {
  position: relative;
  flex: 0 0 auto;
  width: var(--space-4);
  height: var(--space-4);
}
.article-toc-icon::before,
.article-toc-icon::after {
  content: "";
  position: absolute;
  top: 50%;
  width: 60%;
  height: 2px;
  margin-block-start: -1px;
  background: var(--color-text-soft);
}
.article-toc-icon::before {
  inset-inline-start: 0;
  transform: rotate(45deg);
}
.article-toc-icon::after {
  inset-inline-end: 0;
  transform: rotate(-45deg);
}
/* A state change, not an animation: it applies under reduced motion too. */
.article-toc-disclosure[open] .article-toc-icon {
  transform: rotate(180deg);
}
.article-toc-list {
  list-style: none;
  margin: 0;
  padding: 0 0 var(--space-3);
}
.article-toc-item + .article-toc-item {
  border-block-start: 1px solid var(--color-rule);
}
.article-toc-link {
  display: flex;
  align-items: center;
  min-height: 44px;
  padding-block: var(--space-2);
  color: var(--color-text);
  font-size: 1rem;
  line-height: 1.4;
  text-decoration: none;
}
.article-toc-link:hover {
  text-decoration: underline;
  text-underline-offset: 0.2em;
}
.article-toc-link:focus-visible {
  outline: 3px solid var(--color-focus);
  outline-offset: -3px;
}
/* === /pattern article-toc@3 === */

/* === pattern pull-quote@2 (library v229; appended by page_assemble.py -- adopt a newer version by replacing this block, never by adding a second) === */
/* pull-quote v1 - tokens only, selectors prefixed */
.pull-quote {
  --pull-quote-measure: 68ch;
  box-sizing: border-box;
  width: min(100% - 2 * var(--space-4), var(--pull-quote-measure));
  margin-block: var(--space-6);
  margin-inline: auto;
  padding-block: var(--space-5);
  /* The ch measure resolves against this: it lands on the article column. */
  font-size: 1.0625rem;
  border-block: 1px solid var(--color-rule);
}
.pull-quote-claim {
  /* em, not ch - a measure must not depend on the face in use. */
  max-width: 15em;
  margin: 0;
  font-family: var(--font-heading);
  font-size: calc(clamp(1.375rem, 3.2vw, 2rem) * var(--type-scale, 1));
  font-weight: var(--weight-display, 700);
  letter-spacing: calc(-0.02em + var(--heading-tracking, 0) * 1em);
  line-height: calc(1.25 * var(--heading-leading, 1));
  color: var(--color-text);
  text-wrap: balance;
}
@supports (line-height: 1cap) {
  .pull-quote-claim {
    line-height: calc(max(1.25em, 1.45cap) * var(--heading-leading, 1));
  }
}
@media (min-width: 48rem) {
  .pull-quote {
    padding-block: var(--space-6);
  }
}
/* === /pattern pull-quote@2 === */

/* === pattern hero-squeeze@14 (library v229; appended by page_assemble.py -- adopt a newer version by replacing this block, never by adding a second) === */
/* hero-squeeze v10 - tokens only, selectors prefixed */
.hero-squeeze {
  --hero-squeeze-scrim-floor: clamp(0.86, var(--hero-squeeze-scrim-strength, 0.86), 1);
  position: relative;
  isolation: isolate;
  display: grid;
  place-items: center;
  /* min-height, never height: where the content does not fit, the page
   scrolls rather than clipping. svh, not vh. BOTH ENDS: this pattern is the
   whole page, so a header sits above it and a footer below it, and no markup
   here can enclose either. Set both tokens off the rendered page - TOKENS.md,
   The page's furniture. The defaults are generous on purpose: too large
   leaves a band of background under the footer, too small scrolls. */
  min-height: calc(100svh
    - var(--page-header-height, 9.5rem)
    - var(--page-footer-height, 12.5rem));
  padding: var(--space-6) var(--space-4);
  background: var(--color-scrim);
  text-align: center;
}
.hero-squeeze-img {
  position: absolute;
  inset: 0;
  z-index: -2;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.hero-squeeze::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(
    to bottom,
    color-mix(in srgb, var(--color-scrim) calc(var(--hero-squeeze-scrim-floor) * 68%), transparent) 0%,
    color-mix(in srgb, var(--color-scrim) calc(var(--hero-squeeze-scrim-floor) * 100%), transparent) 12%,
    color-mix(in srgb, var(--color-scrim) calc(var(--hero-squeeze-scrim-floor) * 100%), transparent) 100%
  );
}
.hero-squeeze-inner {
  display: grid;
  justify-items: center;
  max-width: min(100%, 38rem);
  color: var(--color-on-scrim);
}
.hero-squeeze-title {
  font-family: var(--font-heading);
  /* --color-heading is barred over a photograph however heavy the scrim. */
  color: var(--color-on-scrim);
  font-size: calc(clamp(2rem, 6vw, 3.25rem) * var(--type-scale, 1));
  font-weight: var(--weight-display, 700);
  letter-spacing: calc(-0.025em + var(--heading-tracking, 0) * 1em);
  line-height: calc(1.08 * var(--heading-leading, 1));
  margin: 0 0 var(--space-4);
  text-wrap: balance;
}
@supports (line-height: 1cap) {
  .hero-squeeze-title {
    line-height: calc(max(1.08em, 1.45cap) * var(--heading-leading, 1));
  }
}
.hero-squeeze-sub {
  font-size: clamp(1rem, 1.6vw, 1.125rem);
  line-height: 1.55;
  max-width: 34ch;
  margin: 0 0 var(--space-6);
}
.hero-squeeze-cta {
  display: grid;
  justify-items: center;
}
.hero-squeeze-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  /* 52px: this is the only control on the page and it is the page's whole job. */
  min-height: 52px;
  padding: var(--space-3) var(--space-6);
  border-radius: var(--btn-radius);
  background: var(--color-primary);
  color: var(--color-on-primary);
  font-size: 1.0625rem;
  font-weight: 700;
  line-height: 1.5;
  text-decoration: none;
}
.hero-squeeze-btn:hover {
  text-decoration: underline;
  text-underline-offset: 0.2em;
}
/* Two bands: a photograph sits behind this and no token describes it, so the
   indicator brings its own ground. Same technique as media-card-grid. */
.hero-squeeze-btn:focus-visible {
  outline: 3px solid var(--color-on-scrim);
  outline-offset: 3px;
  box-shadow: 0 0 0 7px var(--color-scrim);
}
.hero-squeeze-proof {
  margin-top: var(--space-5);
}

/* Lighter only over a placeholder; a photograph keeps the floor above. */
.hero-squeeze img[data-hub-placeholder] {
  background: color-mix(in srgb, var(--color-primary) 24%, var(--color-scrim));
}
.hero-squeeze:has(> .hero-squeeze-img[data-hub-placeholder]) {
  --hero-squeeze-scrim-floor: 0.4;
}

/* Holding a signup-card in place of the join button. The photograph holds
   still while the card changes height from step to step: a fixed height
   taller than any step, anchored at the top and clipped, so the crop never changes. */
.hero-squeeze:has(.signup-card) {
  /* clip, not hidden: a hidden box still scrolls when the card is brought
     into view, and the photograph would move with it. */
  overflow: clip;
}
.hero-squeeze:has(.signup-card) .hero-squeeze-img {
  inset: 0 0 auto 0;
  height: 56rem;
  object-position: center top;
}
.hero-squeeze-cta:has(.signup-card) {
  width: 100%;
}
/* Wide: the words on the left, the card on the right, and the first step
   above the fold. */
@media (min-width: 60rem) {
  .hero-squeeze:has(.signup-card) {
    min-height: 0;
    padding-block: var(--space-6) var(--space-8);
  }
  .hero-squeeze:has(.signup-card) .hero-squeeze-img {
    height: max(100%, 56rem);
  }
  .hero-squeeze-inner:has(.signup-card) {
    width: min(100% - 2 * var(--space-4), var(--container-max));
    max-width: var(--container-max);
    grid-template-columns: minmax(0, 1fr) 24rem;
    column-gap: var(--space-8);
    justify-items: start;
    align-items: center;
    text-align: left;
  }
  .hero-squeeze-inner:has(.signup-card) > :not(.hero-squeeze-cta) {
    grid-column: 1;
  }
  .hero-squeeze-inner:has(.signup-card) > .hero-squeeze-cta {
    grid-column: 2;
    grid-row: 1 / span 6;
    justify-items: stretch;
  }
}
/* === /pattern hero-squeeze@14 === */

/* === page /design-patterns/fonts: its own styles (page_assemble.py; rewritten on every assemble of this page) === */
.dp-label { max-width: var(--container-max, 72rem); margin: var(--space-10, 4rem) auto 0; padding: 0 var(--space-4, 1rem) var(--space-3, .75rem);
  border-bottom: 2px solid var(--color-primary); font-family: var(--font-body); display: grid; gap: .15rem; }
.dp-label-name { font-family: var(--font-heading); font-size: 1.5rem; color: var(--color-heading); }
.dp-label-meta { font-size: .8rem; letter-spacing: .06em; text-transform: uppercase; color: var(--color-primary); }
.dp-label-sum { font-size: .9rem; color: var(--color-text-soft); max-width: 60ch; }
.dp-intro { max-width: var(--container-max, 72rem); margin: 0 auto; padding: var(--space-10, 4rem) var(--space-4, 1rem) var(--space-6, 2rem); font-family: var(--font-body); }
.dp-intro h1 { font-family: var(--font-heading); font-size: clamp(2.2rem, 6vw, 4rem); margin: 0 0 .5rem; color: var(--color-heading); line-height: 1; }
.dp-intro p { color: var(--color-text-soft); max-width: 60ch; margin: 0; }
.fp { --fp-ground: var(--color-bg); max-width: var(--container-max, 72rem); margin: var(--space-6, 2rem) auto;
  padding: 0 var(--space-4, 1rem); display: grid; grid-template-columns: 1fr; gap: var(--space-6, 2rem); align-items: center; }
@media (min-width: 52rem) { .fp { grid-template-columns: 1.1fr 1fr; } .fp--flip .fp-photo { order: -1; } }
.fp-words { font-family: var(--fp-body); line-height: var(--fp-lh, 1.55); color: var(--color-text); }
.fp-tag { display: inline-flex; gap: .5rem; flex-wrap: wrap; align-items: baseline; margin-bottom: .75rem; font-family: var(--font-body); }
.fp-name { font-weight: 700; color: var(--color-primary); text-transform: uppercase; letter-spacing: .08em; font-size: .8rem; }
.fp-fonts { font-size: .8rem; color: var(--color-text-soft); }
.fp-current { font-size: .75rem; background: var(--color-primary); color: var(--color-on-primary); border-radius: 999px; padding: .1rem .55rem; }
.fp-head { font-family: var(--fp-heading); font-size: clamp(2rem, 5vw, 3.4rem); line-height: var(--fp-hl, 1.05);
  letter-spacing: calc(var(--fp-ht, 0) * 1em); margin: 0 0 .75rem; color: var(--color-heading); }
.fp-sub { font-size: 1.1rem; margin: 0 0 1rem; max-width: 46ch; }
.fp-body { margin: 0 0 1.25rem; max-width: 52ch; color: var(--color-text-soft); }
.fp-btn { display: inline-block; font-family: var(--fp-body); font-weight: 700; background: var(--color-primary); color: var(--color-on-primary);
  padding: .8rem 1.4rem; border-radius: var(--btn-radius, .5rem); text-decoration: none; }
.fp-btn:focus-visible { outline: 3px solid var(--color-focus); outline-offset: 3px; }
.fp-suits { margin: 1rem 0 0; font-size: .85rem; color: var(--color-text-soft); font-style: italic; max-width: 52ch; }
.fp-photo img { width: 100%; height: auto; aspect-ratio: 4 / 3; object-fit: cover; border-radius: var(--card-radius, .75rem); display: block; }
.fp--retro-warmth { --fp-heading: 'Fraunces', Georgia, 'Times New Roman', serif; --fp-body: 'Hanken Grotesk', 'Segoe UI', system-ui, -apple-system, sans-serif; --fp-hl: 1.08; --fp-ht: -0.01; --fp-lh: 1.6; }
.fp--classy-luxury { --fp-heading: 'Bodoni Moda', 'Didot', Georgia, serif; --fp-body: 'Public Sans', 'Segoe UI', system-ui, -apple-system, sans-serif; --fp-hl: 1.03; --fp-ht: 0.01; --fp-lh: 1.6; }
.fp--after-dark { --fp-heading: 'Big Shoulders', 'Arial Narrow', 'Helvetica Neue Condensed', sans-serif; --fp-body: 'Archivo', 'Segoe UI', system-ui, -apple-system, sans-serif; --fp-hl: 0.95; --fp-ht: 0.01; --fp-lh: 1.6; }
.fp--stadium-energy { --fp-heading: 'Sofia Sans Extra Condensed', 'Arial Narrow', sans-serif; --fp-body: 'Sofia Sans', 'Segoe UI', system-ui, -apple-system, sans-serif; --fp-hl: 0.95; --fp-ht: 0.02; --fp-lh: 1.6; }
.fp--old-money { --fp-heading: 'Playfair', Georgia, 'Times New Roman', serif; --fp-body: 'Playfair', Georgia, 'Times New Roman', serif; --fp-hl: 0.98; --fp-ht: -0.015; --fp-lh: 1.55; }
.fp--quiet-authority { --fp-heading: 'Source Serif 4', Georgia, 'Times New Roman', serif; --fp-body: 'Source Sans 3', 'Segoe UI', system-ui, -apple-system, sans-serif; --fp-hl: 1.13; --fp-ht: 0.0; --fp-lh: 1.6; }
.fp--bauhaus-modern { --fp-heading: 'Jost', 'Century Gothic', 'Futura', system-ui, sans-serif; --fp-body: 'Literata', Georgia, 'Times New Roman', serif; --fp-hl: 1.03; --fp-ht: 0.01; --fp-lh: 1.61; }
.fp--sunny-side { --fp-heading: 'Gabarito', 'Trebuchet MS', 'Segoe UI', system-ui, sans-serif; --fp-body: 'Figtree', 'Segoe UI', system-ui, -apple-system, sans-serif; --fp-hl: 1.13; --fp-ht: -0.01; --fp-lh: 1.61; }
.fp--zine { --fp-heading: 'Bricolage Grotesque', 'Arial', 'Helvetica Neue', sans-serif; --fp-body: 'Instrument Sans', 'Segoe UI', system-ui, -apple-system, sans-serif; --fp-hl: 0.98; --fp-ht: -0.015; --fp-lh: 1.62; }
.fp--slow-sunday { --fp-heading: 'Newsreader', Georgia, 'Times New Roman', serif; --fp-body: 'Karla', 'Segoe UI', system-ui, -apple-system, sans-serif; --fp-hl: 1.15; --fp-ht: -0.005; --fp-lh: 1.6; }
.fp--art-house { --fp-heading: 'Syne', 'Trebuchet MS', 'Segoe UI', system-ui, sans-serif; --fp-body: 'Epilogue', 'Segoe UI', system-ui, -apple-system, sans-serif; --fp-hl: 1.03; --fp-ht: -0.01; --fp-lh: 1.63; }
.fp--safe-hands { --fp-heading: 'Merriweather', Georgia, 'Times New Roman', serif; --fp-body: 'Merriweather Sans', 'Segoe UI', system-ui, -apple-system, sans-serif; --fp-hl: 1.15; --fp-ht: 0.0; --fp-lh: 1.65; }
.fp--love-letter { --fp-heading: 'Cormorant Garamond', 'Cormorant', Garamond, Georgia, serif; --fp-body: 'Nunito Sans', 'Segoe UI', system-ui, -apple-system, sans-serif; --fp-hl: 1.0; --fp-ht: 0.0; --fp-lh: 1.6; }
.fp--plain-sight { --fp-heading: 'Lexend', 'Segoe UI', system-ui, -apple-system, sans-serif; --fp-body: 'Atkinson Hyperlegible', Verdana, 'Segoe UI', system-ui, sans-serif; --fp-hl: 1.05; --fp-ht: -0.01; --fp-lh: 1.55; }
.fp--loud-and-proud { --fp-heading: 'Unbounded', 'Arial Black', 'Segoe UI', system-ui, sans-serif; --fp-body: 'Nunito', 'Segoe UI', system-ui, -apple-system, sans-serif; --fp-hl: 1.05; --fp-ht: -0.02; --fp-lh: 1.6; }
.fp--plain-speaking { --fp-heading: 'Manrope', 'Segoe UI', system-ui, -apple-system, sans-serif; --fp-body: 'Inter', 'Segoe UI', system-ui, -apple-system, sans-serif; --fp-hl: 1.05; --fp-ht: -0.015; --fp-lh: 1.6; }
/* === /page /design-patterns/fonts === */

/* === pattern author-note@2 (library v229; appended by page_assemble.py -- adopt a newer version by replacing this block, never by adding a second) === */
/* author-note v1 - tokens only, selectors prefixed */
.author-note {
  /* Required: it holds the padding below inside this width, not outside it. */
  box-sizing: border-box;
  width: min(100% - 2 * var(--space-4), 52rem);
  margin-inline: auto;
  margin-block: var(--space-8);
  padding: var(--space-6);
  background: var(--color-surface-soft);
  border: var(--card-border);
  /* Keep both this and the fill above: a brand may set the card edge
     transparent, and a brand may set the soft surface to the page ground. */
  border-block-start: 3px solid var(--color-primary);
  border-radius: var(--card-radius);
  color: var(--color-text);
}
.author-note-heading {
  margin: 0 0 var(--space-4);
  font-family: var(--font-heading);
  /* Not 0.8125rem: this rides --type-scale and would drop under the text floor. */
  font-size: calc(0.875rem * var(--type-scale, 1));
  font-weight: 700;
  letter-spacing: calc(0.06em + var(--heading-tracking, 0) * 1em);
  line-height: calc(1.3 * var(--heading-leading, 1));
  /* --color-text: a label this small is nowhere near the size --color-heading
     is promised at, and this panel is not the page ground either. */
  color: var(--color-text);
  text-transform: uppercase;
}
@supports (line-height: 1cap) {
  .author-note-heading {
    line-height: calc(max(1.3em, 1.45cap) * var(--heading-leading, 1));
  }
}
.author-note-name {
  margin: 0;
  font-family: var(--font-heading);
  font-size: calc(1.375rem * var(--type-scale, 1));
  font-weight: var(--weight-display, 700);
  letter-spacing: calc(-0.015em + var(--heading-tracking, 0) * 1em);
  line-height: calc(1.2 * var(--heading-leading, 1));
  color: var(--color-text);
}
@supports (line-height: 1cap) {
  .author-note-name {
    line-height: calc(max(1.2em, 1.45cap) * var(--heading-leading, 1));
  }
}
.author-note-role {
  margin: var(--space-1) 0 0;
  color: var(--color-text-soft);
  font-size: 0.9375rem;
  font-weight: 500;
  line-height: 1.4;
}
.author-note-bio {
  max-width: 62ch;
  margin: var(--space-4) 0 0;
  font-size: 1rem;
  line-height: 1.65;
  text-wrap: pretty;
}
.author-note-more {
  margin: var(--space-4) 0 0;
  font-size: 0.9375rem;
}
/* Inherit: the underline carries the affordance, on whatever ground the panel
   turns out to be. See the README. */
.author-note-link {
  color: inherit;
  text-decoration: underline;
  text-underline-offset: 0.18em;
}
.author-note-link:hover {
  text-decoration-thickness: 2px;
}
.author-note-link:focus-visible {
  outline: 3px solid var(--color-focus);
  outline-offset: 2px;
}
@media (min-width: 48rem) {
  .author-note {
    padding: var(--space-8);
  }
}
/* === /pattern author-note@2 === */

/* === pattern benefit-tiles@9 (library v229; appended by page_assemble.py -- adopt a newer version by replacing this block, never by adding a second) === */
/* benefit-tiles v2 - tokens only, selectors prefixed */
.benefit-tiles {
  --benefit-tiles-badge-fill: var(--color-primary);
  --benefit-tiles-badge-size: 3rem;
  padding-block: var(--space-8);
  /* No right padding below 48rem. It is what lets the track run past the
   viewport edge, so the next tile is visibly cut instead of stopping short. */
  padding-inline: var(--space-4) 0;
}
.benefit-tiles-track {
  display: flex;
  gap: var(--space-4);
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
  list-style: none;
  margin: 0;
  /* Asymmetric to match the section's missing right padding: leading inset
   from the section, trailing inset from here. */
  padding: var(--space-1) var(--space-4) var(--space-2) 0;
}
.benefit-tiles-track::-webkit-scrollbar {
  display: none;
}
.benefit-tiles-track:focus-visible {
  outline: 2px solid var(--color-focus);
  outline-offset: calc(-1 * var(--space-1));
}
.benefit-tiles-item {
  display: flex;
  flex-direction: column;
  flex: 0 0 auto;
  width: 78vw;
  scroll-snap-align: start;
  box-sizing: border-box;
  min-height: clamp(26rem, 34vw, 32rem);
  padding: clamp(var(--space-5), 2vw, var(--space-6));
  background: var(--color-surface);
  /* The tile is surface, border AND shadow together. A brand may set
   --card-border to transparent, and the tile still has to be a tile. */
  border: var(--card-border);
  border-radius: var(--card-radius);
  box-shadow: var(--card-shadow);
}
.benefit-tiles-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  width: var(--benefit-tiles-badge-size);
  height: var(--benefit-tiles-badge-size);
  border-radius: var(--chip-radius);
  background: var(--benefit-tiles-badge-fill);
  /* The one ink the contract guarantees on this ground. */
  color: var(--color-on-primary);
}
.benefit-tiles-icon {
  display: block;
  width: 1.375rem;
  height: 1.375rem;
}
/* margin-top:auto drives the words to the floor, so tiles carrying unequal
   amounts of copy still line up as a set. */
.benefit-tiles-text {
  margin-top: auto;
  padding-top: var(--space-8);
}
.benefit-tiles-title {
  font-family: var(--font-heading);
  /* --color-text, not --color-heading: this floor is 20px, under the size the
   heading token is contracted for, and the tile is a surface. */
  color: var(--color-text);
  font-size: calc(clamp(1.25rem, 1.6vw, 1.625rem) * var(--type-scale, 1));
  font-weight: var(--weight-display, 700);
  letter-spacing: calc(-0.015em + var(--heading-tracking, 0) * 1em);
  line-height: calc(1.25 * var(--heading-leading, 1));
  margin: 0 0 var(--space-4);
  text-wrap: balance;
}
@supports (line-height: 1cap) {
  .benefit-tiles-title {
    line-height: calc(max(1.25em, 1.45cap) * var(--heading-leading, 1));
  }
}
.benefit-tiles-copy {
  color: var(--color-text-soft);
  font-size: 0.9375rem;
  font-weight: 500;
  line-height: 1.55;
  margin: 0;
}
/* Two up through the tablet band, where the tile no longer needs the height it
   carried as a full-width card. */
@media (min-width: 48rem) {
  .benefit-tiles {
    padding-inline: var(--space-6);
  }
  .benefit-tiles-track {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--space-5);
    overflow-x: visible;
    scroll-snap-type: none;
    max-width: var(--container-max);
    margin-inline: auto;
    padding: 0;
  }
  .benefit-tiles-item {
    width: auto;
    min-height: 24rem;
  }
}
/* Three, five or six tiles: three to a row on six tracks, at every width
   from here up; five centres its last two. Two and four keep the rules above. */
@media (min-width: 48rem) {
  .benefit-tiles-track:has(> :nth-child(3):last-child),
  .benefit-tiles-track:has(> :nth-child(5)) {
    grid-template-columns: repeat(6, minmax(0, 1fr));
  }
  .benefit-tiles-track:has(> :nth-child(3):last-child) > .benefit-tiles-item,
  .benefit-tiles-track:has(> :nth-child(5)) > .benefit-tiles-item {
    grid-column: span 2;
  }
  .benefit-tiles-track:has(> :nth-child(5):last-child) > .benefit-tiles-item:nth-child(4) {
    grid-column: 2 / span 2;
  }
}
@media (min-width: 64.01rem) {
  .benefit-tiles-track {
    grid-template-columns: repeat(4, 1fr);
  }
  .benefit-tiles-item {
    min-height: clamp(26rem, 34vw, 32rem);
  }
  .benefit-tiles-track:has(> :nth-child(2):last-child) {
    grid-template-columns: 1fr 1fr;
    max-width: calc(var(--container-max) * 2 / 3);
  }
  .benefit-tiles-track:has(> :nth-child(5)) > .benefit-tiles-item {
    min-height: 24rem;
  }
}
.benefit-tiles:not(.benefit-tiles--moving) {
  --hub-motion: none;
}
/* === /pattern benefit-tiles@9 === */

/* === pattern capability-tabs@9 (library v229; appended by page_assemble.py -- adopt a newer version by replacing this block, never by adding a second) === */
/* capability-tabs v2 - tokens only, selectors prefixed.
   Nothing here hides a panel: with no behaviour library every panel renders,
   stacked, under its own heading. */
.capability-tabs {
  /* The page gutter. The rail's bleed below is this value three times over -
     negative margin, padding, scroll padding - so change them together. */
  --capability-tabs-gutter: var(--space-4);
  padding-block: var(--space-8);
}
.capability-tabs-inner {
  width: min(100% - 2 * var(--capability-tabs-gutter), var(--container-max));
  margin-inline: auto;
}
.capability-tabs-title {
  margin: 0;
  font-family: var(--font-heading);
  color: var(--color-heading);
  font-size: calc(clamp(1.75rem, 1rem + 2vw, 2.25rem) * var(--type-scale, 1));
  line-height: calc(1.1 * var(--heading-leading, 1));
}
@supports (line-height: 1cap) {
  .capability-tabs-title {
    line-height: calc(max(1.1em, 1.45cap) * var(--heading-leading, 1));
  }
}
.capability-tabs-sub {
  margin: var(--space-3) 0 0;
  max-width: 52ch;
  color: var(--color-text-soft);
  line-height: 1.55;
}
.capability-tabs-panels {
  display: grid;
  gap: var(--space-6);
  margin-block-start: var(--space-6);
}
.capability-tabs-panel {
  display: grid;
  /* Explicit: the image takes its height from the copy beside it, so no
     aspect ratio is set on it anywhere. */
  align-items: stretch;
  background: var(--color-surface-soft);
  border-radius: var(--card-radius);
  /* Clips the image to the panel's corners. */
  overflow: hidden;
}
.capability-tabs-copy {
  padding: var(--space-6);
  align-self: center;
}
.capability-tabs-panel-title {
  margin: 0;
  font-family: var(--font-heading);
  /* --color-text: a panel is a surface, and --color-heading is promised
     against --color-bg only. */
  color: var(--color-text);
  font-size: calc(clamp(1.25rem, 1rem + 1.2vw, 1.875rem) * var(--type-scale, 1));
  line-height: calc(1.15 * var(--heading-leading, 1));
}
@supports (line-height: 1cap) {
  .capability-tabs-panel-title {
    line-height: calc(max(1.15em, 1.45cap) * var(--heading-leading, 1));
  }
}
.capability-tabs-lede {
  margin: var(--space-3) 0 0;
  max-width: 46ch;
  color: var(--color-text-soft);
  line-height: 1.6;
}
.capability-tabs-list {
  display: grid;
  gap: var(--space-3);
  list-style: none;
  margin: var(--space-5) 0 0;
  padding: 0;
}
.capability-tabs-list li {
  position: relative;
  padding-inline-start: var(--space-6);
  color: var(--color-text);
  font-weight: 700;
  line-height: 1.4;
}
.capability-tabs-list li::before {
  content: "";
  position: absolute;
  inset-inline-start: 0;
  top: 0.1em;
  width: var(--space-5);
  height: var(--space-5);
  border-radius: 50%;
  background: var(--color-primary);
}
/* The tick is two borders on a rotated box, so it takes its ink from the
   token rather than from an image. */
.capability-tabs-list li::after {
  content: "";
  position: absolute;
  inset-inline-start: 0.5rem;
  top: calc(0.1em + 0.35rem);
  width: 0.35rem;
  height: 0.65rem;
  border-right: 2px solid var(--color-on-primary);
  border-bottom: 2px solid var(--color-on-primary);
  transform: rotate(45deg);
}
.capability-tabs-media {
  position: relative;
  margin: 0;
  min-height: 15rem;
}
/* Absolute, so the image contributes no height of its own and the copy beside
   it sets the panel's. Take this out and a tall image stretches the panel. */
.capability-tabs-img {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
/* The rail exists only once the behaviour library builds it. */
.capability-tabs .hub-tabs-list {
  gap: var(--space-2);
  margin-block-start: var(--space-6);
}
.capability-tabs .hub-tabs-tab {
  font: inherit;
  font-family: var(--font-heading);
  font-weight: var(--weight-display, 700);
  line-height: calc(1.2 * var(--heading-leading, 1));
  min-height: 44px;
  padding: var(--space-3) var(--space-5);
  border: 0;
  border-radius: var(--chip-radius);
  background: var(--color-surface-soft);
  color: var(--color-text);
  white-space: nowrap;
  cursor: pointer;
}
@supports (line-height: 1cap) {
  .capability-tabs .hub-tabs-tab {
    line-height: calc(max(1.2em, 1.45cap) * var(--heading-leading, 1));
  }
}
.capability-tabs .hub-tabs-tab[aria-selected="true"] {
  background: var(--color-primary);
  color: var(--color-on-primary);
}
.capability-tabs .hub-tabs-tab:focus-visible,
.capability-tabs .hub-tabs-panel:focus-visible {
  outline: 2px solid var(--color-focus);
  outline-offset: 2px;
}
@media (min-width: 48rem) {
  .capability-tabs-panel {
    grid-template-columns: 1fr 1fr;
    column-gap: var(--space-6);
  }
  .capability-tabs-copy {
    padding: var(--space-8);
    padding-inline-end: 0;
  }
  .capability-tabs-media {
    min-height: 20rem;
  }
}
@media (max-width: 47.99rem) {
  .capability-tabs .hub-tabs-list {
    /* Room for the focus ring: this is a scroll container, so anything drawn
       outside the padding box is clipped. */
    padding-block: var(--space-1);
    flex-wrap: nowrap;
    overflow-x: auto;
    scrollbar-width: none;
    margin-inline: calc(-1 * var(--capability-tabs-gutter));
    padding-inline: var(--capability-tabs-gutter);
    scroll-padding-inline: var(--capability-tabs-gutter);
  }
  .capability-tabs .hub-tabs-list::-webkit-scrollbar {
    display: none;
  }
}

.capability-tabs img[data-hub-placeholder] {
  background: color-mix(in srgb, var(--color-primary) 18%, var(--color-surface));
}
/* === /pattern capability-tabs@9 === */

/* === pattern claim-stack@4 (library v229; appended by page_assemble.py -- adopt a newer version by replacing this block, never by adding a second) === */
/* claim-stack v2 - tokens only, selectors prefixed */
/* Each ground names its own ink pair, and every rule below reads the pair.
   The base carries the plain ground's values, so a copy that loses its
   modifier still has a ground, a hairline and its inks. */
.claim-stack,
.claim-stack--plain {
  --claim-stack-ground: var(--color-bg);
  --claim-stack-ink: var(--color-heading, var(--color-text));
  --claim-stack-quiet: var(--color-text-soft);
  --claim-stack-edge: var(--color-rule, color-mix(in srgb, var(--color-text) 18%, transparent));
}
.claim-stack--soft {
  --claim-stack-ground: var(--color-surface-soft);
  --claim-stack-ink: var(--color-text);
  --claim-stack-quiet: var(--color-text-soft);
  --claim-stack-edge: var(--color-rule, color-mix(in srgb, var(--color-text) 18%, transparent));
}
.claim-stack--brand {
  --claim-stack-ground: var(--color-primary);
  --claim-stack-ink: var(--color-on-primary, var(--color-surface));
  --claim-stack-quiet: color-mix(in srgb, var(--color-on-primary, var(--color-surface)) 78%, var(--color-primary));
  --claim-stack-edge: color-mix(in srgb, var(--color-on-primary, var(--color-surface)) 35%, transparent);
}
.claim-stack--deep {
  --claim-stack-ground: var(--color-scrim, var(--color-text));
  --claim-stack-ink: var(--color-on-scrim, var(--color-bg));
  --claim-stack-quiet: color-mix(in srgb, var(--color-on-scrim, var(--color-bg)) 78%, var(--color-scrim, var(--color-text)));
  --claim-stack-edge: color-mix(in srgb, var(--color-on-scrim, var(--color-bg)) 30%, transparent);
}
.claim-stack {
  padding-block: var(--space-8);
  padding-inline: var(--space-4);
  background: var(--claim-stack-ground);
  color: var(--claim-stack-ink);
}
.claim-stack-inner {
  max-width: var(--container-max, 72rem);
  margin-inline: auto;
}
.claim-stack-heading {
  max-width: var(--container-max, 72rem);
  margin: 0 auto var(--space-8);
  font-family: var(--font-heading);
  color: var(--claim-stack-quiet);
  font-size: calc(1.75rem * var(--type-scale, 1));
  font-weight: var(--weight-display, 700);
  letter-spacing: calc(0.02em + var(--heading-tracking, 0) * 1em);
  line-height: calc(1.2 * var(--heading-leading, 1));
}
@supports (line-height: 1cap) {
  .claim-stack-heading {
    line-height: calc(max(1.2em, 1.45cap) * var(--heading-leading, 1));
  }
}
.claim-stack-item {
  /* The ceiling is in vh, not on the spacing ramp. Do not "restore" a token
     here: the ramp's top step is below 10vh on most screens, which pins this
     to one value and the claim never gets a screenful. */
  padding-block: clamp(var(--space-8), 10vh, 20vh);
  border-block-start: 1px solid var(--claim-stack-edge);
}
.claim-stack-item:first-child {
  border-block-start: 0;
  padding-block-start: 0;
}
.claim-stack-claim {
  font-family: var(--font-heading);
  color: var(--claim-stack-ink);
  font-size: calc(clamp(2rem, 1rem + 4.5vw, 4rem) * var(--type-scale, 1));
  font-weight: var(--weight-display, 700);
  letter-spacing: calc(-0.03em + var(--heading-tracking, 0) * 1em);
  line-height: calc(1.05 * var(--heading-leading, 1));
  max-width: 11.25em;
  margin: 0;
  text-wrap: balance;
  overflow-wrap: break-word;
}
@supports (line-height: 1cap) {
  .claim-stack-claim {
    line-height: calc(max(1.05em, 1.45cap) * var(--heading-leading, 1));
  }
}
.claim-stack-note {
  color: var(--claim-stack-quiet);
  font-size: 1.0625rem;
  line-height: 1.55;
  max-width: 44ch;
  margin: var(--space-4) 0 0;
}
@media (min-width: 48rem) {
  .claim-stack {
    padding-inline: var(--space-8);
  }
  .claim-stack-heading {
    margin-block-end: var(--space-12);
  }
}
/* === /pattern claim-stack@4 === */

/* === pattern comparison-table@5 (library v229; appended by page_assemble.py -- adopt a newer version by replacing this block, never by adding a second) === */
/* comparison-table v2 - tokens only, selectors prefixed */
.comparison-table {
  padding-block: var(--space-8);
  padding-inline: var(--space-4);
  background: var(--color-bg);
  color: var(--color-text);
}
.comparison-table-inner {
  max-width: var(--container-max, 72rem);
  margin-inline: auto;
}
.comparison-table-title {
  font-family: var(--font-heading);
  color: var(--color-heading, var(--color-text));
  font-size: calc(clamp(1.75rem, 3vw, 2.5rem) * var(--type-scale, 1));
  line-height: calc(1.15 * var(--heading-leading, 1));
  letter-spacing: calc(-0.02em + var(--heading-tracking, 0) * 1em);
  margin: 0 0 var(--space-3);
  text-wrap: balance;
}
@supports (line-height: 1cap) {
  .comparison-table-title {
    line-height: calc(max(1.15em, 1.45cap) * var(--heading-leading, 1));
  }
}
.comparison-table-intro {
  color: var(--color-text-soft);
  font-size: 1.0625rem;
  line-height: 1.55;
  max-width: 52ch;
  margin: 0 0 var(--space-6);
}
/* overflow on both axes, not overflow-x. Setting only one makes the other
   scrollable anyway, and the sticky head then sticks to a container that
   never scrolls, so it looks as though it does not work. */
.comparison-table-scroll {
  overflow: auto;
  border-radius: var(--card-radius);
}
.comparison-table-scroll:focus-visible {
  outline: 3px solid var(--color-focus, var(--color-primary));
  outline-offset: 3px;
}
/* separate, not collapse: with collapsed borders the table paints the border
   rather than the cell, and a sticky head loses its bottom edge as it moves.
   The box-shadow below draws that edge instead. */
.comparison-table-grid {
  border-collapse: separate;
  border-spacing: 0;
  min-inline-size: 40rem;
  inline-size: 100%;
  text-align: left;
}
.comparison-table-caption {
  caption-side: top;
  text-align: left;
  color: var(--color-text-soft);
  font-size: 0.9375rem;
  line-height: 1.5;
  padding-block-end: var(--space-3);
}
.comparison-table-corner,
.comparison-table-head {
  background: var(--color-surface, var(--color-bg));
  box-shadow: inset 0 -1px 0 var(--color-rule, color-mix(in srgb, var(--color-text) 18%, transparent));
  padding: var(--space-4) var(--space-5);
  vertical-align: bottom;
  text-align: left;
}
/* The criterion column stays put while the values scroll sideways. Without
   it a phone reader ends up looking at three columns of answers with no
   question against them. */
.comparison-table-criterion,
.comparison-table-corner {
  position: sticky;
  inset-inline-start: 0;
  background: var(--color-bg);
  z-index: 1;
}
.comparison-table-corner {
  background: var(--color-surface, var(--color-bg));
  z-index: 2;
}
.comparison-table-name {
  display: block;
  font-family: var(--font-heading);
  color: var(--color-text);
  font-size: calc(1.125rem * var(--type-scale, 1));
  font-weight: var(--weight-display, 700);
  line-height: calc(1.25 * var(--heading-leading, 1));
}
@supports (line-height: 1cap) {
  .comparison-table-name {
    line-height: calc(max(1.25em, 1.45cap) * var(--heading-leading, 1));
  }
}
/* The word says which column is recommended; the tint only repeats it.
   Never ship one without the other. */
.comparison-table-flag {
  display: inline-block;
  margin-block-start: var(--space-2);
  color: var(--color-text);
  font-size: 0.8125rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.comparison-table-head--recommended,
.comparison-table-cell--recommended {
  background: color-mix(in srgb, var(--color-primary) 10%, var(--color-bg));
}
.comparison-table-criterion {
  font-weight: 700;
  color: var(--color-text);
  padding: var(--space-4) var(--space-5);
  border-block-end: 1px solid var(--color-rule, color-mix(in srgb, var(--color-text) 18%, transparent));
  vertical-align: top;
}
.comparison-table-cell {
  color: var(--color-text);
  padding: var(--space-4) var(--space-5);
  border-block-end: 1px solid var(--color-rule, color-mix(in srgb, var(--color-text) 18%, transparent));
  vertical-align: top;
  line-height: 1.5;
}
.comparison-table-row:last-child .comparison-table-criterion,
.comparison-table-row:last-child .comparison-table-cell {
  border-block-end: 0;
}
@media (min-width: 48rem) {
  .comparison-table {
    padding-inline: var(--space-8);
  }
  /* svh, not vh: the mobile address bar would eat into a vh height. The
     vertical scroller exists only where the table is tall enough to want a
     sticky head; below this width it would nest a scroller inside the page. */
  .comparison-table-scroll {
    max-block-size: 80vh; /* vh twin */
    max-block-size: 80svh;
  }
  .comparison-table-corner,
  .comparison-table-head {
    position: sticky;
    inset-block-start: 0;
  }
}
/* === /pattern comparison-table@5 === */

/* === pattern cta-curtain@13 (library v229; appended by page_assemble.py -- adopt a newer version by replacing this block, never by adding a second) === */
/* cta-curtain - tokens only, selectors prefixed. */
.cta-curtain {
  position: relative;
  display: block;
}

/* 100svh, not 100vh: a mobile address bar showing or hiding would
   otherwise break the pin. The cover's negative margin and the spacer carry
   the same pair and must stay in step. border-box keeps the padding inside
   that height: without it the panel is a screen and two --space-8 tall, the
   cover starts that far down it, and the CTA sits below the middle. */
.cta-curtain-panel {
  position: sticky;
  top: 0;
  z-index: 1;
  box-sizing: border-box;
  height: 100vh;
  height: 100vh; /* vh twin */
  height: 100svh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-8) var(--space-4);
  background: var(--color-surface-soft);
}
/* Do not remove: without it a focused control in the panel sits behind the
   cover, which nothing scrolls out of the way. */
.cta-curtain-panel:focus-within {
  z-index: 3;
}
.cta-curtain-inner {
  width: min(100%, 42rem);
  margin-inline: auto;
  text-align: center;
}
.cta-curtain-title {
  margin: 0 0 var(--space-4);
  font-family: var(--font-heading);
  /* --color-text: --color-heading is not guaranteed on a surface. */
  color: var(--color-text);
  font-size: calc(clamp(1.75rem, 1.2rem + 3vw, 3rem) * var(--type-scale, 1));
  line-height: calc(1.05 * var(--heading-leading, 1));
  text-wrap: balance;
}
@supports (line-height: 1cap) {
  .cta-curtain-title {
    line-height: calc(max(1.05em, 1.45cap) * var(--heading-leading, 1));
  }
}
.cta-curtain-lead {
  margin: 0 0 var(--space-6);
  color: var(--color-text-soft);
  font-size: 1.0625rem;
  line-height: 1.6;
}
.cta-curtain-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 48px;
  padding: var(--space-3) var(--space-6);
  background: var(--color-primary);
  color: var(--color-on-primary);
  font-weight: 700;
  text-decoration: none;
  line-height: 1.5;
  border-radius: var(--btn-radius);
}
.cta-curtain-btn:hover {
  background: var(--color-primary-dark);
}
.cta-curtain-btn:focus-visible {
  outline: 3px solid var(--color-focus);
  outline-offset: 3px;
}

/* The cover must stay opaque or the panel shows through, and flow-root
   stops its inner margin collapsing out and opening a gap. */
.cta-curtain-cover {
  position: relative;
  z-index: 2;
  display: flow-root;
  margin-top: -100vh;
  margin-top: -100vh; /* vh twin */
  margin-top: -100svh;
  background: var(--color-bg);
  /* The rounded lower edge is what makes this read as a curtain. */
  border-end-start-radius: calc(var(--card-radius) * 2);
  border-end-end-radius: calc(var(--card-radius) * 2);
  /* Set --cta-curtain-lift: none for a flat brand. */
  box-shadow: var(--cta-curtain-lift, 0 40px 80px -20px
    color-mix(in srgb, var(--color-scrim) 30%, transparent));
}

/* Do not remove: without it the panel never fully uncovers. */
.cta-curtain-spacer {
  display: block;
  height: 100vh;
  height: 100vh; /* vh twin */
  height: 100svh;
}

/* No sticky support: unwind to an ordinary closing section in flow. */
@supports not (position: sticky) {
  .cta-curtain-panel {
    position: static;
    height: auto;
  }
  .cta-curtain-cover {
    margin-top: 0;
    box-shadow: none;
    border-end-start-radius: 0;
    border-end-end-radius: 0;
  }
  .cta-curtain-spacer {
    display: none;
  }
}

/* Too short to hold the panel's own content: same unwind. */
@media (max-height: 33.99rem) {
  .cta-curtain-panel {
    position: static;
    height: auto;
    padding-block: var(--space-6);
  }
  .cta-curtain-cover {
    margin-top: 0;
    box-shadow: none;
    border-end-start-radius: 0;
    border-end-end-radius: 0;
  }
  .cta-curtain-spacer {
    display: none;
  }
}

/* Reduced motion: flatten the depth cue. */
@media (prefers-reduced-motion: reduce) {
  .cta-curtain-cover {
    box-shadow: none;
  }
}

/* Phones: off. A full-screen panel behind a cover is least legible on the
   smallest screen. */
@media (max-width: 34.99rem) {
  .cta-curtain-panel {
    position: static;
    height: auto;
    padding-block: var(--space-6);
  }
  .cta-curtain-cover {
    margin-top: 0;
    box-shadow: none;
    border-end-start-radius: 0;
    border-end-end-radius: 0;
  }
  .cta-curtain-spacer {
    display: none;
  }
}
/* === /pattern cta-curtain@13 === */

/* === pattern gallery-scroll@7 (library v229; appended by page_assemble.py -- adopt a newer version by replacing this block, never by adding a second) === */
/* gallery-scroll v5 - tokens only, selectors prefixed */
.gallery-scroll {
  padding-block: var(--space-3);
}
/* The list is the scroller, not the block, so the arrows the behaviour
   library builds hold still while the photographs move. */
.gallery-scroll-track {
  display: flex;
  gap: var(--space-4);
  list-style: none;
  margin: 0;
  padding: 0 var(--space-4);
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory;
  /* room for the focus ring, so it is not clipped by the overflow */
  scroll-padding-inline: var(--space-4);
  scrollbar-width: none;
}
.gallery-scroll-track::-webkit-scrollbar {
  display: none;
}
.gallery-scroll-item {
  scroll-snap-align: start;
  flex: 0 0 auto;
  width: min(70vw, 22rem);
}
.gallery-scroll-item img {
  width: 100%;
  height: auto;
  border-radius: var(--card-radius);
  box-shadow: var(--card-shadow);
}
.gallery-scroll-caption {
  color: var(--color-text-soft);
  font-size: 0.9rem;
  margin: var(--space-2) 0 0;
}
/* A visible edge on the scroller when it has keyboard focus */
.gallery-scroll-track:focus-visible {
  outline: 2px solid var(--color-focus);
  outline-offset: 2px;
}
@media (prefers-reduced-motion: no-preference) {
  .gallery-scroll-track {
    scroll-behavior: smooth;
  }
}

/* controls: where the previous and next arrows sit, read by the behaviour
   library from these properties. phone: whether a phone shows them. */
.gallery-scroll--top {
  --hub-carousel-controls: top;
  --hub-carousel-look: round;
}
.gallery-scroll--edges {
  --hub-carousel-controls: edges;
  --hub-carousel-look: round;
}
.gallery-scroll--arrows {
  --hub-carousel-phone: show;
}
.gallery-scroll--swipe {
  --hub-carousel-phone: hide;
}
.gallery-scroll .hub-carousel-controls--top {
  padding-inline: var(--space-4);
}
/* Over a photograph the arrows need a ground of their own. */
.gallery-scroll .hub-carousel-controls--edges .hub-carousel-control {
  border: 0;
  background: var(--color-bg);
  color: var(--color-text);
  box-shadow: var(--card-shadow);
}

/* With scripting off nothing builds the previous and next controls, and the
   hidden scroll bar would leave a mouse no way along the row, so it wraps. */
@media (scripting: none) {
  .gallery-scroll-track {
    overflow-x: visible;
    flex-wrap: wrap;
    justify-content: center;
  }
}

.gallery-scroll img[data-hub-placeholder] {
  background: color-mix(in srgb, var(--color-primary) 18%, var(--color-surface));
}
/* === /pattern gallery-scroll@7 === */

/* === pattern hero-overlay@16 (library v229; appended by page_assemble.py -- adopt a newer version by replacing this block, never by adding a second) === */
/* hero-overlay v13 - tokens only, selectors prefixed. Nothing here moves. */
.hero-overlay {
  /* Contrast floor: the scrim carries it, never the photo. */
  --hero-overlay-scrim-floor: clamp(0.92, var(--hero-overlay-scrim-strength, 0.92), 1);
  position: relative;
  /* Own stacking context: the image/scrim/copy ladder must not interleave. */
  isolation: isolate;
  overflow: hidden;
  display: flex;
  align-items: flex-end;
  background: var(--color-bg);
  /* A viewport MINUS what sits above. A plain 100svh puts the foot one
   header below the fold, and the foot is where the control is. svh, not vh.
   The header only: this opener is not the page, so the site footer is not in
   the first viewport - hero-squeeze is the one that subtracts a footer too.
   Set --page-header-height off the rendered page; see TOKENS.md. */
  min-height: calc(100vh - var(--page-header-height, 9.5rem)); /* vh twin */
  min-height: calc(100svh - var(--page-header-height, 9.5rem));
}
.hero-overlay-img {
  position: absolute;
  inset: 0;
  z-index: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Anchor to the top: faces and horizons live in the upper third. */
  object-position: center top;
}
/* A vignette plus a wash that resolves to the page background. */
.hero-overlay::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background-image:
    radial-gradient(circle at 50% 18%,
      color-mix(in srgb, var(--color-bg) 4%, transparent) 0%,
      color-mix(in srgb, var(--color-bg) 26%, transparent) 42%,
      color-mix(in srgb, var(--color-bg) 82%, transparent) 88%),
    linear-gradient(to top,
      var(--color-bg) 0%,
      color-mix(in srgb, var(--color-bg) calc(var(--hero-overlay-scrim-floor) * 100%), transparent) 8%,
      color-mix(in srgb, var(--color-bg) calc(var(--hero-overlay-scrim-floor) * 100%), transparent) 44%,
      color-mix(in srgb, var(--color-bg) calc(var(--hero-overlay-scrim-floor) * 32%), transparent) 72%,
      transparent 100%);
}
.hero-overlay-inner {
  position: relative;
  z-index: 2;
  width: min(100% - 2 * var(--space-4), var(--container-max));
  margin-inline: auto;
  padding-block: var(--space-12) var(--space-8);
}
/* Held narrow: the copy must stay inside the scrim's guaranteed band. */
.hero-overlay-copy {
  max-width: 34rem;
}
.hero-overlay-title {
  margin: 0 0 var(--space-4);
  font-family: var(--font-heading);
  /* --color-text: the ground here is a scrim over a photograph. */
  color: var(--color-text);
  font-size: calc(clamp(2.25rem, 1.4rem + 3.4vw, 4rem) * var(--type-scale, 1));
  line-height: calc(1.05 * var(--heading-leading, 1));
  letter-spacing: calc(-0.02em + var(--heading-tracking, 0) * 1em);
  text-wrap: balance;
}
@supports (line-height: 1cap) {
  .hero-overlay-title {
    line-height: calc(max(1.05em, 1.45cap) * var(--heading-leading, 1));
  }
}
.hero-overlay-sub {
  margin: 0 0 var(--space-6);
  max-width: 32rem;
  /* --color-text-soft, not a dimmed white: only the token is guaranteed. */
  color: var(--color-text-soft);
  font-size: clamp(1rem, 0.95rem + 0.35vw, 1.1875rem);
  line-height: 1.55;
}
.hero-overlay-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
}
.hero-overlay-btn,
.hero-overlay-ghost {
  box-sizing: border-box;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  /* 48px target: above the 44px AAA floor. */
  min-height: 48px;
  padding: var(--space-3) var(--space-6);
  border-radius: var(--btn-radius);
  font-weight: 700;
  line-height: 1.5;
  text-decoration: none;
}
.hero-overlay-btn {
  background: var(--color-primary);
  color: var(--color-on-primary);
}
.hero-overlay-btn:hover {
  background: var(--color-primary-dark);
}
/* --color-text edge: no token is guaranteed over a photograph. */
.hero-overlay-ghost {
  border: 2px solid var(--color-text);
  background: color-mix(in srgb, var(--color-bg) 72%, transparent);
  /* --color-text: this is not large text. */
  color: var(--color-text);
}
.hero-overlay-ghost:hover {
  background: var(--color-bg);
}
/* Both controls need a visible focus ring. */
.hero-overlay-btn:focus-visible,
.hero-overlay-ghost:focus-visible {
  outline: 3px solid var(--color-focus);
  outline-offset: 3px;
}

/* Phones: copy to the top, and the scrim inverts with it. */
@media (max-width: 47.99rem) {
  .hero-overlay {
    align-items: flex-start;
  }
  .hero-overlay::after {
    background-image: linear-gradient(
      to bottom,
      transparent 0,
      color-mix(in srgb, var(--color-bg) calc(var(--hero-overlay-scrim-floor) * 32%), transparent) 13svh,
      color-mix(in srgb, var(--color-bg) calc(var(--hero-overlay-scrim-floor) * 100%), transparent) 25svh,
      color-mix(in srgb, var(--color-bg) calc(var(--hero-overlay-scrim-floor) * 100%), transparent) 88%,
      var(--color-bg) 100%
    );
  }
  .hero-overlay-inner {
    padding-block: max(var(--space-12), 26vh) var(--space-8); /* vh twin */
    padding-block: max(var(--space-12), 26svh) var(--space-8);
  }
  .hero-overlay-title {
    line-height: calc(1.12 * var(--heading-leading, 1));
  }
  @supports (line-height: 1cap) {
    .hero-overlay-title {
      line-height: calc(max(1.12em, 1.45cap) * var(--heading-leading, 1));
    }
  }
}

/* Short viewports: unpin, or the copy is unreachable. */
@media (max-height: 33.99rem) {
  .hero-overlay {
    min-height: auto;
  }
  .hero-overlay-inner {
    padding-block: var(--space-8);
  }
}

.hero-overlay img[data-hub-placeholder] {
  background: color-mix(in srgb, var(--color-primary) 18%, var(--color-surface));
}

/* Holding a signup-card: the photograph holds still from step to step. */
.hero-overlay:has(.signup-card) {
  overflow: clip;
}
.hero-overlay:has(.signup-card) .hero-overlay-img {
  inset: 0 0 auto 0;
  height: 56rem;
}
/* Wide: words left at the contrast floor, card right on its own surface. */
@media (min-width: 60rem) {
  .hero-overlay:has(.signup-card) {
    align-items: flex-start;
    min-height: 0;
  }
  .hero-overlay:has(.signup-card) .hero-overlay-img {
    height: max(100%, 56rem);
  }
  .hero-overlay:has(.signup-card)::after {
    background-image: linear-gradient(to right,
      color-mix(in srgb, var(--color-bg) calc(var(--hero-overlay-scrim-floor) * 100%), transparent) 0%,
      color-mix(in srgb, var(--color-bg) calc(var(--hero-overlay-scrim-floor) * 100%), transparent) 55%,
      color-mix(in srgb, var(--color-bg) calc(var(--hero-overlay-scrim-floor) * 32%), transparent) 78%,
      color-mix(in srgb, var(--color-bg) calc(var(--hero-overlay-scrim-floor) * 10%), transparent) 100%);
  }
  .hero-overlay-inner:has(.signup-card) {
    padding-block: var(--space-6) var(--space-8);
  }
  .hero-overlay-copy:has(.signup-card) {
    max-width: none;
    display: grid;
    grid-template-columns: minmax(0, 1fr) 24rem;
    column-gap: var(--space-8);
    align-items: start;
  }
  .hero-overlay-copy:has(.signup-card) > :not(.hero-overlay-actions) {
    grid-column: 1;
    max-width: 34rem;
  }
  .hero-overlay-copy:has(.signup-card) > .hero-overlay-actions {
    grid-column: 2;
    grid-row: 1 / span 6;
  }
}
/* === /pattern hero-overlay@16 === */

/* === pattern rating-mark@5 (library v229; appended by page_assemble.py -- adopt a newer version by replacing this block, never by adding a second) === */
/* rating-mark v1 - tokens only, selectors prefixed */
/* Sets no colour: it inherits the ink it sits in. See the README. */
.rating-mark {
  display: inline-flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-1) var(--space-2);
  margin: 0;
  font-size: 0.875rem;
  line-height: 1.4;
}
.rating-mark-stars {
  display: inline-flex;
  gap: 0.1em;
}
.rating-mark-star {
  display: block;
  width: 1em;
  height: 1em;
}
.rating-mark-count {
  font-size: 0.8125rem;
}
.rating-mark-value {
  font-weight: var(--weight-display, 700);
}
/* === /pattern rating-mark@5 === */

/* === pattern member-strip@4 (library v229; appended by page_assemble.py -- adopt a newer version by replacing this block, never by adding a second) === */
/* member-strip v1 - tokens only, selectors prefixed */
.member-strip {
  --member-strip-photo: 3.5rem;
}
/* No colour of its own: it inherits the ink of whatever it sits in. */
.member-strip-lead {
  font-size: 0.875rem;
  line-height: 1.5;
  margin: 0 0 var(--space-3);
}
.member-strip-list {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-4) var(--space-3);
  list-style: none;
  margin: 0;
  padding: 0;
}
.member-strip-item {
  display: grid;
  justify-items: center;
  gap: var(--space-1);
  width: var(--member-strip-photo);
  font-size: 0.75rem;
  line-height: 1.3;
  text-align: center;
}
.member-strip-photo {
  display: block;
  width: var(--member-strip-photo);
  height: var(--member-strip-photo);
  border-radius: 50%;
  object-fit: cover;
  /* A ground behind a slow or failed photograph, so the row keeps its shape
   and the names stay on their grid. */
  background: var(--color-surface);
}
.member-strip-name {
  font-weight: 700;
  overflow-wrap: anywhere;
}
/* === /pattern member-strip@4 === */

/* === pattern offer-split@5 (library v229; appended by page_assemble.py -- adopt a newer version by replacing this block, never by adding a second) === */
/* offer-split v1 - tokens only, selectors prefixed */
.offer-split {
  --offer-split-panel-min: 18rem;
  padding-block: var(--space-8);
  padding-inline: var(--space-4);
}
.offer-split-inner {
  display: grid;
  gap: var(--space-6);
  max-width: var(--container-max);
  margin-inline: auto;
}
.offer-split-title {
  font-family: var(--font-heading);
  /* Page ground and a clamp floor above 24px: both halves of the heading
   token's contract. Keep both if you edit it. */
  color: var(--color-heading);
  font-size: calc(clamp(1.75rem, 3.4vw, 2.75rem) * var(--type-scale, 1));
  font-weight: var(--weight-display, 700);
  letter-spacing: calc(-0.02em + var(--heading-tracking, 0) * 1em);
  line-height: calc(1.15 * var(--heading-leading, 1));
  margin: 0 0 var(--space-5);
  text-wrap: balance;
}
@supports (line-height: 1cap) {
  .offer-split-title {
    line-height: calc(max(1.15em, 1.45cap) * var(--heading-leading, 1));
  }
}
.offer-split-body {
  color: var(--color-text-soft);
  font-size: 1rem;
  line-height: 1.65;
  max-width: 48ch;
  margin: 0 0 var(--space-4);
}
.offer-split-body:last-child {
  margin-bottom: 0;
}
/* The one ground in this pattern with a stated ink, which is what lets the
   panel's supporting line sit at body size. */
.offer-split-panel {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  min-height: var(--offer-split-panel-min);
  padding: var(--space-6);
  background: var(--color-primary);
  color: var(--color-on-primary);
  border-radius: var(--card-radius);
}
.offer-split-panel-title {
  font-family: var(--font-heading);
  /* Not --color-heading: this panel paints its own ground. */
  color: var(--color-on-primary);
  font-size: calc(clamp(1.375rem, 2.2vw, 1.875rem) * var(--type-scale, 1));
  font-weight: var(--weight-display, 700);
  letter-spacing: calc(-0.015em + var(--heading-tracking, 0) * 1em);
  line-height: calc(1.2 * var(--heading-leading, 1));
  margin: 0 0 var(--space-3);
  text-wrap: balance;
}
@supports (line-height: 1cap) {
  .offer-split-panel-title {
    line-height: calc(max(1.2em, 1.45cap) * var(--heading-leading, 1));
  }
}
.offer-split-panel-body {
  font-size: 1rem;
  line-height: 1.6;
  margin: 0 0 var(--space-6);
}
/* margin-top:auto sets the control on the panel floor whatever the copy above
   it runs to, so the two columns end level. */
.offer-split-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  margin-top: auto;
  /* 48px target, above the 44px AAA floor. */
  min-height: 48px;
  padding: var(--space-3) var(--space-6);
  border-radius: var(--btn-radius);
  /* The pair inverted; contrast is symmetric, so the ratio holds. */
  background: var(--color-on-primary);
  color: var(--color-primary);
  font-weight: 700;
  line-height: 1.5;
  text-decoration: none;
}
.offer-split-btn:hover {
  text-decoration: underline;
  text-underline-offset: 0.2em;
}
/* Not --color-focus: on this ground it is the brand colour against itself.
   See the README. */
.offer-split-btn:focus-visible {
  outline: 3px solid var(--color-on-primary);
  outline-offset: 4px;
}
@media (min-width: 48rem) {
  .offer-split {
    padding-inline: var(--space-6);
  }
}
@media (min-width: 64rem) {
  .offer-split-inner {
    grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr);
    align-items: stretch;
    column-gap: var(--space-8);
  }
}
/* === /pattern offer-split@5 === */

/* === pattern opener-split@5 (library v229; appended by page_assemble.py -- adopt a newer version by replacing this block, never by adding a second) === */
/* opener-split v1 - tokens only, selectors prefixed */
.opener-split {
  --opener-split-title-measure: 8.75em;
  --opener-split-intro-measure: 42ch;
  display: grid;
  gap: var(--space-5);
  max-width: var(--container-max);
  margin-inline: auto;
  /* Section gutter idiom, so this lines up with what it introduces. */
  padding: var(--space-8) var(--space-4) var(--space-6);
}
.opener-split-eyebrow {
  color: var(--color-text-soft);
  font-size: 0.8125rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  margin: 0 0 var(--space-3);
}
.opener-split-title {
  font-family: var(--font-heading);
  /* Page ground and a clamp floor above 24px: both halves of the heading
   token's contract. Keep both if you edit it. */
  color: var(--color-heading);
  font-size: calc(clamp(1.875rem, 4.6vw, 3.5rem) * var(--type-scale, 1));
  font-weight: var(--weight-display, 700);
  letter-spacing: calc(-0.025em + var(--heading-tracking, 0) * 1em);
  line-height: calc(1.05 * var(--heading-leading, 1));
  margin: 0;
  text-wrap: balance;
}
@supports (line-height: 1cap) {
  .opener-split-title {
    line-height: calc(max(1.05em, 1.45cap) * var(--heading-leading, 1));
  }
}
.opener-split-intro {
  color: var(--color-text-soft);
  font-size: 1rem;
  line-height: 1.65;
  max-width: var(--opener-split-intro-measure);
  margin: 0;
}
.opener-split--ruled {
  border-bottom: 1px solid var(--color-rule);
  padding-bottom: var(--space-8);
}
/* Side by side only from 64rem: two half-width columns at tablet width leave
   the title too narrow to hold a heading. See the README. */
@media (min-width: 48rem) {
  .opener-split {
    padding-inline: var(--space-6);
  }
}
@media (min-width: 64rem) {
  .opener-split {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    align-items: end;
    column-gap: var(--space-6);
  }
  .opener-split-title {
    max-width: var(--opener-split-title-measure);
  }
  .opener-split-intro {
    justify-self: end;
    /* Optical nudge onto the title's baseline: the type sizes differ too
     much for align-items alone. */
    padding-bottom: var(--space-2);
  }
}
/* === /pattern opener-split@5 === */

/* === pattern picker-chips@9 (library v229; appended by page_assemble.py -- adopt a newer version by replacing this block, never by adding a second) === */
/* picker-chips v5 - tokens only, selectors prefixed */
.picker-chips {
  /* The touch-target floor. Every pill is at least this tall and wide. */
  --picker-chips-target: 48px;
  max-width: 32rem;
  margin: 0;
  padding: var(--space-5);
  background: var(--color-surface);
  border: var(--card-border);
  border-radius: var(--card-radius);
  box-shadow: var(--card-shadow);
}
.picker-chips-title {
  margin: 0 0 var(--space-2);
  font-family: var(--font-heading);
  /* --color-text: this is not large text. */
  color: var(--color-text);
  font-size: calc(clamp(1.125rem, 1rem + 0.5vw, 1.375rem) * var(--type-scale, 1));
  line-height: calc(1.2 * var(--heading-leading, 1));
}
@supports (line-height: 1cap) {
  .picker-chips-title {
    line-height: calc(max(1.2em, 1.45cap) * var(--heading-leading, 1));
  }
}
.picker-chips-helper {
  margin: 0 0 var(--space-4);
  color: var(--color-text-soft);
  font-size: 0.9375rem;
}
/* Phones first: one full-width pill per row. */
.picker-chips-list {
  display: flex;
  flex-direction: column;
  /* gap, not margin: the clear space between targets stops a mis-tap. */
  gap: var(--space-3);
  list-style: none;
  margin: 0;
  padding: 0;
}
.picker-chips-item {
  display: flex;
}
.picker-chips-link {
  box-sizing: border-box;
  flex: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  min-height: var(--picker-chips-target);
  min-width: var(--picker-chips-target);
  padding: var(--space-3) var(--space-5);
  background: var(--color-surface);
  /* --color-text: --color-primary-dark is for light grounds only. */
  color: var(--color-text);
  /* The border is the only thing marking this as a control, so it carries
     the boundary contrast on its own. */
  border: 2px solid color-mix(in srgb, var(--color-primary) 75%, var(--color-surface));
  border-radius: var(--chip-radius);
  font-weight: 700;
  line-height: 1.2;
  text-align: center;
  text-decoration: none;
}
/* The picked state commits to both halves of the guaranteed pair. */
.picker-chips-link:hover {
  background: var(--color-primary);
  border-color: var(--color-primary);
  color: var(--color-on-primary);
}
.picker-chips-link:focus-visible {
  outline: 3px solid var(--color-focus);
  outline-offset: 2px;
}
/* Decoration only - aria-hidden in the markup, so it carries no meaning. */
.picker-chips-arrow {
  flex: none;
  font-weight: 400;
  line-height: 1;
}
/* Wide phone up: pills share a row and wrap. */
@media (min-width: 26rem) {
  .picker-chips-list {
    flex-direction: row;
    flex-wrap: wrap;
  }
  .picker-chips-item {
    flex: 0 0 auto;
  }
}
/* === /pattern picker-chips@9 === */

/* === pattern pinned-cards@8 (library v229; appended by page_assemble.py -- adopt a newer version by replacing this block, never by adding a second) === */
/* pinned-cards - tokens only, selectors prefixed */
.pinned-cards {
  --pinned-cards-panel-max: 34rem;
  --pinned-cards-step: 6vh;
  padding-block: var(--space-8);
}
.pinned-cards-head {
  width: min(100% - 2 * var(--space-4), var(--container-max));
  margin: 0 auto var(--space-6);
}
.pinned-cards-eyebrow {
  color: var(--color-text-soft);
  font-size: 0.8125rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  margin: 0 0 var(--space-3);
}
.pinned-cards-title {
  font-family: var(--font-heading);
  /* Page ground and a clamp floor above 24px: both halves of the heading
   token's contract. Keep both if you edit it. */
  color: var(--color-heading);
  font-size: calc(clamp(1.75rem, 3.4vw, 2.75rem) * var(--type-scale, 1));
  font-weight: var(--weight-display, 700);
  letter-spacing: calc(-0.02em + var(--heading-tracking, 0) * 1em);
  line-height: calc(1.15 * var(--heading-leading, 1));
  margin: 0;
  text-wrap: balance;
}
@supports (line-height: 1cap) {
  .pinned-cards-title {
    line-height: calc(max(1.15em, 1.45cap) * var(--heading-leading, 1));
  }
}
.pinned-cards-list {
  list-style: none;
  margin: 0;
  padding: 0;
}
.pinned-cards-item {
  position: relative;
  isolation: isolate;
  display: flex;
  align-items: flex-end;
  /* min-height, never height: a card whose copy outgrows the viewport must
   be able to grow. See the README. border-box keeps the padding inside the
   screen: without it a pinned card is a screen and two paddings tall, and
   the foot of its panel sits under the fold where nothing can scroll to it. */
  box-sizing: border-box;
  min-height: 100vh;
  min-height: 100vh; /* vh twin */
  min-height: 100svh;
  padding: var(--space-5);
  overflow: hidden;
  border-radius: var(--card-radius);
}
.pinned-cards-item + .pinned-cards-item {
  margin-top: var(--space-5);
}
.pinned-cards-img {
  position: absolute;
  inset: 0;
  z-index: -1;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
/* A solid panel, not a scrim: the words never touch the photograph. */
.pinned-cards-panel {
  max-width: var(--pinned-cards-panel-max);
  padding: var(--space-6);
  background: var(--color-surface);
  border-radius: var(--card-radius);
}
.pinned-cards-heading {
  font-family: var(--font-heading);
  /* A panel is not --color-bg, so the heading token promises nothing here. */
  color: var(--color-text);
  font-size: calc(clamp(1.375rem, 2.4vw, 2rem) * var(--type-scale, 1));
  font-weight: var(--weight-display, 700);
  letter-spacing: calc(-0.015em + var(--heading-tracking, 0) * 1em);
  line-height: calc(1.2 * var(--heading-leading, 1));
  margin: 0 0 var(--space-3);
  text-wrap: balance;
}
@supports (line-height: 1cap) {
  .pinned-cards-heading {
    line-height: calc(max(1.2em, 1.45cap) * var(--heading-leading, 1));
  }
}
.pinned-cards-body {
  color: var(--color-text-soft);
  font-size: 1rem;
  line-height: 1.6;
  margin: 0;
}
.pinned-cards-action {
  margin: var(--space-5) 0 0;
}
.pinned-cards-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  /* 48px target, above the 44px AAA floor. */
  min-height: 48px;
  padding: var(--space-3) var(--space-6);
  border-radius: var(--btn-radius);
  background: var(--color-primary);
  color: var(--color-on-primary);
  font-weight: 700;
  line-height: 1.5;
  text-decoration: none;
}
.pinned-cards-btn:hover {
  text-decoration: underline;
  text-underline-offset: 0.2em;
}
.pinned-cards-btn:focus-visible {
  outline: 3px solid var(--color-focus);
  outline-offset: 3px;
}
/* The pin waits on height as well as width: a pinned card cannot be scrolled
   inside, so it is only safe where a whole card fits. See the README. */
@media (min-width: 48rem) and (min-height: 44rem) {
  .pinned-cards-item {
    position: sticky;
    top: 0;
    z-index: var(--pinned-cards-i, 1);
    padding: var(--space-8);
  }
  .pinned-cards-item + .pinned-cards-item {
    margin-top: var(--pinned-cards-step);
  }
}
/* Unpinned on paper, or the stack prints as one card. */
@media print {
  .pinned-cards-item {
    position: static;
    min-height: 0;
  }
}

.pinned-cards img[data-hub-placeholder] {
  background: color-mix(in srgb, var(--color-primary) 18%, var(--color-surface));
}
/* === /pattern pinned-cards@8 === */

/* === pattern portrait-prose@3 (library v229; appended by page_assemble.py -- adopt a newer version by replacing this block, never by adding a second) === */
/* portrait-prose v1 - tokens only, selectors prefixed */
.portrait-prose {
  padding-block: var(--space-8);
  color: var(--color-text);
}
.portrait-prose-inner {
  width: min(100% - 2 * var(--space-4), var(--container-max));
  margin-inline: auto;
  display: grid;
  gap: var(--space-6);
  align-items: start;
}
/* Capped on a phone: a portrait the full width of the screen is a poster,
   and the story is what the section is for. */
.portrait-prose-figure {
  margin: 0;
  max-width: 22rem;
}
.portrait-prose-image {
  display: block;
  width: 100%;
  height: auto;
  border-radius: var(--card-radius);
  box-shadow: var(--card-shadow);
}
.portrait-prose-caption {
  margin-block-start: var(--space-3);
  font-size: 0.875rem;
  line-height: 1.5;
  color: var(--color-text-soft);
}
.portrait-prose-name {
  display: block;
  font-weight: 700;
  color: var(--color-text);
}
.portrait-prose-eyebrow {
  margin: 0 0 var(--space-3);
  font-size: 0.8125rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-text-soft);
}
.portrait-prose-heading {
  margin: 0 0 var(--space-4);
  max-width: 18em;
  font-family: var(--font-heading);
  font-size: calc(clamp(1.75rem, 1.1rem + 2.4vw, 2.75rem) * var(--type-scale, 1));
  font-weight: var(--weight-display, 700);
  letter-spacing: calc(-0.01em + var(--heading-tracking, 0) * 1em);
  line-height: calc(1.15 * var(--heading-leading, 1));
  color: var(--color-heading);
  text-wrap: balance;
}
@supports (line-height: 1cap) {
  .portrait-prose-heading {
    line-height: calc(max(1.15em, 1.45cap) * var(--heading-leading, 1));
  }
}
.portrait-prose-body {
  max-width: 62ch;
  font-size: 1.0625rem;
  line-height: 1.65;
  text-wrap: pretty;
}
.portrait-prose-body p {
  margin: 0 0 var(--space-4);
}
.portrait-prose-body p:last-child {
  margin-block-end: 0;
}
@media (min-width: 48rem) {
  .portrait-prose {
    padding-block: var(--space-12);
  }
  .portrait-prose-inner {
    grid-template-columns: minmax(0, 2fr) minmax(0, 3fr);
    gap: var(--space-8);
  }
  .portrait-prose-figure {
    max-width: none;
  }
  .portrait-prose--start .portrait-prose-figure {
    order: 0;
  }
  .portrait-prose--end .portrait-prose-figure {
    order: 1;
  }
}
/* === /pattern portrait-prose@3 === */

/* === pattern portrait-wall@9 (library v229; appended by page_assemble.py -- adopt a newer version by replacing this block, never by adding a second) === */
/* portrait-wall v3 - tokens only, selectors prefixed */
.portrait-wall {
  padding-block: var(--space-8);
}
.portrait-wall-grid {
  --portrait-wall-mid: 2;
  --portrait-wall-gap: clamp(var(--space-2), 3vw, var(--space-6));
  --portrait-wall-ratio: 3 / 4;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: repeat(3, auto);
  gap: var(--portrait-wall-gap);
  width: min(100% - 2 * var(--space-4), var(--container-max));
  margin-inline: auto;
}
/* Each layer is one ring of tiles laid on the wall's own tracks, which is what
   lets the rules below address a whole ring by position. Take subgrid away and
   every ring collapses into a single column. */
.portrait-wall-grid > .portrait-wall-layer {
  display: grid;
  grid-column: 1 / -1;
  grid-row: 1 / -1;
  grid-template-columns: subgrid;
  grid-template-rows: subgrid;
}
/* Columns count from --portrait-wall-mid; the focal cell stays last. */
/* -2 / -1 is the last row, not `-1`: a bare -1 is a start line, and outside a
   subgrid it opens a fourth row instead of filling the third. */
.portrait-wall-layer:nth-of-type(1) > .portrait-wall-tile:first-of-type {
  grid-column: var(--portrait-wall-mid);
  grid-row: 1;
}
.portrait-wall-layer:nth-of-type(1) > .portrait-wall-tile:last-of-type {
  grid-column: var(--portrait-wall-mid);
  grid-row: -2 / -1;
}
.portrait-wall-layer:nth-of-type(2) > .portrait-wall-tile:nth-of-type(odd) {
  grid-column: calc(var(--portrait-wall-mid) - 1);
}
.portrait-wall-layer:nth-of-type(2) > .portrait-wall-tile:nth-of-type(even) {
  grid-column: calc(var(--portrait-wall-mid) + 1);
}
.portrait-wall-layer:nth-of-type(3) > .portrait-wall-tile:nth-of-type(odd) {
  grid-column: calc(var(--portrait-wall-mid) - 2);
}
.portrait-wall-layer:nth-of-type(3) > .portrait-wall-tile:nth-of-type(even) {
  grid-column: calc(var(--portrait-wall-mid) + 2);
}
.portrait-wall-layer:nth-of-type(4) > .portrait-wall-tile:nth-of-type(odd) {
  grid-column: calc(var(--portrait-wall-mid) - 3);
}
.portrait-wall-layer:nth-of-type(4) > .portrait-wall-tile:nth-of-type(even) {
  grid-column: calc(var(--portrait-wall-mid) + 3);
}
.portrait-wall-tile,
.portrait-wall-focal {
  overflow: hidden;
  border-radius: var(--card-radius);
  background: var(--color-surface-soft);
  box-shadow: var(--portrait-wall-shadow, var(--card-shadow));
}
/* height: auto is load-bearing: without it the img's height attribute stays a
   definite height and the aspect-ratio below never applies. */
.portrait-wall-img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: var(--portrait-wall-ratio);
  object-fit: cover;
}
.portrait-wall-focal {
  position: relative;
  z-index: 1;
  grid-area: 2 / var(--portrait-wall-mid);
}
.portrait-wall-focal-img {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
/* A ring shows only once the wall has columns for it. */
.portrait-wall-layer:nth-of-type(n + 3) > .portrait-wall-tile {
  display: none;
}
@media (min-width: 48rem) {
  /* Three columns keep the tile size five would have. */
  .portrait-wall-grid {
    width: min(100% - 2 * var(--space-4), var(--container-max) * 0.6);
  }
  .portrait-wall-grid:has(> .portrait-wall-layer:nth-of-type(3)) {
    --portrait-wall-mid: 3;
    grid-template-columns: repeat(5, 1fr);
    width: min(100% - 2 * var(--space-4), var(--container-max));
  }
  .portrait-wall-grid:has(> .portrait-wall-layer:nth-of-type(3)) > .portrait-wall-layer:nth-of-type(3) > .portrait-wall-tile {
    display: block;
  }
}
@media (min-width: 64rem) {
  .portrait-wall-grid:has(> .portrait-wall-layer:nth-of-type(4)) {
    --portrait-wall-mid: 4;
    grid-template-columns: repeat(7, 1fr);
  }
  .portrait-wall-grid:has(> .portrait-wall-layer:nth-of-type(4)) > .portrait-wall-layer:nth-of-type(4) > .portrait-wall-tile {
    display: block;
  }
}
/* Without subgrid a layer is its own one-column grid; display: contents hands
   the tiles straight to the wall, and dense packing seats each in its column. */
@supports not (grid-template-columns: subgrid) {
  .portrait-wall-grid {
    grid-auto-flow: dense;
  }
  .portrait-wall-grid > .portrait-wall-layer {
    display: contents;
  }
}
.portrait-wall:not(.portrait-wall--moving) {
  --hub-motion: none;
}
/* === /pattern portrait-wall@9 === */

/* === pattern pricing-tiers@11 (library v229; appended by page_assemble.py -- adopt a newer version by replacing this block, never by adding a second) === */
/* pricing-tiers v5 - tokens only, selectors prefixed */
.pricing-tiers {
  padding-block: var(--space-8);
}
.pricing-tiers-inner {
  width: min(100% - 2 * var(--space-4), var(--container-max));
  margin-inline: auto;
}
.pricing-tiers-title {
  font-family: var(--font-heading);
  color: var(--color-heading);
  font-size: calc(clamp(1.75rem, 1rem + 2vw, 2.25rem) * var(--type-scale, 1));
  margin: 0 0 var(--space-6);
}
.pricing-tiers-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(18rem, 100%), 1fr));
  gap: var(--space-5);
  align-items: stretch;
}
.pricing-tiers-card {
  display: flex;
  flex-direction: column;
  background: var(--color-surface);
  border: var(--card-border);
  border-radius: var(--card-radius);
  box-shadow: var(--card-shadow);
  padding: var(--space-6);
}
.pricing-tiers-flag {
  align-self: start;
  background: color-mix(in srgb, var(--color-primary) 14%, var(--color-surface));
  /* --color-text: --color-primary-dark is for light grounds only. */
  color: var(--color-text);
  font-size: 0.8rem;
  font-weight: 700;
  padding: var(--space-2) var(--space-3);
  border-radius: var(--chip-radius);
  margin: 0 0 var(--space-3);
}
.pricing-tiers-name {
  font-family: var(--font-heading);
  /* --color-text: --color-heading is not guaranteed on a surface. */
  color: var(--color-text);
  font-size: calc(1.25rem * var(--type-scale, 1));
  margin: 0 0 var(--space-2);
}
.pricing-tiers-price {
  /* --color-text: --color-heading is not guaranteed on a surface. */
  color: var(--color-text);
  font-size: calc(clamp(1.75rem, 1.2rem + 2vw, 2.5rem) * var(--type-scale, 1));
  font-weight: var(--weight-display, 700);
  margin: 0 0 var(--space-4);
}
.pricing-tiers-features {
  list-style: none;
  margin: 0 0 var(--space-6);
  padding: 0;
}
.pricing-tiers-features li {
  padding-block: var(--space-2);
  border-bottom: 1px solid var(--color-rule);
}
.pricing-tiers-features li:last-child {
  border-bottom: 0;
}
/* margin-top:auto bottom-aligns every card's CTA whatever the feature count */
.pricing-tiers-btn {
  margin-top: auto;
  display: block;
  text-align: center;
  background: var(--color-primary);
  color: var(--color-on-primary);
  font-weight: 700;
  text-decoration: none;
  padding: var(--space-3) var(--space-4);
  border-radius: var(--btn-radius);
  min-height: 48px;
  line-height: 1.5;
}
.pricing-tiers-btn:hover {
  background: var(--color-primary-dark);
}
/* Focus needs its own indicator, not the hover fill. */
.pricing-tiers-btn:focus-visible {
  outline: 3px solid var(--color-focus);
  outline-offset: 3px;
}
.pricing-tiers:not(.pricing-tiers--moving) {
  --hub-motion: none;
}
/* === /pattern pricing-tiers@11 === */

/* === pattern quote-feature@8 (library v229; appended by page_assemble.py -- adopt a newer version by replacing this block, never by adding a second) === */
/* quote-feature v1 - tokens only, selectors prefixed */
.quote-feature {
  background: var(--color-surface-soft);
  color: var(--color-text);
  padding-block: var(--space-8);
}
.quote-feature-stage {
  position: relative;
  width: min(100% - 2 * var(--space-4), var(--container-max));
  margin-inline: auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  /* Top padding is the eyebrow's room. Cut it and the eyebrow lands on the
     stars. */
  padding-block: var(--space-12) var(--space-8);
}
/* Pinned to the stage, not stacked above the quote, so the quote stays
   optically centred whatever its length. */
.quote-feature-eyebrow {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  margin: 0;
  font-size: 0.8125rem;
  font-weight: 700;
  line-height: 1.4;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--color-text-soft);
}
.quote-feature-block {
  margin: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
}
.quote-feature-stars {
  margin: 0 0 var(--space-5);
  font-size: 1.125rem;
  line-height: 1.2;
  letter-spacing: 0.22em;
  /* --color-text: --color-primary-dark is for light grounds only. */
  color: var(--color-text);
}
/* The measure is what keeps a display-size quote a quote instead of a
   paragraph. Widen 12.5em and it stops being this pattern. It is em and not
   ch because ch is the digit advance of the face in use: Georgia Bold and
   Arial differ by 26%, so one 20ch rule was four lines on some brands and
   five on others. em removes the typeface and keeps the type scale. */
.quote-feature-quote {
  margin: 0;
  max-width: 12.5em;
  font-family: var(--font-heading);
  font-size: calc(clamp(1.5rem, 3.4vw, 2.875rem) * var(--type-scale, 1));
  line-height: calc(1.24 * var(--heading-leading, 1));
  font-weight: var(--weight-display, 700);
  letter-spacing: calc(-0.02em + var(--heading-tracking, 0) * 1em);
  /* --color-text: the stage is a surface, and --color-heading is only
     guaranteed against --color-bg. */
  color: var(--color-text);
}
@supports (line-height: 1cap) {
  .quote-feature-quote {
    line-height: calc(max(1.24em, 1.45cap) * var(--heading-leading, 1));
  }
}
.quote-feature-quote p {
  margin: 0;
}
.quote-feature-author {
  margin-top: var(--space-6);
  display: flex;
  align-items: center;
  gap: var(--space-3);
  text-align: left;
}
.quote-feature-portrait {
  /* The portrait is a face, not a panel: round on every brand. */
  --quote-feature-portrait-radius: 50%;
  flex: none;
  width: 3.25rem;
  height: 3.25rem;
  display: block;
  object-fit: cover;
  border-radius: var(--quote-feature-portrait-radius);
}
.quote-feature-name {
  display: block;
  font-size: 1rem;
  font-weight: 700;
  line-height: 1.25;
  letter-spacing: -0.01em;
  color: var(--color-text);
}
.quote-feature-role {
  display: block;
  font-size: 0.875rem;
  line-height: 1.3;
  color: var(--color-text-soft);
}
@media (min-width: 48rem) {
  .quote-feature {
    padding-block: var(--space-12);
  }
  .quote-feature-stage {
    padding-block: var(--space-12);
  }
  .quote-feature-stars {
    margin-bottom: var(--space-6);
  }
  .quote-feature-author {
    margin-top: var(--space-8);
  }
}
/* === /pattern quote-feature@8 === */

/* === pattern safety-protections@5 (library v229; appended by page_assemble.py -- adopt a newer version by replacing this block, never by adding a second) === */
/* safety-protections v1 - tokens only, selectors prefixed */
.safety-protections {
  padding-block: var(--space-8);
  padding-inline: var(--space-4);
}
.safety-protections-inner {
  max-width: var(--container-max);
  margin-inline: auto;
}
.safety-protections-title {
  font-family: var(--font-heading);
  /* Both halves of the heading token's contract are met here: page ground,
   and a clamp floor above 24px. Keep both if you edit it. */
  color: var(--color-heading);
  font-size: calc(clamp(1.75rem, 3vw, 2.5rem) * var(--type-scale, 1));
  font-weight: var(--weight-display, 700);
  letter-spacing: calc(-0.02em + var(--heading-tracking, 0) * 1em);
  line-height: calc(1.15 * var(--heading-leading, 1));
  margin: 0 0 var(--space-4);
  text-wrap: balance;
}
@supports (line-height: 1cap) {
  .safety-protections-title {
    line-height: calc(max(1.15em, 1.45cap) * var(--heading-leading, 1));
  }
}
.safety-protections-intro {
  color: var(--color-text-soft);
  font-size: 1rem;
  line-height: 1.6;
  max-width: 46ch;
  margin: 0 0 var(--space-8);
}
.safety-protections-list {
  display: grid;
  gap: var(--space-5);
  grid-template-columns: 1fr;
  list-style: none;
  margin: 0;
  padding: 0;
}
.safety-protections-item {
  display: flex;
  flex-direction: column;
  padding: var(--space-6);
  background: var(--color-surface);
  border-radius: var(--card-radius);
  /* A drawn hairline, not the --card-border dial: on some brands the surface
   and the page ground are all but the same colour. */
  border: 1px solid var(--color-rule);
}
.safety-protections-name {
  font-family: var(--font-heading);
  color: var(--color-text);
  font-size: calc(1.1875rem * var(--type-scale, 1));
  font-weight: var(--weight-display, 700);
  line-height: calc(1.3 * var(--heading-leading, 1));
  margin: 0 0 var(--space-3);
  text-wrap: balance;
}
@supports (line-height: 1cap) {
  .safety-protections-name {
    line-height: calc(max(1.3em, 1.45cap) * var(--heading-leading, 1));
  }
}
.safety-protections-what {
  color: var(--color-text-soft);
  font-size: 0.9375rem;
  line-height: 1.6;
  margin: 0 0 var(--space-5);
}
.safety-protections-effect {
  margin-top: auto;
  padding-top: var(--space-4);
  border-top: 1px solid var(--color-rule);
  /* The darkest text in the card: this is the line a reader leaves with.
   Emphasis is weight and position, never a tint. */
  color: var(--color-text);
  font-size: 0.9375rem;
  font-weight: 500;
  line-height: 1.6;
  margin-bottom: 0;
}
.safety-protections-effect-label {
  display: block;
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  margin-bottom: var(--space-2);
}
@media (min-width: 48rem) {
  .safety-protections {
    padding-inline: var(--space-6);
  }
  .safety-protections-list {
    grid-template-columns: repeat(2, 1fr);
  }
}
@media (min-width: 64rem) {
  .safety-protections-list {
    grid-template-columns: repeat(auto-fit, minmax(18rem, 1fr));
  }
}
/* === /pattern safety-protections@5 === */

/* === pattern stat-rows@12 (library v229; appended by page_assemble.py -- adopt a newer version by replacing this block, never by adding a second) === */
/* stat-rows v10 - tokens only, selectors prefixed */
/* Dials, never declared here so a brand's :root reaches them:
   --stat-rows-weight (300), --stat-rows-row-height (9.6875rem). */
.stat-rows {
  padding-block: var(--space-8);
}
.stat-rows-list {
  width: min(100% - 2 * var(--space-4), var(--container-max));
  margin: 0 auto;
  padding: 0;
  border-block-start: 1px solid var(--color-rule);
}
.stat-rows-row {
  display: grid;
  gap: var(--space-2);
  padding-block: var(--space-5);
  border-block-end: 1px solid var(--color-rule);
}
.stat-rows-figure {
  font-family: var(--font-heading);
  color: var(--color-heading);
  font-weight: var(--stat-rows-weight, 300);
  /* Figure and sentence are sized as a pair - both carry the dial. */
  font-size: calc(clamp(1.875rem, 1.4rem + 2.2vw, 2.625rem) * var(--type-scale, 1));
  line-height: calc(1.04 * var(--heading-leading, 1));
  letter-spacing: calc(-0.03em + var(--heading-tracking, 0) * 1em);
}
@supports (line-height: 1cap) {
  .stat-rows-figure {
    line-height: calc(max(1.04em, 1.45cap) * var(--heading-leading, 1));
  }
}
.stat-rows-note {
  margin: 0;
  color: var(--color-text-soft);
  font-weight: var(--stat-rows-weight, 300);
  font-size: calc(clamp(1.375rem, 1.15rem + 0.9vw, 1.875rem) * var(--type-scale, 1));
  line-height: 1.18;
  text-wrap: pretty;
}

/* Tablet up: figure | hairline | sentence; below, the row stacks. */
@media (min-width: 48rem) {
  .stat-rows-row {
    grid-template-columns: minmax(9rem, 18rem) minmax(var(--space-8), 1fr) minmax(0, 27rem);
    gap: var(--space-6);
    align-items: center;
    padding-block: var(--space-6);
    /* min-height, not height: a long sentence still grows its row. */
    min-height: var(--stat-rows-row-height, 9.6875rem);
  }
  .stat-rows-figure {
    grid-area: 1 / 1;
  }
  .stat-rows-note {
    grid-area: 1 / 3;
    /* justify-self only - do not add text-align, which sets the paragraph
   ragged-left. */
    justify-self: end;
  }
  /* A pseudo-element, so it stays out of the accessibility tree. */
  .stat-rows-row::before {
    content: "";
    grid-area: 1 / 2;
    height: 1px;
    /* The hairline fades toward the sentence, in the direction it draws. */
    background: linear-gradient(
      90deg,
      var(--color-rule),
      color-mix(in srgb, var(--color-rule) 16%, transparent)
    );
    transform-origin: left center;
  }
}

/* Motion. Everything above is the finished state; .hub-* comes from the
   runtime and is never applied here. */
@media (prefers-reduced-motion: no-preference) {
  .stat-rows-row.hub-reveal-pending .stat-rows-figure {
    translate: -1.25rem 0;
  }
  .stat-rows-row.hub-reveal-pending .stat-rows-note {
    translate: 1.25rem 0;
  }
  /* Transition on the revealed state only, so the pending state is instant. */
  .stat-rows-row.hub-revealed .stat-rows-figure {
    translate: 0 0;
    transition: translate var(--transition-slow) ease-out
      calc(var(--stat-rows-row-index, 0) * 60ms + 80ms);
  }
  .stat-rows-row.hub-revealed .stat-rows-note {
    translate: 0 0;
    transition: translate var(--transition-slow) ease-out
      calc(var(--stat-rows-row-index, 0) * 60ms + 240ms);
  }
}
@media (min-width: 48rem) and (prefers-reduced-motion: no-preference) {
  .stat-rows-row.hub-reveal-pending::before {
    transform: scaleX(0);
  }
  .stat-rows-row.hub-revealed::before {
    transform: scaleX(1);
    transition: transform var(--transition-slow) ease-out
      calc(var(--stat-rows-row-index, 0) * 60ms + 160ms);
  }
}
.stat-rows:not(.stat-rows--moving) {
  --hub-motion: none;
}
/* === /pattern stat-rows@12 === */

/* === pattern stats-band@12 (library v229; appended by page_assemble.py -- adopt a newer version by replacing this block, never by adding a second) === */
/* stats-band v9 - tokens only, selectors prefixed */

/* The one inverted block on the page: --color-on-primary on
   --color-primary, the only pair the contract guarantees inverted. */
.stats-band {
  background: var(--color-primary);
  color: var(--color-on-primary);
  padding-block: var(--space-12);
}
.stats-band-inner {
  width: min(100% - 2 * var(--space-4), var(--container-max));
  margin-inline: auto;
}
.stats-band-head {
  max-width: 40rem;
  margin: 0 auto var(--space-8);
  text-align: center;
}
.stats-band-eyebrow {
  margin: 0 0 var(--space-3);
  font-family: var(--font-body);
  font-size: 0.8125rem;
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}
.stats-band-title {
  /* Set, not inherited: a brand's own h2 { color } beats inheritance. */
  color: var(--color-on-primary);
  margin: 0;
  font-family: var(--font-heading);
  font-size: calc(clamp(1.625rem, 1.1rem + 2.2vw, 2.75rem) * var(--type-scale, 1));
  font-weight: var(--weight-display, 700);
  line-height: calc(1.08 * var(--heading-leading, 1));
  letter-spacing: calc(-0.025em + var(--heading-tracking, 0) * 1em);
  text-wrap: balance;
}
@supports (line-height: 1cap) {
  .stats-band-title {
    line-height: calc(max(1.08em, 1.45cap) * var(--heading-leading, 1));
  }
}

/* The hairlines are the cells' own borders, not a gap showing through, so
   the lattice never doubles or breaks. */
.stats-band-grid {
  display: grid;
  grid-template-columns: 1fr;
  margin: 0;
  border-top: 1px solid color-mix(in srgb, var(--color-on-primary) 24%, transparent);
  border-left: 1px solid color-mix(in srgb, var(--color-on-primary) 24%, transparent);
  border-radius: var(--card-radius);
  overflow: clip;
}
.stats-band-item {
  padding: var(--space-6) var(--space-4);
  text-align: center;
  border-right: 1px solid color-mix(in srgb, var(--color-on-primary) 24%, transparent);
  border-bottom: 1px solid color-mix(in srgb, var(--color-on-primary) 24%, transparent);
}
.stats-band-figure {
  font-family: var(--font-heading);
  font-size: calc(clamp(2.125rem, 1.4rem + 3vw, 3.5rem) * var(--type-scale, 1));
  font-weight: var(--weight-display, 700);
  line-height: calc(1.02 * var(--heading-leading, 1));
  letter-spacing: calc(-0.03em + var(--heading-tracking, 0) * 1em);
}
@supports (line-height: 1cap) {
  .stats-band-figure {
    line-height: calc(max(1.02em, 1.45cap) * var(--heading-leading, 1));
  }
}
/* The label is a <dd>, so its default indent has to go. It separates from the
   figure by size and weight, never by fading the text - a translucent label
   would put the contrast guarantee back in question on every brand. */
.stats-band-label {
  margin: var(--space-2) 0 0;
  font-family: var(--font-body);
  font-size: 0.9375rem;
  font-weight: 400;
  line-height: 1.4;
}

/* 1 column -> 2 -> 3. The lattice needs no changes at either step. */
@media (min-width: 26rem) {
  .stats-band-grid {
    grid-template-columns: repeat(2, 1fr);
  }
}
@media (min-width: 48rem) {
  .stats-band-grid {
    grid-template-columns: repeat(3, 1fr);
  }
  .stats-band-item {
    padding: var(--space-8) var(--space-4);
  }
}
.stats-band:not(.stats-band--moving) {
  --hub-motion: none;
}
/* === /pattern stats-band@12 === */

/* === pattern steps-numbered@14 (library v229; appended by page_assemble.py -- adopt a newer version by replacing this block, never by adding a second) === */
/* steps-numbered v3 - tokens only, selectors prefixed */
.steps-numbered {
  /* Contrast floor. The words sit on a photograph, so the scrim carries the
   contrast; clamp() holds it whatever the dial is set to. */
  --steps-numbered-scrim-floor: clamp(0.92, var(--steps-numbered-scrim-strength, 0.92), 1);
  padding-block: var(--space-8);
}
.steps-numbered-inner {
  width: min(100% - 2 * var(--space-4), var(--container-max));
  margin-inline: auto;
}
.steps-numbered-title {
  font-family: var(--font-heading);
  color: var(--color-heading);
  font-size: calc(clamp(2rem, 1.4rem + 2.4vw, 3.5rem) * var(--type-scale, 1));
  line-height: calc(1.1 * var(--heading-leading, 1));
  letter-spacing: calc(-0.025em + var(--heading-tracking, 0) * 1em);
  margin: 0 0 var(--space-6);
  text-wrap: balance;
}
@supports (line-height: 1cap) {
  .steps-numbered-title {
    line-height: calc(max(1.1em, 1.45cap) * var(--heading-leading, 1));
  }
}
.steps-numbered-list {
  counter-reset: steps-numbered-count;
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(20rem, 100%), 1fr));
  gap: var(--space-5);
}
/* Full-bleed image at a fixed portrait ratio, clipped to the brand's corner. */
.steps-numbered-item {
  counter-increment: steps-numbered-count;
  position: relative;
  aspect-ratio: 510 / 590;
  overflow: hidden;
  border-radius: var(--card-radius);
  box-shadow: var(--card-shadow);
  background: var(--color-surface-soft);
}
.steps-numbered-img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
/* Three-stop scrim: near-solid where the words are, then fading. */
.steps-numbered-scrim {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: flex-end;
  padding: var(--space-6);
  /* Hold the full level to the top of the text band - the copy is a block,
   not a line. */
  background-image: linear-gradient(
    to top,
    color-mix(in srgb, var(--color-scrim) calc(var(--steps-numbered-scrim-floor) * 100%), transparent) 0%,
    color-mix(in srgb, var(--color-scrim) calc(var(--steps-numbered-scrim-floor) * 100%), transparent) 55%,
    color-mix(in srgb, var(--color-scrim) calc(var(--steps-numbered-scrim-floor) * 43%), transparent) 78%,
    transparent 100%
  );
}
.steps-numbered-content {
  display: flex;
  align-items: flex-start;
  gap: var(--space-5);
  color: var(--color-on-scrim);
}
/* line-height below 1 sets the numeral's cap flush with the heading. */
.steps-numbered-content::before {
  content: counter(steps-numbered-count);
  font-family: var(--font-heading);
  font-size: calc(clamp(64px, 6vw, 84px) * var(--type-scale, 1));
  font-weight: var(--weight-display, 700);
  line-height: 0.8;
  flex: none;
}
.steps-numbered-text {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}
.steps-numbered-heading {
  /* Set, not inherited: a brand's own h3 { color } beats inheritance. */
  color: var(--color-on-scrim);
  font-family: var(--font-heading);
  font-size: calc(clamp(1.125rem, 0.9rem + 0.6vw, 1.375rem) * var(--type-scale, 1));
  line-height: calc(1.15 * var(--heading-leading, 1));
  letter-spacing: calc(-0.01em + var(--heading-tracking, 0) * 1em);
  margin: 0;
  text-wrap: balance;
}
@supports (line-height: 1cap) {
  .steps-numbered-heading {
    line-height: calc(max(1.15em, 1.45cap) * var(--heading-leading, 1));
  }
}
.steps-numbered-body {
  font-size: clamp(0.875rem, 0.8rem + 0.3vw, 1rem);
  line-height: 1.4;
  margin: 0;
}
/* Narrow cards cannot carry an 84px numeral beside the copy, so it steps down
   and the pair stacks rather than the heading wrapping to one word a line.
   The step-down carries the dial too: without it the numeral jumped smaller
   as the viewport narrowed past 30rem on any brand with the dial above 1,
   which is a worse fault than a size that never moves at all. */
@media (max-width: 29.99rem) {
  .steps-numbered-content {
    flex-direction: column;
    gap: var(--space-2);
  }
  .steps-numbered-content::before {
    font-size: calc(clamp(48px, 14vw, 64px) * var(--type-scale, 1));
    /* Stacked, the line box holds the numeral's glyphs in any face. */
    line-height: normal;
  }
  .steps-numbered-scrim {
    padding: var(--space-5);
  }
}

.steps-numbered img[data-hub-placeholder] {
  background: color-mix(in srgb, var(--color-primary) 18%, var(--color-surface));
}
.steps-numbered:not(.steps-numbered--moving) {
  --hub-motion: none;
}
/* === /pattern steps-numbered@14 === */

/* === pattern testimonial-carousel@11 (library v229; appended by page_assemble.py -- adopt a newer version by replacing this block, never by adding a second) === */
/* testimonial-carousel v8 - tokens only, selectors prefixed. */
.testimonial-carousel {
  /* Phones show the active card alone; the three-up stage starts at 60rem.
     Two numbers place all three cards - change these, not the transforms. */
  --testimonial-carousel-card-w: min(100vw - 2 * var(--space-5), 34rem);
  --testimonial-carousel-target: 2.75rem;
  position: relative;
  /* Required: this is what crops the cards that hang outside the viewport. */
  overflow: hidden;
  padding-block: var(--space-12);
}
.testimonial-carousel-inner {
  width: min(100% - 2 * var(--space-4), var(--container-max));
  margin-inline: auto;
  text-align: center;
}
.testimonial-carousel-title {
  margin: 0 0 var(--space-8);
  font-family: var(--font-heading);
  color: var(--color-heading);
  font-size: calc(clamp(1.75rem, 1rem + 2vw, 2.25rem) * var(--type-scale, 1));
  letter-spacing: calc(-0.02em + var(--heading-tracking, 0) * 1em);
}
/* Full bleed: the neighbouring cards sit well outside any container. */
.testimonial-carousel-machine {
  position: relative;
  width: 100vw;
  margin-left: calc(50% - 50vw);
  margin-top: var(--space-8);
}
/* Clipped, NOT hidden. display:none, visibility:hidden and the hidden
   attribute each drop these out of the tab order, and the radio group is the
   keyboard interface. They must also stay siblings, ahead of the stage. */
.testimonial-carousel-input,
.testimonial-carousel-dot-text {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  border: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}
/* Pinned mid-stage: at the machine's own start edge it sits off-screen, and
   focusing it would scroll the cropped section sideways. */
.testimonial-carousel-input {
  top: 0;
  left: 50%;
}
.testimonial-carousel-stage {
  display: grid;
  justify-items: center;
  align-items: start;
}
.testimonial-carousel-card {
  /* A face is round on every brand, so this is not --card-radius. */
  --testimonial-carousel-avatar-radius: 50%;
  /* Every card on the one cell: the stage is the tallest of them, so it
     cannot grow over the dots and cannot resize as the reader moves. */
  grid-area: 1 / 1;
  margin-top: var(--space-8);
  width: var(--testimonial-carousel-card-w);
  min-height: 15.5rem;
  /* Room for the portrait that hangs above the card. */
  padding: max(var(--space-12), 4.5rem) var(--space-6) var(--space-8);
  background: var(--color-surface);
  /* --color-text: this is not large text. */
  color: var(--color-text);
  border: var(--card-border);
  border-radius: var(--card-radius);
  box-shadow: var(--card-shadow);
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transform: scale(0.88);
}
.testimonial-carousel-avatar {
  position: absolute;
  top: calc(-1 * var(--space-6));
  left: 50%;
  transform: translateX(-50%);
  box-sizing: border-box;
  width: 5.5rem;
  height: 5.5rem;
  object-fit: cover;
  border-radius: var(--testimonial-carousel-avatar-radius);
  border: var(--space-1) solid var(--color-surface);
  background: var(--color-surface);
  box-shadow: var(--card-shadow);
}
.testimonial-carousel-quote {
  margin: 0 auto;
  max-width: 27rem;
}
.testimonial-carousel-quote p {
  margin: 0;
  font-family: var(--font-heading);
  font-size: calc(clamp(1.0625rem, 0.95rem + 0.6vw, 1.3125rem) * var(--type-scale, 1));
  line-height: calc(1.28 * var(--heading-leading, 1));
  font-weight: var(--weight-display, 700);
  letter-spacing: calc(-0.035em + var(--heading-tracking, 0) * 1em);
  color: inherit;
}
@supports (line-height: 1cap) {
  .testimonial-carousel-quote p {
    line-height: calc(max(1.28em, 1.45cap) * var(--heading-leading, 1));
  }
}
.testimonial-carousel-person {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-1);
  margin-top: var(--space-6);
}
.testimonial-carousel-name {
  font-size: 1.0625rem;
  line-height: 1.2;
  font-weight: 500;
}
/* Size and weight, not colour: the active card changes ground. */
.testimonial-carousel-role {
  font-size: 0.875rem;
  line-height: 1.4;
  font-weight: 400;
}
/* ACTIVE CARD. One line per slide, here and in each list that follows. */
.testimonial-carousel-input--1:checked ~ .testimonial-carousel-stage .testimonial-carousel-card--1,
.testimonial-carousel-input--2:checked ~ .testimonial-carousel-stage .testimonial-carousel-card--2,
.testimonial-carousel-input--3:checked ~ .testimonial-carousel-stage .testimonial-carousel-card--3 {
  z-index: 2;
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
  transform: scale(1);
  background: var(--color-primary);
  color: var(--color-on-primary);
  border-color: var(--color-primary);
}
.testimonial-carousel-dots {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  margin-top: var(--space-4);
}
.testimonial-carousel-dot {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  /* The tap target is the label; the pill inside it is only the mark. */
  min-width: var(--testimonial-carousel-target);
  min-height: var(--testimonial-carousel-target);
  cursor: pointer;
}
.testimonial-carousel-dot::before {
  content: "";
  display: block;
  width: var(--space-2);
  height: var(--space-2);
  border-radius: var(--chip-radius);
  /* Not --color-rule: brands may set that as soft as they like, and these
     are the only controls on the pattern. */
  background: var(--color-text-soft);
}
.testimonial-carousel-dot:hover::before {
  background: var(--color-primary);
}
/* ACTIVE DOT. Width carries the state as well as colour. */
.testimonial-carousel-input--1:checked ~ .testimonial-carousel-dots .testimonial-carousel-dot--1::before,
.testimonial-carousel-input--2:checked ~ .testimonial-carousel-dots .testimonial-carousel-dot--2::before,
.testimonial-carousel-input--3:checked ~ .testimonial-carousel-dots .testimonial-carousel-dot--3::before {
  width: var(--space-5);
  background: var(--color-primary);
}
/* FOCUS. It lands on a clipped input, so it is painted on the two things the
   reader can see. Drop either half and the carousel is focusable with no
   visible focus at all. */
.testimonial-carousel-input--1:focus-visible ~ .testimonial-carousel-dots .testimonial-carousel-dot--1::before,
.testimonial-carousel-input--2:focus-visible ~ .testimonial-carousel-dots .testimonial-carousel-dot--2::before,
.testimonial-carousel-input--3:focus-visible ~ .testimonial-carousel-dots .testimonial-carousel-dot--3::before,
.testimonial-carousel-input--1:focus-visible ~ .testimonial-carousel-stage .testimonial-carousel-card--1,
.testimonial-carousel-input--2:focus-visible ~ .testimonial-carousel-stage .testimonial-carousel-card--2,
.testimonial-carousel-input--3:focus-visible ~ .testimonial-carousel-stage .testimonial-carousel-card--3 {
  outline: 3px solid var(--color-focus);
  outline-offset: var(--space-1);
}
@media (min-width: 60rem) {
  .testimonial-carousel {
    --testimonial-carousel-card-w: clamp(22.5rem, 34vw, 34rem);
    /* Centre to centre. Keep it larger than the card width or the neighbours
       climb on top of the active card. */
    --testimonial-carousel-side-offset: clamp(25.5rem, 45vw, 42rem);
  }
  /* PREVIOUS CARD. */
  .testimonial-carousel-input--1:checked ~ .testimonial-carousel-stage .testimonial-carousel-card--3,
  .testimonial-carousel-input--2:checked ~ .testimonial-carousel-stage .testimonial-carousel-card--1,
  .testimonial-carousel-input--3:checked ~ .testimonial-carousel-stage .testimonial-carousel-card--2 {
    z-index: 1;
    opacity: 1;
    visibility: visible;
    pointer-events: auto;
    transform: translateX(calc(-1 * var(--testimonial-carousel-side-offset))) scale(0.94);
  }
  /* NEXT CARD. */
  .testimonial-carousel-input--1:checked ~ .testimonial-carousel-stage .testimonial-carousel-card--2,
  .testimonial-carousel-input--2:checked ~ .testimonial-carousel-stage .testimonial-carousel-card--3,
  .testimonial-carousel-input--3:checked ~ .testimonial-carousel-stage .testimonial-carousel-card--1 {
    z-index: 1;
    opacity: 1;
    visibility: visible;
    pointer-events: auto;
    transform: translateX(var(--testimonial-carousel-side-offset)) scale(0.94);
  }
}
/* controls: where the previous and next arrows sit, read by the behaviour
   library from these properties. dots: the round pair under the slide
   dots, centred. */
.testimonial-carousel--top {
  --hub-carousel-controls: top;
  --hub-carousel-look: round;
}
.testimonial-carousel--edges {
  --hub-carousel-controls: edges;
  --hub-carousel-look: round;
}
.testimonial-carousel--dots {
  --hub-carousel-controls: under;
  --hub-carousel-look: round;
}
/* The machine is full bleed; the pair keeps to the column. */
.testimonial-carousel .hub-carousel-controls--top {
  max-width: var(--container-max);
  margin-inline: auto;
  padding-inline: var(--space-4);
}
/* Above the neighbouring cards, which sit a layer up, on a ground of its
   own so it reads over them. */
.testimonial-carousel .hub-carousel-controls--edges {
  z-index: 2;
}
.testimonial-carousel .hub-carousel-controls--edges .hub-carousel-control {
  border: 0;
  background: var(--color-bg);
  color: var(--color-text);
  box-shadow: var(--card-shadow);
}
@media (prefers-reduced-motion: no-preference) {
  .testimonial-carousel-card {
    transition:
      transform var(--transition-slow) ease,
      opacity var(--transition-slow) ease,
      visibility var(--transition-slow) ease,
      background var(--transition-fast) ease,
      color var(--transition-fast) ease,
      border-color var(--transition-fast) ease;
  }
  .testimonial-carousel-dot::before {
    transition: width var(--transition-fast) ease,
      background var(--transition-fast) ease;
  }
}
@media (prefers-reduced-motion: reduce) {
  .testimonial-carousel-card,
  .testimonial-carousel-dot::before {
    transition: none;
  }
}
/* === /pattern testimonial-carousel@11 === */

/* === pattern testimonial-grid@12 (library v229; appended by page_assemble.py -- adopt a newer version by replacing this block, never by adding a second) === */
/* testimonial-grid v4 - tokens only, selectors prefixed */
.testimonial-grid {
  padding-block: var(--space-8);
}
.testimonial-grid-inner {
  width: min(100% - 2 * var(--space-4), var(--container-max));
  margin-inline: auto;
}
.testimonial-grid-title {
  margin: 0 0 var(--space-8);
  font-family: var(--font-heading);
  color: var(--color-heading);
  font-size: calc(clamp(1.75rem, 1rem + 2vw, 2.25rem) * var(--type-scale, 1));
  letter-spacing: calc(-0.02em + var(--heading-tracking, 0) * 1em);
}
.testimonial-grid-list {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(17rem, 100%), 1fr));
  gap: var(--space-8) var(--space-5);
  align-items: stretch;
  list-style: none;
  margin: 0;
  /* headroom for the portraits, which overhang the top edge of the first row */
  padding: var(--space-6) 0 0;
}
.testimonial-grid-item {
  display: flex;
}
.testimonial-grid-card {
  /* The portrait is a face, not a panel: round on every brand. */
  --testimonial-grid-avatar-radius: 50%;
  position: relative;
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  margin: 0;
  background: var(--color-surface);
  /* --color-text: this is not large text. */
  color: var(--color-text);
  border: var(--card-border);
  border-radius: var(--card-radius);
  box-shadow: var(--card-shadow);
  /* deep top padding clears the overhanging portrait */
  padding: var(--space-12) var(--space-5) var(--space-6);
}
/* The portrait breaks the top edge, centred on it, ringed in the surface
   colour so it reads as lifted off the card rather than pasted onto it. */
.testimonial-grid-avatar {
  position: absolute;
  top: calc(-1 * var(--space-6));
  left: 50%;
  transform: translateX(-50%);
  box-sizing: border-box;
  width: 5rem;
  height: 5rem;
  object-fit: cover;
  border-radius: var(--testimonial-grid-avatar-radius);
  border: var(--space-1) solid var(--color-surface);
  background: var(--color-surface);
  box-shadow: var(--card-shadow);
}
/* The fill is decoration; this is the meaning. */
.testimonial-grid-flag {
  margin: 0 0 var(--space-4);
  font-size: 0.75rem;
  font-weight: 700;
  line-height: 1;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  /* --color-text: --color-primary-dark is for light grounds only. */
  color: var(--color-text);
}
.testimonial-grid-quote {
  margin: 0;
  max-width: 27rem;
}
/* The weight contrast the card is built on: the quote heavy and tightly
   tracked, the name below it light. */
.testimonial-grid-quote p {
  margin: 0;
  font-family: var(--font-heading);
  font-size: calc(clamp(1.0625rem, 0.95rem + 0.6vw, 1.3125rem) * var(--type-scale, 1));
  line-height: calc(1.28 * var(--heading-leading, 1));
  font-weight: var(--weight-display, 700);
  letter-spacing: calc(-0.035em + var(--heading-tracking, 0) * 1em);
  color: inherit;
}
@supports (line-height: 1cap) {
  .testimonial-grid-quote p {
    line-height: calc(max(1.28em, 1.45cap) * var(--heading-leading, 1));
  }
}
/* margin-top:auto bottom-aligns the attribution across a row. */
.testimonial-grid-person {
  margin-top: auto;
  padding-top: var(--space-6);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-1);
}
.testimonial-grid-name {
  font-size: 1.0625rem;
  line-height: 1.2;
  font-weight: 500;
  color: inherit;
}
.testimonial-grid-role {
  font-size: 0.875rem;
  line-height: 1.4;
  color: var(--color-text-soft);
}
.testimonial-grid-source {
  margin-top: var(--space-2);
  font-size: 0.875rem;
  /* --color-text: --color-primary-dark is for light grounds only. */
  color: var(--color-text);
}
.testimonial-grid-source:focus-visible {
  outline: 2px solid var(--color-focus);
  outline-offset: 2px;
}
/* One card may invert to --color-primary with --color-on-primary. */
.testimonial-grid-item--featured .testimonial-grid-card {
  background: var(--color-primary);
  color: var(--color-on-primary);
  border-color: color-mix(in srgb, var(--color-on-primary) 30%, transparent);
}
/* Ring from --color-on-primary: the featured ground is --color-primary. */
.testimonial-grid-item--featured .testimonial-grid-source:focus-visible {
  outline-color: var(--color-on-primary);
}
.testimonial-grid-item--featured .testimonial-grid-flag,
.testimonial-grid-item--featured .testimonial-grid-role,
.testimonial-grid-item--featured .testimonial-grid-source {
  color: var(--color-on-primary);
}
/* Lock the row to three from tablet-landscape up; below that the cards fall
   to two and then one on their own. */
@media (min-width: 60rem) {
  .testimonial-grid-list {
    grid-template-columns: repeat(3, 1fr);
  }
}
/* === /pattern testimonial-grid@12 === */

/* === pattern trust-row@4 (library v229; appended by page_assemble.py -- adopt a newer version by replacing this block, never by adding a second) === */
/* trust-row v2 - tokens only, selectors prefixed */

/* The hairlines and the space inside them are the whole frame: no background,
   no card. Do not add one. The padding, not the rule, is what separates the
   strip from its neighbours, so keep it whatever --color-rule looks like. */
.trust-row {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: clamp(var(--space-6), 6vw, var(--space-12));
  margin-block: clamp(var(--space-6), 6vh, var(--space-12)) clamp(var(--space-5), 4vh, var(--space-8));
  padding-block: clamp(var(--space-6), 4vh, var(--space-8));
  border-top: 1px solid var(--color-rule);
  border-bottom: 1px solid var(--color-rule);
  font-family: var(--font-body);
}

.trust-row-membership {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}
.trust-row-mark {
  flex: none;
  width: auto;
  height: var(--trust-row-mark-height, 2.375rem);
  max-width: 100%;
}
.trust-row-membership-name {
  margin: 0;
  color: var(--color-text);
  font-size: 0.9375rem;
  font-weight: 700;
  line-height: 1.2;
}
/* --color-text on --color-surface-soft is a guaranteed pair; a brand tint
   under this label is not. Do not swap the ground. */
.trust-row-membership-status {
  display: inline-block;
  margin-top: var(--space-1);
  padding: var(--space-1) var(--space-2);
  background: var(--color-surface-soft);
  border-radius: var(--chip-radius);
  color: var(--color-text);
  font-size: 0.6875rem;
  font-weight: 700;
}

.trust-row-badges {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  justify-content: center;
  gap: clamp(var(--space-5), 3vw, var(--space-8));
  list-style: none;
  margin: 0;
  padding: 0;
}
.trust-row-badge {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-2);
  max-width: 9rem;
  color: var(--color-text-soft);
  font-size: 0.75rem;
  font-weight: 700;
  line-height: 1.3;
  text-align: center;
}
/* Keep the mix. Bare --color-primary-dark is a dark ink and disappears on a
   dark brand. The icon is aria-hidden either way, so never drop a label and
   leave the glyph standing for it. */
.trust-row-badge-icon {
  display: flex;
  color: color-mix(in srgb, var(--color-primary-dark) 65%, var(--color-text));
}
.trust-row-badge-icon svg {
  width: 1.75rem;
  height: 1.75rem;
}

/* Wide phone up: the lockup and the badges share one row and wrap. */
@media (min-width: 35rem) {
  .trust-row {
    flex-direction: row;
  }
}
/* === /pattern trust-row@4 === */

/* === page /design-patterns/patterns: its own styles (page_assemble.py; rewritten on every assemble of this page) === */
.dp-label { max-width: var(--container-max, 72rem); margin: var(--space-10, 4rem) auto 0; padding: 0 var(--space-4, 1rem) var(--space-3, .75rem);
  border-bottom: 2px solid var(--color-primary); font-family: var(--font-body); display: grid; gap: .15rem; }
.dp-label-name { font-family: var(--font-heading); font-size: 1.5rem; color: var(--color-heading); }
.dp-label-meta { font-size: .8rem; letter-spacing: .06em; text-transform: uppercase; color: var(--color-primary); }
.dp-label-sum { font-size: .9rem; color: var(--color-text-soft); max-width: 60ch; }
.dp-intro { max-width: var(--container-max, 72rem); margin: 0 auto; padding: var(--space-10, 4rem) var(--space-4, 1rem) var(--space-6, 2rem); font-family: var(--font-body); }
.dp-intro h1 { font-family: var(--font-heading); font-size: clamp(2.2rem, 6vw, 4rem); margin: 0 0 .5rem; color: var(--color-heading); line-height: 1; }
.dp-intro p { color: var(--color-text-soft); max-width: 60ch; margin: 0; }
/* === /page /design-patterns/patterns === */

/* === pattern hero-band@3 (library v237; appended by page_assemble.py -- adopt a newer version by replacing this block, never by adding a second) === */
/* hero-band v1 - tokens only, selectors prefixed */
/* Each ground names its own ink; every rule below reads the pair. */
.hero-band--plain {
  --hero-band-ground: var(--color-bg);
  --hero-band-ink: var(--color-text-soft);
  --hero-band-title-ink: var(--color-heading);
  --hero-band-btn-face: var(--color-primary);
  --hero-band-btn-ink: var(--color-on-primary);
  --hero-band-ring: var(--color-focus);
}
.hero-band--soft {
  --hero-band-ground: var(--color-surface-soft);
  --hero-band-ink: var(--color-text);
  --hero-band-title-ink: var(--color-text);
  --hero-band-btn-face: var(--color-primary);
  --hero-band-btn-ink: var(--color-on-primary);
  --hero-band-ring: var(--color-focus);
}
.hero-band--brand {
  --hero-band-ground: var(--color-primary);
  --hero-band-ink: var(--color-on-primary);
  --hero-band-title-ink: var(--color-on-primary);
  --hero-band-btn-face: var(--color-on-primary);
  --hero-band-btn-ink: var(--color-primary);
  --hero-band-ring: var(--color-on-primary);
}
.hero-band--deep {
  --hero-band-ground: var(--color-scrim);
  --hero-band-ink: var(--color-on-scrim);
  --hero-band-title-ink: var(--color-on-scrim);
  --hero-band-btn-face: var(--color-primary);
  --hero-band-btn-ink: var(--color-on-primary);
  --hero-band-ring: var(--color-on-scrim);
}
.hero-band {
  background: var(--hero-band-ground);
  color: var(--hero-band-ink);
  padding-block: var(--space-5) var(--space-8);
}
.hero-band-inner {
  width: min(100% - 2 * var(--space-4), var(--container-max));
  margin-inline: auto;
  display: grid;
  gap: var(--space-5);
  align-items: center;
}
/* The photograph leads on a phone; from 48rem the photo rung places it. */
.hero-band-visual {
  order: -1;
  overflow: clip;
  border-radius: var(--card-radius);
}
.hero-band-img {
  display: block;
  width: 100%;
  /* A band, not a screen: from the width, never the viewport height. */
  height: clamp(11rem, 48vw, 16rem);
  object-fit: cover;
}
.hero-band-eyebrow {
  font-size: 0.8125rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  margin: 0 0 var(--space-3);
}
.hero-band-title {
  font-family: var(--font-heading);
  color: var(--hero-band-title-ink);
  font-size: calc(clamp(1.75rem, 1.2rem + 2.6vw, 3.25rem) * var(--type-scale, 1));
  font-weight: var(--weight-display, 700);
  letter-spacing: calc(-0.02em + var(--heading-tracking, 0) * 1em);
  line-height: calc(1.08 * var(--heading-leading, 1));
  max-width: 14em;
  margin: 0 0 var(--space-4);
  text-wrap: balance;
}
@supports (line-height: 1cap) {
  .hero-band-title {
    line-height: calc(max(1.08em, 1.45cap) * var(--heading-leading, 1));
  }
}
.hero-band-sub {
  font-size: 1.0625rem;
  line-height: 1.55;
  max-width: 46ch;
  margin: 0 0 var(--space-5);
}
.hero-band-btn {
  box-sizing: border-box;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 48px;
  padding: var(--space-3) var(--space-6);
  border-radius: var(--btn-radius);
  background: var(--hero-band-btn-face);
  color: var(--hero-band-btn-ink);
  font-weight: 700;
  line-height: 1.5;
  text-decoration: none;
}
.hero-band-btn:hover {
  text-decoration: underline;
  text-underline-offset: 0.2em;
}
.hero-band-btn:focus-visible {
  outline: 3px solid var(--hero-band-ring);
  outline-offset: 3px;
}
/* Behind, the words never sit on the photograph: on a panel of the ground. */
.hero-band--behind {
  padding-top: 0;
}
.hero-band--behind .hero-band-visual {
  margin-inline: calc(-1 * var(--space-4));
  border-radius: 0;
}
.hero-band--behind .hero-band-copy {
  position: relative;
  margin-top: calc(-1 * var(--space-8));
  padding: var(--space-5) var(--space-4);
  background: var(--hero-band-ground);
  border-radius: var(--card-radius);
}
@media (min-width: 48rem) {
  .hero-band {
    padding-block: var(--space-8);
  }
  .hero-band-inner {
    grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.9fr);
    column-gap: var(--space-8);
  }
  .hero-band-img {
    height: clamp(16rem, 30vw, 24rem);
  }
  .hero-band--end .hero-band-visual {
    order: 0;
  }
  .hero-band--start .hero-band-inner {
    grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr);
  }
  .hero-band--start .hero-band-visual {
    order: -1;
  }
  .hero-band--behind {
    position: relative;
    isolation: isolate;
  }
  .hero-band--behind .hero-band-inner {
    grid-template-columns: minmax(0, min(36rem, 62%));
    min-height: clamp(18rem, 30vw, 24rem);
  }
  .hero-band--behind .hero-band-visual {
    position: absolute;
    inset: 0;
    z-index: -1;
    margin: 0;
  }
  .hero-band--behind .hero-band-img {
    height: 100%;
  }
  .hero-band--behind .hero-band-copy {
    margin-top: 0;
    padding: var(--space-6);
  }
  /* Keep in step with the panel's track: a placeholder draws beside it. */
  .hero-band--behind .hero-band-img[data-hub-placeholder] {
    box-sizing: border-box;
    padding: var(--space-6) var(--space-8) var(--space-6) calc((100% - min(100% - 2 * var(--space-4), var(--container-max))) / 2 + min(36rem, 0.62 * min(100% - 2 * var(--space-4), var(--container-max))) + var(--space-8));
    object-fit: contain;
  }
}

.hero-band img[data-hub-placeholder] {
  background: color-mix(in srgb, var(--color-primary) 18%, var(--color-surface));
}

.hero-band:not(.hero-band--moving) {
  --hub-motion: none;
}
@media (prefers-reduced-motion: no-preference) {
  .hero-band--moving .hero-band-img {
    animation: hero-band-drift 5s ease-out 1 both;
  }
  @keyframes hero-band-drift {
    from {
      scale: 1.08;
    }
  }
}
/* === /pattern hero-band@3 === */

/* === page /new-pages/community-a: its own styles (page_assemble.py; rewritten on every assemble of this page) === */
.cm-interests { max-width: var(--container-max, 72rem); margin: 0 auto; padding: var(--space-10, 4rem) var(--space-4, 1rem); font-family: var(--font-body); }
.cm-interests h2 { font-family: var(--font-heading); font-size: clamp(1.8rem, 4vw, 2.6rem); margin: 0 0 .5rem; color: var(--color-heading); }
.cm-interests p { color: var(--color-text-soft); margin: 0 0 1.25rem; max-width: 60ch; }
.cm-chips { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: .5rem; }
.cm-chips li { border: 1px solid var(--color-rule); border-radius: var(--chip-radius, 999px); padding: .35rem .8rem; font-size: .9rem; background: var(--color-surface); color: var(--color-text); }
/* === /page /new-pages/community-a === */

/* === page /new-pages/community-b: its own styles (page_assemble.py; rewritten on every assemble of this page) === */
.cm-interests { max-width: var(--container-max, 72rem); margin: 0 auto; padding: var(--space-10, 4rem) var(--space-4, 1rem); font-family: var(--font-body); }
.cm-interests h2 { font-family: var(--font-heading); font-size: clamp(1.8rem, 4vw, 2.6rem); margin: 0 0 .5rem; color: var(--color-heading); }
.cm-interests p { color: var(--color-text-soft); margin: 0 0 1.25rem; max-width: 60ch; }
.cm-chips { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: .5rem; }
.cm-chips li { border: 1px solid var(--color-rule); border-radius: var(--chip-radius, 999px); padding: .35rem .8rem; font-size: .9rem; background: var(--color-surface); color: var(--color-text); }
/* === /page /new-pages/community-b === */

/* === page /design-patterns/menu-buttons: its own styles (page_assemble.py; rewritten on every assemble of this page) === */
.mb-wrap { max-width: var(--container-max, 72rem); margin: 0 auto; padding: var(--space-10, 4rem) var(--space-4, 1rem); font-family: var(--font-body); }
.mb-intro h1 { font-family: var(--font-heading); font-size: clamp(2.2rem, 6vw, 4rem); line-height: 1; margin: 0 0 .5rem; color: var(--color-heading); }
.mb-intro p, .mb-sub { color: var(--color-text-soft); max-width: 62ch; margin: 0 0 1.5rem; }
.mb-h2 { font-family: var(--font-heading); font-size: clamp(1.6rem, 4vw, 2.4rem); margin: 3rem 0 .25rem; color: var(--color-heading); border-bottom: 2px solid var(--color-primary); padding-bottom: .4rem; }
.mb-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 22rem), 1fr)); gap: 1.5rem; }
.mb-item { margin: 0; display: grid; gap: .6rem; align-content: start; }
.mb-item figcaption { display: grid; gap: .15rem; color: var(--color-text); }
.mb-tag { font-size: .75rem; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--color-primary); }
.mb-note { font-size: .85rem; color: var(--color-text-soft); }
.mb-frame { width: 100%; max-width: 390px; height: 560px; border: 1px solid var(--color-rule); border-radius: var(--card-radius, .75rem); background: var(--color-bg); }
/* === /page /design-patterns/menu-buttons === */

/* === pattern hero-bento@2 (library v248; appended by page_assemble.py -- adopt a newer version by replacing this block, never by adding a second) === */
/* hero-bento v1 - tokens only, selectors prefixed.
   .lp-grid and .mem-card* below are the platform's markup, a contract. */
.hero-bento {
  padding-block: var(--space-5) var(--space-8);
  background: var(--color-bg);
  color: var(--color-text);
}
.hero-bento-grid {
  width: min(100% - 2 * var(--space-4), var(--container-max));
  margin-inline: auto;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  grid-template-areas: "lead" "join" "cells";
}
.hero-bento-lead {
  grid-area: lead;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  padding: var(--space-6) var(--space-5);
}
.hero-bento-join {
  grid-area: join;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: flex-start;
  gap: var(--space-3);
  padding: var(--space-5);
}
/* Holding the card, the tile is the card: the form fills it edge to edge and
   the tile's own edge is the one border. */
.hero-bento-join:has(.signup-card) {
  align-items: stretch;
  padding: 0;
}
.hero-bento .hero-bento-join:has(.signup-card) {
  background: var(--color-surface);
}
.hero-bento-join:has(.signup-card) > .hero-bento-join-line {
  padding: var(--space-4) var(--space-5) 0;
}
.hero-bento-join .signup-card {
  max-width: none;
}
.hero-bento-join .signup-card-form {
  border: 0;
  border-radius: 0;
  box-shadow: none;
}
.hero-bento-cells {
  grid-area: cells;
  display: flex;
  flex-wrap: wrap;
  align-content: stretch;
  margin: 0;
  padding: 0;
  list-style: none;
}
/* Every tile grows to fill its row, so one left out leaves no gap. */
.hero-bento-cells > li {
  box-sizing: border-box;
  flex: 1 1 11rem;
  min-width: 0;
  min-height: clamp(9rem, 14vw, 12rem);
}
.hero-bento-photo,
.hero-bento-second {
  position: relative;
  overflow: clip;
}
.hero-bento-cells > .hero-bento-photo {
  flex-basis: 100%;
  min-height: clamp(14rem, 30vw, 22rem);
}
.hero-bento-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.hero-bento-figure,
.hero-bento-members,
.hero-bento-interests {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  padding: var(--space-5);
}
.hero-bento-cells > .hero-bento-members {
  flex-basis: 20rem;
}
/* The figure is sized to its own tile, so a number never breaks. */
.hero-bento-cells > .hero-bento-figure {
  flex-basis: 12rem;
  container-type: inline-size;
}
.hero-bento-figure {
  justify-content: flex-end;
  background: var(--color-primary);
  color: var(--color-on-primary);
}
.hero-bento-eyebrow {
  margin: 0 0 var(--space-3);
  color: var(--color-text-soft);
  font-size: 0.8125rem;
  font-weight: 700;
  line-height: 1.4;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}
.hero-bento-title {
  max-width: 12em;
  margin: 0 0 var(--space-4);
  font-family: var(--font-heading);
  color: var(--color-text);
  font-size: calc(clamp(2rem, 1.3rem + 2.6vw, 3.5rem) * var(--type-scale, 1));
  font-weight: var(--weight-display, 700);
  letter-spacing: calc(-0.02em + var(--heading-tracking, 0) * 1em);
  line-height: calc(1.05 * var(--heading-leading, 1));
  text-wrap: balance;
}
@supports (line-height: 1cap) {
  .hero-bento-title {
    line-height: calc(max(1.05em, 1.45cap) * var(--heading-leading, 1));
  }
}
.hero-bento-sub {
  max-width: 42ch;
  margin: 0;
  color: var(--color-text-soft);
  font-size: 1.0625rem;
  line-height: 1.55;
}
.hero-bento-join-line,
.hero-bento-cell-title {
  margin: 0;
  color: var(--color-text);
  font-size: calc(0.9375rem * var(--type-scale, 1));
  font-weight: 700;
  line-height: 1.4;
}
.hero-bento-btn {
  box-sizing: border-box;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 48px;
  padding: var(--space-3) var(--space-6);
  border-radius: var(--btn-radius);
  background: var(--color-primary);
  color: var(--color-on-primary);
  font-weight: 700;
  line-height: 1.5;
  text-decoration: none;
}
.hero-bento-btn:hover {
  text-decoration: underline;
  text-underline-offset: 0.2em;
}
.hero-bento-btn:focus-visible {
  outline: 3px solid var(--color-focus);
  outline-offset: 3px;
}
.hero-bento-figure-num {
  margin: 0;
  font-family: var(--font-heading);
  font-size: calc(clamp(1.5rem, 17cqi, 2.75rem) * var(--type-scale, 1));
  font-weight: var(--weight-display, 700);
  letter-spacing: calc(-0.02em + var(--heading-tracking, 0) * 1em);
  line-height: calc(1.05 * var(--heading-leading, 1));
}
@supports (line-height: 1cap) {
  .hero-bento-figure-num {
    line-height: calc(max(1.05em, 1.45cap) * var(--heading-leading, 1));
  }
}
.hero-bento-figure-label {
  margin: 0;
  font-size: 0.9375rem;
  line-height: 1.45;
}
.hero-bento-chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin: 0;
  padding: 0;
  list-style: none;
}
.hero-bento-chip {
  padding: var(--space-1) var(--space-3);
  border-radius: var(--chip-radius);
  background: var(--color-surface-soft);
  color: var(--color-text);
  font-size: 0.875rem;
  font-weight: 700;
  line-height: 1.4;
}
.hero-bento .lp-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(4.75rem, 100%), 1fr));
  gap: var(--space-3);
  margin: 0;
  padding: 0;
  list-style: none;
}
.hero-bento .mem-card {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  min-width: 0;
}
.hero-bento .mem-card img,
.hero-bento .mem-card__initial {
  display: block;
  width: 100%;
  aspect-ratio: 1 / 1;
  object-fit: cover;
  border-radius: var(--card-radius);
  background: var(--color-surface-soft);
}
.hero-bento .mem-card__initial {
  display: grid;
  place-items: center;
  font-family: var(--font-heading);
  font-size: calc(1.5rem * var(--type-scale, 1));
  color: var(--color-primary);
  background: color-mix(in srgb, var(--color-primary) 12%, var(--color-surface));
}
.hero-bento .mem-card .badge {
  position: absolute;
  top: var(--space-1);
  inset-inline-start: var(--space-1);
  max-width: calc(100% - 2 * var(--space-1));
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  padding: 0 var(--space-1);
  border-radius: var(--chip-radius);
  background: var(--color-primary);
  color: var(--color-on-primary);
  font-size: 0.75rem;
  font-weight: 700;
  line-height: 1.5;
}
.hero-bento .mem-card__name {
  margin: var(--space-1) 0 0;
  color: var(--color-text);
  font-size: 0.875rem;
  font-weight: 700;
  line-height: 1.3;
  overflow: hidden;
}
/* A tile shows a face and a name; the member's own line is for member-grid. */
.hero-bento .mem-card__line {
  display: none;
}
.hero-bento .mem-card__where {
  margin: 0;
  overflow: hidden;
  color: var(--color-text-soft);
  font-size: 0.8125rem;
  line-height: 1.4;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.hero-bento .mem-card__cta {
  display: flex;
  align-items: center;
  min-height: 44px;
  margin-top: auto;
  color: var(--color-primary);
  font-size: 0.8125rem;
  font-weight: 700;
  text-decoration: none;
}
.hero-bento .mem-card__cta:hover {
  text-decoration: underline;
}
.hero-bento .mem-card__cta:focus-visible {
  outline: 2px solid var(--color-focus);
  outline-offset: 2px;
}
.hero-bento .mem-card--join {
  display: grid;
  place-items: center;
  padding: var(--space-3);
  border: var(--card-border);
  border-radius: var(--card-radius);
  background: color-mix(in srgb, var(--color-primary) 8%, var(--color-surface));
  text-align: center;
}
.hero-bento .lp-members__empty {
  margin: 0;
  color: var(--color-text-soft);
  font-size: 0.9375rem;
  line-height: 1.55;
}
/* cells: one block ruled by hairlines, or separate cards. */
.hero-bento--ruled .hero-bento-grid,
.hero-bento--ruled .hero-bento-cells {
  gap: 1px;
  background: var(--color-rule);
}
.hero-bento--ruled .hero-bento-grid {
  overflow: clip;
  border: 1px solid var(--color-rule);
  border-radius: var(--card-radius);
}
.hero-bento--ruled .hero-bento-lead,
.hero-bento--ruled .hero-bento-join,
.hero-bento--ruled .hero-bento-cells > li:not(.hero-bento-figure) {
  background: var(--color-bg);
}
.hero-bento--spaced .hero-bento-grid,
.hero-bento--spaced .hero-bento-cells {
  gap: var(--space-4);
}
.hero-bento--spaced .hero-bento-lead,
.hero-bento--spaced .hero-bento-join,
.hero-bento--spaced .hero-bento-cells > li {
  overflow: clip;
  border: var(--card-border);
  border-radius: var(--card-radius);
  box-shadow: var(--card-shadow);
}
.hero-bento--spaced .hero-bento-lead {
  background: var(--color-surface-soft);
}
.hero-bento--spaced .hero-bento-join,
.hero-bento--spaced .hero-bento-cells > li:not(.hero-bento-figure) {
  background: var(--color-surface);
}
@media (min-width: 60rem) {
  .hero-bento--start .hero-bento-grid {
    grid-template-columns: minmax(0, 11fr) minmax(0, 13fr);
    grid-template-rows: 1fr auto;
    grid-template-areas: "lead cells" "join cells";
  }
  .hero-bento--end .hero-bento-grid {
    grid-template-columns: minmax(0, 13fr) minmax(0, 11fr);
    grid-template-rows: 1fr auto;
    grid-template-areas: "cells lead" "cells join";
  }
  .hero-bento--top .hero-bento-grid {
    grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
    grid-template-areas: "lead join" "cells cells";
  }
  .hero-bento--top .hero-bento-cells > .hero-bento-photo {
    flex-basis: 24rem;
  }
  .hero-bento-lead {
    padding: var(--space-6);
  }
  /* Holding the card beside the tiles, the headline steps down a size so
     the card's first question stays on the first screen. */
  .hero-bento--start .hero-bento-grid:has(.signup-card) .hero-bento-title,
  .hero-bento--end .hero-bento-grid:has(.signup-card) .hero-bento-title {
    font-size: calc(clamp(2rem, 1.2rem + 2vw, 2.75rem) * var(--type-scale, 1));
  }
}

.hero-bento img[data-hub-placeholder] {
  background: color-mix(in srgb, var(--color-primary) 18%, var(--color-surface));
  object-fit: contain;
}

.hero-bento:not(.hero-bento--moving) {
  --hub-motion: none;
}
@media (prefers-reduced-motion: no-preference) {
  .hero-bento--moving .mem-card {
    transition: translate var(--transition-fast) ease-out;
  }
  .hero-bento--moving .mem-card:hover,
  .hero-bento--moving .mem-card:focus-within {
    translate: 0 calc(-1 * var(--space-1));
  }
}
/* === /pattern hero-bento@2 === */

/* === F-Buddy UK: homepage option headline accent and phone arch layouts (hand-written 2026-10-02, home-f..l) === */
:root {
  --color-accent-on-deep: #ff3b42; /* the brand red lifted to 5:1 on --color-scrim */
}
.hl-accent { color: var(--color-primary); }
.hl-accent--bright { color: var(--color-accent-on-deep); }
.hl-accent--ink { color: var(--color-scrim); }
@media (max-width: 47.99rem) {
  /* home-k: the card rides up over the foot of the arch, so she looks out over it */
  .hero-portrait--peek .hero-portrait-inner { display: flex; flex-direction: column; gap: var(--space-3); }
  .hero-portrait--peek .hero-portrait-copy { display: contents; }
  .hero-portrait--peek .hero-portrait-title { order: 1; margin: 0; }
  .hero-portrait--peek .hero-portrait-sub { order: 2; margin: 0; }
  .hero-portrait--peek .hero-portrait-visual { order: 3; width: min(18rem, 80%); margin-inline: auto; }
  .hero-portrait--peek .hero-portrait-inner:has(.signup-card) .hero-portrait-img {
    height: clamp(12rem, 58vw, 15rem);
    border-end-start-radius: 0;
    border-end-end-radius: 0;
    object-position: 50% 8%;
  }
  .hero-portrait--peek .hero-portrait-cta { order: 4; position: relative; z-index: 1; margin-top: -4.5rem; align-self: stretch; }
  .hero-portrait--peek .hero-portrait-cta .signup-card { width: 100%; box-sizing: border-box; }
  /* home-l: a small arch beside the words on a red rule, so the card starts higher */
  .hero-portrait--beside .hero-portrait-inner {
    grid-template-columns: minmax(0, 1fr) 9.5rem;
    grid-template-areas: "title visual" "sub visual" "cta cta";
    column-gap: var(--space-4);
    row-gap: var(--space-2);
    align-items: end;
  }
  .hero-portrait--beside .hero-portrait-copy { display: contents; }
  .hero-portrait--beside .hero-portrait-title { grid-area: title; margin: 0; }
  .hero-portrait--beside .hero-portrait-sub { grid-area: sub; margin: 0; align-self: start; }
  .hero-portrait--beside .hero-portrait-visual { grid-area: visual; order: 0; border-block-end: 3px solid var(--color-primary); }
  .hero-portrait--beside .hero-portrait-inner:has(.signup-card) .hero-portrait-img {
    height: 13rem;
    border-end-start-radius: 0;
    border-end-end-radius: 0;
    object-position: 45% 6%;
  }
  .hero-portrait--beside .hero-portrait-cta { grid-area: cta; margin-top: var(--space-3); }
}
/* home-k: the member strip shows faces only -- its age-range line ("Members aged 28-41, here now") is never shown, on the partner's word */
.hero-portrait--peek .signup-card-members p { display: none; }
/* Menu fix (masthead-nav@12): a third-level list set pointer-events: auto, so inside a closed
   dropdown it stayed hoverable while invisible and opened "More" from empty space. It takes its
   parent panel's state instead. */
.masthead-nav-links ul ul ul { pointer-events: inherit; }
/* home-k, home-l (2026-10-03): the search line above the big headline. It is part of the h1,
   so the page's main heading names what the page is about; set small, in the body face. */
.hero-portrait-kicker {
  display: block;
  margin-block-end: var(--space-3);
  font-family: var(--font-body);
  font-size: 1rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  line-height: 1.3;
  color: inherit;
}
/* home-k, home-l (2026-10-03, partner's word): the member faces in the sign-up card wait for the
   first answer, so the first question sits higher on a phone. Scoped to the two arch layouts. */
.hero-portrait--peek .signup-card:not(:has(input:checked)) .signup-card-members,
.hero-portrait--beside .signup-card:not(:has(input:checked)) .signup-card-members { display: none; }
/* home-k, home-l (2026-10-03, partner's pick): smaller member cards, so twenty fit. --compact sits
   beside the pattern's rail rung: one swipeable row of small cards on a phone, a wrapping grid
   from 48rem, where every card fits and the carousel shows no arrows. */
.member-grid.member-grid--compact.member-grid--rail .mem-card { width: min(31vw, 8rem); }
.member-grid.member-grid--compact .mem-card__name { font-size: 0.9375rem; }
.member-grid.member-grid--compact .mem-card__where,
.member-grid.member-grid--compact .mem-card__line { font-size: 0.8rem; }
@media (min-width: 48rem) {
  .member-grid.member-grid--compact.member-grid--rail .lp-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(8.5rem, 1fr));
    overflow-x: visible;
    scroll-snap-type: none;
    max-width: var(--container-max);
    margin-inline: auto;
  }
  .member-grid.member-grid--compact.member-grid--rail .mem-card { width: auto; }
}
@media (scripting: none) {
  .member-grid.member-grid--compact.member-grid--rail .lp-grid { grid-template-columns: repeat(auto-fill, minmax(6.5rem, 1fr)); }
  .member-grid.member-grid--compact.member-grid--rail .mem-card { width: auto; }
}
/* Town pages (/locations/fuck-buddy-*, 2026-10-03): the old page's map beside its words; the
   member note centred under the block; a tighter opener on phones; and the sign-up card as on
   home-k -- faces only after the first answer, never the age range (partner's word, 2026-10-02/03). */
.prose-column .town-map { float: right; width: 9rem; height: auto; margin: 0 0 var(--space-4) var(--space-5); }
.member-grid + .source-note { width: min(100% - 2 * var(--space-4), var(--container-max)); margin-inline: auto; text-align: center; color: var(--color-text-soft); }
@media (max-width: 47.99rem) { .hero-stated.hero-stated--deep { padding-block: var(--space-6); } }
.hero-stated .signup-card:not(:has(input:checked)) .signup-card-members { display: none; }
.hero-stated .signup-card-members p { display: none; }
/* /locations (2026-10-03): the town list grouped by area inside one link-cluster. */
.link-cluster .link-cluster-area {
  margin: var(--space-6) 0 var(--space-3);
  font-family: var(--font-heading);
  font-size: calc(1.25rem * var(--type-scale, 1));
  line-height: var(--heading-leading, 1.15);
  color: var(--color-heading);
}
/* /faq (2026-10-03): the old site's 'As featured in' press logos (The Sun, Nuts; footer of every
   old page), kept on the partner's word, in a slim band at the foot of the page, above the footer, as on the old site. */
.as-featured {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: center;
  gap: var(--space-2) var(--space-4); padding: var(--space-4) var(--space-4);
  padding-block: var(--space-5);
}
.as-featured-label {
  margin: 0; font-size: 0.8125rem; letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--color-text-soft);
}
.as-featured img { display: block; width: 168px; height: auto; }
/* Blog posts (/blog/*, 2026-10-03; partner: "nicer looking ... full width images"). The old
   pictures are small (236-1200px), so the full width comes from the post's own picture blurred
   behind the header; the sharp picture sits over the header's foot, never past 1.25x its size. */
.post-hero {
  --post-hero-overlap: clamp(3rem, 12vw, 7rem);
  position: relative;
  isolation: isolate;
  overflow: hidden;
  color: var(--color-on-scrim);
  padding-block: var(--space-5) 0;
}
.post-hero::before,
.post-hero::after {
  content: "";
  position: absolute;
  inset: 0 0 var(--post-hero-overlap) 0;
  z-index: -1;
}
.post-hero::before {
  background: var(--color-scrim) var(--post-hero-bg, none) center / cover no-repeat;
  filter: blur(26px) saturate(1.15);
  clip-path: inset(0);
}
.post-hero::after { background: linear-gradient(180deg, rgb(24 23 25 / 0.72), rgb(24 23 25 / 0.88)); }
.post-hero--plain { padding-block-end: var(--space-8); }
.post-hero--plain::before, .post-hero--plain::after { inset: 0; }
.post-hero-inner {
  width: min(100% - 2 * var(--space-4), 46rem);
  margin-inline: auto;
  padding-block-end: var(--space-7, 2.5rem);
}
.post-hero-crumbs { font-size: 0.875rem; color: rgb(255 255 255 / 0.75); margin-block-end: var(--space-6); }
.post-hero-crumbs a { color: inherit; text-underline-offset: 0.2em; }
.post-hero-crumbs [aria-current] { color: var(--color-on-scrim); }
.post-hero-sep { margin-inline: var(--space-2); }
.post-hero-byline {
  display: flex; flex-wrap: wrap; align-items: center;
  gap: var(--space-1, 0.25rem) var(--space-4);
  margin: var(--space-4) 0 0;
  font-size: 0.9375rem;
  color: rgb(255 255 255 / 0.8);
}
.post-hero-byline > span + span::before {
  content: "";
  display: inline-block;
  width: 4px; height: 4px; border-radius: 50%;
  margin-inline-end: var(--space-4);
  vertical-align: middle;
  background: var(--color-accent-on-deep);
}
.post-hero-author { color: var(--color-on-scrim); font-weight: 600; }
@media (max-width: 47.99rem) {
  .post-hero-author { flex-basis: 100%; }
  .post-hero-byline > .post-hero-author + span::before { display: none; }
}
.post-hero-title {
  margin: 0;
  font-family: var(--font-heading);
  font-size: calc(clamp(2.25rem, 6vw, 4rem) * var(--type-scale, 1));
  line-height: calc(1.02 * var(--heading-leading, 1));
  letter-spacing: calc(-0.01em + var(--heading-tracking, 0) * 1em);
  font-weight: var(--weight-display, 700);
  color: var(--color-on-scrim);
  text-wrap: balance;
}
.post-hero-image {
  display: block;
  width: min(100% - 2 * var(--space-4), 56rem, var(--post-hero-image-w, 56rem) * 1.25);
  height: auto;
  margin-inline: auto;
  border-radius: 1rem;
  box-shadow: 0 1.5rem 3rem -1rem rgb(0 0 0 / 0.45);
}
.post-body { --prose-column-measure: 42rem; font-size: 1.125rem; line-height: 1.75; padding-block: var(--space-8); }
.post-body h2::before {
  content: "";
  display: block;
  width: 2.5rem; height: 4px;
  margin-block-end: var(--space-3);
  border-radius: 2px;
  background: var(--color-primary);
}
.post-body a { color: var(--color-primary-dark); text-underline-offset: 0.18em; }
@media (max-width: 47.99rem) { .post-body { font-size: 1.0625rem; padding-block: var(--space-6); } }
.post-cards { background: var(--color-surface-soft); padding-block: var(--space-8); }
.post-cards-inner { width: min(100% - 2 * var(--space-4), 64rem); margin-inline: auto; }
.post-cards-heading {
  margin: 0 0 var(--space-5);
  font-family: var(--font-heading);
  font-size: calc(clamp(1.75rem, 3vw, 2.25rem) * var(--type-scale, 1));
  color: var(--color-heading);
}
.post-cards-list { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-4); }
@media (min-width: 48rem) { .post-cards-list { grid-template-columns: repeat(3, 1fr); gap: var(--space-5); } }
.post-card-link {
  display: grid; gap: var(--space-2); align-content: start;
  height: 100%;
  padding-block-end: var(--space-4);
  border-radius: 1rem; overflow: hidden;
  background: var(--color-surface, #fff);
  color: var(--color-text); text-decoration: none;
  box-shadow: 0 1px 2px rgb(0 0 0 / 0.06), 0 0.5rem 1.5rem -0.75rem rgb(0 0 0 / 0.18);
  transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.post-card-link:hover, .post-card-link:focus-visible { transform: translateY(-3px); box-shadow: 0 1px 2px rgb(0 0 0 / 0.06), 0 1rem 2rem -0.75rem rgb(0 0 0 / 0.28); }
.post-card-image { display: block; width: 100%; height: auto; aspect-ratio: 16 / 10; object-fit: cover; background: var(--color-scrim); }
.post-card-date, .post-card-title { padding-inline: var(--space-4); }
.post-card-date { font-size: 0.75rem; letter-spacing: 0.08em; text-transform: uppercase; color: var(--color-text-soft); margin-block-start: var(--space-2); }
.post-card-title { font-family: var(--font-heading); font-size: 1.25rem; line-height: 1.2; color: var(--color-heading); }
@media (prefers-reduced-motion: reduce) { .post-card-link { transition: none; } .post-card-link:hover { transform: none; } }
/* /blog (2026-10-03): the plain dark header with the old lede, the three most-read posts as big
   cards, then every post by year -- a compact row on phones (thumbnail, date, title), cards with
   the post's own opening words from 48rem. */
.post-hero--index { padding-block: var(--space-6) var(--space-8); }
.post-hero-lede { margin: var(--space-4) 0 0; max-width: 38rem; font-size: 1.125rem; line-height: 1.6; color: rgb(255 255 255 / 0.85); }
.post-cards--top { background: var(--color-bg); padding-block-end: 0; }
.post-cards-year {
  margin: var(--space-8) 0 var(--space-4);
  padding-block-start: var(--space-4);
  border-block-start: 1px solid var(--color-rule);
  font-family: var(--font-heading);
  font-size: calc(1.5rem * var(--type-scale, 1));
  color: var(--color-heading);
}
.post-cards-heading + .post-cards-year { margin-block-start: 0; }
.post-card-excerpt { padding-inline: var(--space-4); font-size: 0.9375rem; line-height: 1.55; color: var(--color-text-soft); }
@media (max-width: 47.99rem) {
  .post-cards-list--all { gap: var(--space-3); }
  .post-cards-list--all .post-card-link {
    grid-template-columns: 6.5rem 1fr;
    grid-template-rows: auto 1fr;
    column-gap: var(--space-3);
    row-gap: var(--space-1);
    padding: 0;
    align-items: start;
  }
  .post-cards-list--all .post-card-image { grid-row: 1 / span 2; height: 100%; min-height: 5.5rem; aspect-ratio: auto; }
  .post-cards-list--all .post-card-date { padding: var(--space-3) var(--space-3) 0 0; margin: 0; }
  .post-cards-list--all .post-card-title { padding: 0 var(--space-3) var(--space-3) 0; font-size: 1.0625rem; }
  .post-cards-list--all .post-card-excerpt { display: none; }
}

/* --- Header menu polish (2026-10-04, partner: "the menu should look really good ... well spaced
   out ... the menu drawer"). Scoped to this brand's header rung (--plain, always on the charcoal
   ground), so a re-append of masthead-nav never meets it. Plain rgba, min/max-width queries and
   no :has / color-mix, so older phones get the same header. --- */
.masthead-nav.masthead-nav--plain {
  --fb-nav-line: rgba(255, 255, 255, 0.12);
  --fb-nav-ghost: rgba(255, 255, 255, 0.38);
}
@media (min-width: 60rem) {
  /* The links sit centred between the logo and the buttons, each in an even box: the tap floor
     was left-aligning short words ("FAQ") inside 44px and leaving a gap after them. */
  .masthead-nav--plain.masthead-nav--inline .masthead-nav-links > ul {
    justify-content: center;
    gap: var(--space-1);
  }
  .masthead-nav--plain .masthead-nav-links > ul > li > a {
    position: relative;
    justify-content: center;
    padding: var(--space-2) var(--space-4);
    font-size: 1.125rem;
    letter-spacing: 0.01em;
  }
  .masthead-nav--plain .masthead-nav-links > ul > li > a[href]:hover {
    text-decoration: none;
  }
  /* A short brand-red bar under the link on hover and focus, instead of an underline. */
  .masthead-nav--plain .masthead-nav-links > ul > li > a::before {
    content: "";
    position: absolute;
    left: var(--space-4);
    right: var(--space-4);
    bottom: 0.3rem;
    height: 2px;
    border-radius: 2px;
    background: var(--color-primary);
    transform: scaleX(0);
    transform-origin: center;
  }
  .masthead-nav--plain .masthead-nav-links > ul > li > a:hover::before,
  .masthead-nav--plain .masthead-nav-links > ul > li > a:focus-visible::before {
    transform: scaleX(1);
  }
  /* Log in and Join read as a pair: same height, same type, one outlined and one filled. */
  .masthead-nav--plain .masthead-nav-controls {
    gap: var(--space-3);
  }
  .masthead-nav--plain .masthead-nav-login {
    justify-content: center;
    min-height: var(--masthead-nav-tap);
    padding: 0 var(--space-5);
    border: 1px solid var(--fb-nav-ghost);
    border-radius: var(--btn-radius);
    font-size: 1rem;
  }
  .masthead-nav--plain .masthead-nav-login:hover {
    border-color: var(--masthead-nav-ink);
    text-decoration: none;
  }
  .masthead-nav--plain .masthead-nav-join {
    font-size: 1rem;
  }
}
@media (min-width: 60rem) and (prefers-reduced-motion: no-preference) {
  .masthead-nav--plain .masthead-nav-links > ul > li > a::before {
    transition: transform 0.18s ease-out;
  }
}
@media (max-width: 59.99rem) {
  /* The drawer: a lifted charcoal panel over a darker page, the links big and ruled like a list,
     then Join and Log in straight under them (not pinned to the foot, where the platform's
     cookie notice sits on a first visit). */
  .masthead-nav--plain.masthead-nav--drawer .masthead-nav-tray {
    width: min(22rem, 86vw);
    gap: 0;
    background-image: linear-gradient(rgba(255, 255, 255, 0.045), rgba(255, 255, 255, 0.045));
    box-shadow: -12px 0 32px rgba(0, 0, 0, 0.45);
    padding-left: var(--space-5);
    padding-right: var(--space-5);
    padding-bottom: calc(var(--space-5) + env(safe-area-inset-bottom, 0px));
  }
  .masthead-nav--plain.masthead-nav--drawer .masthead-nav-disclosure::before {
    background: rgba(8, 8, 10, 0.72);
    -webkit-backdrop-filter: blur(3px);
    backdrop-filter: blur(3px);
  }
  .masthead-nav--plain.masthead-nav--drawer .masthead-nav-links > ul {
    gap: 0;
    border-top: 1px solid var(--fb-nav-line);
  }
  .masthead-nav--plain.masthead-nav--drawer .masthead-nav-links > ul > li {
    border-bottom: 1px solid var(--fb-nav-line);
  }
  .masthead-nav--plain.masthead-nav--drawer .masthead-nav-links > ul > li > a {
    justify-content: space-between;
    min-height: 3.5rem;
    padding: var(--space-3) var(--space-1);
    font-size: 1.75rem;
    line-height: 1.1;
    letter-spacing: 0.005em;
  }
  .masthead-nav--plain.masthead-nav--drawer .masthead-nav-links > ul > li > a[href]:hover {
    text-decoration: none;
    color: var(--color-primary);
  }
  /* A chevron at the row's end says "this goes somewhere". */
  .masthead-nav--plain.masthead-nav--drawer .masthead-nav-links > ul > li > a[href]::after {
    content: "";
    flex: 0 0 auto;
    width: 0.5rem;
    height: 0.5rem;
    margin-left: var(--space-4);
    border-top: 2px solid var(--color-primary);
    border-right: 2px solid var(--color-primary);
    transform: rotate(45deg);
  }
  .masthead-nav--plain.masthead-nav--drawer .masthead-nav-controls {
    order: 1;
    flex-direction: column-reverse;
    padding-top: var(--space-6);
    gap: var(--space-3);
  }
  .masthead-nav--plain.masthead-nav--drawer .masthead-nav-join {
    flex: 0 0 auto;
    min-height: 3.25rem;
    font-size: 1.125rem;
  }
  .masthead-nav--plain.masthead-nav--drawer .masthead-nav-login {
    justify-content: center;
    min-height: 3.25rem;
    border: 1px solid var(--fb-nav-ghost);
    border-radius: var(--btn-radius);
    font-size: 1.125rem;
  }
}

/* --- One type scale across the site (2026-10-04, partner: "a consistent font palette across
   the whole site"). The blog was built on its own sizes; these put it on the pages' own:
   page headline = the hero headline, card titles in the heading weight. --- */
.post-hero-title {
  font-size: calc(clamp(2.5rem, 7vw, 4.5rem) * var(--type-scale, 1));
  letter-spacing: calc(-0.03em + var(--heading-tracking, 0) * 1em);
  text-wrap: balance;
}
.post-card-title {
  font-weight: var(--weight-display, 700);
}

/* --- The platform's cookie notice, in the brand's colours and type rather than its default
   green and grey. Extra element selectors outrank the notice's own component styles. --- */
html body .cookie-consent.is-visible {
  background: rgba(24, 23, 25, 0.97);
  border-top: 1px solid rgba(255, 255, 255, 0.12);
}
html body .cookie-consent .btn-cookie {
  min-height: 2.75rem;
  padding: 0 var(--space-5);
  border: 0;
  border-radius: var(--btn-radius);
  background: var(--color-primary);
  color: var(--color-on-primary);
  font-family: var(--font-heading);
  font-size: 1rem;
  font-weight: var(--weight-display, 700);
  cursor: pointer;
}
html body .cookie-consent .cookie-policy-link {
  color: inherit;
}

/* --- Sign-up card highlight (2026-10-04): the box being typed in takes the brand's red, as a red
   edge with a soft red glow, in place of the plain ring. The transparent outline is what Windows'
   high-contrast mode draws, so the box still shows focus there. --- */
.signup-card .signup-card-field input:focus,
.signup-card .signup-card-field select:focus {
  border-color: var(--color-primary);
  outline: 2px solid transparent;
  box-shadow: 0 0 0 3px rgba(216, 28, 36, 0.28);
}

/* --- Homepage guides and the Contact header (2026-10-04): the line under "Fuck buddy guides" and the
   link after the cards get their own space; a link in the dark page header reads in the header's
   own white, underlined, not the brand red that is too faint on charcoal at this size. --- */
.post-cards-heading + p {
  margin: calc(-1 * var(--space-3)) 0 var(--space-5);
  color: var(--color-text-soft);
}
.post-cards-list + p {
  margin: var(--space-5) 0 0;
  font-weight: 600;
}
.post-hero-lede a {
  color: inherit;
  text-decoration: underline;
  text-underline-offset: 0.2em;
}

/* --- Comparison table at full height (2026-10-06, partner on /features: the table's own scroll box
   gave the page a second, inner scrollbar). From 48rem the pattern caps the box at 80vh so its head
   can stick; with 18 short rows the whole table reads better in the page's own scroll. Sideways
   scrolling on phones is untouched. --- */
@media (min-width: 48rem) {
  .comparison-table .comparison-table-scroll {
    max-block-size: none;
  }
}

/* --- Members' reviews on /community (2026-10-06): real reviews from the platform, word for word, as
   plain quote cards - no portraits (member photos are blurred on this brand), the member's own star
   rating in words for screen readers and as stars to the eye. --- */
.fb-reviews { padding-block: var(--space-9); background: var(--color-bg); }
.fb-reviews-inner { width: min(100% - 2 * var(--space-4), 72rem); margin-inline: auto; }
.fb-reviews-title {
  margin: 0 0 var(--space-2);
  font-family: var(--font-heading);
  font-size: calc(clamp(1.75rem, 3vw, 2.25rem) * var(--type-scale, 1));
  font-weight: var(--weight-display, 700);
  letter-spacing: calc(-0.02em + var(--heading-tracking, 0) * 1em);
  color: var(--color-heading);
}
.fb-reviews-intro { margin: 0 0 var(--space-6); color: var(--color-text-soft); max-width: 46ch; }
.fb-reviews-list { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-4); }
@media (min-width: 40rem) { .fb-reviews-list { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 64rem) { .fb-reviews-list { grid-template-columns: repeat(4, 1fr); } }
.fb-review {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  padding: var(--space-5);
  border: 1px solid var(--color-rule);
  border-radius: var(--card-radius);
  background: var(--color-surface, #fff);
}
.fb-review-stars { margin: 0; color: var(--color-primary); font-size: 1.05rem; letter-spacing: 0.08em; }
.fb-review-stars-off { color: var(--color-rule); }
.fb-review-quote { margin: 0; flex: 1 1 auto; }
.fb-review-quote p { margin: 0; font-size: 1.0625rem; line-height: 1.5; color: var(--color-text); }
.fb-review-who { margin: 0; font-weight: 700; font-size: 0.9375rem; color: var(--color-heading); }
/* === /F-Buddy UK hand-written === */

/* === older-phone fallbacks (generated by working/audit/css_fallbacks.py -- do not hand-edit) === */
@supports not (color: color-mix(in srgb, red 50%, blue)) {
@media (max-width: 59.99rem) { .cta-sticky {
  box-shadow: 0 -1px 0 transparent,
                0 -8px 24px transparent;
} }
.masthead-nav.masthead-nav--plain {
  --masthead-nav-edge: transparent;
}
.colophon.colophon--plain {
  color: var(--color-rule);
}
.signup-steps-opt-face {
  border: 2px solid var(--color-rule);
}
.signup-steps-opt:hover .signup-steps-opt-face {
  border-color: var(--color-primary);
}
.signup-steps-opt input:checked + .signup-steps-opt-face {
  background: var(--color-surface);
}
.signup-steps-tick {
  border: 2px solid var(--color-text-soft);
}
.signup-steps-field input {
  border: 2px solid var(--color-rule);
}
.signup-steps-seg {
  background: var(--color-rule);
}
.signup-steps-seg::after {
  background: linear-gradient(90deg, transparent, var(--color-surface), transparent);
}
.signup-steps-members {
  background: var(--color-surface);
}
.signup-steps-chip span {
  border: 2px solid var(--color-rule);
}
.signup-steps-reward {
  background: var(--color-surface);
}
.signup-steps-wheel {
  background: linear-gradient(transparent 88px, var(--color-surface) 88px 132px, transparent 132px);
}
.masthead-nav--brand {
  --masthead-nav-edge: transparent;
}
@media (max-width: 59.99rem) { .masthead-nav--drawer .masthead-nav-disclosure::before {
  background: var(--color-scrim);
} }
.signup-card-opt-face {
  border: 2px solid var(--color-rule);
}
.signup-card-opt:hover .signup-card-opt-face {
  border-color: var(--color-primary);
}
.signup-card-opt input:checked + .signup-card-opt-face {
  background: var(--color-surface);
}
.signup-card-tick {
  border: 2px solid var(--color-text-soft);
}
.signup-card-field input,
.signup-card-field select {
  border: 2px solid var(--color-rule);
}
.signup-card-seg {
  background: var(--color-rule);
}
.signup-card-seg::after {
  background: linear-gradient(90deg, transparent, var(--color-surface), transparent);
}
.signup-card-members {
  background: var(--color-surface);
}
.signup-card-chip span {
  border: 2px solid var(--color-rule);
}
.signup-card-reward {
  background: var(--color-surface);
}
.signup-card-wheel {
  background: linear-gradient(transparent 88px, var(--color-surface) 88px 132px, transparent 132px);
}
.hero-split img[data-hub-placeholder] {
  background: var(--color-surface);
}
.heading-block-eyebrow::before,
.heading-block-eyebrow::after {
  background: transparent;
}
.member-grid .mem-card__initial {
  background: var(--color-surface);
}
.member-grid .mem-card--join {
  background: var(--color-surface);
}
.member-grid .lp-members__empty {
  border: 1px dashed transparent;
}
.photo-band img[data-hub-placeholder] {
  background: var(--color-surface);
}
.hero-portrait img[data-hub-placeholder] {
  background: var(--color-surface);
}
.hero-centred img[data-hub-placeholder] {
  background: var(--color-surface);
}
.zigzag-rows img[data-hub-placeholder] {
  background: var(--color-surface);
}
.cta-image::after {
  background: linear-gradient(
    to bottom,
    var(--color-scrim) 0%,
    var(--color-scrim) 22%,
    var(--color-scrim) 78%,
    var(--color-scrim) 100%
  );
}
.cta-image-ghost {
  background: var(--color-scrim);
}
.cta-image img[data-hub-placeholder] {
  background: var(--color-scrim);
}
.feature-panels-icon {
  background: transparent;
}
.member-filter-tab {
  border: 1.5px solid transparent;
}
.member-filter-tab:hover {
  background: var(--color-surface);
}
.anchored-split,
.anchored-split--plain {
  --anchored-split-edge: var(--color-rule, transparent);
}
.anchored-split--soft {
  --anchored-split-edge: var(--color-rule, transparent);
}
.listing-rows,
.listing-rows--plain {
  --listing-rows-edge: var(--color-rule, transparent);
}
.listing-rows--soft {
  --listing-rows-edge: var(--color-rule, transparent);
}
.listing-rows--brand {
  --listing-rows-edge: transparent;
}
.media-card-grid-scrim {
  background-image: linear-gradient(
    to top,
    var(--color-scrim) 0%,
    var(--color-scrim) 45%,
    var(--color-scrim) 70%,
    transparent 100%
  );
}
.photo-cards img[data-hub-placeholder] {
  background: var(--color-surface);
}
.article-figure img[data-hub-placeholder] {
  background: var(--color-surface);
}
.hero-squeeze::after {
  background: linear-gradient(
    to bottom,
    var(--color-scrim) 0%,
    var(--color-scrim) 12%,
    var(--color-scrim) 100%
  );
}
.hero-squeeze img[data-hub-placeholder] {
  background: var(--color-scrim);
}
.capability-tabs img[data-hub-placeholder] {
  background: var(--color-surface);
}
.claim-stack,
.claim-stack--plain {
  --claim-stack-edge: var(--color-rule, transparent);
}
.claim-stack--soft {
  --claim-stack-edge: var(--color-rule, transparent);
}
.claim-stack--brand {
  --claim-stack-quiet: var(--color-on-primary, var(--color-surface));
  --claim-stack-edge: transparent;
}
.claim-stack--deep {
  --claim-stack-quiet: var(--color-rule);
  --claim-stack-edge: transparent;
}
.comparison-table-corner,
.comparison-table-head {
  box-shadow: inset 0 -1px 0 var(--color-rule, transparent);
}
.comparison-table-head--recommended,
.comparison-table-cell--recommended {
  background: var(--color-bg);
}
.comparison-table-criterion {
  border-block-end: 1px solid var(--color-rule, var(--color-rule));
}
.comparison-table-cell {
  border-block-end: 1px solid var(--color-rule, var(--color-rule));
}
.cta-curtain-cover {
  box-shadow: var(--cta-curtain-lift, 0 40px 80px -20px
    transparent);
}
.gallery-scroll img[data-hub-placeholder] {
  background: var(--color-surface);
}
.hero-overlay::after {
  background-image: radial-gradient(circle at 50% 18%,
      transparent 0%,
      transparent 42%,
      var(--color-bg) 88%),
    linear-gradient(to top,
      var(--color-bg) 0%,
      var(--color-bg) 8%,
      var(--color-bg) 44%,
      var(--color-bg) 72%,
      transparent 100%);
}
.hero-overlay-ghost {
  background: var(--color-bg);
}
@media (max-width: 47.99rem) { .hero-overlay::after {
  background-image: linear-gradient(
      to bottom,
      transparent 0,
      var(--color-bg) 13svh,
      var(--color-bg) 25svh,
      var(--color-bg) 88%,
      var(--color-bg) 100%
    );
} }
.hero-overlay img[data-hub-placeholder] {
  background: var(--color-surface);
}
@media (min-width: 60rem) { .hero-overlay:has(.signup-card)::after {
  background-image: linear-gradient(to right,
      var(--color-bg) 0%,
      var(--color-bg) 55%,
      var(--color-bg) 78%,
      var(--color-bg) 100%);
} }
.picker-chips-link {
  border: 2px solid var(--color-primary);
}
.pinned-cards img[data-hub-placeholder] {
  background: var(--color-surface);
}
.pricing-tiers-flag {
  background: var(--color-surface);
}
@media (min-width: 48rem) { .stat-rows-row::before {
  background: linear-gradient(
      90deg,
      var(--color-rule),
      transparent
    );
} }
.stats-band-grid {
  border-top: 1px solid transparent;
  border-left: 1px solid transparent;
}
.stats-band-item {
  border-right: 1px solid transparent;
  border-bottom: 1px solid transparent;
}
.steps-numbered-scrim {
  background-image: linear-gradient(
    to top,
    var(--color-scrim) 0%,
    var(--color-scrim) 55%,
    var(--color-scrim) 78%,
    transparent 100%
  );
}
.steps-numbered img[data-hub-placeholder] {
  background: var(--color-surface);
}
.testimonial-grid-item--featured .testimonial-grid-card {
  border-color: transparent;
}
.trust-row-badge-icon {
  color: var(--color-primary-dark);
}
.hero-band img[data-hub-placeholder] {
  background: var(--color-surface);
}
.hero-bento .mem-card__initial {
  background: var(--color-surface);
}
.hero-bento .mem-card--join {
  background: var(--color-surface);
}
.hero-bento img[data-hub-placeholder] {
  background: var(--color-surface);
}
}
/* === /older-phone fallbacks === */

/* Homepage (2026-10-07, the client's review): the offer is the headline, the slogan sits under it. */
.hero-portrait-slogan {
  font-family: var(--font-heading);
  font-size: calc(clamp(1.375rem, 1.1rem + 1.2vw, 1.875rem) * var(--type-scale, 1));
  font-weight: var(--weight-display, 700);
  line-height: 1.15;
  margin: 0 0 var(--space-3);
  color: var(--hero-portrait-title-ink);
}
@media (max-width: 47.99rem) {
  /* On a phone the sign-up form must clear the cookie bar on a 390x640 screen: the portrait goes,
     and the card sits straight under the words. */
  .hero-portrait--peek .hero-portrait-slogan { order: 2; margin: 0; }
  .hero-portrait--peek .hero-portrait-sub { order: 3; }
  .hero-portrait--peek .hero-portrait-inner:has(.signup-card) .hero-portrait-sub { display: none; } /* the card's own first question says the same */
  .hero-portrait--peek .hero-portrait-inner:has(.signup-card) .hero-portrait-visual { display: none; }
  .hero-portrait--peek .hero-portrait-inner:has(.signup-card) .hero-portrait-cta { margin-top: var(--space-2); }
}

/* Blog posts (2026-10-07, the client's review): the homepage's sign-up card straight under the post
   header, so every post has a call to action on its first screen. */
.post-join { position: relative; z-index: 1; padding: 0 var(--space-4) var(--space-6); }
.post-join-inner { max-width: 30rem; margin-inline: auto; }
.post-join .signup-card { width: 100%; box-sizing: border-box; }
/* the member faces wait for the first answer, as on the homepage */
.post-join .signup-card:not(:has(input:checked)) .signup-card-members { display: none; }
.post-join .signup-card-members p { display: none; }

/* Member cards (2026-10-07, the client's review): the bio line is not shown -- some members' bios read
   like scams or chat-bait and the block cannot filter on them. Photo, name, age and town stay. */
.member-grid .mem-card__line, .mem-card .mem-card__line { display: none; }

/* Comparison pages (2026-10-07): with only two sites side by side the table fits a phone, so it does
   not scroll sideways there; the four-site hub keeps the pattern's sticky first column and side scroll. */
@media (max-width: 47.99rem) {
  .comparison-table--pair .comparison-table-grid { min-inline-size: 0; }
  .comparison-table--pair .comparison-table-criterion,
  .comparison-table--pair .comparison-table-corner,
  .comparison-table--pair .comparison-table-head,
  .comparison-table--pair .comparison-table-cell { padding: var(--space-3); }
  .comparison-table--pair .comparison-table-criterion { position: static; inline-size: 30%; }
}

/* Short phones (2026-10-07, the client's review: the sign-up form's Next button must clear the cookie bar
   on a 390x640 screen). Only under 760px tall, and not on the homepage (its own phone rules already
   clear it): the subline above the card goes (the card's first question says the same), the spacing
   above and inside the card tightens, and a blog post's breadcrumb line goes and its headline steps
   down a size. Taller phones and laptops are unchanged. */
@media (max-width: 47.99rem) and (max-height: 760px) {
  .hero-stated:has(.signup-card) { padding-block-start: var(--space-5); }
  .hero-stated:has(.signup-card) .hero-stated-sub,
  .hero-stated:has(.signup-card) .hero-stated-eyebrow { display: none; }
  .hero-stated:has(.signup-card) .hero-stated-title { margin-block-end: var(--space-3); }
  .hero-stated .signup-card, .post-join .signup-card { padding-block-start: var(--space-3); }
  .post-hero:has(.post-join) .post-hero-crumbs { display: none; }
  .post-hero:has(.post-join) .post-hero-inner { padding-block-start: var(--space-4); }
  .post-hero:has(.post-join) .post-hero-title { font-size: 2rem; margin-block-end: var(--space-2); }
  .post-hero:has(.post-join) .post-hero-byline { font-size: 0.875rem; margin-block-end: 0; }
  .post-hero:has(.post-join) .post-hero-byline > span:not(:first-child) { display: none; } /* dates stay in the post's data */
  .post-hero:has(.post-join) .post-hero-inner { padding-block-end: var(--space-3); }
  .post-join { padding-block-end: var(--space-4); }
}

/* === F-Buddy UK: dark red header and the lace hero (hand-written 2026-10-07, client review
   with mock-ups fbuk-branding-mockup-desktop/phone) ===
   Header: the dark red from the shading in the logo's F, instead of the charcoal; Join keeps
   the bright brand red so it still stands out. White on #A31820 is 7.4:1. The footer stays
   charcoal. Two-class selectors, as the furniture block above, so they outrank the pattern. */
:root {
  --color-header-red: #a31820;
}
.masthead-nav.masthead-nav--plain {
  --masthead-nav-ground: var(--color-header-red);
  --masthead-nav-panel-face: var(--color-header-red);
  --masthead-nav-edge: rgba(255, 255, 255, 0.22);
}
/* On the red header the brand red no longer shows: the drawer's row chevrons, a link's hover
   colour and the desktop hover bar under a link go white instead. Same selectors as the menu polish
   block, later in the file, so these win. */
.masthead-nav--plain.masthead-nav--drawer .masthead-nav-links > ul > li > a[href]::after {
  border-top-color: rgba(255, 255, 255, 0.7);
  border-right-color: rgba(255, 255, 255, 0.7);
}
.masthead-nav--plain.masthead-nav--drawer .masthead-nav-links > ul > li > a[href]:hover {
  color: rgba(255, 255, 255, 0.8);
}
@media (min-width: 60rem) {
  .masthead-nav--plain .masthead-nav-links > ul > li > a::before {
    background: #ffffff;
  }
}
/* Hero: the old homepage's hand-and-lace photo behind the words, under a dark tint so the
   white headline reads; the model portrait is gone. Phones get a 900px copy (about 25KB). */
.hero-portrait--lace {
  position: relative;
  isolation: isolate;
  overflow: hidden;
}
.hero-lace-bg,
.hero-lace-bg img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}
.hero-lace-bg { z-index: -2; }
.hero-lace-bg img {
  object-fit: cover;
  object-position: 30% 60%;
}
.hero-portrait--lace::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: rgba(18, 12, 12, 0.6);
}
@media (max-width: 47.99rem) {
  .hero-portrait--lace .hero-portrait-kicker,
  .hero-portrait--lace .hero-portrait-title,
  .hero-portrait--lace .hero-portrait-slogan {
    text-align: center;
    margin-inline: auto;
  }
}
@media (min-width: 48rem) {
  /* Words and card on the right half; the hand and the lace show on the left. */
  .hero-portrait--lace .hero-portrait-copy { grid-column: 2; }
  .hero-portrait--lace::before {
    background: linear-gradient(90deg, rgba(18, 12, 12, 0.35) 0%, rgba(18, 12, 12, 0.55) 45%, rgba(18, 12, 12, 0.7) 100%);
  }
}
/* === /F-Buddy UK: dark red header and the lace hero === */
