/* ==========================================================================
   SECTION — "For businesses going places"   (#testimonials)
   --------------------------------------------------------------------------
   Display heading + rating on the left, four Google pull-quotes 2x2 on the
   right. Stacks to one column of four cards below 768.

   Every number below was read off the signed-off reference with Playwright at
   300/320/360/390/480/576/600/700/767/768/900/991/992/1024/1100/1199/1200/
   1280/1440/1600/1920 and then expressed in the shared tokens. Reference
   values @1440, for the record:

     section          margin-block 56.308 (= 2u = --br-section-y)
                      PLUS padding-top 56.308 — this section approaches deeper
                      than its neighbours, it is not a collapsed-margin artefact
     row              12-col, 5 / 7, column gap 28.154 (= 1u)     @992+
                                                17.046 (= 2u/3)   @768-991
                      stacked, row gap 18.769 (= 2u/3)            @<768
     left column      bottom-aligned, stack gap 18.769 (= 2u/3)
     heading          Archivo 800  89.143 / 75.771 (0.85) / normal  #0e0f0c
                      text-wrap: balance, hyphens: manual — the reference
                      hyphenates and then suppresses it; we decline it
                      outright and render identically. See the rule.
     rating           Inter 400 20 / 28 / +0.005em  #454745, 8px above baseline
                      of the stack gap; the "4.9" runs 600 in #0e0f0c
     card grid        2 x 1fr, gap 16, 24 below the top of the column
     card             padding 28.154 (= 1u), radius 28.154 (= --br-radius-lg),
                      internal gap a flat 18, CTA pinned to the bottom
     Google mark      28 tall incl. 4/8 padding, white plate, radius 8
     quote            Inter 600 20 / 28 / +0.005em
                      ink #1f1902 on gold  ·  gold #f1c305 on ink
     CTA              48 tall, 11/24 pad, pill, 16/24/600 at -0.011em
                      ink pill + gold label on gold  ·  the inverse on ink
                      48 tall at EVERY width. The reference drops to 40 tall
                      / 4px 12px at 320 and below (measured: the switch sits
                      between 320 and 321) — deliberately NOT reproduced,
                      because 40px is under the 44px touch-target minimum.
                      Cost is +42px of section height at 320 and +66px at
                      300; from 321 up the two are identical. This is the
                      only geometric divergence in the section — do not
                      "correct" it back. Geometry lives in base.css .br-btn.

   Type, colour, the button, the card radius and the container all come from
   the shared foundation, so this file only carries layout and the two
   surface-specific paint jobs.
   ========================================================================== */

.br-testimonials {
  /* Measured: 2u of margin top and bottom (which collapses with the
     neighbouring sections, keeping the gap at 2u rather than 4u) AND 2u of
     padding above the content. The reference really does give this section a
     4u approach and a 2u exit — it is asymmetric on purpose. */
  margin-block: var(--br-section-y);
  padding-top: var(--br-section-y);

  /* The row's column gutter. 2u/3 from 768, 1u from 992 — measured, and the
     step is at 992 like every other breakpoint in the system. */
  --br-testimonials-col-gap: var(--br-flow-xs);

  /* A flat 18px at every width from 320 to 1920 — it does not ride --br-u and
     it is not a step on the 4px scale. It appears nowhere else on the page, so
     it stays local rather than being promoted into tokens.css. */
  --br-testimonials-card-gap: 18px;
}

/* --------------------------------------------------------------------------
   Row — stacked by default, 5 / 7 from 768.

   The track widths are the reference's own 12-column arithmetic rather than a
   plain 5fr/7fr, including the 1px it takes off each column. That 1px is why
   the reference's cards stop 2px short of the container's right edge, and
   reproducing it keeps this section in register with the reference rather than
   with an idealised grid.
   -------------------------------------------------------------------------- */
.br-testimonials__layout {
  display: grid;
  /* The same 1px the reference takes off every column, kept in the stacked
     case too — without it the cards are 1px wider than the reference and the
     quotes rewrap. */
  grid-template-columns: calc(100% - 1px);
  gap: var(--br-flow-xs);
}

@media (min-width: 768px) {
  .br-testimonials__layout {
    grid-template-columns:
      calc((100% + var(--br-testimonials-col-gap)) * 5 / 12 - var(--br-testimonials-col-gap) - 1px)
      calc((100% + var(--br-testimonials-col-gap)) * 7 / 12 - var(--br-testimonials-col-gap) - 1px);
    column-gap: var(--br-testimonials-col-gap);
  }
}

