/* ==========================================================================
   Broad Risk Insurance Brokers — reset, base elements, shared components
   --------------------------------------------------------------------------
   Depends on tokens.css. Load tokens.css FIRST.

   What lives here: things every section needs and nobody should build twice
   — the reset, base typography, the container, and the five components that
   repeat across the page (button, card, eyebrow, field, icon circle).

   What does NOT live here: anything section-specific. If only one section
   needs it, it belongs in that section's stylesheet.
   ========================================================================== */

/* ==========================================================================
   1. RESET
   ========================================================================== */

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

html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  -moz-tab-size: 4;
  tab-size: 4;
  scroll-behavior: smooth;
  /* The reference sets a scroll offset so anchored sections clear the header. */
  scroll-padding-top: calc(var(--br-nav-h) + var(--br-space-4));
}

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

body,
h1, h2, h3, h4, h5, h6,
p, figure, blockquote, dl, dd, ul, ol, pre { margin: 0; }

ul[role="list"],
ol[role="list"] { list-style: none; padding: 0; }

body {
  min-height: 100vh;
  background: var(--br-bg);
  color: var(--br-text);
  font-family: var(--br-font-body);
  font-size: var(--br-body-size);
  line-height: var(--br-body-lh);
  letter-spacing: var(--br-body-ls);
  font-weight: var(--br-weight-regular);
  /* Measured on the reference. Without this our type renders visibly heavier
     than the reference on macOS — it is the single biggest giveaway in a
     side-by-side. Do not remove. */
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  /* text-rendering is deliberately left at "auto", which is what the
     reference computes. optimizeLegibility was tried here and removed:
     across a 1px viewport sweep it moved no line width anywhere on the
     page, so it bought zero fidelity while forcing the kerning and
     ligature processing that has a known history of layout jank on large
     display type. Don't reintroduce it. */
  overflow-x: hidden;
}

img, picture, video, canvas, svg {
  display: block;
  max-width: 100%;
}

img, video { height: auto; }

svg { flex-shrink: 0; }

input, button, textarea, select {
  font: inherit;
  letter-spacing: inherit;
  color: inherit;
}

button { background: none; border: 0; padding: 0; cursor: pointer; }

a { color: inherit; }

table { border-collapse: collapse; border-spacing: 0; }

hr {
  height: 0;
  color: inherit;
  border: 0;
  border-top: 1px solid var(--br-border);
  margin: 0;
}

::selection {
  background: var(--br-gold);
  color: var(--br-ink);
}

/* ==========================================================================
   2. BASE TYPOGRAPHY
   Headings default to the Inter 600 scale, which is what the reference uses
   for every section heading. Display headings (Archivo 800) are opt-in via
   the .br-display-* classes — they are a deliberate, sparing choice.
   ========================================================================== */

h1, h2, h3, h4, h5, h6 {
  color: var(--br-text-heading);
  font-family: var(--br-font-body);
  font-weight: var(--br-heading-weight);
  text-wrap: balance;
  /* Guard against a token that cannot wrap — a pasted URL, a German compound,
     an unspaced product name.

     What this does NOT do, despite the obvious guess: it does not stop the
     page scrolling sideways. `body { overflow-x: hidden }` above already does
     that, and it works — measured with a 70-character unbreakable token in
     this heading at 390 and 1440, `window.scrollTo(9999, 0)` leaves scrollX at
     0 in both. (`documentElement.scrollWidth` DOES read 1245 in that state,
     which looks alarming and means nothing: it reports content bounds, not
     scrollability. Don't diagnose off it.)

     What it does is stop the word being clipped away and LOST. Without it the
     overflowing text is simply invisible past the viewport edge, which is the
     reference's behaviour and fails WCAG 1.4.4 at 200% zoom. Breaking it keeps
     it readable.

     `break-word`, NOT `anywhere`: `anywhere` also shrinks the element's
     min-content size, which would let a grid track collapse under a heading.
     `break-word` only affects the break itself and is inert until a line
     genuinely cannot fit — verified across all 14 sections at
     320/390/768/1024/1440/1920: not one line box moved. */
  overflow-wrap: break-word;
}

h1 {
  font-size: var(--br-h2-lg-size);
  line-height: var(--br-h2-lg-lh);
  letter-spacing: var(--br-h2-lg-ls);
}

h2 {
  font-size: var(--br-h2-size);
  line-height: var(--br-h2-lh);
  letter-spacing: var(--br-h2-ls);
}

h3 {
  font-size: var(--br-h3-size);
  line-height: var(--br-h3-lh);
  letter-spacing: var(--br-h3-ls);
}

h4, h5, h6 {
  font-size: var(--br-h4-size);
  line-height: var(--br-h4-lh);
  letter-spacing: var(--br-h4-ls);
}

/* Paragraphs break with the browser's default greedy algorithm.
   CORRECTED 2026-08-18 (renewal-section agent): this was `pretty`, which is
   a nicer default in the abstract but is NOT what we are reproducing — all
   14 paragraphs in the reference compute to `wrap`/`auto`. `pretty` reflows
   the last two lines to avoid an orphan, so wherever the reference happily
   leaves a short final line our rag silently differed. Caught on the renewal
   lead at 480px: reference ends "...caught out when it / counts.", `pretty`
   pulled the word down to "...caught out when / it counts." Same box, same
   font size, different rag — the sort of thing a blind side-by-side reads as
   "not the same page".
   Headings keep `balance` above: that IS measured on the reference.

   `overflow-wrap` is the same guard the headings carry — see the note there.
   Body copy needs it most: it is the text most likely to receive a pasted
   link, and unlike display type it is never art-directed to bleed, so there is
   no case where breaking a too-long token is the wrong answer. Verified inert
   on the shipped copy across all 14 sections. */
p { text-wrap: auto; overflow-wrap: break-word; }

strong, b { font-weight: var(--br-weight-semibold); color: var(--br-text-strong); }

small {
  font-size: var(--br-small-size);
  line-height: var(--br-small-lh);
  letter-spacing: var(--br-small-ls);
}

