/* Quality Web Library bundle: built by bq-cdn/tools/bundle.py from bq-cdn bbb70b3 on 2026-10-23. Do not edit; re-run the tool.
   Files: css/v1/tokens.css, css/v1/base.css, css/v1/motion.css, css/v1/components/adoption-table.css, css/v1/components/button.css, css/v1/components/changelog.css, css/v1/components/chip-list.css, css/v1/components/choice-group.css, css/v1/components/choice-toggle.css, css/v1/components/figure-band.css, css/v1/components/form-field.css, css/v1/components/grain.css, css/v1/components/nav-drawer.css, css/v1/components/nav-fab.css, css/v1/components/nav.css, css/v1/components/photo-mosaic.css, css/v1/components/sample-card.css, css/v1/components/sublabel.css, css/v1/components/toc-grid.css, css/v1/sections/review-header.css, css/v1/sections/stat-row.css */

/* ---- css/v1/tokens.css ---- */
/* ==========================================================================
   Quality Web Library, v1
   tokens.css: the variable layer every site overrides

   Source: cdn.brandquality.com/css/v1/tokens.css
   Read the README at cdn.brandquality.com/README.md before using.

   HOW A SITE USES THIS
   Link this file first, then define the client's brand in a :root block
   AFTER it. Override the semantic tokens (--color-*, --font-*). Never edit
   this file for one client. Components reference these names and nothing
   else, so a rebrand is a token swap, never a find-and-replace.

   NAMING
   Category namespaces per design-system/naming-conventions.md section 3:
   --color-*  --font-*  --text-*  --space-*  --radius-*  --shadow-*
   --ease-*   --dur-*   --reveal-*  --nav-*  --container-*

   VALUES
   Ported from shipped builds, not invented here. Motion and reveal values
   are the ones NBA Region IX and the RCOC campaign pages agree on. Type
   floor and breakpoint follow _shared/web-patterns/mobile-floors.md.
   Typeface: Montserrat, locked for now across its weights (September 11, 2026).
   ========================================================================== */

:root {
  /* ---------- Color: semantic layer (the client overrides these) ---------- */
  --color-bg: #ffffff;              /* page background */
  --color-surface: #f6f6f4;         /* cards, panels, insets */
  --color-surface-dark: #161616;    /* dark bands, review-page header end */
  --color-ink: #141414;             /* primary text */
  --color-ink-muted: #6a6a6a;       /* secondary text, captions */
  --color-ink-on-dark: #ffffff;     /* text on dark surfaces */
  --color-line: #d9d9d6;            /* default border */
  --color-line-soft: #ebebe8;       /* hairlines, dividers */
  --color-primary: #141414;         /* the brand's main action color */
  --color-primary-hover: #3a3a3a;   /* a hover has to be a visible shift, not a shade */
  --color-on-primary: #ffffff;      /* text and icon on the primary fill */
  /* Accent: none. Neutral means achromatic (Diallo, September 11, 2026): the
     stock draws its underline, dots and hover in ink and gray, and a brand
     supplies the hue in its own :root block. The Brand Quality palette lives
     in library.json as a palette, not here. */
  --color-accent: #141414;          /* highlights, active underline, dots */
  --color-accent-hover: #3a3a3a;
  --color-on-accent: #ffffff;       /* text and icon on an accent fill. Every palette sets this;
                                       a button never guesses its text colour from --color-ink */
  /* --color-ghost-ink is NOT set here on purpose. button.css reads
     var(--color-ghost-ink, var(--color-primary)); a palette whose primary sits
     close to its ground (NBA wine on wine) sets it to its ink. Defining it here
     as var(--color-primary) would freeze it to the neutral value at :root and
     it would never follow an override. */
  --color-link: #141414;
  --color-link-hover: #6a6a6a;

  /* Review-page dark header values, shared by every client review page.
     Read from first-option/sacnas, bwl/installation, nul/ull. Do not re-derive. */
  --color-black: #000000;
  --color-header-end: #161616;
  --color-dark-line: #3a3a3a;
  --color-dark-line-soft: #262626;
  --color-dark-muted: #9a9a9a;


  /* ---------- Light bands and the form register ----------
     Added September 11, 2026, after the harvest found 19 entries reading these
     with a source client's hex as the fallback, so a card pulled onto another
     brand quietly arrived in that client's colours. Neutral is achromatic here
     like the rest of this file; every palette in library.json carries its own
     set. A "band" is a light section on a dark site (the news, person and
     affiliate cards, the article body, the form card). */
  --color-band-light: #ffffff;        /* the band's ground */
  --color-band-light-tint: #f6f6f4;   /* a second, quieter ground on the same band */
  --color-band-card: #ffffff;         /* a card sitting on the band */
  --color-band-stone: #ebebe8;        /* the band's edge and dividers */
  --color-band-ink: #141414;          /* text on the band */
  --color-band-ink-muted: #6a6a6a;
  --color-band-accent-ink: #141414;   /* the band's accent text; a hue on a branded palette */

  --color-form-tint: #d9d9d6;         /* the control's resting border and fill tint */
  --color-form-ink: #141414;          /* label and value */
  --color-form-focus: #141414;        /* the focus ring */

  /* Radial pools in a mesh-gradient section. Two stops, light then bright. */
  --color-mesh-1: #e4e4e0;
  --color-mesh-2: #d4d4cf;

  /* Semantic states */
  --color-success: #3d7a4d;
  --color-warning: #ac8838;
  --color-error: #b83232;
  --color-info: #3b5773;

  /* ---------- Typography ---------- */
  /* Montserrat is the neutral typeface (Diallo, September 11, 2026): the face on
     every BQ review page and on Brand Quality's own pages. This file names it;
     the page loads it (library.json include.fonts carries the Google Fonts link,
     weights 300 to 900). A client on another face overrides both tokens. */
  --font-heading: "Montserrat", -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
  --font-body: "Montserrat", -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
  --font-mono: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace;

  /* Type scale. --text-body is the mobile floor: body copy never below 17px. */
  --text-xs: 12px;
  --text-sm: 14px;
  --text-body: 17px;
  --text-md: 18px;
  --text-lg: 20px;
  --text-xl: 24px;
  --text-2xl: 36px;
  --text-3xl: 56px;
  --text-display: 72px;
  --text-label: 12.5px;             /* nav links, button labels, eyebrows */

  --leading-tight: 1.1;
  --leading-snug: 1.25;
  --leading-body: 1.55;

  --tracking-label: .16em;          /* uppercase nav links */
  --tracking-button: .14em;         /* uppercase button labels */
  --tracking-eyebrow: .2em;

  /* ---------- Spacing (4px base) ---------- */
  --space-xs: 4px;
  --space-sm: 8px;
  --space-md: 16px;
  --space-lg: 24px;
  --space-xl: 40px;
  --space-2xl: 64px;
  --space-3xl: 96px;
  --gutter: clamp(20px, 4vw, 60px); /* horizontal page padding */

  /* ---------- Layout ---------- */
  --container-max: 1280px;
  --container-wide: 1680px;         /* review-page nav width */
  --container-narrow: 720px;
  --nav-h: 64px;
  --bp-phone: 640px;                /* reference only; media queries cannot read vars */

  /* ---------- Radius and shadow ---------- */
  --radius-sm: 4px;
  --radius-md: 8px;
  --radius-lg: 12px;
  --radius-xl: 16px;
  --radius-full: 999px;

  --shadow-sm: 0 2px 8px rgba(0, 0, 0, .08);
  --shadow-md: 0 10px 26px rgba(0, 0, 0, .14);
  --shadow-lg: 0 24px 60px rgba(0, 0, 0, .22);

  /* ---------- Motion: easing ---------- */
  /* One signature reveal curve everywhere. Slow start, fast middle, slow finish. */
  --ease-reveal: cubic-bezier(0.22, 1, 0.36, 1);
  --ease-state: cubic-bezier(0.4, 0, 0.2, 1);      /* hover and state changes */
  --ease-cinema: cubic-bezier(0.65, 0, 0.35, 1);   /* long ambient moves */
  --ease-emph: cubic-bezier(0.16, 1, 0.3, 1);      /* emphatic arrivals */

  /* ---------- Motion: duration ---------- */
  --dur-fast: 220ms;
  --dur: 480ms;
  --dur-slow: 820ms;

  /* ---------- Motion: scroll reveal ---------- */
  --reveal-distance: 22px;
  --reveal-duration: 1500ms;
  --reveal-stagger: 200ms;
}

/* A page can opt into a dark base by setting data-theme="dark" on <html>.
   Client sites that are dark by design (NBA Region IX) override the semantic
   tokens directly instead; this block is the neutral default only. */
:root[data-theme="dark"] {
  --color-bg: #0f0f0f;
  --color-surface: #161616;
  --color-ink: #f4f4f2;
  --color-ink-muted: #9a9a9a;
  --color-line: #3a3a3a;
  --color-line-soft: #262626;
  --color-primary: #f4f4f2;
  --color-primary-hover: #cfcfca;   /* darker on hover: white to whiter is not a hover */
  --color-on-primary: #0f0f0f;
  --color-link: #f4f4f2;
  --color-accent: #f4f4f2;
  --color-accent-hover: #cfcfca;
  --color-on-accent: #0f0f0f;
  --color-link-hover: #9a9a9a;
  --color-band-light: #1a1a1a;
  --color-band-light-tint: #202020;
  --color-band-card: #161616;
  --color-band-stone: #262626;
  --color-band-ink: #f4f4f2;
  --color-band-ink-muted: #9a9a9a;
  --color-band-accent-ink: #f4f4f2;
  --color-form-tint: #3a3a3a;
  --color-form-ink: #f4f4f2;
  --color-form-focus: #f4f4f2;
  --color-mesh-1: #1e1e1e;
  --color-mesh-2: #262626;
  --shadow-sm: 0 2px 8px rgba(0, 0, 0, .4);
  --shadow-md: 0 10px 26px rgba(0, 0, 0, .5);
  --shadow-lg: 0 24px 60px rgba(0, 0, 0, .6);
}

/* ---- css/v1/base.css ---- */
/* ==========================================================================
   Quality Web Library, v1
   base.css: reset, typography, layout primitives, utilities

   Source: cdn.brandquality.com/css/v1/base.css
   Requires tokens.css first.

   Mobile-first. Base styles are the phone; min-width queries layer desktop.
   The floors in _shared/web-patterns/mobile-floors.md are enforced here:
   body copy never below 17px, hover states only under (hover: hover),
   reduced motion honored, Safari aspect-ratio grids use align-items: start.
   ========================================================================== */

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

html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  scroll-behavior: auto; /* Lenis owns the scroll when present; see motion.js */
}

body {
  margin: 0;
  background: var(--color-bg);
  color: var(--color-ink);
  font-family: var(--font-body);
  font-size: var(--text-body);
  line-height: var(--leading-body);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

img, svg, video, canvas { display: block; max-width: 100%; }
img { height: auto; }
button, input, select, textarea { font: inherit; color: inherit; }
button { cursor: pointer; background: none; border: 0; padding: 0; }
a { color: var(--color-link); text-decoration-thickness: 1px; text-underline-offset: .14em; }

@media (hover: hover) {
  /* :where() keeps this at zero specificity, so a component's own hover colour
     (a button's text on its fill) always wins. Without it a:hover (0,1,1)
     beat .qw-btn (0,1,0) and every button's label went link-gray on hover. */
  :where(a:hover) { color: var(--color-link-hover); }
}

/* ---------- Headings ---------- */
h1, h2, h3, h4 {
  margin: 0 0 var(--space-md);
  font-family: var(--font-heading);
  line-height: var(--leading-tight);
  font-weight: 700;
  text-wrap: balance;
}
h1 { font-size: clamp(var(--text-2xl), 5vw, var(--text-3xl)); }
h2 { font-size: clamp(var(--text-xl), 3.4vw, var(--text-2xl)); }
h3 { font-size: var(--text-xl); }
h4 { font-size: var(--text-lg); }
p  { margin: 0 0 var(--space-md); }
p:last-child { margin-bottom: 0; }

/* Eyebrow: the small uppercase label above a heading */
.qw-eyebrow {
  display: block;
  margin-bottom: var(--space-sm);
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase;
  color: var(--color-ink-muted);
}

/* ---------- Layout primitives ---------- */
.qw-container {
  width: 100%;
  max-width: var(--container-max);
  margin-inline: auto;
  padding-inline: var(--gutter);
}
.qw-container--wide { max-width: var(--container-wide); }
.qw-container--narrow { max-width: var(--container-narrow); }

.qw-section { padding-block: var(--space-2xl); }
@media (min-width: 900px) {
  .qw-section { padding-block: var(--space-3xl); }
}

/* Section header contract: eyebrow, heading, one line of lead copy */
.qw-section__head { max-width: 62ch; margin-bottom: var(--space-xl); }
.qw-section__head--center { margin-inline: auto; text-align: center; }

/* Grid that survives Safari: aspect-ratio children collapse under stretch */
.qw-grid {
  display: grid;
  gap: var(--space-lg);
  align-items: start;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 280px), 1fr));
}

/* ---------- Utilities (u- prefix, one job each) ---------- */
.u-visually-hidden {
  position: absolute !important;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0);
  white-space: nowrap; border: 0;
}
.u-text-center { text-align: center; }
.u-mono { font-family: var(--font-mono); }

/* Mobile-only line break. Desktop keeps the space; phone breaks the line. */
.u-br-mobile { display: none; }
@media (max-width: 640px) {
  .u-br-mobile { display: inline; }
}

/* ---------- Focus ---------- */
:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 3px;
}

/* ---------- Reduced motion base ---------- */
@media (prefers-reduced-motion: reduce) {
  :root { --dur-fast: 0ms; --dur: 0ms; --dur-slow: 0ms; --reveal-duration: 0ms; }
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
}