@media (min-width: 992px) {
  .br-testimonials { --br-testimonials-col-gap: var(--br-flow-sm); }
}

/* --------------------------------------------------------------------------
   Left column.
   Measured: the heading and rating sit on the BOTTOM of the row from 768 up,
   so the last line of "places" lands level with the bottom of the last card.
   Below 768 they go back to the top of their own stack.
   -------------------------------------------------------------------------- */
.br-testimonials__heading-col {
  display: flex;
  flex-direction: column;
  gap: var(--br-flow-xs);
}

@media (min-width: 768px) {
  .br-testimonials__heading-col { justify-content: flex-end; }
}

.br-testimonials__heading {
  text-wrap: balance;

  /* The reference asks for `hyphens: auto` and then immediately suppresses it
     with `hyphenate-limit-chars: 14 6` — a 14-character word with 6 letters
     before the break, which no word in this heading clears. The hyphenation
     therefore never fires; the declaration exists only to stop Chrome's
     defaults (about 5/2/2) cutting the display type into "For busin- /
     esses goi- / ng places".

     We say that directly instead. `hyphens: manual` is what the reference is
     really expressing, and it does not depend on a property Firefox has never
     implemented and Safari only shipped in 17. In those browsers the
     reference's limits are dropped, `hyphens: auto` takes over at the default
     limits, and the heading collapses from 4 lines to 5 with hyphen tails —
     measured at 768/840/1160/1200/1440/1920, tails of 16.7 to 32px. The
     largest element on the page, broken in a major browser.

     Checked before switching: line rects are byte-identical to the
     reference's rule at all 25 widths tested from 320 to 1920 in Chrome, and
     section height is unchanged at every one. Zero fidelity cost. Do not put
     `hyphens: auto` back. */
  hyphens: manual;
}

/* ==========================================================================
   KNOWN INHERITED ISSUE — decided by the client, not here.
   Written up for them in  rebuild/notes/testimonials.md  (with screenshots).
   That file is the decision; this comment is the pointer to it.
   --------------------------------------------------------------------------
   The longest heading line ("businesses") overruns its own 5-column track by
   up to 93.2px — peaking at 1200 — and paints ON TOP of the second-row card
   between 1138 and 1391, up to 66px deep at 1200. The reference does the same
   thing to the same pixel (2.0px at 1140, 11.7 at 1160, 21.5 at 1180, 66.0 at
   1200, 57.6 at 1220, 47.5 at 1250, 37.4 at 1280, 23.9 at 1320, 10.5 at 1360,
   3.8 at 1380, 0.4 at 1390 — both files measured at every one, identical).

   Reproducing it is the correct fidelity call and it is what ships. It is
   also the one thing a demanding eye flags, and 1200 is a 13" MacBook, so it
   is NOT quietly left in a code comment: the trade-off, the measurements and
   the options are in the client note above, for the client to answer.

   The obvious fix is the wrong one. `position: relative; z-index: 1` on
   .br-testimonials__heading-col does remove the clipping — by painting 86px of
   near-black display type across the Google Reviews badge on the gold card.
   Worse than the problem. Don't.

   If the client chooses to correct it, this is the measured remedy — band
   scoped, so every width outside 1138-1391 stays byte-identical:

     @media (min-width: 1138px) and (max-width: 1391px) {
       .br-testimonials__heading { font-size: min(var(--br-display-lg-size), 6.2vw); }
     }

   Measured (_r8-remedy.mjs, plus a 2px sweep of 1130-1400): overlap exactly 0
   at all 128 widths inside the band. The sweep also pins the true onset at
   1136 rather than 1138 — but the overlap there is 0.02px, a twentieth of a
   CSS pixel and a twenty-fifth of a device pixel at 2x, so the band is left
   where it is rather than widened to chase something no display can render;
   section
   height, card boxes, quote wrap and line count all unchanged to 0.00px; the
   heading loses 13% at 1200 and 2-4% at the band edges; pixel divergence from
   the reference 2.4-4.0% inside the band and 0.0000-0.0082% (i.e. unchanged)
   outside it. The 6.2vw cap is derived, not guessed — the collision clears
   when the widest line fits its track plus the column gutter, and 1200 is the
   binding width because the container maxes out there while the gutter grows.

   Two alternatives were measured and are worse, so don't re-derive them:
     · clamp(67px, 5.5vw, 79.7px) — same effect, 22% type loss at 1200 instead
       of 13%, and a 12px size step at the band edge instead of 2px.
     · A continuous "always fit the track" cap — shrinks the heading at EVERY
       width, including the ones that are already correct (89.1 -> 87.1 at
       1440, 72.7 -> 66.0 at 1136). Strictly the worst of the three.
   ========================================================================== */