/* -- type utilities --------------------------------------------------------
   Section agents: use these instead of restating sizes. They are the ONLY
   sanctioned way to change type scale.
   -------------------------------------------------------------------------- */

.br-display-xl,
.br-display-lg,
.br-display-md {
  font-family: var(--br-font-display);
  font-weight: var(--br-display-weight);
  /* The declared weight (900) is one step above the heaviest face we load
     (800), which is exactly the situation an engine is allowed to answer by
     smearing the glyphs into a fake bold. Chrome does not, today, which is why
     this changes nothing measurable — heading ink is identical with and
     without it at 390/430/768/1440/1920, and the reference computes the same
     `none` on its own headings. It is here so that the day a different engine
     or font stack decides to synthesise, it cannot: the five display headings
     stay the 800 face Warren signed off. Belt to the token's brace. */
  font-synthesis-weight: none;
  line-height: var(--br-display-lh);
  letter-spacing: var(--br-display-ls);
  color: var(--br-text-heading);
  /* Display headings carry the page. Their line breaks are art-directed —
     balance them per-section with <br> or a max-width, not automatically. */
  text-wrap: initial;
  /* And they opt OUT of the break-word guard the h1–h6 rule sets. At this size
     an ordinary word is routinely wider than its own measure and is MEANT to
     bleed: the reference's "For businesses going places" is 89.14px type in a
     499.23px box, computes `overflow-wrap: normal`, and lets "businesses"
     (510.98px) hang 12px past the edge. That is the design, and the rebuilt
     testimonials heading reproduces it to the decimal.
     With break-word inherited, that same word breaks mid-stem into
     "businesse / s going" — measured, screenshotted, and far worse than the
     bleed it replaces. The page-level `overflow-x: hidden` already contains
     the pathological case, so nothing is at risk here. */
  overflow-wrap: normal;
}

.br-display-xl { font-size: var(--br-display-xl-size); }
.br-display-lg { font-size: var(--br-display-lg-size); }
.br-display-md { font-size: var(--br-display-md-size); }

.br-h2-lg {
  font-family: var(--br-font-body);
  font-size: var(--br-h2-lg-size);
  line-height: var(--br-h2-lg-lh);
  letter-spacing: var(--br-h2-lg-ls);
  font-weight: var(--br-heading-weight);
  color: var(--br-text-heading);
}

.br-h2 { font-size: var(--br-h2-size); line-height: var(--br-h2-lh); letter-spacing: var(--br-h2-ls); font-weight: var(--br-heading-weight); }
.br-h3 { font-size: var(--br-h3-size); line-height: var(--br-h3-lh); letter-spacing: var(--br-h3-ls); font-weight: var(--br-heading-weight); }
.br-h4 { font-size: var(--br-h4-size); line-height: var(--br-h4-lh); letter-spacing: var(--br-h4-ls); font-weight: var(--br-heading-weight); }

/* NO text-wrap HERE. It carried `pretty` for part of 2026-08-18 and was
   reverted the same day (testimonials agent) — this is the second time the
   same idea has been tried and measured back out, so the reasoning is written
   down properly rather than left as an absence.

   It is not a "beyond-reference win with no fidelity cost". It has a cost, and
   the sweep that cleared it only looked at one paragraph. Every lead paragraph
   on the reference computes text-wrap-style: auto — all fourteen of them,
   checked directly (_r6-lead.mjs), not inferred — so `pretty` is a divergence
   wherever it fires, and it fires more often than a single-element sweep sees.
   Caught on the testimonials rating line at 768: the reference sets "Rated 4.9
   ★ from 26 Google / reviews.", `pretty` pulled a word down to "…from 26 /
   Google reviews." Block height identical, rag different — which is precisely
   what a blind side-by-side reads as "not the same page", and it took the
   section's pixel divergence at 768 from 0.0041% to 0.1963%.

   This is the same conclusion the `p` rule below already records: it was
   `pretty` too, and the renewal agent removed it for the same reason at 480.
   A per-class re-introduction is the same bug with a narrower selector.

   If a specific stranded word is genuinely worth fixing, fix it in that
   section's own stylesheet against that section's own measurements, where the
   trade is visible to whoever makes it. Not here, for every lead on the
   page, on the strength of one. */
.br-lead {
  font-size: var(--br-body-lg-size);
  line-height: var(--br-body-lg-lh);
  letter-spacing: var(--br-body-lg-ls);
  color: var(--br-text);
}

.br-body { font-size: var(--br-body-size); line-height: var(--br-body-lh); letter-spacing: var(--br-body-ls); }
.br-body-sm { font-size: var(--br-body-sm-size); line-height: var(--br-body-sm-lh); letter-spacing: var(--br-body-sm-ls); }
.br-small { font-size: var(--br-small-size); line-height: var(--br-small-lh); letter-spacing: var(--br-small-ls); }
.br-muted { color: var(--br-text-muted); }

/* ==========================================================================
   3. LAYOUT PRIMITIVES
   ========================================================================== */

.br-container {
  width: 100%;
  max-width: var(--br-container-outer);
  margin-inline: auto;
  padding-inline: var(--br-gutter);
}

/* A narrow measure for centred intro copy. Measured on the reference:
   604px and 840px are the two constrained widths in use. */
.br-measure { max-width: var(--br-measure); }
.br-measure-wide { max-width: var(--br-measure-wide); }
.br-measure-center { margin-inline: auto; text-align: center; }

/* Vertical rhythm. Section agents put .br-section on the <section>. */
.br-section { padding-block: var(--br-section-y); }
.br-section-lg { padding-block: var(--br-section-y-lg); }
.br-section-top { padding-top: var(--br-section-y); }
.br-section-bottom { padding-bottom: var(--br-section-y); }

/* Surface helpers — pair with .br-on-dark / .br-on-gold from tokens.css. */
.br-surface-band { background: var(--br-bg-band); }
.br-surface-gold { background: var(--br-bg-gold); }
.br-surface-dark { background: var(--br-bg-dark); }