/* ---- css/v1/motion.css ---- */
/* ==========================================================================
   Quality Web Library, v1
   motion.css: the scroll reveal system

   Source: cdn.brandquality.com/css/v1/motion.css
   Requires tokens.css. Pair with js/v1/motion.js for the observer and Lenis.

   Ported from nba-region-ix/css/motion.css and the RCOC campaign pages,
   which agree on every value. This is the same reveal that runs on every
   BQ property built since June 2026. Do not re-derive it per site.

   Design principles (Diallo):
   - Smooth, subtle, easy. Ease-out, never ease-in.
   - Nothing harsh, nothing abrupt. Patient, intentional, dynamic.

   THE PATTERN
   <div data-reveal>              fades up 22px when it enters the viewport
   <div data-reveal="left">       slides in from the left
   <div data-reveal="right">      slides in from the right
   <div data-reveal="fade">       opacity only
   <div data-reveal="up-large">   double travel
   <div data-reveal="scale">      up plus a slight scale from .96
   <div data-reveal="scale-down"> settles from 1.15 to 1
   <div data-reveal="rule">       does not animate itself; takes .is-revealed
                                  so a component can drive its own parts

   <ul data-reveal-group>         children with data-reveal auto-stagger
   <ul data-reveal-group data-reveal-stagger="180">   custom stagger in ms
   <li data-reveal data-reveal-delay="380">           explicit delay in ms

   Reveals fire once (IntersectionObserver + unobserve) and use keyframes,
   not transitions, so timing is deterministic even if the render pipeline
   pauses. Reduced motion makes everything visible instantly.
   ========================================================================== */

@keyframes qw-reveal-up {
  from { opacity: 0; transform: translateY(var(--reveal-distance)); }
  to   { opacity: 1; transform: translateY(0); }
}
@keyframes qw-reveal-left {
  from { opacity: 0; transform: translateX(calc(var(--reveal-distance) * -1)); }
  to   { opacity: 1; transform: translateX(0); }
}
@keyframes qw-reveal-right {
  from { opacity: 0; transform: translateX(var(--reveal-distance)); }
  to   { opacity: 1; transform: translateX(0); }
}
@keyframes qw-reveal-fade {
  from { opacity: 0; }
  to   { opacity: 1; }
}
@keyframes qw-reveal-up-large {
  from { opacity: 0; transform: translateY(calc(var(--reveal-distance) * 2)); }
  to   { opacity: 1; transform: translateY(0); }
}
@keyframes qw-reveal-scale {
  from { opacity: 0; transform: translateY(var(--reveal-distance)) scale(.96); }
  to   { opacity: 1; transform: translateY(0) scale(1); }
}
@keyframes qw-reveal-scale-down {
  from { opacity: 0; transform: scale(1.15); }
  to   { opacity: 1; transform: scale(1); }
}

/* Oct 18, 2026 (Safari): the page can sit unpainted for a second or two while its
   fonts load, and an entrance that starts in that time finishes unseen, so the
   content pops in. motion.js puts .qw-wait on <html> until the stylesheets and
   fonts are in and a frame has been drawn; until then every animation holds on its
   first frame. Add the class in an inline <head> script as well, so animations that
   start before motion.js runs hold too:
     <script>document.documentElement.classList.add('js','qw-wait');setTimeout(function(){document.documentElement.classList.remove('qw-wait')},4000)</script> */
html.qw-wait *, html.qw-wait *::before, html.qw-wait *::after { animation-play-state: paused !important; }

[data-reveal] { opacity: 0; }

[data-reveal].is-revealed {
  animation: qw-reveal-up var(--reveal-duration) var(--ease-reveal) var(--reveal-delay, 0ms) forwards;
}
[data-reveal="left"].is-revealed       { animation-name: qw-reveal-left; }
[data-reveal="right"].is-revealed      { animation-name: qw-reveal-right; }
[data-reveal="fade"].is-revealed       { animation-name: qw-reveal-fade; }
[data-reveal="up-large"].is-revealed   { animation-name: qw-reveal-up-large; }
[data-reveal="scale"].is-revealed      { animation-name: qw-reveal-scale; }
[data-reveal="scale-down"].is-revealed { animation-name: qw-reveal-scale-down; }

/* data-reveal="rule": the element stays put and only registers with the observer.
   A component reads .is-revealed and animates its own parts (the step's rule
   draws in, a chapter band's numeral settles). Defined here, September 11, 2026,
   because four entries used the value while only step.css implemented it, so any
   page linking one of the other three without the step got the default reveal. */
[data-reveal="rule"] { opacity: 1; transform: none; }
[data-reveal="rule"].is-revealed { animation: none; }

/* ---------- Page load entrance ----------
   For hero content that should rise on load without waiting for scroll.
   Pure CSS so it has no JS dependency. Stagger with --rise-delay. */
@keyframes qw-rise-in {
  from { opacity: 0; transform: translateY(16px); }
  to   { opacity: 1; transform: translateY(0); }
}
[data-rise] {
  opacity: 0;
  animation: qw-rise-in 2200ms var(--ease-reveal) var(--rise-delay, 200ms) forwards;
}

/* ---------- Back to top ----------
   Mobile-first floating control. Shown by motion.js after the reader has
   scrolled past ~80% of a viewport. Hidden on desktop unless a site opts in
   with .qw-back-to-top--always. */
.qw-back-to-top {
  position: fixed;
  right: 16px;
  bottom: 16px;
  z-index: 70;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border-radius: var(--radius-full);
  background: rgba(8, 8, 18, .62);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  border: 1px solid rgba(255, 255, 255, .42);
  color: #fff;
  box-shadow: var(--shadow-md);
  opacity: 0;
  transform: translateY(8px);
  pointer-events: none;
  transition: opacity var(--dur-fast) var(--ease-reveal), transform var(--dur-fast) var(--ease-reveal);
}
.qw-back-to-top svg { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; }
.qw-back-to-top.is-visible { opacity: 1; transform: translateY(0); pointer-events: auto; }
@media (min-width: 900px) {
  .qw-back-to-top:not(.qw-back-to-top--always) { display: none; }
}

/* ---------- Reduced motion ---------- */
@media (prefers-reduced-motion: reduce) {
  [data-reveal], [data-rise] { opacity: 1; animation: none; transform: none; }
}

/* ---- css/v1/components/adoption-table.css ---- */
/* ==========================================================================
   Quality Web Library, v1 (candidate, harvested 2026-09-11)
   qw-adoption-table: the adoption table with verdict pills

   Source (proposed): cdn.brandquality.com/css/v1/components/adoption-table.css
   Requires tokens.css. No JS.

   Ported from nba-region-ix/_inspiration-review.html page furniture (.recs,
   .recs th, .recs td, .pill, .pill--yes, .pill--maybe, .pill--no,
   .pill--primary).

   THE RULES
   - A full-width collapsed table, 14px, 24px above: 11px uppercase accent
     headers, hairline rows, 14px 16px cells, pattern name in the ink,
     placement in the muted ink.
   - Verdict pills 11px / 600 uppercase: --yes (Secondary, Adopt) green
     wash, --maybe amber wash, --no (Cut, Pass) gray wash, --primary accent
     fill. The vocabulary is library.json's verdicts block.
   - Under 640px the table scrolls sideways inside its wrapper.

   MARKUP
   <div class="qw-adoption-table-wrap">
     <table class="qw-adoption-table">
       <thead><tr><th>Pattern</th><th>Verdict</th><th>Where it goes</th></tr></thead>
       <tbody>
         <tr><td><strong>Pattern name</strong></td><td><span class="qw-adoption-table__pill qw-adoption-table__pill--yes">Adopt</span></td><td>Placement.</td></tr>
       </tbody>
     </table>
   </div>

   MODIFIERS
   .qw-adoption-table__pill--primary accent fill (Primary)
   .qw-adoption-table__pill--yes success wash (Secondary, Adopt)
   .qw-adoption-table__pill--maybe warning wash (Maybe)
   .qw-adoption-table__pill--no gray wash (Cut, Pass)
   ========================================================================== */

.qw-adoption-table-wrap { overflow-x: auto; }
.qw-adoption-table {
  width: 100%;
  border-collapse: collapse;
  margin-top: 24px;
  font-size: var(--text-sm);                    /* 14px */
}
.qw-adoption-table th, .qw-adoption-table td {
  text-align: left;
  padding: 14px 16px;
  border-bottom: 1px solid var(--color-line-soft);
  vertical-align: top;
}
.qw-adoption-table th {
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--color-accent);
}
.qw-adoption-table td { color: var(--color-ink-muted); }
.qw-adoption-table td strong { color: var(--color-ink); }
.qw-adoption-table__pill {
  display: inline-block;
  padding: 3px 10px;
  border-radius: 10px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  white-space: nowrap;
}
.qw-adoption-table__pill--yes     { background: color-mix(in srgb, var(--color-success) 20%, transparent); color: var(--color-success); }   /* rgba(61,122,77,.20) / #7DBA8E */
.qw-adoption-table__pill--maybe   { background: color-mix(in srgb, var(--color-warning) 20%, transparent); color: var(--color-warning); }   /* rgba(172,136,56,.20) / #D4AC55 */
.qw-adoption-table__pill--no      { background: color-mix(in srgb, var(--color-ink-muted) 20%, transparent); color: color-mix(in srgb, var(--color-ink) 45%, transparent); } /* rgba(132,129,138,.20) / muted */
.qw-adoption-table__pill--primary { background: var(--color-accent); color: var(--color-on-accent); }                                        /* tan-200 / wine-800 */
@media (max-width: 640px) {
  .qw-adoption-table { min-width: 560px; }
}

/* ---- css/v1/components/button.css ---- */
/* ==========================================================================
   Quality Web Library, v1
   qw-btn: the BQ button

   Source: cdn.brandquality.com/css/v1/components/button.css
   Requires tokens.css. Status and use count live in library.json.

   Ported from black-women-lawyers/installation/2026 (.dl-btn), which is the
   canonical spec in _shared/web-patterns/client-review-pages.md, cross-checked
   against rcoc/campaign/review (.btn) and first-option/sacnas/2026.

   THE RULES (Diallo)
   - A link the client is meant to click is a button, and it reads as one.
   - Pill. inline-flex. 12.5px / 800 / .14em / uppercase.
   - An accent fill, never a dark slab. The fill is --color-primary; a site
     sets that to its own action color (BWL emerald, LCC giving gold).
   - Significant buttons carry an icon (Standard 14). 16px stroked SVG in
     the .qw-btn svg slot, set inline at the END of the label.
   - Hover: lift, color shift, sheen sweep. Active: scale(.96).
   - Hover only under (hover: hover). Sheen off under reduced motion.
   - A row of buttons carries a heading and one line saying what they are.

   MARKUP
   <a class="qw-btn" href="...">
     Open the brief
     <svg viewBox="0 0 24 24" aria-hidden="true">...</svg>
   </a>

   MODIFIERS
   .qw-btn--ghost     transparent, primary border and text
   .qw-btn--accent    --color-accent fill, --color-on-accent text (gold on LCC)
   .qw-btn--on-dark   for dark bands: white fill, near-black text (fixed, not --color-ink,
                      because on a dark palette --color-ink is light and white on white
                      is what you get. Caught by Diallo on the gallery, September 11)

   TEXT ON A FILL comes from the palette (--color-on-primary, --color-on-accent),
   never from --color-ink. A hover is a visible shift of the fill that keeps the
   text readable; the palettes are written so that holds, and the gallery
   measures it (contrast at rest and on hover, every palette, every variant).
   .qw-btn--wait      dashed placeholder for a link that is not live yet
   .qw-btn--sm        smaller padding for dense rows
   ========================================================================== */

.qw-btn {
  position: relative;
  overflow: hidden;
  display: inline-flex;
  align-items: center;
  gap: 10px;
  flex: 0 0 auto;
  padding: 10px 24px;
  border-radius: var(--radius-full);
  border: 1.5px solid var(--color-primary);
  background: var(--color-primary);
  color: var(--color-on-primary);
  font-family: var(--font-body);
  font-size: var(--text-label);
  font-weight: 800;
  line-height: 1.2;
  letter-spacing: var(--tracking-button);
  text-transform: uppercase;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  box-shadow: var(--shadow-sm);
  transition:
    background var(--dur-fast) var(--ease-reveal),
    border-color var(--dur-fast) var(--ease-reveal),
    color var(--dur-fast) var(--ease-reveal),
    transform var(--dur-fast) var(--ease-reveal),
    box-shadow var(--dur-fast) var(--ease-reveal);
}

.qw-btn svg {
  position: relative;
  z-index: 1;
  width: 16px;
  height: 16px;
  flex: none;
  fill: none;
  stroke: currentColor;
  stroke-width: 2.2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* Sheen sweep */
.qw-btn::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(100deg, transparent 22%, rgba(255, 255, 255, .38) 46%, rgba(255, 255, 255, .38) 54%, transparent 78%);
  transform: translateX(-160%);
}
@keyframes qw-btn-sheen {
  from { transform: translateX(-160%); }
  to   { transform: translateX(160%); }
}

@media (hover: hover) {
  .qw-btn:hover {
    background: var(--color-primary-hover);
    border-color: var(--color-primary-hover);
    color: var(--color-on-primary);   /* stated, so no link rule can take it */
    transform: translateY(-2px);
    box-shadow: var(--shadow-md);
  }
  .qw-btn:hover::after { animation: qw-btn-sheen 900ms var(--ease-reveal) forwards; }
}
.qw-btn:active { transform: scale(.96); }
.qw-btn:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 3px; }

/* ---------- Modifiers ---------- */
.qw-btn--ghost {
  background: transparent;
  color: var(--color-ghost-ink, var(--color-primary));   /* a dark palette whose primary sits close to its ground sets --color-ghost-ink to its ink */
  border-color: var(--color-primary);
  box-shadow: none;
}
@media (hover: hover) {
  .qw-btn--ghost:hover { background: var(--color-primary); color: var(--color-on-primary); }
}

.qw-btn--accent {
  background: var(--color-accent);
  border-color: var(--color-accent);
  color: var(--color-on-accent);
}
@media (hover: hover) {
  .qw-btn--accent:hover { background: var(--color-accent-hover); border-color: var(--color-accent-hover); color: var(--color-on-accent); }
}