/* Measured 8px, on top of the 2u/3 stack gap above. */
.br-testimonials__rating { margin-top: var(--br-space-2); }

/* Measured #0e0f0c — the heading ink, a notch cooler than --br-text-strong,
   which is what base.css gives <strong> by default. */
.br-testimonials__rating strong { color: var(--br-text-heading); }

/* --------------------------------------------------------------------------
   Card grid.
   Both flat values, measured: a 16px gutter and a 24px drop from the top of
   the column at every width from 320 to 1920.
   -------------------------------------------------------------------------- */
.br-testimonials__grid {
  display: grid;
  gap: var(--br-space-4);
  margin-top: var(--br-space-6);
}

@media (min-width: 768px) {
  .br-testimonials__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* The <li> is the grid cell; the card fills it, so two cards side by side
   finish level however differently their quotes wrap.

   `min-width: 0` is not defensive boilerplate here. Grid and flex items both
   default to `min-width: auto`, which refuses to shrink below the content's
   own minimum — and at 768 the longest CTA label has a minimum wider than the
   card. Without this the Jamiesons card grows past its track and overlaps the
   card beside it. */
.br-testimonials__item {
  display: flex;
  min-width: 0;
}

/* --------------------------------------------------------------------------
   Card.
   `align-items: flex-start` is measured behaviour, not a preference: it is
   what makes the Google mark keep its own width and the CTA shrink-wrap its
   label instead of stretching across the card.
   -------------------------------------------------------------------------- */
.br-testimonials__card {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--br-testimonials-card-gap);
  margin: 0;
  padding: var(--br-u);
  border-radius: var(--br-radius-lg);
  /* .br-on-gold / .br-on-dark re-point --br-bg, so the two card surfaces are
     one declaration and every child — quote, focus ring, CTA — follows. */
  background: var(--br-bg);
}

/* The Google mark keeps its white plate on both surfaces. Height is measured
   border-box: 28 tall including its 4px of vertical padding. */
.br-testimonials__mark {
  width: auto;
  height: 28px;
  padding: var(--br-space-1) var(--br-space-2);
  background: var(--br-white);
  border-radius: var(--br-radius-sm);
}

.br-testimonials__quotation { margin: 0; }

/* Size / leading / tracking come from .br-lead, which reads the shared
   --br-h4-size ramp. Recorded because it was raised as a divergence and is not
   one any more: this section used to diff 0.78% of strong pixels at exactly
   430 because the ramp reached its own 18px cap one viewport pixel early
   (18.0000 here against the reference's 17.9999), and a font instantiated at a
   different size rasterises every glyph in the paragraph differently. The
   industries agent re-fitted --br-h4-size's first segment by least squares over
   55 measured points, and the shelf now starts at 431 like the reference.
   Re-measured here (_r8-lead430.mjs): 430 reads 17.9999px / 0.0899997em in BOTH
   files, and the diff at 430 is now 0.0009% (19 pixels in 2.15 million).
   Nothing to do — and specifically do NOT hard-code 17.9999px here, which
   would fix one width and break the ramp at every other. */