/* The one hairline in the system. */
.br-hairline { border: 0; border-top: 1px solid var(--br-border); }

/* ==========================================================================
   4. ACCESSIBILITY PRIMITIVES
   ========================================================================== */

.br-visually-hidden:not(:focus):not(:active) {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.br-skip-link {
  position: absolute;
  top: var(--br-space-2);
  left: var(--br-space-2);
  z-index: 999;
  transform: translateY(calc(-100% - var(--br-space-4)));
  padding: var(--br-space-3) var(--br-space-5);
  border-radius: var(--br-radius-pill);
  background: var(--br-gold);
  color: var(--br-ink);
  font-size: var(--br-ui-size);
  line-height: var(--br-ui-lh);
  font-weight: var(--br-ui-weight);
  letter-spacing: var(--br-ui-ls);
  text-decoration: none;
  box-shadow: var(--br-shadow-menu);
  transition: transform var(--br-dur) var(--br-ease);
}

.br-skip-link:focus { transform: translateY(0); }

/* Global focus treatment. Every interactive element gets a visible ring; the
   ring colour is a token, so it flips to gold inside .br-on-dark and stays
   ink inside .br-on-gold. Both directions clear WCAG contrast. */
:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
  /* 2px ring at 2px offset -- both measured off the reference. Deliberately
     NOT thickened: a 2px solid ring already meets WCAG 2.2 SC 2.4.13's "area
     of a 2px perimeter" minimum, and at 17.53:1 on white it clears the 3:1
     contrast requirement many times over. A 3px ring was tried and reverted
     -- it bought no accessibility headroom and was the only interactive-state
     value on the page that visibly differed from the signed-off design. */
  outline: 2px solid var(--br-focus);
  outline-offset: 2px;
  border-radius: var(--br-radius-xs);
}

/* ==========================================================================
   5. BUTTON
   Geometry measured off the reference: 48px tall, 11px/24px padding,
   16/24 Inter 600 at -0.011em, fully pilled.
   ========================================================================== */

.br-btn {
  --_btn-bg: transparent;
  --_btn-color: var(--br-text-strong);
  --_btn-border: transparent;

  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--br-space-2);

  /* DELIBERATE, PERMANENT DEPARTURE FROM THE REFERENCE -- do not "correct".
     The reference's button collapses to 34px tall at viewports <=320px, which
     fails the 44px minimum touch target (WCAG 2.5.5 / 2.5.8). We hold 48px at
     every width. This is the largest measured divergence from the reference
     anywhere in the rebuild, and it is on purpose.

     Breakpoint corrected 2026-08-18 (speak-section agent) from "<=336px":
     walked the reference one pixel at a time from 300 to 336 and it switches
     between 320 and 321 exactly, so the rule is max-width:320px. The old
     figure would have put the compensating rule below on the wrong side of
     three common phone widths. */
  min-height: var(--br-btn-h);
  padding: 11px var(--br-btn-px);

  font-family: var(--br-font-body);
  font-size: var(--br-ui-size);
  line-height: var(--br-ui-lh);
  font-weight: var(--br-ui-weight);
  letter-spacing: var(--br-ui-ls);
  text-align: center;
  text-decoration: none;
  white-space: nowrap;
  /* Measured 4.8px on the reference. Lives on the SHARED block, not on the
     underlined variants, so every variant is on the same footing. It is inert
     on a button that has no underline, but --ghost and --ghost-accent each
     used to declare it privately, which left --primary / --dark / --outline
     computing `auto`: the first one of those to gain an underline would have
     sat at the browser default offset next to ghosts sitting at 4.8px, on the
     same row, for no reason anybody could have found. */
  text-underline-offset: 4.8px;

  background: var(--_btn-bg);
  color: var(--_btn-color);
  border: 1px solid var(--_btn-border);
  border-radius: var(--br-radius-pill);

  cursor: pointer;
  appearance: none;
  /* The decoration properties are in the list because --ghost and
     --ghost-accent animate their underline on hover. Without them the label
     colour eased over 150ms while the underline SNAPPED from auto (~1px) to
     2px on the same hover — two properties, one gesture, two timings, and the
     eye catches the mismatch on the thicker of the two. text-decoration-color
     rides along so the underline cannot flash a stale colour mid-ease while
     `color` is still interpolating. */
  transition:
    background-color var(--br-dur) var(--br-ease),
    border-color var(--br-dur) var(--br-ease),
    color var(--br-dur) var(--br-ease),
    text-decoration-thickness var(--br-dur) var(--br-ease),
    text-decoration-color var(--br-dur) var(--br-ease);
}

.br-btn:focus-visible {
  /* Same 2px/2px as the global ring -- restated because .br-btn carries its
     own border-radius and would otherwise take the global rule's radius. */
  outline: 2px solid var(--br-focus);
  outline-offset: 2px;
}

/* -- variants ------------------------------------------------------------ */

/* Primary — the gold pill. Measured hover #d6ac00. */
.br-btn--primary {
  --_btn-bg: var(--br-gold);
  --_btn-border: var(--br-gold);
  --_btn-color: var(--br-ink);
  min-width: min(var(--br-btn-min-w), 100%);
}
.br-btn--primary:hover { --_btn-bg: var(--br-gold-hover); --_btn-border: var(--br-gold-hover); }
.br-btn--primary:active { --_btn-bg: var(--br-gold-active); --_btn-border: var(--br-gold-active); }

/* Dark — ink fill, used on the gold band where gold-on-gold would vanish.
   Measured hover #2b2305. */
.br-btn--dark {
  --_btn-bg: var(--br-ink);
  --_btn-border: var(--br-ink);
  --_btn-color: var(--br-white);
  min-width: min(var(--br-btn-min-w), 100%);
}
.br-btn--dark:hover { --_btn-bg: var(--br-ink-hover); --_btn-border: var(--br-ink-hover); }
.br-btn--dark:active { --_btn-bg: var(--br-ink-active); --_btn-border: var(--br-ink-active); }

