/* ==========================================================================
   SECTION — "Switching brokers is simple"   (#switching)
   --------------------------------------------------------------------------
   Two columns: copy on the left, a flat brand-gold 3:4 canvas on the right,
   vertically centred against each other. Stacks copy-then-canvas below 768.

   Every number below was read off the signed-off reference with Playwright
   and then expressed in the shared tokens — nothing here is eyeballed.
   Reference values @1440, for the record:

     section            margin-block 56.3076  (= 2u = --br-section-y), padding 0
     columns            1fr / 1fr, align-items center
     column gap         150.154  (= 16u/3 = --br-flow-2xl)   @1200+
                        106.215  (= 4u)                      @992–1199
                         51.138  (= 2u    = --br-flow-lg)    @768–991
     stacked row gap     48.231  (= 2u    = --br-flow-lg)    @<768
     heading            Inter 600 45.457 / 57 / -0.03em  #0e0f0c  (base h2)
                        text-wrap balance, hyphens auto, hyphenate-limit-chars
                        14 8 — all three measured on the reference h2, all three
                        reproduced below. The limit is not optional trim: with
                        `hyphens: auto` alone the headline hyphenates at 260-262
                        where the reference does not.
     heading → lead      28.154  (= 1u    = --br-flow-sm)
     lead               Inter 400 20 / 28 / +0.005em     #454745  (.br-lead)
                        hyphens manual — that is the reference <p> value and the
                        initial value, so it is inherited, not restated.
                        text-wrap auto, NOT pretty. The lead ends on a one-word
                        line at 55 of 1381 widths; that is the reference's own
                        rag and it is reproduced rather than corrected. Measured
                        both ways — see the note on .br-switching__lead.
     lead → button       37.538  (= 4u/3  = --br-flow-md)
     button             gold pill, 227.375 x 48, 11/24 pad  (.br-btn--primary)
                        The reference drops this to 4/12 pad — 34px tall — at
                        every width <=320. NOT reproduced: 34px fails the 44px
                        minimum touch target and 320 is a real device width, not
                        a test width. We hold 11/24 (48px) all the way down.
                        Deliberate, and the ONLY geometry in this section that
                        departs from the reference — a future re-measure will
                        read the 14px delta as a regression. It is not. Leave it.
     canvas             aspect 3:4, #f1c305, radius 28.154 (= 1u = --br-radius-lg)

   Type, colour, the button and the container are all shared already, so this
   file carries the layout plus the two line-breaking properties that are
   specific to this copy (the heading's hyphenation limits and the long-word
   guard) — everything else it needs, it inherits.
   ========================================================================== */

/* --------------------------------------------------------------------------
   Section rhythm.

   The reference gives this section vertical MARGIN and zero padding, and that
   is load-bearing rather than stylistic: adjacent section margins collapse, so
   two neighbouring sections yield one 2u gap (56.31px @1440) rather than two
   stacked 2u gaps.

   ASSEMBLY CONTRACT — this only holds in normal block flow. If the element
   that wraps the sections is display:flex or display:grid, margin collapsing
   is switched off and EVERY inter-section gap silently doubles to 112.62px.
   Padding, a border, or overflow other than visible on the wrapper breaks it
   the same way. So when the page is assembled:

     - the sections' common parent stays plain block flow, and
     - `node rebuild/tests/section-gap.mjs <page.html>` asserts it, and fails
       loudly rather than quietly measuring nothing if the page is absent.

   If a future layout genuinely needs a flex/grid wrapper, the fix is to drop
   these margins to `margin-block: 0` and give the wrapper `row-gap:
   var(--br-section-y)` — NOT to halve the token.
   -------------------------------------------------------------------------- */
.br-switching {
  margin-block: var(--br-section-y);
}

/* --------------------------------------------------------------------------
   Layout — stacked by default, two columns from 768.
   -------------------------------------------------------------------------- */
.br-switching__layout {
  display: flex;
  flex-direction: column;
  gap: var(--br-flow-lg);
}

/* Children stretch to the column width on purpose: the button row below sizes
   itself from that width, not from its own content.

   min-width:0 is unconditional, not scoped to the two-column breakpoint. A
   flex item's automatic minimum size is content-based, and this column's
   content includes a button whose label we do not control; without it, a label
   longer than the column widens the column and scrolls the whole page
   sideways. It has to hold in the STACKED layout too — that is where the
   viewport is narrowest and the failure is worst. */