.br-testimonials__quotation-text {
  font-weight: var(--br-weight-semibold);
  /* base.css gives <p> `text-wrap: pretty`, which reflows the last two lines
     to avoid an orphan. The reference wraps normally and hyphenates, which is
     what breaks "knowledge-able" across a line in the second quote. Both are
     needed to land on the reference's line count — and the line count is the
     card's height. */
  text-wrap: wrap;
  hyphens: auto;
  /* NOTE, so nobody adds a local overflow-wrap here again: the quote is a <p>,
     and base.css already gives every <p> `overflow-wrap: break-word`. That is
     enough, and it was checked rather than assumed — a 38-character
     unhyphenatable token in quote 1 at 1440 ends 36px INSIDE the card with the
     base rule, and 154px OUTSIDE it (over the top of the next card) without.
     `anywhere` was tried on top and reverted: its only difference from
     `break-word` is the min-content contribution, and nothing here sizes to
     min-content — the grid tracks are minmax(0, 1fr) and the item carries
     min-width: 0. It was a second rule that did nothing.

     The button is the opposite case and needs its own guard — see
     .br-btn--wrap in base.css for why breaking is wrong there. */
  /* Measured, and it tightens as the card gets wider — the narrower the
     column, the more willing the reference is to break a word:

       <840    7 3      840-1159    8 3      >=1160   10 4 3

     The two thresholds are off the system's 768/992/1200 grid, which is why
     they are stated here rather than reached for from a token. This is what
     decides whether "knowledge-able" and "sub-stantial" break, which decides
     the line count, which decides the height of the card — so it is not a
     typographic nicety, it is the layout. Chrome's default (about 5 2 2)
     breaks far more than the reference at every width. */
  hyphenate-limit-chars: 7 3;
}

/* NOT text-wrap: pretty — considered, measured, declined 2026-08-18.
   The case for it was that the last line of card 1 falls to 13-14% of the
   column between 480 and 576, and of card 4 to 13% at 544-576, and that
   `pretty` would tidy that band and nothing else.

   Measured at 21 widths from 320 to 1920 (_r6-pretty.mjs), it does not:
   it changes the wrap at 390, 480, 520, 544, 576, 640, 900, 992, 1024, 1160,
   1200, 1280 and 1920 — thirteen of twenty-one, including THREE of the four
   judged widths. At 390 and 1920 it goes further and suppresses the
   reference's hyphen breaks outright: "knowledge-able" on card 2 stops
   breaking, which is visible at the character level in a side-by-side.
   Section height never moves, so this buys nothing structural.

   And the widow it was meant to fix is not one. Every short last line in that
   band is a WHOLE word carrying its closing quote mark, recovered from the
   render rather than eyeballed (caretRangeFromPoint at the start of the last
   line rect):

     480   card 1  14%  `mind."`        520   card 1  13%  `mind."`
     544   card 4  13%  `rates."`       576   card 4  13%  `rates."`

   Not a stranded fragment anywhere. (Round 7 reported the 576 case as
   `mind."`; it is card 4's `rates."` — card 1 is 97% full at that width. The
   conclusion is unchanged, but the record should be right.) Every card in that
   band ends on a short line; it reads as rhythm, not as an accident.

   The trade was: match the reference's line breaking at every width the work
   is judged at, or tidy one band no one specified at the cost of three that
   are. Fidelity wins, and it wins on the numbers rather than on principle.
   If this comes back, re-run _r6-pretty.mjs before re-arguing it.

   If the client ever relaxes pixel-parity below tablet — and only then — the
   safe scope is phone-only, where none of the judged widths live:

     @media (max-width: 767px) {
       .br-testimonials__quotation-text { text-wrap: pretty; }
     }

   Even that is not free: 390 is inside it, and 390 is one of the four judged
   widths AND the width where `pretty` suppresses the reference's own
   "knowledge-able" break. Re-run _r6-pretty.mjs and confirm the 390 breaks
   survive before shipping it. Written up for the client in
   rebuild/notes/testimonials.md so the option is visible outside this file. */

@media (min-width: 840px) {
  .br-testimonials__quotation-text { hyphenate-limit-chars: 8 3; }
}

@media (min-width: 1160px) {
  .br-testimonials__quotation-text { hyphenate-limit-chars: 10 4 3; }
}

/* Where `hyphenate-limit-chars` is not implemented — Firefox at any version,
   Safari before 17 — the three rules above are dropped and `hyphens: auto`
   falls back to the engine defaults (about 5/2/2). Those break far more
   eagerly than the reference and put mid-word hyphens in the pull-quotes that
   the design never sanctioned. Degrading to over-hyphenation is worse than
   degrading to none, so those browsers get none.

   Measured cost of the fallback: section height is identical to the reference
   at 320/390/768/840/992/1440/1920 and 28px taller at 1160 and 1200 — the
   same magnitude the unguarded fallback moved by, but with clean word breaks
   instead of "knowledge-able" and "sub-stantial". Chrome supports the
   property, so this block never applies there. */