/* Outline — hairline ink pill. Measured: on hover it FILLS with gold-hover
   rather than tinting, which is what makes the card CTAs feel deliberate. */
.br-btn--outline {
  --_btn-bg: transparent;
  --_btn-border: var(--br-border-strong);
  --_btn-color: var(--br-text-strong);
}
.br-btn--outline:hover {
  --_btn-bg: var(--br-gold-hover);
  --_btn-border: var(--br-gold-hover);
  --_btn-color: var(--br-ink);
}
.br-btn--outline:active { --_btn-bg: var(--br-gold-active); --_btn-border: var(--br-gold-active); }

/* Ghost — pill geometry, underlined label, no chrome until hover.
   The hover plate is a token, so it is transparent on white and a
   translucent white wash on photography (both measured).

   Thickness is left at `auto`, which is what the reference resolves to. Both
   render 1.00 CSS px, but a forced 1px lands the underline 2 device px lower
   at 3x — the reference occupies rows 104-106 and a forced value 106-108 —
   which reads as sub-pixel misregistration on retina. */
.br-btn--ghost {
  --_btn-bg: transparent;
  --_btn-border: transparent;
  --_btn-color: var(--br-text-strong);
  text-decoration: underline;
  /* text-underline-offset now lives on the shared .br-btn block above. */
}
/* On white the hover plate is transparent and the label only moves #1F1902 →
   #2B2305, a delta of ~3 in Lab — faithful to the reference, but invisible,
   and hover is an axis where this rebuild is meant to beat it. Thickening the
   underline is the idiom .br-link already uses, so the two read as one system.
   Rest state stays `auto`, so this is a real change in weight, not a no-op. */
.br-btn--ghost:hover {
  --_btn-bg: var(--br-ghost-hover-bg);
  --_btn-color: var(--br-ghost-hover-color);
  text-decoration-thickness: 2px;
}
/* Focus took the ring but not the label colour, which was a real divergence —
   caught by the round-2 state walk, not by any pixel diff, because a diff only
   ever sees the rest state.

   Measured on the reference's warren@broadrisk.com.au link, 1.5s settle per
   state: rest rgb(31,25,2) -> hover rgb(31,25,2) -> focus rgb(43,35,5). So the
   reference moves the label on FOCUS and, on this control, not on hover at all
   — the opposite way round from the assumption in the hover note above. Ours
   answered focus with the ring alone and left the label at rest colour.

   Written against --br-ghost-hover-color rather than --br-ink-hover directly.
   The two are the same #2b2305 on white, which is all the light-surface bar
   asks for, but the token is re-pointed to --br-white inside .br-on-photo /
   .br-on-dark. Hard-coding the ink value would put near-black on the hero
   photograph the moment someone tabs to a ghost button there — the one place
   the ring alone genuinely is not enough. Underline thickness stays `auto`:
   the reference does not thicken on focus, and hover already owns that signal.
   ------------------------------------------------------------------------- */
.br-btn--ghost:focus-visible { --_btn-color: var(--br-ghost-hover-color); }

/* PRESS. Deliberately the LAST of the three state rules, and deliberately
   unfenced. Both of those are fixes; both were the same bug wearing two hats.

   1. Unfenced. This used to read `--_btn-bg: var(--br-ghost-hover-bg)` with the
      real press plate quarantined in an @media (hover: none) block below, so on
      a light surface a mouse press resolved to `transparent`: the button
      answered hover beautifully and then went completely silent the moment you
      clicked it. Forced-state capture, mean ink per pixel over the button box —
      rest 18.444, press 18.444, bit-identical — against the reference's
      18.444 -> 44.384. It also contradicted itself, because the touch path DID
      paint a plate, and contradicted its own sibling .br-btn--ghost-accent,
      which has never been fenced. Input mode is not a design decision.

   2. Last, so it outranks :focus-visible above at equal specificity. Measured
      on the reference, focus and press held together:
          focus        label #2b2305, ring 2px
          focus+press  label #0e0f0c, ring 2px
      Press wins the label there and did not here, which meant a keyboard user
      holding Enter got the plate but not the label move — the same "goes silent
      on press" complaint, one input device further along. Order alone fixes it;
      no !important, no extra selector weight.

   Underline thickness is carried in so a touch user, who never sees :hover, gets
   the weight change a mouse user already gets on the way in. On desktop :active
   always arrives with :hover, so that declaration is a no-op there. */
.br-btn--ghost:active {
  --_btn-bg: var(--br-ghost-press-bg);
  --_btn-color: var(--br-ghost-press-color);
  text-decoration-thickness: 2px;
}

/* Ghost, gold label — the same button when it sits on ink.
   Measured hover colour #f8dc7a. */
.br-btn--ghost-accent {
  --_btn-bg: transparent;
  --_btn-border: transparent;
  --_btn-color: var(--br-gold);
  text-decoration: underline;
  /* text-underline-offset now lives on the shared .br-btn block above. */
}
/* Hover, focus and press all read from the one surface-aware gold ramp rather
   than a hard-coded tint, so this button inverts with its surface exactly the
   way --primary does. On ink that resolves #f1c305 -> #f8dc7a -> #fbf3d4; on
   white it resolves #f1c305 -> #d6ac00 -> #bd9700. Both match the reference.

   :focus-visible gets the same colour move as :hover because the reference
   does that too — its gold link shifts to #f8dc7a on keyboard focus, not just
   under the pointer (measured in _r5-refghost.mjs). Without it the ring
   appeared but the label sat dead, so hover and focus read as two different
   systems.

   Deliberately NOT thickening the underline here, even though .br-btn--ghost
   does. Those two are consistent at the level that matters — every hover must
   announce itself — but they have opposite problems. On white, ghost's colour
   move is #1F1902 -> #2B2305, which is invisible, so the underline has to do
   the work. On ink, this button goes gold -> bright butter, which is about as
   loud as a hover gets. Thickening on top of that buys no legibility and does
   cost fidelity: the reference holds `auto` through hover (measured), and a
   2px rule is plainly visible side by side. */