.qw-btn--on-dark {
  background: #fff;
  border-color: #fff;
  color: #141414;
}
@media (hover: hover) {
  .qw-btn--on-dark:hover { background: #d9d9d6; border-color: #d9d9d6; color: #141414; }
}

.qw-btn--wait {
  background: transparent;
  border-style: dashed;
  border-color: var(--color-line);
  color: var(--color-ink-muted);
  cursor: default;
  box-shadow: none;
}
.qw-btn--wait::after { display: none; }
@media (hover: hover) {
  .qw-btn--wait:hover { transform: none; background: transparent; border-color: var(--color-line); color: var(--color-ink-muted); box-shadow: none; }
}

.qw-btn--sm { padding: 7px 18px; font-size: 10.5px; gap: 8px; }
.qw-btn--sm svg { width: 14px; height: 14px; }

/* ---------- Button row ----------
   Carries a heading and one line above it. That is the rule, not a suggestion. */
.qw-btn-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-sm) var(--space-md);
  margin-block: var(--space-lg);
}

@media (max-width: 620px) {
  .qw-btn { font-size: 10.5px; padding: 8px 18px; }
}

@media (prefers-reduced-motion: reduce) {
  .qw-btn::after { display: none; }
}

/* ---- css/v1/components/changelog.css ---- */
/* ==========================================================================
   Quality Web Library, v1 (candidate, harvested 2026-09-11)
   qw-changelog: the what-changed panel

   Source (proposed): cdn.brandquality.com/css/v1/components/changelog.css
   Requires tokens.css. No JS.

   Ported from nba-region-ix/_inspiration-review.html page furniture
   (.changelog, .changelog h4, ul, li, strong) and the version flag
   (.v4-flag).

   THE RULES
   - A ruled panel under the page lead: 1px soft border with a 3px accent
     left rule, 8px radius, 24px padding, a 4% accent wash, 32px above.
   - One 11px uppercase accent h4 per version, then a 14px muted list with
     bold leads; a second version block sits 24px under the first.
   - The flag is an inline 11px uppercase pill in the deep primary beside
     the eyebrow ("Lock-in pass").

   MARKUP
   <div class="qw-changelog">
     <h4 class="qw-changelog__title">What changed in v6.2</h4>
     <ul>
       <li><strong>Sample 1.</strong> What changed and why.</li>
     </ul>
   </div>
   <span class="qw-changelog__flag">Lock-in pass</span>

   MODIFIERS
   none.
   ========================================================================== */

.qw-changelog {
  margin-top: 32px;
  padding: 24px;
  border: 1px solid var(--color-line-soft);
  border-left: 3px solid var(--color-accent);
  border-radius: var(--radius-md);
  background: color-mix(in srgb, var(--color-accent) 4%, transparent);  /* rgba(237,208,160,.04) */
}
.qw-changelog__title {
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 700;
  color: var(--color-accent);
  text-transform: uppercase;
  letter-spacing: 0.1em;
  margin: 0 0 12px;
}
.qw-changelog__title + .qw-changelog__title, ul + .qw-changelog__title { margin-top: 24px; }
.qw-changelog ul { margin: 0; padding-left: 20px; font-size: var(--text-sm); color: var(--color-ink-muted); } /* 14px */
.qw-changelog li { margin-bottom: 6px; }
.qw-changelog strong { color: var(--color-ink); }
.qw-changelog code { font-family: var(--font-mono); font-size: 13px; background: color-mix(in srgb, var(--color-ink) 6%, transparent); padding: 2px 6px; border-radius: var(--radius-sm); color: var(--color-accent); }

/* The version flag beside the eyebrow */
.qw-changelog__flag {
  display: inline-block;
  padding: 4px 10px;
  margin-left: 12px;
  border-radius: 12px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  background: var(--color-primary-hover);       /* crimson-700 */
  color: var(--color-on-primary);               /* tan-100 */
  vertical-align: middle;
}

/* ---- css/v1/components/chip-list.css ---- */
/* ==========================================================================
   Quality Web Library, v1 (candidate, harvested 2026-09-11)
   qw-chip-list: a centred row of contents chips

   Source (proposed): cdn.brandquality.com/css/v1/components/chip-list.css
   Requires tokens.css. No JS.

   Ported from rcoc/campaign/phase1 (.chips, .chips li). Under each document
   title the page lists what the document contains as small bordered chips
   with a 3px light-green left edge. Four instances on the source page.

   THE RULES (read from the source)
   - A plain list, centred, wrapping, .34rem apart.
   - Each chip is a white box with a hairline border, 8px radius, and a
     3px accent left edge. Bold, sentence case, no tracking.

   MARKUP
   <ul class="qw-chip-list">
     <li>Campaign theme</li>
     <li>Story in three lengths</li>
   </ul>

   MODIFIERS
   none.
   ========================================================================== */

.qw-chip-list {
  list-style: none;
  margin: 0 auto 1.2rem;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: .34rem;
  justify-content: center;
  max-width: none;
}
.qw-chip-list li {
  font-size: .8rem;
  font-weight: 700;
  letter-spacing: 0;
  color: var(--color-ink);
  background: var(--color-surface);
  border: 1px solid var(--color-line);
  border-radius: 8px;
  border-left: 3px solid var(--color-mesh-1, var(--color-primary-hover));
  padding: .42rem .68rem;
}

/* ---- css/v1/components/choice-group.css ---- */
/* ==========================================================================
   Quality Web Library, v1 (candidate, harvested 2026-09-11)
   qw-choice: selectable radio sets, three shapes: a segmented toggle, a
   grid of amount tiles, and two-up option cards with a name and a price

   Source (proposed): cdn.brandquality.com/css/v1/components/choice-group.css
   Requires tokens.css. No JS: native radios, visually hidden, drive the
   state through :checked.

   Ported from nba-region-ix/css/pages.css (.donate-toggle, --small, --two,
   __option, __label, .donate-amount-grid, .donate-amount-option, __label,
   .dues-type-grid, .dues-type-option, __card, __name, __price, and the
   640 / 520px blocks).

   THE RULES (read from the source comments)
   - Selected is the brand's primary gradient with reversed cream text,
     "the same treatment across the page so the selection state is
     consistent" (frequency, dedication, amount, membership type).
   - At rest a warm tint on a 6px inset track (toggle) or a tinted tile
     (amount, type); hover deepens the tint.

   MARKUP (toggle)
   <div class="qw-choice qw-choice--toggle">
     <label class="qw-choice__option"><input type="radio" name="freq" checked><span class="qw-choice__label">One-time</span></label>
     <label class="qw-choice__option"><input type="radio" name="freq"><span class="qw-choice__label">Monthly</span></label>
   </div>

   MARKUP (amounts)
   <div class="qw-choice qw-choice--amounts">
     <label class="qw-choice__option"><input type="radio" name="amount" value="25"><span class="qw-choice__label">$25</span></label>
   </div>

   MARKUP (type cards)
   <div class="qw-choice qw-choice--cards">
     <label class="qw-choice__option"><input type="radio" name="type" checked>
       <span class="qw-choice__card"><span class="qw-choice__name">Individual</span><span class="qw-choice__price">$00</span></span>
     </label>
   </div>

   MODIFIERS
   .qw-choice--toggle   segmented, 3 across (--two: 2; --small: 13px)
   .qw-choice--amounts  3 across, serif figures (2 under 640px)
   .qw-choice--cards    2 across, name and price (1 under 520px)
   ========================================================================== */

.qw-choice__option {
  position: relative;
  display: block;
  cursor: pointer;
}
.qw-choice__option input {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}

