/* Quality Web Library bundle: built by bq-cdn/tools/bundle.py from bq-cdn d42a76f 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/form-field.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/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); }

/* ---- public/fonts/fonts.css (the site's own type) ---- */
/* RareCo Creative · self-hosted type (Oct 5, 2026).
   Served from this site, not from Google, so every browser gets the same
   files, nothing a privacy setting or blocker can strip, and no third-party
   request on page load. Both faces are SIL Open Font License 1.1 (licences
   beside the files). Source: the Fontsource packages (@fontsource/instrument-serif
   5.x, @fontsource-variable/archivo 5.x), latin subset.
   Panchang joined Oct 18, 2026: the official variable WOFF2 from the Fontshare
   download (unmodified, renamed only; ITF Free Font License, which permits and
   recommends self-hosting on your own site, beside the file). It replaced the
   api.fontshare.com stylesheet, which made Safari wait on two other hosts
   before its first paint.
   url()s are root-relative because this file is bundled into /css/qw-lib.css
   (bq-cdn/tools/bundle.py); it is no longer linked on its own. */

@font-face {
  font-family: "Instrument Serif"; font-style: italic; font-weight: 400; font-display: swap;
  src: url("/fonts/instrument-serif-latin-400-italic.woff2?v=1") format("woff2");
}
@font-face {
  font-family: "Instrument Serif"; font-style: normal; font-weight: 400; font-display: swap;
  src: url("/fonts/instrument-serif-latin-400-normal.woff2?v=1") format("woff2");
}
/* one variable file carries every weight (100 to 900) and width (62% to 125%) */
@font-face {
  font-family: "Archivo"; font-style: normal; font-weight: 100 900; font-stretch: 62% 125%; font-display: swap;
  src: url("/fonts/archivo-latin-wdth-normal.woff2?v=1") format("woff2-variations"), url("/fonts/archivo-latin-wdth-normal.woff2?v=1") format("woff2");
}
/* Panchang: one variable file, weights 200 to 800 (the page uses 300, 700 and 800) */
@font-face {
  font-family: "Panchang"; font-style: normal; font-weight: 200 800; font-display: swap;
  src: url("/fonts/panchang-variable.woff2?v=1") format("woff2-variations"), url("/fonts/panchang-variable.woff2?v=1") format("woff2");
}