.br-switching__content {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

/* --------------------------------------------------------------------------
   Long-word guard on the copy — the same argument as the CTA below, applied to
   the two elements above it.

   The shipped headline and lead break fine, but neither string is ours forever;
   a policy name, a URL or a hyphen-free compound pasted in later arrives as one
   unbreakable token. Measured before this rule: a 61-character token laid out
   909px wide inside a 288px box at 320 (1043 in 358 at 390, 1121 in 318 at 768)
   and `body { overflow-x: hidden }` in base.css swallowed the overflow with no
   scrollbar to reveal it — silent truncation, which is precisely the mechanism
   the CTA rule below spends 19 lines refusing to copy from the reference. It
   would have been incoherent to guard the button and not the words above it.

   `anywhere` rather than `break-word`, matching the CTA rule below. The two
   were measured against each other rather than argued about: the 61-character
   token is contained identically at 260/320/390/768/1024/1440, the 260-1700
   sweep gives zero rag divergence from the reference under either, and across
   five alternate headings x 321 widths both produce the same 11 mid-word
   breaks — every one of them a word that genuinely cannot fit its line
   ("recommendations" at 30px in a 228px box), which is the guard working, not
   a defect. Behaviourally identical, so consistency with the CTA decides it.

   Note the min-content reasoning that forces `anywhere` on the CTA does NOT
   apply here, even though the value is the same. The CTA is a flex item sized
   from its own content, so its min-content is load-bearing; the heading and
   lead are stretched to a column that already carries min-width:0, so their
   min-content sizes nothing and `break-word` would have worked too. Same
   value, different reason — worth knowing before someone "simplifies" the CTA
   rule to match on the assumption they share a cause.

   hyphens:auto is measured on the reference h2, and it does NOT travel alone —
   that is the trap. Copying `hyphens: auto` by itself changed the rag at
   260-262: the reference reads "Switching / brokers / is simple", ours became
   "Switching brok- / ers is simple", same 228px box, same 30px font. The
   reference also computes `hyphenate-limit-chars: 14 8`, so a word must reach
   14 characters before it may hyphenate at all, with 8 before the break and 8
   after. "brokers" is 7 and "Switching" is 9 — under the reference's limits
   nothing in this headline is eligible, which is why `auto` renders inert
   there and live here. Both properties are reproduced; taking one without the
   other is what produced the only rag divergence in the 1441-width sweep.

   The -webkit- pair is additive hardening, not a second opinion:
   hyphenate-limit-chars is Chromium/Firefox-only, so in Safari the standard
   property is dropped and `hyphens: auto` reverts to hyphenating short words —
   the reference has that same hole. before/after: 8 is the closest Safari
   equivalent (it cannot express the 14-character word minimum, so words of
   14-15 characters hyphenate in Chromium and not in Safari; nothing in the
   shipped copy is affected). Chromium ignores the prefixed pair, so this
   cannot move the rendering the side-by-side is judged on.

   The lead is left alone: the reference <p> computes `manual`, which is also
   the initial value, so restating it would be noise.
   -------------------------------------------------------------------------- */
.br-switching__heading,
.br-switching__lead {
  overflow-wrap: anywhere;
}

.br-switching__heading {
  hyphens: auto;
  hyphenate-limit-chars: 14 8;
  -webkit-hyphenate-limit-before: 8;
  -webkit-hyphenate-limit-after: 8;
}

/* The two measured gaps differ (1u above the lead, 4u/3 above the button), so
   they are stated as margins rather than one uniform flex `gap`.

   NO `text-wrap: pretty` HERE — considered, measured, declined. Reading this
   because you spotted the widow: yes, it is real, and it is deliberate.

   The lead ends on a one-word last line ("broker.") at 55 of the 1381 widths
   from 320 to 1700 — 351-352, 460-469, 656-663, 768-772, 825-826, 987-991,
   1296-1318. `text-wrap: pretty` clears all 55. It is still the wrong trade
   here, for two measured reasons:

   1. It breaks parity at 768 — a judged breakpoint, not an interstitial. The
      reference sets "…managed by your senior / broker."; `pretty` sets
      "…managed by your / senior broker." Phase-matched pixel diff of the whole
      section (_r5-px.mjs, both documents shifted to a common fractional y):

          width   shipped vs ref            with `pretty` vs ref
           390    0 px                      0 px
           768    0 px                      10617 px  (0.8113%, 9475 strong)
          1024    0 px                      0 px
          1300    0 px                      4741 px  (0.1434%, 4226 strong)
          1440    2 px                      2 px

      Zero becomes 0.81% at the one width most likely to be opened next to the
      reference after 1440 and 390.

   2. At the narrow cluster it is not the advertised "pull one word down". At
      351-352 it re-flows four of six lines — "gaps and exposures, then present
      clear / recommendations, pricing and next / steps — managed by your
      senior / broker." becomes "gaps and exposures, then present / clear
      recommendations, pricing / and next steps — managed by your / senior
      broker." A different paragraph shape, not a tidied last line.

   The contract for this rebuild is the blind side-by-side, and a divergence is
   a loss in either direction — including when ours is the better-set one. So
   the widow stays: it is the reference's rag, reproduced exactly, and the
   shipped build matches it at 1381 of 1381 widths.

   This is the second deliberate departure-decision in this file, and the
   opposite call to the CTA's 320px note below: there we broke fidelity because
   the reference's 34px tap target fails an accessibility floor on a real
   device. Here nothing fails — a widow is a taste defect, not a usability one
   — so fidelity wins. That is the line between the two.

   Same conclusion the shared base.css records twice (testimonials at 768,
   renewal at 480). Please do not re-add it without re-running
   `node scripts/_r5-widow.mjs 320 1700 1` and `node scripts/_r5-px.mjs`.

   HARNESS WARNING for whoever re-runs that sweep: run the documents
   SEQUENTIALLY. The first version of _r5-widow.mjs swept all three under
   Promise.all, and under three-browser contention `setViewportSize` had not
   reached the renderer before `evaluate` ran — every width was measured
   against a stale layout and it reported the exact inverse of the truth
   ("mine has 0 widows, ref has 55"). It is sequential now, with an explicit
   wait on innerWidth plus two rAFs, validated against fresh pages opened at
   each width. A concurrent rag sweep is not evidence. */
.br-switching__lead {
  margin-top: var(--br-flow-sm);
}

/* --------------------------------------------------------------------------
   Button row.
   Measured behaviour: the CTA fills the width when the row it sits in is 445px
   or narrower, and drops back to its natural width above that. That is a
   property of the ROW, not the viewport — at a 1200px viewport the copy column
   is 427px and the button goes full width, while at 1199px the column is 465px
   and it does not. A container query is the only honest way to say that.
   -------------------------------------------------------------------------- */
.br-switching__actions {
  container: br-switching-actions / inline-size;
  display: flex;
  flex-wrap: wrap;
  gap: var(--br-flow-2xs);
  margin-top: var(--br-flow-md);
}

/* The CTA must never be able to scroll the page sideways, whatever label it is
   given. .br-btn is nowrap by default — correct for a pill that sizes itself to
   its own text, wrong the moment the text is longer than the column it sits in.

   The reference "solves" this by letting the button grow past its column (742px
   inside a 447px column at 480) and relying on an ancestor with overflow:hidden
   to clip it — so the label is silently truncated. We do not copy that. Capping
   the pill at its column and letting the label wrap shows the whole label and
   still never scrolls. It costs no fidelity: a label that fits on one line is
   shrink-to-fit and measures exactly the same width either way, which the 1px
   sweep confirms at all 1381 widths.

   `anywhere`, not `break-word`, is the backstop for the one case wrapping
   alone cannot fix — a single unbreakable string longer than the column. The
   two look identical but only `anywhere` counts toward the element's
   min-content size, and min-content is exactly what stops the button (a flex
   item) from shrinking. With `break-word` a 61-character unbroken label still
   scrolled the page by 107px at 320; with `anywhere` it is 0 at every width.
   It does not touch max-content, so a label that fits is unaffected. */
.br-switching__cta {
  max-width: 100%;
  white-space: normal;
  overflow-wrap: anywhere;
}

/* Measured behaviour, reproduced: the pill fills the row at <=445px and returns
   to its natural width above it. */
@container br-switching-actions (max-width: 445px) {
  .br-switching__cta { width: 100%; }
}

/* Engines without container queries fall back to viewport bands.
   These are not guesses: sweeping the reference at 1px from 320 to 1700 gives
   full-width at 320–477, 768–1158 and 1200–1236, and natural width between.
   The middle band is the one that matters — 478–767 is stacked but the column
   is still wider than 445px, so the reference renders a natural-width pill
   there. Collapsing all of <768 to full width would be a visible 290px-wide
   fidelity break, so the three measured bands are stated separately. */
@supports not (container-type: inline-size) {
  @media (max-width: 477px),
         (min-width: 768px) and (max-width: 1158px),
         (min-width: 1200px) and (max-width: 1236px) {
    .br-switching__cta { width: 100%; }
  }
}

/* --------------------------------------------------------------------------
   Canvas — the gold block. aspect-ratio rather than a padding hack, so it can
   never clip and never needs a fixed height.
   -------------------------------------------------------------------------- */
.br-switching__canvas {
  position: relative;
  overflow: hidden;
  width: 100%;
  aspect-ratio: 3 / 4;
  background: var(--br-bg-gold);
  border-radius: var(--br-radius-lg);
}

/* THE DRAWING. Same 3:4 box the flat panel had, and the viewBox is 600x800 so
   one user unit is one CSS pixel at the panel's width at 1440 — every number
   in the markup can be read as the size it actually draws.

   Vocabulary lifted from assets/sketch-*.svg, which is what the founder asked
   it to sit beside: ink line at weight 5, round caps and joins, white fills,
   gold for the one accent per drawing. The difference is the ground — those
   are ink on cream inside a card, this is ink on the brand gold the panel
   already was, so nothing is drawn to re-establish a background. */
.br-switching__art {
  position: absolute;
  inset: 0;
  inline-size: 100%;
  block-size: 100%;
}

.br-switching__rim,
.br-switching__rim-accent,
.br-switching__thread {
  fill: none;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.br-switching__rim {
  stroke: var(--br-ink);
  stroke-width: 5;
}
/* Light on the top-left of the rim — WHITE, not gold.

   Gold was the obvious choice and it was wrong: the sketches it borrows from
   put gold on cream, and this panel's ground IS gold, so a gold arc over the
   ink rim did not read as an accent at all. It read as a hole — the rim
   appeared to break at the top-left and the circle looked unclosed.

   White is already in the drawing (the three badges) and it is the only value
   that reads as light against both the ink line and the gold behind it. */
.br-switching__rim-accent {
  stroke: var(--br-white);
  stroke-width: 9;
}

/* THE DRAWN STEPS. Every value below is taken off assets/sketch-*.svg rather
   than chosen to look similar to them — this is the same hand as those three,
   or it is a near-miss, and a near-miss is worse than an obvious difference. */
.br-switching__steps {
  stroke: var(--br-ink);
  stroke-width: 5;
  stroke-linecap: round;
  stroke-linejoin: round;
  fill: none;
}

/* `1 14` at weight 6 — the dotted arc that loops the broker in
   sketch-broker.svg, to the number. Not a dash: at this spacing the round cap
   makes each mark a dot, which is what stops it reading as a rule. It also
   CURVES, because nothing in those drawings is a straight horizontal line. */
.br-switching__thread {
  stroke-dasharray: 1 14;
  stroke-width: 6;
}

/* Drawn as a path so it is not perfectly round. A true circle sitting beside a
   hand-drawn one is the single detail that gives the whole style away. */
.br-switching__badge {
  fill: var(--br-white);
}

/* THE CREAM CARD, AND WHY EACH DRAWING NEEDS ONE.

   Gold is the accent in all three sketches — the tie, the filled bubble, the
   ticks, the paired energy marks. Every one of them sits on #FBF7EC, because
   those drawings live inside a white card on a white section.

   This panel's ground IS the brand gold. So the first pass lost exactly the
   marks that carry the style: the paper plane leaving step one and all three
   spark pairs were gold drawn on gold and rendered invisible. The gold ticks
   in step three survived only because they happen to sit on a white page.

   Same mistake as the rim accent earlier in this file, in a second place. The
   fix is not to recolour the accents — it is to give them the ground the
   reference gives them. Which also lands this panel on the same construction
   as .br-difference__figure: a cream rounded card with a drawing in it.

   --br-bg-wash is the token those cards already use for this exact job
   ("cream illustration tiles"), so this is the same surface rather than a
   colour that matches it today. */
.br-switching__card {
  fill: var(--br-bg-wash);
  stroke: none;
}

/* The white fill inside the drawing itself — the clipboard in
   sketch-review.svg, the speech bubble in sketch-comms.svg. Reads as paper
   against the cream, which is the separation the reference relies on. */
.br-switching__paper,
.br-switching__lens {
  fill: var(--br-white);
}

/* THE DRAWINGS ARE LIGHTER THAN THE FRAME AROUND THEM, and this is arithmetic
   rather than taste. Those sketches are ~300 units of drawing carrying a 5-unit
   line, about 1:60. Three of these fit across a 600-unit panel, so each is
   ~150 units — at weight 5 that is 1:30, twice as heavy, and the first pass
   came out as blobs with the counters filled in.
   3.4 restores the ratio the reference actually draws at. */
.br-switching__draw {
  stroke-width: 3.4;
}

/* Ruled lines: lighter again, as they are inside the shape they rule. */
.br-switching__rule {
  stroke-width: 3;
}

/* Gold does exactly two jobs in those sketches — it fills one shape, and it
   strokes the ticks. Both at a heavier weight than the ink around them, which
   is what makes an accent read as an accent and not as a thinner line. */
.br-switching__gold-fill {
  fill: var(--br-gold);
  stroke: var(--br-gold);
}
.br-switching__gold-stroke {
  stroke: var(--br-gold);
  stroke-width: 7;
}

.br-switching__handle {
  stroke-width: 9;
}

/* The paired ticks every one of the three sketches carries — the mark that
   says something moved. Gold, weight 6, no other job. */
.br-switching__spark {
  stroke: var(--br-gold);
  stroke-width: 6;
}

/* SVG text inherits none of the page's type sizing, so it is stated here.
   Both are centred on their own x, which is why every numeral and label in the
   markup carries one coordinate and no measured offset. */
/* stroke: none IS THE IMPORTANT LINE HERE. The steps group carries the ink
   stroke that draws every path inside it, and SVG text inherits stroke exactly
   as a path does — so the labels came out as 5-unit outlined lettering with
   the counters closing up, which is what the founder saw and called not
   styled like the rest of the page. Text is filled, never stroked. */
.br-switching__numeral,
.br-switching__label {
  text-anchor: middle;
  fill: var(--br-ink);
  stroke: none;
  paint-order: normal;
  font-family: var(--br-font-display, Archivo), system-ui, sans-serif;
}
.br-switching__numeral {
  font-size: 34px;
  font-weight: 800;
  /* `central` rather than a hand-tuned dy: it centres on the glyph box instead
     of the baseline, so the numeral stays in its badge under whatever font
     actually gets used. */
  dominant-baseline: central;
}
.br-switching__label {
  font-size: 25px;
  font-weight: 600;
}

/* The canvas WAS a flat colour block carrying nothing, so print and forced
   colours dropped it whole — half a page of nothing beside the copy. It
   carries a drawing now, and the drawing survives both: ink strokes and white
   fills are exactly what a forced palette and a printer can render.

   The photograph inside it does not survive forced colours — an <image> is not
   re-coloured, so it would be the one full-colour object in an otherwise
   forced palette. It goes; the circle it was clipped to stays, and reads as
   the empty rim of a diagram, which is honest. */
@media (forced-colors: active) {
  .br-switching__canvas { border: 1px solid CanvasText; }
  .br-switching__art image { display: none; }
}

@media print {
  .br-switching__canvas {
    background: none;
    print-color-adjust: economy;
  }
}

/* --------------------------------------------------------------------------
   768+ — two equal columns, centred on each other.
   -------------------------------------------------------------------------- */
@media (min-width: 768px) {
  .br-switching__layout {
    flex-direction: row;
    align-items: center;
  }

  .br-switching__content,
  .br-switching__canvas {
    flex: 1 1 0;
    /* .br-switching__content already carries min-width:0 unconditionally; the
       canvas needs it here because this is the only place it is a flex item. */
    min-width: 0;
  }

  /* Copy leads in source order and on screen; the canvas is the second column.
     Stated explicitly so the stacked order above stays copy-first. */
  .br-switching__canvas { order: 1; }
}

/* The column gap widens in two measured steps, both multiples of the same
   fluid unit the rest of the page is built on. */
@media (min-width: 992px) {
  /* 4u — the one step the flow scale doesn't already name (it runs …3u, 16u/3),
     so it is derived from --br-u rather than hard-coded as a pixel value. */
  .br-switching__layout { column-gap: calc(var(--br-u) * 4); }
}

@media (min-width: 1200px) {
  .br-switching__layout { column-gap: var(--br-flow-2xl); }
}