.br-btn--ghost-accent:hover { --_btn-color: var(--br-gold-hover); }
.br-btn--ghost-accent:focus-visible { --_btn-color: var(--br-gold-hover); }
.br-btn--ghost-accent:active {
  --_btn-color: var(--br-gold-active);
  --_btn-bg: var(--br-ghost-accent-press-bg);
}

/* The other half of the 320px story. The reference changes THREE things when
   it drops into its narrow mode at <=320: height 48 -> 34, padding-block
   11 -> 4, and padding-inline 24 -> 12. Only the first two are touch-target
   properties, and only those two are what the divergence note above is
   entitled to reject. The inline padding rode along with them by accident,
   because `padding` is one shorthand — so we were sitting 12px wider per side
   than the reference at the one width where there is no room to spare.

   Restored here. On a full-width stacked pill it is invisible (the label is
   centred, so the box is the same box and the glyphs do not move — verified
   at 320/root 16, line boxes identical before and after). What it buys is the
   24px of inner room the reference has and we did not: at 320 with the root
   font-size at 20px or 24px, warren@broadrisk.com.au needs 202.6px and had
   only 201/187 to sit in, so it wrapped to two lines and stood the button up
   at 72px against the reference's 34. With the padding corrected it fits on
   one line again, at 48px, and the section keeps both the touch target and
   the reference's proportions.
   ------------------------------------------------------------------------- */
@media (max-width: 320px) {
  .br-btn { padding-inline: var(--br-btn-px-xs); }
}

/* -- sizes --------------------------------------------------------------- */
.br-btn--xs { min-height: var(--br-btn-h-xs); padding: var(--br-space-2) var(--br-btn-px-xs); min-width: 0; }
.br-btn--sm { min-height: var(--br-btn-h-sm); padding: var(--br-space-2) var(--br-btn-px-sm); min-width: 0; }
.br-btn--lg { min-height: var(--br-btn-h-lg); padding: var(--br-space-4) var(--br-btn-px-lg); }

/* -- modifiers ----------------------------------------------------------- */
.br-btn--block { display: flex; width: 100%; min-width: 0; }
/* A button whose label is CONTENT, not chrome — the review pills read
   "<business name> on Google", so the longest word in this component is a
   trading name nobody on this team gets to choose. `white-space: normal`
   lets it wrap between words. `overflow: clip` is what stops a name that
   cannot wrap from scrolling the whole page.

   The bug it fixes: a 42-character hyphen-free name overflowed the pill and
   pushed documentElement.scrollWidth to 381 at a 320 viewport, 890 at 768
   and 1063 at 1024 — a horizontal scrollbar on the entire document because
   of one customer's name. Overflowing inline content extends the document's
   scrollable area unless some ancestor clips it; the reference happens to
   have one, we did not.

   Why clip and not `overflow-wrap: anywhere`, which was tried first and
   reverted: `anywhere` (and `break-word`, which line-breaks identically)
   breaks a word the moment it exceeds the CONTENT box — and the reference
   lets a long word run into the 24px padding without breaking. "Jamiesons
   Accountants on Google" is exactly that case at 768: the word measures
   96.47px against an 87.48px content box but ends 14px inside the pill's own
   edge, so the reference sets it on three lines and never breaks it. With
   `anywhere` it split mid-word into four lines — a visible, permanent
   regression on real copy at one of the four judged widths, traded for a
   nicer failure mode on copy no client has. Wrong trade.

   Clipping is exactly the reference's own behaviour, just held closer in: it
   clips at a section ancestor, this clips at the pill. Both lose the tail of
   a pathological name; only this one cannot leak into the page's scroll
   width. Verified: line boxes are identical to the reference at 320 / 390 /
   768 / 1024 / 1200 / 1440 / 1920 — clipping at the PADDING box, not the
   content box, is what makes the 768 case land unchanged.

   `clip` rather than `hidden` on purpose. `hidden` makes the button a
   scroll container, so a stray focus or an anchor jump inside it could
   scroll the label out of view with no way to get it back, and it would
   also establish a formatting context this inline-flex control has no use
   for. `clip` clips and nothing else. Safari before 16 ignores it and
   degrades to today's behaviour, which is the pre-existing state, not a new
   fault. An element's own outline is not subject to its own clipping, so
   the focus ring is unaffected — verified by screenshot. */
.br-btn--wrap {
  white-space: normal;
  text-align: left;
  justify-content: flex-start;
  overflow: clip;
}

/* -- disabled ------------------------------------------------------------ */
.br-btn:disabled,
.br-btn[aria-disabled="true"] {
  opacity: 0.45;
  cursor: not-allowed;
  pointer-events: none;
}
/* Keyboard users must still be able to reach a disabled control to learn why. */
.br-btn[aria-disabled="true"] { pointer-events: auto; }
.br-btn[aria-disabled="true"]:hover {
  --_btn-bg: var(--_btn-bg);
  --_btn-border: var(--_btn-border);
  --_btn-color: var(--_btn-color);
}

/* -- forced colours ------------------------------------------------------
   Windows High Contrast Mode (and any forced-colors mode) throws away author
   background-color. Every variant above distinguishes itself by fill, so
   without this the gold primary and the chrome-less ghost collapse to the
   same system button: two CTAs side by side become indistinguishable and the
   primary/secondary hierarchy is gone.

   Filled variants opt out of the override and repaint with the SYSTEM accent
   pair, which is guaranteed legible in whatever theme the user picked — this
   is why it is Highlight/HighlightText and not one of our hexes; a hardcoded
   colour here would be the actual accessibility bug. Everything else stays
   fully system-painted and just takes a visible boundary, so emphasis still
   reads in the right order: solid accent > bounded > text-only.
   ------------------------------------------------------------------------ */