@supports not (hyphenate-limit-chars: 10 4 3) {
  .br-testimonials__quotation-text { hyphens: manual; }
}

/* Measured: ink quote on gold, gold quote on ink. Both read through the
   surface token sets, so neither is a hard-coded hex. */
.br-testimonials__card--gold .br-testimonials__quotation-text { color: var(--br-text-strong); }
.br-testimonials__card--ink  .br-testimonials__quotation-text { color: var(--br-text-accent); }

/* Measured: the CTA is pinned to the bottom edge of the card, so the pills in
   a row line up even when one quote runs a line longer. The full width is what
   gives the pill below a definite box to cap itself against — see the CTA. */
.br-testimonials__source {
  margin-top: auto;
  width: 100%;
}

/* The pill shrink-wraps its label (182.86px for "Tracey on Google" @1440) and
   wraps to two lines when the card is too narrow for it — which is every card
   at 768, and the Jamiesons card at 1440. base.css's --primary / --dark
   variants would force a 200px floor, so this uses the bare .br-btn plus the
   two measured colour ways. */
.br-testimonials__cta {
  min-width: 0;
  /* The cap is measured, and it is what keeps the longest label honest: at 768
     "Jamiesons Accountants on Google" has a min-content width wider than the
     card, and without this the pill pushes its own card past its grid track
     and into the one beside it. */
  max-width: 100%;
}

/* The two pills are the same control on opposite surfaces, and their press
   ramps run in OPPOSITE directions — both measured with a real mouse on the
   reference, 1.5s settle per state (a 250ms read samples the 150ms ease
   mid-flight and reports colours that are in neither design):

     card    pill  rest      hover     pressed
     gold    ink   #1f1902   #2b2305   #0e0f0c   darkens
     ink     gold  #f1c305   #f8dc7a   #fbf3d4   LIGHTENS

   Nothing below hard-codes those. Ink darkens on every surface, so the ink
   pill just reads the ramp. Gold is the one that flips, and it flips because
   of what is BEHIND it, not because of which component it is — so the flip
   lives in .br-on-dark in tokens.css and the ink card gets it for free by
   carrying that class. A gold pill on a dark card that darkened under the
   pointer would read as disabled: there is no light behind it for the eye to
   measure the change against. */

/* Gold card → ink pill, gold label. */
.br-testimonials__card--gold .br-testimonials__cta {
  --_btn-bg: var(--br-ink);
  --_btn-border: var(--br-ink);
  --_btn-color: var(--br-gold);
}
/* The label lift is the one deliberate divergence in these four rules, and it
   is here because the ink pill's own hover is nearly invisible: #1f1902 ->
   #2b2305 is twelve units of red on a fill that is already almost black. Side
   by side with the gold pill opposite it — which travels #f1c305 -> #f8dc7a,
   a change you cannot miss — the ink pill looked broken rather than subtle.

   Gold going paler on ink is the reference's own idiom, not an invention: its
   gold TEXT links on ink slabs hover to exactly this #f8dc7a (measured on the
   industries block's "Get a quote"). We are applying the move it already
   makes for gold-on-ink to the one gold-on-ink control it forgot. Fill,
   border and press step are all reference-exact; only the label moves. */
.br-testimonials__card--gold .br-testimonials__cta:hover {
  --_btn-bg: var(--br-ink-hover);
  --_btn-border: var(--br-ink-hover);
  --_btn-color: var(--br-gold-tint);
}
.br-testimonials__card--gold .br-testimonials__cta:active {
  --_btn-bg: var(--br-ink-active);
  --_btn-border: var(--br-ink-active);
}

/* Ink card → gold pill, ink label. The card carries .br-on-dark, so
   --br-gold-hover / --br-gold-active already resolve to the lightening ramp
   here; these are byte-for-byte the declarations the light-surface primary
   uses, which is the point — one button, two surfaces, no second rule. */
.br-testimonials__card--ink .br-testimonials__cta {
  --_btn-bg: var(--br-gold);
  --_btn-border: var(--br-gold);
  --_btn-color: var(--br-ink);
}
.br-testimonials__card--ink .br-testimonials__cta:hover {
  --_btn-bg: var(--br-gold-hover);
  --_btn-border: var(--br-gold-hover);
}
.br-testimonials__card--ink .br-testimonials__cta:active {
  --_btn-bg: var(--br-gold-active);
  --_btn-border: var(--br-gold-active);
}