/* ---------- Toggle ---------- */
.qw-choice--toggle {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 6px;
  background: color-mix(in srgb, var(--color-form-tint, #B48C5A) 8%, transparent);
  padding: 6px;
  border-radius: var(--radius-md);
}
.qw-choice--toggle.qw-choice--two { grid-template-columns: repeat(2, 1fr); }
.qw-choice--toggle .qw-choice__label {
  display: block;
  text-align: center;
  font-family: var(--font-body);
  font-size: var(--text-sm);
  font-weight: 600;
  padding: 12px 14px;
  border-radius: calc(var(--radius-md) - 4px);
  color: var(--color-band-ink-muted, #454247);
  transition: background-color var(--dur-fast) ease, color var(--dur-fast) ease, box-shadow var(--dur-fast) ease;
}
.qw-choice--toggle .qw-choice__option input:checked + .qw-choice__label {
  background: linear-gradient(135deg, var(--color-primary) 0%, var(--color-primary-hover) 100%);   /* crimson-500 to crimson-700 #6E0F1F shipped */
  color: var(--color-band-card, #FFFCF6);
  box-shadow: 0 6px 16px -6px rgba(135, 20, 39, 0.45);
}
@media (hover: hover) {
  .qw-choice--toggle .qw-choice__option:hover .qw-choice__label { color: var(--color-primary-hover); }
  .qw-choice--toggle .qw-choice__option input:checked:hover + .qw-choice__label,
  .qw-choice--toggle .qw-choice__option input:checked + .qw-choice__label:hover { color: var(--color-band-card, #FFFCF6); }
}
.qw-choice--toggle.qw-choice--small .qw-choice__label {
  font-size: 13px;
  padding: 10px 12px;
}

/* ---------- Amount tiles ---------- */
.qw-choice--amounts {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 12px;
  margin-bottom: 16px;
}
.qw-choice--amounts .qw-choice__label {
  display: block;
  text-align: center;
  font-family: var(--font-heading);
  font-size: clamp(20px, 2vw, 26px);
  font-weight: 600;
  padding: 18px 16px;
  background: color-mix(in srgb, var(--color-form-tint, #B48C5A) 10%, transparent);
  border: 1.5px solid transparent;
  border-radius: var(--radius-md);
  color: var(--color-form-ink, #3D2818);
  transition: background-color var(--dur-fast) ease, border-color var(--dur-fast) ease, transform 180ms ease;
}
@media (hover: hover) {
  .qw-choice--amounts .qw-choice__option:hover .qw-choice__label { background: color-mix(in srgb, var(--color-form-tint, #B48C5A) 18%, transparent); }
}
.qw-choice--amounts .qw-choice__option input:checked + .qw-choice__label {
  background: linear-gradient(135deg, var(--color-primary) 0%, var(--color-primary-hover) 100%);
  border-color: var(--color-primary-hover);     /* crimson-600 shipped */
  color: var(--color-band-card, #FFFCF6);
  transform: translateY(-1px);
  box-shadow: 0 8px 20px -8px rgba(135, 20, 39, 0.40);
}

/* ---------- Type cards ---------- */
.qw-choice--cards {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
}
.qw-choice__card {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 20px 22px;
  background: color-mix(in srgb, var(--color-form-tint, #B48C5A) 10%, transparent);
  border: 1.5px solid transparent;
  border-radius: var(--radius-md);
  transition: background-color var(--dur-fast) ease, border-color var(--dur-fast) ease, transform 180ms ease;
}
.qw-choice__name {
  font-family: var(--font-body);
  font-size: var(--text-xs);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  font-weight: 700;
  color: var(--color-band-ink-muted, #454247);
  transition: color var(--dur-fast) ease;
}
.qw-choice__price {
  font-family: var(--font-heading);
  font-size: clamp(26px, 2.6vw, 34px);
  font-weight: 600;
  color: var(--color-form-ink, #3D2818);
  line-height: 1;
  transition: color var(--dur-fast) ease;
}
@media (hover: hover) {
  .qw-choice--cards .qw-choice__option:hover .qw-choice__card { background: color-mix(in srgb, var(--color-form-tint, #B48C5A) 18%, transparent); }
}
.qw-choice--cards .qw-choice__option input:checked + .qw-choice__card {
  background: linear-gradient(135deg, var(--color-primary) 0%, var(--color-primary-hover) 100%);
  border-color: var(--color-primary-hover);
  transform: translateY(-1px);
  box-shadow: 0 8px 20px -8px rgba(135, 20, 39, 0.40);
}
.qw-choice--cards .qw-choice__option input:checked + .qw-choice__card .qw-choice__name,
.qw-choice--cards .qw-choice__option input:checked + .qw-choice__card .qw-choice__price { color: var(--color-band-card, #FFFCF6); }
.qw-choice__option input:focus-visible + .qw-choice__card,
.qw-choice__option input:focus-visible + .qw-choice__label {
  outline: 2px solid var(--color-form-focus, #B05A1F);
  outline-offset: 2px;
}

/* ---------- Responsive ---------- */
@media (max-width: 640px) {
  .qw-choice--amounts { grid-template-columns: repeat(2, 1fr); }
  .qw-choice--toggle { grid-template-columns: 1fr; }
}
@media (max-width: 520px) {
  .qw-choice--cards { grid-template-columns: 1fr; }
}

/* ---- css/v1/components/choice-toggle.css ---- */
/* ==========================================================================
   Quality Web Library, v1 (candidate, harvested 2026-09-11)
   qw-choice: a one-of-two chooser (pay the deposit, pay in full)

   Source (proposed): cdn.brandquality.com/css/v1/components/choice-toggle.css
   Requires tokens.css. choice-toggle.js flips is-selected and aria-pressed.

   Ported from bq-payments/payments-page/index.html (.pay-option-block,
   .pay-option-label, .pay-options, .pay-option-btn, .selected, .opt-title,
   .check, .opt-amount, .opt-desc, the 480px rule); the earlier
   bq-payments/index.html has the same rules at smaller type (NOTES).

   THE RULES (read from the source)
   - A card with a tracked question, then two buttons side by side, each
     a check dot, a title, the amount and one line.
   - The selected button fills with the accent at 15% and takes an accent
     border; its dot fills solid. Everything transitions in .15s.
   - Under 480px the buttons stack.
   - Night arrangement of the Brand Quality palette (see invoice-card).

   MARKUP
   <div class="qw-choice" data-js="choice">
     <div class="qw-choice__label">How would you like to pay?</div>
     <div class="qw-choice__options">
       <button class="qw-choice__btn is-selected" type="button" aria-pressed="true" data-value="deposit">
         <span class="qw-choice__title"><span class="qw-choice__check"></span> Pay deposit</span>
         <span class="qw-choice__amount">$0.00</span>
         <span class="qw-choice__desc">Pay the deposit now, the balance later</span>
       </button>
       ...
     </div>
   </div>

   MODIFIERS
   is-selected      the chosen option
   ========================================================================== */

.qw-choice {
  margin-bottom: var(--space-md);
  background: var(--color-surface);
  border: 1px solid var(--color-line);
  border-radius: var(--radius-md);
  overflow: hidden;
}
.qw-choice__label {
  font-size: var(--text-xs);                  /* 12px */
  font-weight: 700;
  letter-spacing: 2px;
  text-transform: uppercase;
  color: var(--color-ink-muted);
  padding: 14px 20px 10px;
}
.qw-choice__options { display: flex; padding: 0 12px 12px; gap: 8px; }
.qw-choice__btn {
  flex: 1;
  background: color-mix(in srgb, var(--color-ink-on-dark) 5%, transparent);
  border: 1.5px solid var(--color-line);
  border-radius: 6px;
  padding: 12px 16px;
  cursor: pointer;
  text-align: left;
  transition: all .15s ease;
  font-family: inherit;
  color: var(--color-ink);
}
@media (hover: hover) {
  .qw-choice__btn:hover {
    background: color-mix(in srgb, var(--color-ink-on-dark) 8%, transparent);
    border-color: color-mix(in srgb, var(--color-ink-on-dark) 20%, transparent);
  }
}
.qw-choice__btn.is-selected {
  background: color-mix(in srgb, var(--color-accent) 15%, transparent);
  border-color: var(--color-accent);
}
.qw-choice__title {
  font-size: 15px;
  font-weight: 700;
  color: var(--color-ink);
  margin-bottom: 3px;
  display: flex;
  align-items: center;
  gap: 6px;
}
.qw-choice__check {
  width: 14px;
  height: 14px;
  border-radius: 50%;
  border: 2px solid var(--color-line);
  display: inline-block;
  flex-shrink: 0;
  transition: all .15s ease;
}
.qw-choice__btn.is-selected .qw-choice__check {
  border-color: var(--color-accent);
  background: var(--color-accent);
}
.qw-choice__amount { display: block; font-size: 21px; font-weight: 700; color: var(--color-ink-on-dark); }
.qw-choice__desc { display: block; font-size: 13px; color: var(--color-ink-muted); margin-top: 2px; }

@media (max-width: 480px) {
  .qw-choice__options { flex-direction: column; }
}

/* ---- css/v1/components/figure-band.css ---- */
/* ==========================================================================
   Quality Web Library, v1 (candidate, harvested 2026-09-11)
   qw-figure-band: a dark gradient panel carrying one or two big figures

   Source (proposed): cdn.brandquality.com/css/v1/components/figure-band.css
   Requires tokens.css. No JS. The panel rides motion.js (data-reveal).

   Ported from rcoc/campaign/meeting/2026-09-01 (.bldg, .tier, .tier + .tier,
   .tier-amt, .tier-k, .tier p, the 1000px rule) and
   rcoc/campaign/meeting/2026-09-08 (.tot, .tot-k, .tot-note, .tot-amt, the
   1000px rule). The same gradient and shadow carry two layouts: two tiers
   side by side with a rule between them (building naming rights), and a
   label with its total on one row (the print budget).

   THE RULES (read from the source comments)
   - The section that closes the page gets the only dark panel.
   - Two tiers side by side with a rule between them, because the decision
     being asked for is which of the two, not whether one number is right.
   - The figure is the largest type on the page: 800, line-height .95,
     -.045em, tabular numerals, paper on the deep green.
   - The kicker is gold; the note is paper at 82% (tiers) or 80% (total).
   - Under 1000px the tiers stack with the rule turned horizontal, and the
     total row stacks with the figure under the label.

   MARKUP (tiers)
   <div class="qw-figure-band qw-figure-band--tiers" data-reveal>
     <div class="qw-figure-band__tier">
       <span class="qw-figure-band__amt">$0,000,000</span>
       <span class="qw-figure-band__k">Option one</span>
       <p>One line on what this option means.</p>
     </div>
     <div class="qw-figure-band__tier">...</div>
   </div>

   MARKUP (total)
   <div class="qw-figure-band qw-figure-band--total" data-reveal>
     <div>
       <p class="qw-figure-band__k">Full budget, both groups</p>
       <p class="qw-figure-band__note">One line of context.</p>
     </div>
     <span class="qw-figure-band__amt">$0,000</span>
   </div>

   MODIFIERS
   .qw-figure-band--tiers   two columns, a rule between
   .qw-figure-band--total   one row, label left and figure right
   .qw-figure-band--stack   with --tiers: the tiers in one column, left-aligned,
                            a rule between (lifecommunitycenter, harvested 2026-09-22)
   ========================================================================== */

.qw-figure-band {
  background: linear-gradient(150deg,
    color-mix(in srgb, var(--color-surface-dark) 83%, #000) 0%,    /* #28422F */
    var(--color-surface-dark) 46%,                                 /* #304F38 */
    color-mix(in srgb, var(--color-surface-dark) 70%, #000) 100%); /* #22352A */
  box-shadow: 0 26px 60px -34px rgba(34, 53, 42, .75);
  color: var(--color-ink-on-dark);
}

.qw-figure-band__amt {
  display: block;
  font-size: clamp(2.1rem, 5.2vw, 3.6rem);
  font-weight: 800;
  line-height: .95;
  letter-spacing: -.045em;
  color: var(--color-ink-on-dark);
  font-variant-numeric: tabular-nums;
}
.qw-figure-band__k {
  display: block;
  margin: 1rem 0 .7rem;
  font-size: .72rem;
  font-weight: 800;
  letter-spacing: .22em;
  text-transform: uppercase;
  color: var(--color-accent-hover);   /* #EEC549, gold on the dark ground */
}

/* ---------- --tiers ---------- */
.qw-figure-band--tiers {
  display: grid;
  grid-template-columns: 1fr 1fr;
  padding: clamp(2.2rem, 4.6vw, 3.6rem) clamp(1.6rem, 3.8vw, 3.2rem);
}
.qw-figure-band__tier { padding: 0 clamp(1.2rem, 3vw, 2.6rem); }
.qw-figure-band__tier + .qw-figure-band__tier {
  border-left: 1px solid color-mix(in srgb, var(--color-ink-on-dark) 18%, transparent);
}
.qw-figure-band__tier p {
  margin: 0;
  font-size: 1rem;
  line-height: 1.6;
  color: color-mix(in srgb, var(--color-ink-on-dark) 82%, transparent);
}

/* ---------- --total ---------- */
.qw-figure-band--total {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: clamp(1.5rem, 4vw, 3.5rem);
  margin-top: clamp(1.6rem, 3.4vw, 2.4rem);
  padding: clamp(1.8rem, 4vw, 2.8rem) clamp(1.6rem, 3.6vw, 3rem);
}
.qw-figure-band--total .qw-figure-band__k { margin: 0 0 .6rem; }
.qw-figure-band__note {
  margin: 0;
  font-size: .92rem;
  line-height: 1.6;
  color: color-mix(in srgb, var(--color-ink-on-dark) 80%, transparent);
  max-width: 34rem;
}
.qw-figure-band--total .qw-figure-band__amt {
  flex: 0 0 auto;
  font-size: clamp(2.1rem, 5.4vw, 3.5rem);
}

/* ---------- responsive, last ---------- */
@media (max-width: 1000px) {
  .qw-figure-band--tiers {
    grid-template-columns: 1fr;
    padding-top: clamp(1.8rem, 5vw, 2.6rem);
    padding-bottom: clamp(1.8rem, 5vw, 2.6rem);
  }
  .qw-figure-band__tier { padding: 1.7rem 0; }
  .qw-figure-band__tier + .qw-figure-band__tier {
    border-left: 0;
    border-top: 1px solid color-mix(in srgb, var(--color-ink-on-dark) 18%, transparent);
  }
  .qw-figure-band--total { flex-direction: column; align-items: flex-start; gap: 1.4rem; }
}

/* ---------- Stack: the tiers in one column, left-aligned, ruled between ----------
   Second property on the band (lifecommunitycenter, 2026-09-22): the three
   figures of the ask stacked beside the giving table, each tier left-aligned
   with its note at 26ch, a paper hairline between tiers. */
.qw-figure-band--stack {
  grid-template-columns: 1fr;
  align-content: start;
  border-radius: 14px;
  text-align: left;
  padding: 26px 10px 28px;
}
.qw-figure-band--stack .qw-figure-band__tier { text-align: left; padding: 0 22px; }
.qw-figure-band--stack .qw-figure-band__tier p { max-width: 26ch; }
.qw-figure-band--stack .qw-figure-band__amt { font-size: clamp(30px, 2.8vw, 42px); white-space: nowrap; }
.qw-figure-band--stack .qw-figure-band__tier + .qw-figure-band__tier {
  border-left: 0;
  border-top: 1px solid color-mix(in srgb, var(--color-ink-on-dark) 18%, transparent);
  margin-top: 22px;
  padding-top: 22px;
}

/* ---- css/v1/components/form-field.css ---- */
/* ==========================================================================
   Quality Web Library, v1 (candidate, harvested 2026-09-11)
   qw-field: the form field register on the light form card: label,
   input, select, textarea, checkbox, legend, required and optional
   marks, validation

   Source (proposed): cdn.brandquality.com/css/v1/components/form-field.css
   Requires tokens.css. Validation classes are toggled by the site's own
   form script (is-invalid on the control, is-visible on the summary).

   Ported from nba-region-ix/css/pages.css (.donate-field, __legend,
   __optional, __legend--payment, .donate-input-row, --three,
   .donate-input-wrap, .donate-input-label, .donate-input-wrap input,
   .donate-select, .donate-field__custom*, .donate-card-input*,
   .donate-checkbox*, .donate-field__security, .req, .contact-form__req-note,
   .donate-form__req-note, .contact-form__optional, .is-invalid,
   .field-error, .form-error-summary, .contact-form__honeypot, and the
   contact form's own control rules) and css/components.css (.form-group,
   .form-label, .form-control, the dark-surface register).

   THE RULES (read from the source comments)
   - Warm copper, not wine: the payment surfaces are "all warm light
     surfaces, clean and ready to give rather than authoritative".
   - A field is a 12px tracked uppercase label over a 1.5px warm-tinted
     control, 14px 16px, that goes white with a copper ring on focus.
   - The select draws its own chevron: a red pill with a white arrow,
     one svg, on the right. background-color, not the shorthand, on
     focus so the chevron never disappears.
   - Required is a small red asterisk after the label; optional is a
     small italic note. Invalid is a red border, a faint red wash and a
     one-line error under the control; a summary box sits at the top.

   MARKUP
   <fieldset class="qw-fieldset">
     <legend class="qw-fieldset__legend">Your information <span class="qw-fieldset__optional">(optional)</span></legend>
     <div class="qw-field-row">
       <label class="qw-field">
         <span class="qw-field__label">First name<span class="qw-req" aria-hidden="true">*</span></span>
         <input class="qw-field__control" type="text" name="first_name" required>
       </label>
     </div>
     <label class="qw-field">
       <span class="qw-field__label">State</span>
       <select class="qw-field__control qw-field__control--select" name="state"><option>Select</option></select>
     </label>
     <label class="qw-checkbox">
       <input type="checkbox" name="renew">
       <span class="qw-checkbox__box" aria-hidden="true"></span>
       <span class="qw-checkbox__label">Renew each year<span class="qw-checkbox__note">Renews until canceled.</span></span>
     </label>
   </fieldset>

   MODIFIERS
   .qw-field-row--three          2fr 1fr 1fr
   .qw-fieldset__legend--payment  primary, a step larger
   .qw-field--compact            the contact form's 11px label and 10px 14px control
   .qw-field__control--select    the drawn chevron
   .qw-field__control--textarea  resize vertical, min 140px
   .qw-field--currency           a currency mark beside a serif number input
   .qw-field--card               the card-number look with brand chips
   .qw-field--on-dark            the dark-surface register from components.css
   ========================================================================== */

/* ---------- Fieldset and legend ---------- */
.qw-fieldset {
  border: 0;
  padding: 0;
  margin: 0 0 clamp(28px, 3vh, 36px);
  min-width: 0;
}
.qw-fieldset:last-of-type { margin-bottom: clamp(20px, 2vh, 28px); }
.qw-fieldset__legend {
  font-family: var(--font-body);
  font-size: 13px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--color-form-ink, #3D2818);    /* warm dark brown, not wine */
  font-weight: 700;
  margin: 0 0 var(--space-md);
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  gap: 12px;
}
.qw-fieldset__optional {
  font-size: var(--text-xs);
  text-transform: none;
  font-weight: 600;
  color: var(--color-band-ink-muted, #5F5C61);
  font-style: italic;
  letter-spacing: 0.04em;
}
.qw-fieldset__legend--payment {
  color: var(--color-primary);
  font-size: 15px;
}
.qw-fieldset__lede {
  font-family: var(--font-body);
  font-size: 15px;
  color: var(--color-band-ink-muted, #454247);
  margin: 0 0 14px;
}

/* ---------- Rows ---------- */
.qw-field-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px;
  margin-bottom: 14px;
}
.qw-field-row--three { grid-template-columns: 2fr 1fr 1fr; }
.qw-field-row > .qw-field { margin-bottom: 0; }
@media (max-width: 640px) {
  .qw-field-row, .qw-field-row--three { grid-template-columns: 1fr; }
}

/* ---------- Field ---------- */
.qw-field {
  display: block;
  margin-bottom: 14px;
}
.qw-field__label {
  display: block;
  font-family: var(--font-body);
  font-size: var(--text-xs);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--color-band-ink-muted, #454247);
  font-weight: 600;
  margin-bottom: 8px;
}
.qw-field__control {
  width: 100%;
  border: 1.5px solid color-mix(in srgb, var(--color-form-tint, #B48C5A) 20%, transparent);
  background: color-mix(in srgb, var(--color-form-tint, #B48C5A) 6%, transparent);
  border-radius: var(--radius-md);
  padding: 14px 16px;
  font-family: var(--font-body);
  font-size: 15px;
  color: var(--color-form-ink, #3D2818);
  outline: none;
  transition: border-color var(--dur-fast) ease, background-color var(--dur-fast) ease, box-shadow var(--dur-fast) ease;
}
.qw-field__control::placeholder { color: var(--color-band-ink-muted, #84818A); }
.qw-field__control:focus {
  border-color: var(--color-form-focus, #B05A1F);
  background-color: var(--color-band-card, #FFFCF6);
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--color-form-focus, #B05A1F) 14%, transparent);
}
.qw-field__control--select {
  appearance: none;
  -webkit-appearance: none;
  -moz-appearance: none;
  /* One asset: a red pill with a white chevron. The circle fill is crimson-400 #D14C4A, literal in the data url. */
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='28' height='28' viewBox='0 0 28 28' fill='none'><circle cx='14' cy='14' r='14' fill='%23D14C4A'/><path d='M9 12l5 5 5-5' stroke='white' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'/></svg>");
  background-repeat: no-repeat;
  background-position: right 12px center;
  background-size: 28px 28px;
  padding-right: 56px;
  cursor: pointer;
}
.qw-field__control--textarea {
  resize: vertical;
  min-height: 140px;
}

/* ---------- Compact (the contact form) ---------- */
.qw-field--compact { margin-bottom: 0; }
.qw-field--compact .qw-field__label {
  font-size: 11px;
  margin-bottom: 5px;
}
.qw-field--compact .qw-field__control {
  /* Rendered values: the later .contact-form input rule (16px, 14px 16px, 1px rgba(50,0,25,.18), white)
     wins the cascade over .contact-form--hero input (14px, 10px 14px, warm tint). See README. */
  font-size: 16px;
  padding: 14px 16px;
  border: 1px solid color-mix(in srgb, var(--color-band-ink, #320019) 18%, transparent);
  background: var(--color-band-light, #FFFFFF);
  color: var(--color-band-ink, #320019);
}
.qw-field--compact .qw-field__control:focus {
  border-color: var(--color-primary);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-primary) 16%, transparent);
}
.qw-field--compact .qw-field__control--textarea {
  font-family: var(--font-heading);
  line-height: 1.5;
}
.qw-field__optional {
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: none;
  color: var(--color-band-ink-muted, #84818A);
  font-style: italic;
  font-weight: 600;
  margin-left: 4px;
}

/* ---------- Currency input ---------- */
.qw-field--currency .qw-field__wrap {
  display: flex;
  align-items: center;
  background: color-mix(in srgb, var(--color-form-tint, #B48C5A) 6%, transparent);
  border: 1.5px solid color-mix(in srgb, var(--color-form-tint, #B48C5A) 20%, transparent);
  border-radius: var(--radius-md);
  padding: 0 16px;
  transition: border-color var(--dur-fast) ease, background-color var(--dur-fast) ease;
}
.qw-field--currency .qw-field__wrap:focus-within {
  border-color: var(--color-form-focus, #B05A1F);
  background: var(--color-band-card, #FFFCF6);
}
.qw-field__currency {
  font-family: var(--font-heading);
  font-size: var(--text-lg);
  color: var(--color-form-ink, #3D2818);
  font-weight: 600;
  margin-right: 8px;
}
.qw-field--currency .qw-field__wrap input {
  flex: 1;
  border: 0;
  background: transparent;
  font-family: var(--font-heading);
  font-size: var(--text-md);
  color: var(--color-form-ink, #3D2818);
  padding: 14px 0;
  outline: none;
  min-width: 0;
}
.qw-field--currency .qw-field__wrap input::-webkit-outer-spin-button,
.qw-field--currency .qw-field__wrap input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.qw-field--currency .qw-field__label { font-size: var(--text-xs); letter-spacing: 0.16em; }

/* ---------- Card input (the Stripe look, before Elements) ---------- */
.qw-field--card .qw-field__wrap {
  display: flex;
  align-items: center;
  border: 1.5px solid color-mix(in srgb, var(--color-form-tint, #B48C5A) 20%, transparent);
  background: color-mix(in srgb, var(--color-form-tint, #B48C5A) 6%, transparent);
  border-radius: var(--radius-md);
  padding: 0 16px;
  gap: 12px;
  transition: border-color var(--dur-fast) ease, background-color var(--dur-fast) ease, box-shadow var(--dur-fast) ease;
}
.qw-field--card .qw-field__wrap:focus-within {
  border-color: var(--color-form-focus, #B05A1F);
  background: var(--color-band-card, #FFFCF6);
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--color-form-focus, #B05A1F) 14%, transparent);
}
.qw-field--card .qw-field__wrap input {
  flex: 1;
  border: 0;
  background: transparent;
  padding: 14px 0;
  font-family: var(--font-mono);
  font-size: 15px;
  letter-spacing: 0.02em;
  color: var(--color-form-ink, #3D2818);
  outline: none;
  min-width: 0;
}
.qw-field__brands { display: flex; gap: 6px; flex-shrink: 0; }
.qw-field__brand {
  display: inline-flex;
  align-items: center;
  font-family: var(--font-body);
  font-size: 10px;
  letter-spacing: 0.1em;
  font-weight: 700;
  padding: 4px 8px;
  border-radius: var(--radius-sm);
  background: color-mix(in srgb, var(--color-form-tint, #B48C5A) 14%, transparent);
  color: var(--color-band-ink-muted, #454247);
}
.qw-field__security {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: var(--text-xs);
  color: var(--color-band-ink-muted, #5F5C61);
  margin: 14px 0 0;
  font-style: italic;
}
.qw-field__security svg { color: var(--color-form-focus, #B05A1F); flex-shrink: 0; width: 14px; height: 14px; fill: none; stroke: currentColor; stroke-width: 1.4; stroke-linecap: round; stroke-linejoin: round; }

/* ---------- Checkbox ---------- */
.qw-checkbox {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  cursor: pointer;
  margin-bottom: 12px;
  font-family: var(--font-body);
  font-size: var(--text-sm);
  line-height: 1.45;
  color: var(--color-form-ink, #3D2818);
  position: relative;
}
.qw-checkbox:last-child { margin-bottom: 0; }
.qw-checkbox input {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}
.qw-checkbox__box {
  display: inline-block;
  width: 20px;
  height: 20px;
  border: 1.5px solid color-mix(in srgb, var(--color-form-tint, #B48C5A) 35%, transparent);
  background: var(--color-band-card, #FFFCF6);
  border-radius: 5px;
  flex-shrink: 0;
  margin-top: 1px;
  position: relative;
  transition: background-color 180ms ease, border-color 180ms ease;
}
.qw-checkbox__box::after {
  content: '';
  position: absolute;
  inset: 4px;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='10' viewBox='0 0 12 10' fill='none'><path d='M1 5l3.5 3.5L11 1' stroke='white' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/></svg>");
  background-repeat: no-repeat;
  background-size: contain;
  opacity: 0;
  transition: opacity 180ms ease;
}
.qw-checkbox input:checked + .qw-checkbox__box {
  background: var(--color-form-focus, #B05A1F);
  border-color: var(--color-form-focus, #B05A1F);
}
.qw-checkbox input:checked + .qw-checkbox__box::after { opacity: 1; }
.qw-checkbox input:focus-visible + .qw-checkbox__box { outline: 2px solid var(--color-form-focus, #B05A1F); outline-offset: 2px; }
.qw-checkbox__note {
  display: block;
  font-size: var(--text-xs);
  color: var(--color-band-ink-muted, #5F5C61);
  margin-top: 3px;
  font-weight: 400;
}
/* A tinted consent block around a set of checkboxes */
.qw-fieldset--consent {
  background: color-mix(in srgb, var(--color-accent-hover) 45%, transparent);   /* rgba(245,229,201,.45) tan-100 */
  padding: 20px 22px;
  border-radius: var(--radius-md);
}

/* ---------- Required, optional, notes ---------- */
.qw-req {
  color: var(--color-primary);
  font-weight: 700;
  font-size: 0.95em;
  margin-left: 4px;
  display: inline-block;
  line-height: 1;
  vertical-align: baseline;
}
.qw-req-note {
  font-family: var(--font-body);
  font-size: var(--text-xs);
  color: var(--color-band-ink-muted, #5F5C61);
  margin: 16px 0 0;
  letter-spacing: 0.02em;
}
.qw-req-note .qw-req { margin-left: 0; margin-right: 4px; }
.qw-form-legal {
  font-family: var(--font-body);
  font-size: var(--text-xs);
  color: var(--color-band-ink-muted, #5F5C61);
  line-height: 1.5;
  margin: 18px 0 0;
  font-style: italic;
}

/* ---------- Validation ---------- */
.qw-field__control.is-invalid,
.qw-field .is-invalid {
  border-color: var(--color-primary) !important;                                             /* crimson-500 shipped */
  background-color: color-mix(in srgb, var(--color-primary) 5%, transparent) !important;     /* rgba(209,76,74,.05) crimson-400 */
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-primary) 12%, transparent) !important;
}
.qw-field__error {
  display: block;
  font-family: var(--font-body);
  font-size: 11.5px;
  font-weight: 600;
  color: var(--color-primary);
  margin-top: 6px;
  letter-spacing: 0.02em;
}
.qw-form-summary {
  display: none;
  background: color-mix(in srgb, var(--color-primary) 8%, transparent);
  border: 1.5px solid var(--color-primary);
  border-radius: var(--radius-md);
  padding: 14px 18px;
  margin-bottom: 20px;
  font-family: var(--font-body);
  font-size: 13px;
  color: var(--color-primary-hover);          /* crimson-700 shipped */
  font-weight: 600;
  letter-spacing: 0.01em;
}
.qw-form-summary.is-visible { display: block; }

/* ---------- Honeypot ---------- */
.qw-honeypot {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
  opacity: 0;
  pointer-events: none;
}

/* ---------- On dark (components.css .form-control) ---------- */
.qw-field--on-dark .qw-field__label {
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--color-ink);
  letter-spacing: 0;
  text-transform: none;
}
.qw-field--on-dark .qw-field__control {
  font-size: var(--text-body);              /* 16px shipped; the floor is 17px */
  color: var(--color-ink);
  background: var(--color-surface);
  border: 1.5px solid var(--color-line);
  padding: 12px 16px;
  appearance: none;
}
.qw-field--on-dark .qw-field__control:focus {
  border-color: var(--color-primary);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-primary) 12%, transparent);
}
.qw-field--on-dark .qw-field__control:invalid:not(:placeholder-shown) { border-color: var(--color-error); }

/* ---- css/v1/components/grain.css ---- */
/* ==========================================================================
   Quality Web Library, v1 (candidate, harvested 2026-09-11)
   qw-grain: a fixed film-grain layer over the whole page

   Source (proposed): cdn.brandquality.com/css/v1/components/grain.css
   Requires nothing. No JS. Put the class on <body>.

   Ported from rcoc/campaign/identity (body::after) and
   rcoc/campaign/identity/_share-card.html (body::after). The pitch deck
   runs the same layer at .26.

   THE RULES (read from the source comments)
   - It is here to kill banding in the large mesh gradients as much as for
     texture, so it is rasterised once and never moves (position: fixed).
   - Lighter on a cream ground (.14) than on a deep one (.26). The share
     card runs .10 so it reads as the same surface.
   - Multiply blend, no pointer events, above the page (z-index 9) and
     below the sticky chrome (60+). Off in print.

   MARKUP
   <body class="qw-grain">            .14, the light-ground default
   <body class="qw-grain qw-grain--card">   .10, the share card
   <body class="qw-grain qw-grain--deep">   .26, the pitch deck (cited, not read)

   MODIFIERS
   .qw-grain--card   opacity .10
   .qw-grain--deep   opacity .26
   ========================================================================== */

.qw-grain { position: relative; }
.qw-grain::after {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 9;
  pointer-events: none;
  opacity: .14;
  mix-blend-mode: multiply;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.78' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}
.qw-grain--card::after { opacity: .10; position: absolute; z-index: 3; }
.qw-grain--deep::after { opacity: .26; }

@media print {
  .qw-grain::after { display: none; }
}

/* ---- css/v1/components/nav-drawer.css ---- */
/* ==========================================================================
   Quality Web Library, v1 (candidate, harvested 2026-09-11)
   qw-nav-drawer: a native <dialog> side drawer for the mobile nav

   Source (proposed): cdn.brandquality.com/css/v1/components/nav-drawer.css
   Requires tokens.css. Pair with nav-drawer.js (open, close, the
   collapsible sub-list, close on an in-page choice, close above 860px).
   The toggle is qw-nav__toggle from nav.css; the source's own hamburger
   values are recorded in the README.

   Ported from rcoc/campaign/pitch (.mobile-nav, ::backdrop, @starting-style,
   .mobile-nav__inner, __head, __close, __links, __sub-trigger, __caret,
   .has-sub, .mobile-nav__sub).

   THE RULES (read from the source comments)
   - A native <dialog>, so the focus trap, Escape and the backdrop come
     free. Slides in from the left over 420ms on the reveal curve; the
     backdrop is a blurred dark wash.
   - A brand row with a close button, then hairline-separated links at
     18px. A section with sub-sections collapses by default (the source:
     nine phase links between two top-level items "made the drawer read
     as a wall"); its overview link stays first inside the sub-list so the
     parent section stays reachable.
   - Tap feedback (:active) shifts the link right 6px and colours it.

   MARKUP
   <dialog class="qw-nav-drawer" id="qw-nav-drawer" data-js="nav-drawer" aria-label="Sections">
     <div class="qw-nav-drawer__inner">
       <div class="qw-nav-drawer__head">
         <img src="..." alt="Brand Quality">
         <button class="qw-nav-drawer__close" type="button" data-js="nav-drawer-close" aria-label="Close menu">
           <svg viewBox="0 0 24 24" aria-hidden="true"><path d="M6 6l12 12M18 6L6 18" stroke="currentColor" stroke-width="2" stroke-linecap="round"/></svg>
         </button>
       </div>
       <ul class="qw-nav-drawer__links">
         <li><a data-target="#about" role="link" tabindex="0">About</a></li>
         <li class="qw-nav-drawer__group">
           <button class="qw-nav-drawer__sub-trigger" type="button" data-js="nav-drawer-sub" aria-expanded="false">
             The plan
             <svg class="qw-nav-drawer__caret" viewBox="0 0 12 8" aria-hidden="true"><path d="M1 1.5 6 6.5l5-5" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/></svg>
           </button>
           <ul class="qw-nav-drawer__sub">
             <li><a data-target="#plan" role="link" tabindex="0">The plan, overview</a></li>
           </ul>
         </li>
       </ul>
     </div>
   </dialog>

   MODIFIERS
   none.
   ========================================================================== */

.qw-nav-drawer {
  position: fixed;
  inset: 0;
  margin: 0;
  width: 100%;
  max-width: 340px;
  height: 100%;
  max-height: 100%;
  padding: 0;
  border: none;
  border-right: 1px solid var(--color-line);
  background: var(--color-bg);
  color: var(--color-ink);
  overflow-y: auto;
  overscroll-behavior: contain;
}
.qw-nav-drawer::backdrop { background: rgb(0 8 16 / 0.62); backdrop-filter: blur(3px); }
@starting-style {
  .qw-nav-drawer[open] { transform: translateX(-100%); opacity: 0; }
}
.qw-nav-drawer[open] {
  transform: translateX(0);
  opacity: 1;
  transition: transform 420ms var(--ease-reveal), opacity 300ms var(--ease-reveal);
}
/* the exit (lifecommunitycenter, harvested 2026-09-22): nav-drawer.js adds
   is-closing, the panel slides back out over 300ms on the state curve, and
   only then does the dialog close. Before this the entrance animated and
   every way out snapped. */
.qw-nav-drawer[open].is-closing {
  transform: translateX(-100%);
  opacity: 0;
  transition: transform 300ms var(--ease-state), opacity 300ms var(--ease-state);
}
/* --stagger (opt-in): the links enter one after another once the panel is
   in, 45ms apart from 120ms, each li carrying --qw-nav-drawer-i. */
.qw-nav-drawer--stagger[open] .qw-nav-drawer__links > li {
  animation: qw-nav-drawer-item 520ms var(--ease-reveal) both;
  animation-delay: calc(120ms + var(--qw-nav-drawer-i, 0) * 45ms);
}
.qw-nav-drawer--stagger[open].is-closing .qw-nav-drawer__links > li { animation: none; }
@keyframes qw-nav-drawer-item { from { opacity: 0; transform: translateX(-14px); } to { opacity: 1; transform: none; } }
.qw-nav-drawer__inner {
  min-height: 100%;
  padding: var(--space-lg) var(--space-lg) var(--space-xl);
  display: flex;
  flex-direction: column;
  gap: 32px;
}
.qw-nav-drawer__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
}
.qw-nav-drawer__head img { height: 32px; width: auto; }
.qw-nav-drawer__close {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 42px;
  height: 42px;
  padding: 0;
  color: color-mix(in srgb, var(--color-ink) 76%, transparent);
  background: rgb(255 255 255 / 0.06);
  border: 1px solid rgb(255 255 255 / 0.14);
  border-radius: var(--radius-sm);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.qw-nav-drawer__close svg { width: 20px; height: 20px; fill: none; }
.qw-nav-drawer__close:active { background: rgb(255 255 255 / 0.13); }

.qw-nav-drawer__links { display: flex; flex-direction: column; margin: 0; padding: 0; list-style: none; }
.qw-nav-drawer__links li { border-bottom: 1px solid var(--color-line-soft); }
.qw-nav-drawer__links a {
  display: block;
  padding-block: 20px;
  font-size: 18px;
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--color-ink);
  text-decoration: none;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: color var(--dur-fast) var(--ease-state), padding-left var(--dur-fast) var(--ease-state);
}
.qw-nav-drawer__links a:active { color: var(--color-accent); padding-left: 6px; }
.qw-nav-drawer__links li.qw-nav-drawer__group { border-bottom: none; }

.qw-nav-drawer__sub-trigger {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-md);
  padding: 20px 0;
  background: none;
  border: 0;
  border-bottom: 1px solid var(--color-line-soft);
  border-radius: 0;
  font-family: inherit;
  font-size: 18px;
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--color-ink);
  text-align: left;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: color var(--dur-fast) var(--ease-state);
}
.qw-nav-drawer__sub-trigger:active { color: var(--color-accent); }
.qw-nav-drawer__caret {
  width: 13px;
  height: 9px;
  flex: none;
  color: color-mix(in srgb, var(--color-ink) 54%, transparent);
  transition: transform var(--dur) var(--ease-emph);
}
.qw-nav-drawer__group.is-open > .qw-nav-drawer__sub-trigger { color: var(--color-accent); }
.qw-nav-drawer__group.is-open .qw-nav-drawer__caret { transform: rotate(180deg); color: var(--color-accent); }

.qw-nav-drawer__sub { display: none; flex-direction: column; margin: 0; padding: 0; list-style: none; }
.qw-nav-drawer__group.is-open > .qw-nav-drawer__sub { display: flex; }
.qw-nav-drawer__sub li { border-bottom: 1px solid var(--color-line-soft); }
.qw-nav-drawer__sub li:last-child { border-bottom: none; }
.qw-nav-drawer__sub a {
  padding-block: var(--space-md);
  padding-left: var(--space-md);
  font-size: 15px;
  font-weight: 500;
  color: color-mix(in srgb, var(--color-ink) 76%, transparent);
}
.qw-nav-drawer__sub a:active { color: var(--color-accent); padding-left: calc(var(--space-md) + 6px); }

@media (prefers-reduced-motion: reduce) {
  .qw-nav-drawer[open], .qw-nav-drawer[open].is-closing { transition: none; }
  .qw-nav-drawer--stagger[open] .qw-nav-drawer__links > li { animation: none; }
}

/* ---- css/v1/components/nav-fab.css ---- */
/* ==========================================================================
   Quality Web Library, v1 (candidate, harvested 2026-09-11)
   qw-nav-fab: the mobile circle hamburger and its full-screen overlay menu

   Source (proposed): cdn.brandquality.com/css/v1/components/nav-fab.css
   Requires tokens.css. Pair with nav-fab.js (open, close, scroll lock,
   active item) and motion.js (the links carry data-target, no href).

   House pattern from the national-urban-league/conference/2026/ull review
   page, read here from rcoc/campaign/identity (.nav-fab, .mobile-menu,
   .mobile-menu-links, body.menu-open) and rcoc/campaign/naming (same
   selectors). The two RCOC pages disagree on four overlay values; the
   identity values are the ones below and both sets are in the README.

   THE RULES (read from the source comments)
   - Below 900px the sticky bar is hidden and the circle takes over: a
     six-item bar either wraps into a tall block or scrolls sideways, and
     both cost more than they give on a phone.
   - A page with no desktop bar (naming) still carries the circle: it ADDS
     navigation on a phone rather than replacing it.
   - The page must not scroll behind the overlay: body gets is-menu-open,
     and Lenis is stopped while the overlay is open.
   - Dark chrome, fixed on purpose like the review subnav: it is not a
     brand decision. Only the active colour reads the accent token.

   MARKUP
   <button class="qw-nav-fab" data-js="nav-fab" aria-label="Open menu"
           aria-expanded="false" aria-controls="qw-menu">
     <span></span><span></span><span></span>
   </button>
   <div class="qw-nav-fab__menu" id="qw-menu" data-js="nav-fab-menu" aria-hidden="true">
     <ul class="qw-nav-fab__links">
       <li><a data-target="#overview" role="link" tabindex="0">Overview</a></li>
     </ul>
   </div>

   MODIFIERS
   none. Shown under 900px only; a site that wants it at every width can
   override the media query in its own stylesheet.
   ========================================================================== */

.qw-nav-fab {
  display: none;
  position: fixed;
  top: 14px;
  right: 14px;
  z-index: 70;
  width: 46px;
  height: 46px;
  border-radius: 50%;
  padding: 0;
  cursor: pointer;
  background: rgba(16, 16, 16, .9);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  border: 1px solid var(--color-dark-line);
  box-shadow: 0 6px 18px rgba(0, 0, 0, .45);
}
.qw-nav-fab span {
  position: absolute;
  left: 13px;
  right: 13px;
  height: 2px;
  background: #fff;
  border-radius: 2px;
  transition: transform 300ms var(--ease-reveal), opacity 200ms var(--ease-reveal);
}
.qw-nav-fab span:nth-child(1) { top: 17px; }
.qw-nav-fab span:nth-child(2) { top: 22px; }
.qw-nav-fab span:nth-child(3) { top: 27px; }
.qw-nav-fab.is-open span:nth-child(1) { transform: translateY(5px) rotate(45deg); }
.qw-nav-fab.is-open span:nth-child(2) { opacity: 0; }
.qw-nav-fab.is-open span:nth-child(3) { transform: translateY(-5px) rotate(-45deg); }

.qw-nav-fab__menu {
  display: none;
  position: fixed;
  inset: 0;
  z-index: 60;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 34px;
  background: rgba(10, 10, 10, .97);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  opacity: 0;
  pointer-events: none;
  transition: opacity 320ms var(--ease-reveal);
}
.qw-nav-fab__menu.is-open { opacity: 1; pointer-events: auto; }

.qw-nav-fab__links {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 28px;
}
.qw-nav-fab__links a {
  color: #fff;
  text-decoration: none;
  font-size: 16px;
  font-weight: 700;
  letter-spacing: .2em;
  text-transform: uppercase;
  cursor: pointer;
  transition: color 200ms var(--ease-reveal);
}
.qw-nav-fab__links a.is-active { color: var(--color-accent); }
.qw-nav-fab__links a:active { color: var(--color-accent); }

/* the page must not scroll behind the overlay */
body.is-menu-open { overflow: hidden; }

@media (max-width: 900px) {
  .qw-nav-fab { display: block; }
  .qw-nav-fab__menu { display: flex; }
}

@media (prefers-reduced-motion: reduce) {
  .qw-nav-fab span, .qw-nav-fab__menu { transition: none !important; }
}

/* ---- css/v1/components/nav.css ---- */
/* ==========================================================================
   Quality Web Library, v1
   qw-nav: the sticky top bar, in two variants

   Source: cdn.brandquality.com/css/v1/components/nav.css
   Requires tokens.css. Pair with js/v1/nav.js for the toggle and scrollspy.

   VARIANT A  .qw-nav            site navigation: brand, links, actions, toggle
   VARIANT B  .qw-nav--sub       review-page subnav: in-page links, dot
                                 separators, active underline, scrollspy

   Variant B values are read from first-option/sacnas/2026,
   black-women-lawyers/installation/2026 and national-urban-league/ull,
   which agree (client-review-pages.md, "The exact values"). Copy them, do
   not re-derive them. No box-shadow: none of the three has one.

   MARKUP (variant A)
   <header class="qw-nav" data-js="nav">
     <div class="qw-nav__inner qw-container qw-container--wide">
       <a class="qw-nav__brand" href="/"><img src="..." alt="Client"></a>
       <nav class="qw-nav__links" aria-label="Primary">
         <ul><li><a href="/about/">About</a></li> ...</ul>
       </nav>
       <div class="qw-nav__actions"><a class="qw-btn qw-btn--sm" href="...">Donate</a></div>
       <button class="qw-nav__toggle" data-js="nav-toggle" aria-expanded="false" aria-controls="qw-nav-panel" aria-label="Open menu">
         <span></span><span></span><span></span>
       </button>
     </div>
     <div class="qw-nav__panel" id="qw-nav-panel"> ...mobile links... </div>
   </header>

   MARKUP (variant B, in-page links carry NO href per Standard 12)
   <nav class="qw-nav qw-nav--sub" data-js="subnav" aria-label="Sections">
     <div class="qw-nav__inner">
       <ul class="qw-nav__links">
         <li><a data-target="#concepts">Concepts</a></li>
         <li><a data-target="#video">Video</a></li>
       </ul>
     </div>
   </nav>
   ========================================================================== */

.qw-nav {
  position: sticky;
  top: 0;
  z-index: 60;
  background: color-mix(in srgb, var(--color-bg) 88%, transparent);
  -webkit-backdrop-filter: blur(12px);
  backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--color-line-soft);
}

.qw-nav__inner {
  display: flex;
  align-items: center;
  gap: 28px;
  min-height: var(--nav-h);
  padding-inline: var(--gutter);
  max-width: var(--container-wide);
  margin-inline: auto;
}

.qw-nav__brand { display: inline-flex; align-items: center; flex: 0 1 auto; min-width: 0; }
.qw-nav__brand img, .qw-nav__brand svg { width: auto; height: auto; max-height: 32px; max-width: 100%; }

.qw-nav__links { flex: 1 1 auto; min-width: 0; }
.qw-nav__links > ul,
ul.qw-nav__links {
  display: flex;
  align-items: center;
  gap: 0;
  margin: 0;
  padding: 0;
  list-style: none;
}
.qw-nav__links a {
  position: relative;
  display: inline-block;
  padding: 6px 0;
  color: var(--color-ink-muted);
  font-size: var(--text-label);
  font-weight: 700;
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  transition: color var(--dur-fast) var(--ease-state);
}
.qw-nav__links a::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: 1px;
  height: 2px;
  background: var(--color-accent);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 260ms var(--ease-state);
}
@media (hover: hover) {
  .qw-nav__links a:hover { color: var(--color-ink); }
  .qw-nav__links a:hover::after { transform: scaleX(1); }
}
.qw-nav__links a.is-active { color: var(--color-ink); }
.qw-nav__links a.is-active::after { transform: scaleX(1); }

/* Dot separators between links */
.qw-nav__links li + li::before {
  content: "";
  display: inline-block;
  width: 4px; height: 4px;
  margin: 0 18px;
  border-radius: 50%;
  background: var(--color-accent);
  vertical-align: middle;
}

.qw-nav__actions { display: flex; align-items: center; gap: var(--space-sm); margin-left: auto; flex: 0 0 auto; }

/* ---------- Mobile toggle and panel (variant A) ---------- */
.qw-nav__toggle {
  display: none;
  flex: 0 0 44px;            /* a flex item shrinks below its width; pin it */
  flex-direction: column;
  justify-content: center;
  gap: 5px;
  width: 44px; height: 44px;
  margin-left: auto;
  padding: 10px;
}
.qw-nav__toggle span {
  display: block;
  width: 24px;               /* the zero-width tap target trap: spans need a width */
  height: 2px;
  background: var(--color-ink);
  border-radius: 2px;
  transition: transform var(--dur-fast) var(--ease-state), opacity var(--dur-fast) var(--ease-state);
}
.qw-nav__toggle[aria-expanded="true"] span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.qw-nav__toggle[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
.qw-nav__toggle[aria-expanded="true"] span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

.qw-nav__panel {
  display: none;
  border-top: 1px solid var(--color-line-soft);
  padding: var(--space-md) var(--gutter) var(--space-lg);
}
.qw-nav__panel ul { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-sm); }
.qw-nav__panel a {
  display: block;
  padding: 10px 0;
  color: var(--color-ink);
  font-size: var(--text-md);
  font-weight: 600;
  text-decoration: none;
}
.qw-nav.is-open .qw-nav__panel { display: block; }

@media (max-width: 820px) {
  .qw-nav:not(.qw-nav--sub) .qw-nav__links { display: none; }
  .qw-nav:not(.qw-nav--sub) .qw-nav__toggle { display: inline-flex; }
  .qw-nav__actions { margin-left: auto; }
  .qw-nav__inner { gap: 12px; padding-inline: 16px; }
  .qw-nav__brand img, .qw-nav__brand svg { max-height: 28px; }
  .qw-nav__actions .qw-btn { font-size: 10.5px; padding: 7px 14px; gap: 6px; }
  .qw-nav__actions .qw-btn svg { width: 13px; height: 13px; }
}

/* ---------- Variant B: review-page subnav ---------- */
.qw-nav--sub {
  background: rgba(10, 10, 10, .84);
  border-top: 1px solid var(--color-dark-line-soft);
  border-bottom: 1px solid var(--color-dark-line-soft);
}
.qw-nav--sub .qw-nav__inner { padding-inline: 60px; }
.qw-nav--sub .qw-nav__links > ul,
.qw-nav--sub ul.qw-nav__links { flex-wrap: wrap; justify-content: center; row-gap: 6px; }
.qw-nav--sub .qw-nav__links a { color: var(--color-dark-muted); }
.qw-nav--sub .qw-nav__links a.is-active,
.qw-nav--sub .qw-nav__links a:hover { color: #fff; }

@media (max-width: 820px) {
  .qw-nav--sub .qw-nav__inner { padding: 12px 20px; gap: 16px; }
}
@media (max-width: 620px) {
  .qw-nav--sub .qw-nav__links li + li::before { margin: 0 11px; width: 3px; height: 3px; }
  .qw-nav--sub .qw-nav__links a { font-size: 10px; letter-spacing: .12em; }
}

/* Light-bodied page carrying the subnav (rcoc/campaign/review) */
.qw-nav--sub.qw-nav--light {
  background: rgba(255, 255, 255, .9);
  border-color: var(--color-line-soft);
}
.qw-nav--sub.qw-nav--light .qw-nav__links a { color: var(--color-ink-muted); }
.qw-nav--sub.qw-nav--light .qw-nav__links a.is-active,
.qw-nav--sub.qw-nav--light .qw-nav__links a:hover { color: var(--color-ink); }

/* ---- css/v1/components/photo-mosaic.css ---- */
/* ==========================================================================
   Quality Web Library, v1 (candidate, harvested 2026-09-11)
   qw-photo-mosaic: five photographs, one tall hero cell, captions on the image

   Source (proposed): cdn.brandquality.com/css/v1/components/photo-mosaic.css
   Requires tokens.css and motion.css/motion.js (the figures settle out of
   a slight push-in: the mosaic carries data-reveal-group and each figure
   data-reveal="scale-down"; the source stamped the 180ms stagger from JS).

   Ported from rcoc/campaign/pitch (.mosaic, .mosaic figure, img,
   figure::after, .is-hero, .is-plan, figcaption, the motion.css mosaic
   rule, the 768px rules).

   THE RULES (read from the source comments)
   - Two columns; from 900px three (1 / 1.35 / 1) in two rows at a fixed
     height, the hero cell spanning both rows in the middle.
   - Photographs desaturated and darkened under a bottom gradient;
     hover restores them and pushes in 4.5%.
   - A white-ground line drawing (a floor plan) is inverted so it reads
     as a blueprint (--plan).
   - Captions sit on the image, tracked uppercase.
   - Under 768px the hero leads full width and the rest sit two by two.

   MARKUP
   <div class="qw-photo-mosaic" data-reveal-group data-reveal-stagger="180">
     <figure class="qw-photo-mosaic__hero" data-reveal="scale-down"><img src="..." alt="..."><figcaption>Caption</figcaption></figure>
     <figure data-reveal="scale-down"><img ...><figcaption>Caption</figcaption></figure>
     ...
     <figure class="qw-photo-mosaic__plan" data-reveal="scale-down"><img ...><figcaption>Plan</figcaption></figure>
   </div>

   MODIFIERS
   .qw-photo-mosaic__hero   the tall middle cell
   .qw-photo-mosaic__plan   inverted line drawing
   ========================================================================== */

.qw-photo-mosaic {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-md);
  margin-top: 48px;
}
@media (min-width: 900px) {
  .qw-photo-mosaic {
    grid-template-columns: 1fr 1.35fr 1fr;
    grid-template-rows: repeat(2, minmax(0, 1fr));
    height: clamp(380px, 36vw, 580px);
  }
  .qw-photo-mosaic .qw-photo-mosaic__hero { grid-column: 2; grid-row: 1 / span 2; }
}
.qw-photo-mosaic figure {
  position: relative;
  overflow: hidden;
  margin: 0;
  border-radius: var(--radius-lg);
  background: var(--color-surface-dark);
  min-height: 170px;
}
.qw-photo-mosaic img {
  width: 100%; height: 100%;
  object-fit: cover;
  filter: saturate(0.62) brightness(0.82);
  transition: transform var(--dur-slow) var(--ease-emph), filter var(--dur-slow) var(--ease-state);
}
.qw-photo-mosaic figure::after {
  content: "";
  position: absolute; inset: 0;
  background: linear-gradient(180deg,
    color-mix(in srgb, var(--color-bg) 0%, transparent) 40%,
    color-mix(in srgb, var(--color-surface-dark) 72%, transparent) 100%);
  pointer-events: none;
}
.qw-photo-mosaic .qw-photo-mosaic__plan img { filter: invert(1) saturate(0) brightness(0.82) contrast(1.1); }
@media (hover: hover) {
  .qw-photo-mosaic figure:hover img { transform: scale(1.045); filter: saturate(0.9) brightness(0.95); }
  .qw-photo-mosaic .qw-photo-mosaic__plan:hover img { filter: invert(1) saturate(0) brightness(0.95) contrast(1.15); }
}
.qw-photo-mosaic figcaption {
  position: absolute;
  left: 20px; bottom: 20px;
  z-index: 2;
  font-size: clamp(13.5px, 0.88vw, 15px);
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.9);
}

/* the settle: 1800ms on the cinema curve, from scale(1.15) */
.qw-photo-mosaic figure[data-reveal="scale-down"].is-revealed {
  animation-duration: 1800ms;
  animation-timing-function: var(--ease-cinema);
}

@media (max-width: 768px) {
  .qw-photo-mosaic { grid-template-columns: repeat(2, 1fr); }
  .qw-photo-mosaic .qw-photo-mosaic__hero { grid-column: 1 / -1; }
}

/* ---- css/v1/components/sample-card.css ---- */
/* ==========================================================================
   Quality Web Library, v1 (candidate, harvested 2026-09-11)
   qw-sample-card: the inspiration-review sample frame

   Source (proposed): cdn.brandquality.com/css/v1/components/sample-card.css
   Requires tokens.css. No JS.

   Ported from nba-region-ix/_inspiration-review.html page furniture
   (.sample, .sample__header, .tag, .badge-new, .badge-fix, .badge-primary,
   .sample__note, .sample__demo, .sample__demo--light,
   .sample__demo--cream).

   THE RULES
   - A surface card, 12px radius, 32px padding, 24px above the previous.
     Header: the numbered h3 and a mono 11px tag (component, scroll,
     motion...) on a baseline row that wraps.
   - Badges after the title: --new (primary fill), --fix (18% accent wash),
     --primary (accent fill); 10px / 700 uppercase pills.
   - The demo well: 24px above, 32px padding, 8px radius, page colour;
     --light is white with dark ink, --cream is the warm paper.
   - The note: 13px muted, ruled above, 16px.

   MARKUP
   <div class="qw-sample-card">
     <div class="qw-sample-card__header">
       <h3>1 &middot; Sample title <span class="qw-sample-card__badge qw-sample-card__badge--fix">v6.2: what changed</span></h3>
       <span class="qw-sample-card__tag">component &middot; deployed</span>
     </div>
     <p>One line on what to look at.</p>
     <div class="qw-sample-card__demo"> ... the live sample ... </div>
     <p class="qw-sample-card__note">Notes on the sample.</p>
   </div>

   MODIFIERS
   .qw-sample-card__badge--new primary fill
   .qw-sample-card__badge--fix 18% accent wash
   .qw-sample-card__badge--primary accent fill
   .qw-sample-card__demo--light white well
   .qw-sample-card__demo--cream warm paper well
   ========================================================================== */

.qw-sample-card {
  border: 1px solid var(--color-line-soft);
  border-radius: var(--radius-lg);
  padding: 32px;
  background: var(--color-surface);
  margin-top: 24px;
}
.qw-sample-card__header {
  display: flex; justify-content: space-between; align-items: baseline;
  margin-bottom: 8px;
  gap: 16px;
  flex-wrap: wrap;
}
.qw-sample-card__header h3 { color: var(--color-ink); margin: 0; font-family: var(--font-heading); font-size: 24px; line-height: 1.25; font-weight: 600; }
.qw-sample-card__tag { font-family: var(--font-mono); font-size: 11px; color: color-mix(in srgb, var(--color-ink) 45%, transparent); white-space: nowrap; }
.qw-sample-card__badge {
  padding: 2px 8px;
  border-radius: 10px;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  margin-left: 6px;
  font-family: var(--font-body);
  vertical-align: middle;
}
.qw-sample-card__badge--new { background: var(--color-primary); color: var(--color-on-primary); }                              /* crimson-500 / tan-100 */
.qw-sample-card__badge--fix { background: color-mix(in srgb, var(--color-accent) 18%, transparent); color: var(--color-link); }  /* rgba(237,208,160,.18) / tan-300 */
.qw-sample-card__badge--primary { background: var(--color-accent); color: var(--color-on-accent); }                              /* tan-200 / wine-800 */
.qw-sample-card > p { color: var(--color-ink-muted); margin: 0 0 16px; }
.qw-sample-card__note {
  font-size: 13px;
  color: color-mix(in srgb, var(--color-ink) 45%, transparent);
  margin: 16px 0 0;
  padding-top: 16px;
  border-top: 1px solid var(--color-line-soft);
}
.qw-sample-card__demo {
  margin-top: 24px;
  padding: 32px;
  border-radius: var(--radius-md);
  background: var(--color-bg);                  /* --bg-surface-tint = wine-800 */
}
.qw-sample-card__demo--flush { padding: 0; }
.qw-sample-card__demo--light { background: #FFFFFF; color: #1B181C; }   /* fixed: a white well inside a dark page */
.qw-sample-card__demo--light * { color: inherit; }
.qw-sample-card__demo--cream { background: #FDF9ED; color: #1B181C; }   /* tan-25 */
.qw-sample-card__demo--cream * { color: inherit; }
@media (max-width: 640px) {
  .qw-sample-card { padding: 20px; }
  .qw-sample-card__demo { padding: 20px; }
  .qw-sample-card__demo--flush { padding: 0; }
}

/* ---- css/v1/components/sublabel.css ---- */
/* ==========================================================================
   Quality Web Library, v1 (candidate, harvested 2026-09-11, merged from
   the review-pages and rest harvests)
   qw-sublabel: the tracked uppercase label with a hairline running out to
   the right, and an optional bracketed tag

   Source (proposed): cdn.brandquality.com/css/v1/components/sublabel.css
   Requires tokens.css. No JS. May carry data-reveal for motion.js (the
   reel pages do).

   Read from seven pages on five properties, all shipping .sub-label,
   .lbl, .tag and ::after with the same values:
   - black-women-lawyers/installation/2026 (plus the 560px wrap)
   - first-option/sacnas/2026 (plus .sub-label--sub and the scroll margin)
   - first-option/nsbe/2026 (same as SACNAS without --sub)
   - national-urban-league/conference/2026/ull and /virtual (no phone rule)
   - rareco/wellsfargo/jd and bq-work/screengfx (margin-top 0: the label
     opens the band on a reel page; data-reveal on the row)
   Every size, weight, tracking and colour agrees across the seven. The
   only value that differs is the top margin: 40px on five pages, 0 on the
   two reel pages (carried as --first). Only First Option sets the scroll
   margin; only SACNAS ships --sub.

   THE RULES (read from the source)
   - It labels one piece of work inside a band: the deliverable name, then
     the placement in brackets, then a hairline to the edge. It is the
     second level under the rule title (qw-rule-title) on a review page,
     or the one heading over the single asset on a reel page.
   - 14px / 700 / .3em uppercase. The tag is 12px / 400 / .24em in the
     muted colour, 8px after the name. The hairline is flex: 1.
   - 40px above, 26px below. The first one in a band, or one that opens a
     grid column, drops its top margin (the sources did this per grid
     class; here it is the --first modifier and the :first-child rule).
   - Under 560px the name wraps, tracks .2em at 12.5px, and the tag drops
     to its own line at 10.5px.
   - A sub-label nested under another one steps down (--sub): 11px / .24em
     in the muted colour, 18px below. The group label leads; the per-item
     labels read as its children (SACNAS presentation samples).

   MARKUP
   <div class="qw-sublabel" id="projection" data-reveal>
     <span class="qw-sublabel__name">Projection screen<span class="qw-sublabel__tag">[ Center ]</span></span>
   </div>

   MODIFIERS
   .qw-sublabel--first   no top margin (opens a band or a grid column;
                         the reel pages' default)
   .qw-sublabel--sub     the nested, quieter size
   ========================================================================== */

.qw-sublabel {
  display: flex;
  align-items: center;
  gap: 18px;
  margin: 40px 0 26px;                            /* bwl, sacnas, nsbe, ull, virtual; jd and screengfx ship 0 above (--first) */
  scroll-margin-top: calc(var(--nav-h) + 24px);   /* first-option: a subnav target lands 24px under the bar */
}
.qw-sublabel::after {
  content: "";
  height: 1px;
  background: var(--color-line-soft);
  flex: 1;
}
.qw-sublabel:first-child,
.qw-sublabel--first { margin-top: 0; }

.qw-sublabel__name {
  font-size: var(--text-sm);        /* 14px on all seven */
  font-weight: 700;
  letter-spacing: .3em;
  text-transform: uppercase;
  white-space: nowrap;
  color: var(--color-ink);
}
.qw-sublabel__tag {
  font-weight: 400;
  font-size: var(--text-xs);        /* 12px on all seven */
  color: var(--color-ink-muted);
  margin-left: 8px;
  letter-spacing: .24em;
}

/* ---------- nested size (sacnas) ---------- */
.qw-sublabel--sub { margin-bottom: 18px; }
.qw-sublabel--sub .qw-sublabel__name {
  font-size: 11px;
  letter-spacing: .24em;
  color: var(--color-ink-muted);
}

/* bwl, sacnas, nsbe, jd, screengfx; NUL has no phone rule */
@media (max-width: 560px) {
  .qw-sublabel__name { white-space: normal; letter-spacing: .2em; font-size: var(--text-label); }   /* 12.5px */
  .qw-sublabel__tag { display: block; margin: 6px 0 0; font-size: 10.5px; }
  .qw-sublabel--sub .qw-sublabel__name { font-size: 10.5px; letter-spacing: .18em; }
}

/* ---- css/v1/components/toc-grid.css ---- */
/* ==========================================================================
   Quality Web Library, v1 (candidate, harvested 2026-09-11)
   qw-toc-grid: numbered table-of-contents tiles

   Source (proposed): cdn.brandquality.com/css/v1/components/toc-grid.css
   Requires tokens.css and motion.js (in-page links carry data-target, no href).

   Ported from nba-region-ix/_inspiration-review.html page furniture (.toc,
   .toc a, .toc a span.num).

   THE RULES
   - A four-across grid (one column under 768px) of bordered tiles, 12px
     apart, 48px above: 14px 16px padding, 8px radius, 13px ink text on a 2%
     ink wash, a mono 11px accent number before the label.
   - Hover: 5% wash and the strong line, 200ms.

   MARKUP
   <nav class="qw-toc-grid" aria-label="Sections">
     <a data-target="#updated" role="link" tabindex="0"><span class="qw-toc-grid__num">01</span>Updated samples</a>
   </nav>

   MODIFIERS
   none.
   ========================================================================== */

.qw-toc-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 12px;
  margin-top: 48px;
}
.qw-toc-grid a {
  border: 1px solid var(--color-line-soft);
  border-radius: var(--radius-md);
  padding: 14px 16px;
  font-family: var(--font-body);
  font-size: 13px;
  color: var(--color-ink);
  background: color-mix(in srgb, var(--color-ink) 2%, transparent);   /* rgba(255,255,255,.02) */
  text-decoration: none;
  cursor: pointer;
  transition: background 200ms ease, border-color 200ms ease;
}
@media (hover: hover) {
  .qw-toc-grid a:hover { background: color-mix(in srgb, var(--color-ink) 5%, transparent); border-color: var(--color-line); color: var(--color-ink); }
}
.qw-toc-grid__num { color: var(--color-accent); font-family: var(--font-mono); font-size: 11px; margin-right: 8px; }
@media (max-width: 768px) {
  .qw-toc-grid { grid-template-columns: 1fr; }
}

/* ---- css/v1/sections/review-header.css ---- */
/* ==========================================================================
   Quality Web Library, v1 (candidate, harvested 2026-09-11)
   qw-review-header: the BQ review-page header band

   Source (proposed): cdn.brandquality.com/css/v1/sections/review-header.css
   Requires tokens.css. No JS. Usually followed by qw-nav--sub.

   Read from rcoc/campaign/identity (header.hero, .stack, .bq-mark,
   .bq-mark--header, .header-rule, .clientmark, .page-title, .page-kicker,
   the hero-rise-in choreography), which ported it unchanged from
   campaign/phase1, which took it from the SACNAS and BWL builds. The
   source comment: "Values kept, not approximated".

   THE RULES (read from the source comments)
   - Black-to-charcoal band, the BQ mark, a hairline divider, the client
     mark LARGER than the BQ mark (this is the client's page), the project
     title flanked by hairlines, a gold kicker.
   - Five-step entrance choreography on load: mark, rule, client mark,
     title, kicker, 900ms each on the reveal curve, 100 to 700ms apart.
   - Dark chrome shared by every client review page: the band values read
     the review-page tokens (--color-black, --color-header-end,
     --color-dark-line, --color-dark-line-soft), not the brand.

   MARKUP
   <header class="qw-review-header">
     <div class="qw-container qw-review-header__stack">
       <div class="qw-review-header__bq">
         <a href="https://brandquality.com/" target="_blank" rel="noopener" aria-label="Brand Quality">
           <img src="https://cdn.brandquality.com/brand/bq-hztl-white.png" alt="Brand Quality">
         </a>
       </div>
       <div class="qw-review-header__rule"></div>
       <img class="qw-review-header__client" src="..." alt="Client">
       <div class="qw-review-header__title">
         <div class="qw-review-header__ln"></div>
         <h1>Project title</h1>
         <div class="qw-review-header__ln"></div>
       </div>
       <p class="qw-review-header__kicker">Section name</p>
     </div>
   </header>

   MODIFIERS
   none yet.
   ========================================================================== */

.qw-review-header {
  background: linear-gradient(var(--color-black), var(--color-header-end));
  border-bottom: 1px solid var(--color-dark-line-soft);
  padding: 52px 0 40px;
}
.qw-review-header__stack { display: flex; flex-direction: column; align-items: center; }

/* the BQ mark is the smaller of the two: this is the client's page */
.qw-review-header__bq a { display: inline-block; position: relative; }
.qw-review-header__bq img { display: block; height: auto; opacity: .95; width: 158px; max-width: 48vw; }

.qw-review-header__rule {
  width: min(440px, 60%);
  height: 1px;
  background: var(--color-dark-line-soft);
  margin: 24px auto 30px;
}

.qw-review-header__client { width: 250px; max-width: 70vw; height: auto; }

.qw-review-header__title {
  margin-top: 28px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 22px;
  width: 100%;
}
.qw-review-header__ln { height: 1px; background: var(--color-dark-line); flex: 1; max-width: 200px; }
.qw-review-header__title h1 {
  margin: 0;
  font-size: clamp(15px, 2.35vw, 26px);
  font-weight: 800;
  color: #ffffff;
  letter-spacing: .2em;
  text-transform: uppercase;
  text-align: center;
  white-space: nowrap;
}

.qw-review-header__kicker {
  margin: 14px 0 0;
  text-align: center;
  font-size: 11px;
  font-weight: 800;
  letter-spacing: .3em;
  text-transform: uppercase;
  color: var(--color-accent);
}

/* ---------- entrance choreography ---------- */
.qw-review-header__bq,
.qw-review-header__rule,
.qw-review-header__client,
.qw-review-header__title,
.qw-review-header__kicker {
  opacity: 0;
  animation: qw-review-header-rise 900ms var(--ease-reveal) forwards;
}
.qw-review-header__bq     { animation-delay: 100ms; }
.qw-review-header__rule   { animation-delay: 260ms; }
.qw-review-header__client { animation-delay: 420ms; }
.qw-review-header__title  { animation-delay: 580ms; }
.qw-review-header__kicker { animation-delay: 700ms; }
@keyframes qw-review-header-rise {
  from { opacity: 0; transform: translateY(16px); }
  to   { opacity: 1; transform: translateY(0); }
}

@media (prefers-reduced-motion: reduce) {
  .qw-review-header__bq, .qw-review-header__rule, .qw-review-header__client,
  .qw-review-header__title, .qw-review-header__kicker {
    opacity: 1 !important; transform: none !important; animation: none !important;
  }
}

@media print {
  .qw-review-header { background: #fff; color: #000; }
  .qw-review-header__title h1, .qw-review-header__kicker { color: #000; }
}

/* ---- css/v1/sections/stat-row.css ---- */
/* ==========================================================================
   Quality Web Library, v1 (candidate, harvested 2026-09-11)
   qw-stat-row: a hairline band of big figures with small labels

   Source (proposed): cdn.brandquality.com/css/v1/sections/stat-row.css
   Requires tokens.css. Pair with stat-row.js for the count-up
   (data-count on a figure; figures in one row share one clock).

   Ported from rcoc/campaign/pitch (.stats, .stats--three, .stat__num,
   .stat__label, the 768px rules).

   THE RULES
   - A hairline top and bottom; two columns on a phone, four from 860px
     (three with --three, and the last of three spans both columns under
     768px).
   - The figure: 800 weight, tabular, tight, in its own colour; the label
     under it in the tertiary tone. A figure can set its own size
     (--qw-stat-size) for a date or a phrase.

   MARKUP
   <div class="qw-stat-row qw-stat-row--three" data-js="stat-row">
     <div class="qw-stat" style="--qw-accent: var(--color-accent)">
       <span class="qw-stat__num" data-count="1800000" data-prefix="$">$1,800,000</span>
       <span class="qw-stat__label">Goal</span>
     </div>
   </div>

   MODIFIERS
   .qw-stat-row--three   three across from 860px
   .qw-stat-row--strip   no gaps, a hairline between cells, 26px 22px cells
                         (lifecommunitycenter, harvested 2026-09-22)
   ========================================================================== */

.qw-stat-row {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--space-xl) 32px;
  margin-block: var(--space-2xl);
  padding-block: var(--space-xl);
  border-top: 1px solid var(--color-line);
  border-bottom: 1px solid var(--color-line);
}
@media (min-width: 860px) {
  .qw-stat-row { grid-template-columns: repeat(4, 1fr); }
  .qw-stat-row--three { grid-template-columns: repeat(3, 1fr); gap: var(--space-xl) 48px; }
}

.qw-stat__num {
  display: block;
  font-size: var(--qw-stat-size, clamp(26px, 2.5vw, 44px));
  font-weight: 800;
  line-height: 1;
  letter-spacing: -0.035em;
  color: var(--qw-accent, var(--color-accent));
  font-variant-numeric: tabular-nums;
}
.qw-stat__label {
  display: block;
  margin-top: var(--space-md);
  font-size: clamp(13.5px, 0.88vw, 15px);
  font-weight: 600;
  letter-spacing: 0.06em;
  color: color-mix(in srgb, var(--color-ink) 54%, transparent);
  line-height: 1.45;
}

@media (max-width: 768px) {
  .qw-stat-row { grid-template-columns: repeat(2, 1fr); gap: 32px 20px; }
  .qw-stat-row--three { grid-template-columns: repeat(2, 1fr); }
  .qw-stat-row--three .qw-stat:last-child { grid-column: 1 / -1; }
}

/* ---------- Strip: the cells touch, a hairline between them ----------
   Second campaign on the row (lifecommunitycenter, 2026-09-22): four facts
   as a hairline strip, no gap, each cell 26px 22px with a hairline on its
   right; two by two under 640px with the hairlines re-sorted. */
.qw-stat-row--strip { gap: 0; padding-block: 0; margin-block: clamp(32px, 4vw, 48px) 0; }
.qw-stat-row--strip .qw-stat { padding: 26px 22px; border-right: 1px solid var(--color-line); }
.qw-stat-row--strip .qw-stat:last-child { border-right: 0; }
@media (max-width: 640px) {
  .qw-stat-row--strip { grid-template-columns: 1fr 1fr; }
  .qw-stat-row--strip .qw-stat:nth-child(2) { border-right: 0; }
  .qw-stat-row--strip .qw-stat:nth-child(-n+2) { border-bottom: 1px solid var(--color-line); }
}

/* ---- public/fonts/fonts.css (the site's own type) ---- */
/* LIFE Community Center · self-hosted type (Standard 21, Oct 19, 2026).
   Montserrat, the site's one face, served from this site instead of Google
   Fonts so Safari never waits on another host before its first paint.
   Source: the Fontsource package @fontsource-variable/montserrat 5.3.0, the
   latin subset, unmodified (every character on the site is in it). SIL Open
   Font License 1.1, licence beside the file (OFL-montserrat.txt). One
   variable file carries every weight the site uses (300 to 900); italics are
   synthesized by the browser, exactly as they were from Google, which served
   no italic for this site.
   url()s are root-relative because this file is bundled into /css/qw-lib.css
   by bq-cdn/tools/bundle.py; it is not linked on its own. */

@font-face {
  font-family: "Montserrat"; font-style: normal; font-weight: 100 900; font-display: swap;
  src: url("/fonts/montserrat-latin-wght-normal.woff2?v=1") format("woff2-variations"), url("/fonts/montserrat-latin-wght-normal.woff2?v=1") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