@media (forced-colors: active) {
  .br-btn--primary,
  .br-btn--dark {
    forced-color-adjust: none;
    background: Highlight;
    color: HighlightText;
    border-color: Highlight;
  }
  /* The filled variants opt out above, so their focus ring has to come from
     the forced palette too — otherwise it is drawn in --br-focus against a
     Highlight fill and can vanish into it. */
  .br-btn--primary:focus-visible,
  .br-btn--dark:focus-visible { outline-color: HighlightText; }

  .br-btn--outline,
  .br-btn--ghost,
  .br-btn--ghost-accent { border-color: ButtonText; }

  /* The icon circles draw their ring with box-shadow, and forced-colors
     discards author box-shadow outright — so all three rings vanish and the
     glyphs float unmoored, with the 48px module that sets a section's vertical
     rhythm reading as a bare 24px mark. Repaint the ring as a real border in
     CanvasText. box-sizing: border-box (line 20) means the element is still
     exactly 48x48, so normal mode is untouched.

     Deliberately on the base class, not just the hairline variant: --filled
     and --gold trade the ring for a background, and forced-colors flattens
     background to Canvas too, so they lose their shape by the same mechanism
     and want the same boundary. */
  .br-icon-circle { border: 1px solid CanvasText; }
}
/* Form controls have the same forced-colors problem as the buttons above, but
   their fix CANNOT live in this block — see the forced-colors rules at the end
   of section 9. They have to come after `outline: none`, and a media query
   adds no specificity. */

/* ==========================================================================
   6. INLINE TEXT LINK
   Distinct from .br-btn--ghost: this is a link inside a paragraph, so it
   inherits the paragraph's size and sits on the text baseline.
   ========================================================================== */

.br-link {
  color: var(--br-text-strong);
  font-weight: var(--br-weight-semibold);
  text-decoration: underline;
  text-underline-offset: 0.3em;
  text-decoration-thickness: 1px;
  border-radius: var(--br-radius-xs);
  transition: color var(--br-dur) var(--br-ease), text-decoration-color var(--br-dur) var(--br-ease);
}
.br-link:hover { color: var(--br-ink-hover); text-decoration-thickness: 2px; }
.br-on-dark .br-link:hover { color: var(--br-gold-tint); }
.br-link:active { color: var(--br-ink-active); }

/* ==========================================================================
   7. CARD
   Measured: white, radius 28.154 @1440 (= 1u), padding 37.538 / 28.154
   (= 4u/3 and 1u), shadow 0 24px 64px rgba(31,25,2,.16) when lifted.
   ========================================================================== */

.br-card {
  display: flex;
  flex-direction: column;
  background: var(--br-bg-surface);
  color: var(--br-text);
  border-radius: var(--br-radius-lg);
  padding: var(--br-card-py) var(--br-card-px);
}

.br-card--flush { padding: 0; overflow: hidden; }
.br-card--elevated { box-shadow: var(--br-shadow-card); }
.br-card--outlined { box-shadow: var(--br-ring-hairline); }
.br-card--tight { padding: var(--br-card-px); }

/* The hero form card is its own measured size: radius 24px, not 1u. */
.br-card--form {
  border-radius: var(--br-radius-card);
  box-shadow: var(--br-shadow-card);
  padding: var(--br-space-7) var(--br-space-7) 26px;
  max-width: 464px;
  width: 100%;
}

/* Interactive cards only — a static card must not animate on hover. */
.br-card--interactive {
  transition: box-shadow var(--br-dur) var(--br-ease), transform var(--br-dur) var(--br-ease);
}
.br-card--interactive:hover { box-shadow: var(--br-shadow-card); transform: translateY(-2px); }
.br-card--interactive:focus-within { box-shadow: var(--br-shadow-card); }

@media (prefers-reduced-motion: reduce) {
  .br-card--interactive:hover { transform: none; }
}

/* ==========================================================================
   8. EYEBROW
   Measured: 11.5 / 21.7 / 700 / 0.1em / uppercase, colour #8a6d00 on white.
   ========================================================================== */

.br-eyebrow {
  display: block;
  font-family: var(--br-font-body);
  font-size: var(--br-eyebrow-size);
  line-height: var(--br-eyebrow-lh);
  font-weight: var(--br-eyebrow-weight);
  letter-spacing: var(--br-eyebrow-ls);
  text-transform: uppercase;
  color: var(--br-text-accent);
  margin: 0 0 var(--br-space-2);
}

/* ==========================================================================
   9. FORM FIELD
   Measured: label 13/20/600 #454745 with a 7px gap; control 15.5px/500,
   13px/14px padding, 8px radius, 1px #d9d9d9 border, hover #b5b5b5,
   focus = ink border + a 3px gold halo.
   ========================================================================== */

.br-field {
  display: block;
  margin-bottom: var(--br-field-gap);
}

.br-field:last-child { margin-bottom: 0; }

.br-field-label {
  display: block;
  font-size: var(--br-label-size);
  line-height: var(--br-label-lh);
  font-weight: var(--br-label-weight);
  letter-spacing: var(--br-label-ls);
  color: var(--br-text);
  margin-bottom: var(--br-field-label-gap);
}

.br-field-hint {
  display: block;
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--br-text-muted);
  margin-top: var(--br-space-1);
}

.br-input,
.br-select,
.br-textarea {
  display: block;
  width: 100%;
  padding: var(--br-field-py) var(--br-field-px);
  font-family: var(--br-font-body);
  font-size: var(--br-field-size);
  font-weight: var(--br-field-weight);
  line-height: 21.7px;
  letter-spacing: normal;
  color: var(--br-text-strong);
  background: var(--br-white);
  border: 1px solid var(--br-border-control);
  border-radius: var(--br-radius-sm);
  appearance: none;
  transition: border-color var(--br-dur) var(--br-ease), box-shadow var(--br-dur) var(--br-ease);
}

.br-textarea { min-height: 120px; resize: vertical; line-height: 1.5; }

.br-input::placeholder,
.br-textarea::placeholder { color: var(--br-neutral-500); }

/* A select showing its placeholder option has to LOOK unanswered.
   A <select> has no ::placeholder, so an unchosen control renders its
   placeholder option in full ink — pixel-identical to a real answer. On the
   hero form that means a user scanning the card sees three filled fields and
   no cue that anything is outstanding; the required+disabled guard blocks the
   submit, but only after they have tried. This is the signalling half of that
   fix.

   --br-text-muted is the fine-print grey already used by the form's own
   helper and note lines (#6a6c6a, 5.3:1 on white) — same register as a text
   input's placeholder, no new token, and still an AA text colour rather than
   the sub-4.5:1 grey most placeholders get away with.

   The list items stay full ink: only the CLOSED control is unanswered, and
   greying the whole menu would make every option look disabled. Native menus
   honour option colour on Windows/Linux; macOS paints its own menu and
   ignores both — that is fine, the closed-state colour is the one that
   carries the signal and it is honoured everywhere.

   :has() is the whole mechanism, so browsers without it (Safari < 15.4,
   Firefox < 121) simply keep today's full-ink placeholder — the pre-existing
   behaviour, never a broken one, and the functional guard is unaffected. */
.br-select:has(option[value=""]:checked) { color: var(--br-text-muted); }
.br-select option { color: var(--br-text-strong); }

.br-input:hover,
.br-select:hover,
.br-textarea:hover { border-color: var(--br-border-control-hover); }

/* Focus is doubled on purpose: an ink edge carries the contrast, the gold
   halo carries the brand. The halo alone is not enough on a light surface. */
.br-input:focus-visible,
.br-select:focus-visible,
.br-textarea:focus-visible {
  outline: none;
  border-color: var(--br-focus);
  box-shadow: 0 0 0 3px var(--br-focus-halo), 0 0 0 1px var(--br-focus);
}

/* Mouse users get the same treatment — a form control is the one place a
   plain :focus ring is expected rather than noisy. */
.br-input:focus,
.br-select:focus,
.br-textarea:focus {
  outline: none;
  border-color: var(--br-focus);
  box-shadow: 0 0 0 3px var(--br-focus-halo), 0 0 0 1px var(--br-focus);
}

/* -- forced colours, form controls ---------------------------------------
   Same class of problem the button block solved in section 5, one surface
   further in — and the reason it is HERE and not up there.

   Both focus rules above draw the ring entirely with box-shadow, having
   turned the outline off. Forced-colors mode (Windows High Contrast) discards
   author box-shadow outright and repaints border-color from the system
   palette, so BOTH halves of that ring vanish at once: a focused Company /
   Industry / Work email control renders pixel-identical to an unfocused one
   and a keyboard user loses their place inside the only form on the page.

   An outline survives, because forced-colors keeps author outlines and just
   recolours them. But `outline: none` sits two rules above at equal
   specificity (0,2,0) and a media query adds none of its own, so the same
   declaration written inside the section-5 block loses on source order and
   silently does nothing — verified in emulation before this was moved:
   outline-style computed `none` at focus with the rule in the old position,
   `solid` here.

   Highlight rather than a hex for the reason already written into the
   section-5 comment: the ring has to be legible in whatever theme the user
   picked, and a hardcoded colour is the actual accessibility bug. :focus is
   carried alongside :focus-visible to match the decision one rule above —
   a form control shows its ring on pointer focus too, and select in
   particular does not always match :focus-visible on click.
   ------------------------------------------------------------------------ */
@media (forced-colors: active) {
  .br-input:focus,
  .br-select:focus,
  .br-textarea:focus,
  .br-input:focus-visible,
  .br-select:focus-visible,
  .br-textarea:focus-visible {
    outline: 2px solid Highlight;
    outline-offset: 1px;
  }
}

.br-input:disabled,
.br-select:disabled,
.br-textarea:disabled {
  background: var(--br-neutral-100);
  color: var(--br-text-muted);
  border-color: var(--br-neutral-300);
  cursor: not-allowed;
}

.br-input[aria-invalid="true"],
.br-select[aria-invalid="true"],
.br-textarea[aria-invalid="true"] { border-color: #b3261e; }

.br-field-error {
  display: block;
  font-size: 12.5px;
  line-height: 1.5;
  color: #b3261e;
  margin-top: var(--br-space-1);
  font-weight: var(--br-weight-medium);
}

/* Chevron, redrawn on our own 24x24 grid. The reference's belongs to an icon
   set we are not permitted to carry across, so this reproduces its RENDERED
   BOX and OPTICAL MASS with our own stroked construction.

   Reference, read off the computed style rather than guessed:
     background-size : 14px   <- NOT 16
     path            : a FILLED caret, mitred terminals, 45deg limbs
     outer extents   : x 5.7 -> 18.3 = 12.6 units, y 7.9 -> 15.6 = 7.7 units
     limb thickness  : 1.4 x sqrt(2) = 1.98 units
   At 14px that is a 7.35 x 4.49 css mark.

   Ours is a stroke, so round caps carry half the stroke past each endpoint:
   outer span = path span + stroke-width. Solving that against the reference's
   extents keeps the box fixed for any weight, which leaves stroke-width free
   to be tuned for INK rather than guessed. Swept 1.70-2.00 in _r4-chevsweep
   .mjs, measuring coverage-weighted ink against the reference:

       1.70  0.943      1.85  1.010   <- shipped
       1.75  0.951      1.90  1.024
       1.80  0.983      2.00  1.059

   1.85 with arms at x 6.62/17.38 and the apex at y 14.67. Limbs land at
   47deg rather than 45 because a round cap ends half a stroke above its
   endpoint where the reference's mitre is cut horizontally 1.4 units up;
   holding both spans is worth two degrees nobody can resolve on a 7px mark.

   TWO EARLIER PASSES GOT THIS WRONG, both by trusting a number over a render:
     1. M6 9.5 / 12 15.5 / 18 9.5 at 1.75 and 16px — read light and flat.
     2. Widening the path to a 12.6-unit span while LEAVING background-size at
        16px. 16px was the actual defect the first pass had been quietly
        compensating for; correcting only the path took the icon to 1.58x the
        reference's ink and it was visibly fatter at 8x.
   If you touch the path, the weight or the size, re-run _r4-chev.mjs and LOOK
   at the picture it writes. Two passes of arithmetic got this wrong; one
   glance at the 8x crop caught it both times. */
.br-select {
  padding-right: 38px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%231f1902' stroke-width='1.85' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6.62 8.82 12 14.67 17.38 8.82'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right var(--br-field-px) center;
  background-size: 14px 14px;
  cursor: pointer;
}

.br-select:disabled { cursor: not-allowed; opacity: 0.6; }

/* iOS zoom guard. The reference sets 15.5px on every control at every width,
   which makes mobile Safari zoom the whole page the moment a field takes
   focus — the user then has to pinch back out to see the rest of the form.
   Below the tablet breakpoint we round the control type up to the 16px
   threshold Safari uses. The control box does not move: it is
   13px + 21.7px line-box + 13px + 2px border = 49.7px either way, because
   the line-height is a fixed length, not a ratio. This is the one place in
   the hero we deliberately diverge from the reference, and it is invisible
   at 0.5px on a 15.5px face. */
@media (max-width: 767px) {
  .br-input,
  .br-select,
  .br-textarea { font-size: 16px; }
}

/* On dark surfaces the control inverts rather than staying a white slab. */
.br-on-dark .br-input,
.br-on-dark .br-select,
.br-on-dark .br-textarea {
  background: rgba(255, 255, 255, 0.06);
  color: var(--br-white);
  border-color: var(--br-border-control);
}
/* Same geometry as the light chevron above, white. Keep the two in sync —
   if you change one path or stroke-width, change both. */
/* Identical geometry to the light chevron above, in white. Keep the two in
   lockstep — same path, same stroke-width. background-size is inherited from
   the .br-select rule, so only the colour changes here. */
.br-on-dark .br-select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23ffffff' stroke-width='1.85' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6.62 8.82 12 14.67 17.38 8.82'/%3E%3C/svg%3E");
}
.br-on-dark .br-input::placeholder,
.br-on-dark .br-textarea::placeholder { color: rgba(255, 255, 255, 0.55); }

/* ==========================================================================
   10. ICON CIRCLE
   Measured: 48px, fully pilled, ring = inset 0 0 0 1px rgba(14,15,12,.12),
   holding a 24px icon in the heading ink. Filled variants measured at 40px
   (gold) and 72px (8% ink wash).
   ========================================================================== */

.br-icon-circle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  width: var(--br-icon-circle);
  height: var(--br-icon-circle);
  border-radius: var(--br-radius-pill);
  box-shadow: var(--br-ring-hairline);
  background: transparent;
  color: var(--br-text-heading);
}

.br-icon-circle > svg {
  width: var(--br-icon);
  height: var(--br-icon);
}

/* Icons are drawn, not filled — keep the whole set on one stroke weight. */
.br-icon-circle > svg[data-stroke],
.br-icon[data-stroke] {
  fill: none;
  stroke: currentColor;
  stroke-width: var(--br-icon-stroke);
  stroke-linecap: round;
  stroke-linejoin: round;
}

.br-icon-circle--filled {
  box-shadow: none;
  background: var(--br-bg-band-alpha);
  width: var(--br-icon-circle-lg);
  height: var(--br-icon-circle-lg);
}

.br-icon-circle--gold {
  box-shadow: none;
  background: var(--br-gold);
  color: var(--br-ink);
  width: var(--br-icon-circle-sm);
  height: var(--br-icon-circle-sm);
}
.br-icon-circle--gold > svg { width: 20px; height: 20px; }

.br-icon-circle--lg { width: var(--br-icon-circle-lg); height: var(--br-icon-circle-lg); }
.br-icon-circle--sm { width: var(--br-icon-circle-sm); height: var(--br-icon-circle-sm); }
.br-icon-circle--sm > svg { width: 20px; height: 20px; }

/* Standalone icon, no circle. */
.br-icon {
  width: var(--br-icon);
  height: var(--br-icon);
  flex: 0 0 auto;
  color: currentColor;
}

/* ==========================================================================
   11. PRINT — quiet, but not broken.
   ========================================================================== */

@media print {
  body { background: #fff; color: #000; }
  .br-skip-link, .br-btn { box-shadow: none; }
}

/* ==========================================================================
   GOOGLE REVIEWS — the snapshot band under the curated testimonials.
   Deliberately quieter than .br-testimonials: those four are chosen quotes on
   gold and ink, this is the volume behind the "26 Google reviews" claim. Same
   card radius and hairline as the rest of the system, no new tokens.
   ========================================================================== */
.br-reviews { padding-block: var(--br-section-y); }

.br-reviews__heading {
  margin: 0 0 var(--br-flow-md);
  font-size: var(--br-h2-fs);
  line-height: var(--br-h2-lh);
  font-weight: var(--br-h2-fw);
  letter-spacing: var(--br-h2-ls);
}

.br-reviews__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(17rem, 1fr));
  gap: var(--br-flow-sm);
  /* Cards hug their own text. Grid rows default to the height of the tallest
     item, which on real reviews — one is two lines, its neighbour fifteen —
     left a card that was four-fifths empty box. */
  align-items: start;
  margin: 0;
  padding: 0;
  list-style: none;
}

.br-reviews__card {
  margin: 0;
  padding: var(--br-flow-sm);
  border: 1px solid var(--br-border);
  border-radius: var(--br-radius-md);
  background: var(--br-bg);
}

.br-reviews__quote { margin: 0; }
.br-reviews__quote p { margin: 0; text-wrap: pretty; }

.br-reviews__by {
  display: flex;
  flex-wrap: wrap;
  gap: 0 0.5ch;
  margin-top: var(--br-flow-xs);
  font-size: var(--br-small-fs);
  line-height: var(--br-small-lh);
  color: var(--br-text-muted);
}
