/* ==========================================================================
   COVER — "Cover for every commercial exposure"
   --------------------------------------------------------------------------
   Depends on tokens.css + base.css. Load those first.

   HOW TO RE-VERIFY. Every number in this file comes out of one of these.
   Run them before changing anything here, and again afterwards — a claim in
   a comment is only worth what the next person can reproduce:

     node scripts/_c7-diff2.mjs <widths>   phase-aligned device-pixel diff
     node scripts/_c7-geom.mjs   <widths>  the measured constants, ref vs ours
     node scripts/_c7-root.mjs   <widths>  section height at root 16/18/20/24/32
     node scripts/_c7-fold.mjs   <range>   button-row fold + button boxes
     node scripts/_c7-widow.mjs  <range>   rag parity + the text-wrap trade
     node scripts/_c7-stress.mjs           hostile copy across 280-1920

   TWO WAYS TO MEASURE THIS SECTION WRONG, both of which have produced
   confident, wrong review findings on this file already:

   a) Clipping the preview from y=0. That captures the section's own
      collapsing top margin, which the reference clip taken at y=5091.78 does
      not — the reference clip starts at the section border-box. On its own
      it reads as a 56px vertical offset and a ~3% diff that is not there.
   b) Comparing renders whose fractional page-y differs. Glyphs rasterise per
      sub-pixel phase, so two identical layouts sitting at .29 and .78 of a
      pixel differ in every antialiased edge.

   _c7-diff2.mjs handles both: it measures both section border-boxes, bakes
   the offset into a copy of the preview so the fractional y matches, and
   only then screenshots. It BAKES the offset rather than setting it at
   runtime so both pages are plain first loads and get identical treatment.

   FIDELITY — measured 2026-08-18 with _c7-diff2.mjs at 41 widths:
   280 300 320 321 330 360 375 390 393 402 412 414 419 428 430 431 480 540
   576 640 700 744 768 800 834 900 960 992 1024 1100 1180 1200 1208 1280
   1366 1440 1512 1600 1728 1920 2560.

     38 of the 41 are 0.0000% different, at 0.00px of section-height
     difference. Not "under a tolerance" — zero differing pixels.
     The three exceptions are 280 (9.4709%), 300 (9.5790%) and 320
     (9.3686%). All three are deviation 1 below, all three are the same
     28px, and at all three the heading and the lead are pixel-identical:
     the entire difference is two buttons and everything they push down.
     1920 carries a 0.03px section-height difference at 0.0000% pixels.

   The 430px band, because a reviewer will look there: 430 (iPhone Pro Max)
   ran 0.9240% and 419 ran 0.8408% until 2026-08-18, when --br-h4-size was
   re-fitted in tokens.css. The cause was one shared token reaching its 18px
   shelf a viewport pixel early, so the lead was instantiated at 18.0000
   where the reference is still at 17.9999 — a different raster size for
   every glyph in the paragraph. It is a token-level fault, not a cover-level
   one; four other sections shared it. Both widths are 0.0000% now, and the
   old value reproduces both figures exactly if anyone wants to confirm the
   cause:
     C7_CSS=':root{--br-h4-size:clamp(1rem,0.636325rem + 1.81833vw,1.125rem)}' \
       node scripts/_c7-diff2.mjs 419,430

   THREE STATED DEVIATIONS FROM THE REFERENCE. All deliberate, all cost
   height, none is a miss. 1 is a founder call and is written up in
   rebuild/DECISIONS.md; 2 and 3 are judgement calls recorded here.

   1. BUTTON HEIGHT AT 320px AND BELOW — the one visible deviation, and the
      only thing in this section a viewer could name in a blind test.
      The reference steps its buttons down to padding 4px 12px / 34px tall
      at exactly 320 and back up to 11px 24px / 48px at exactly 321
      (_c7-fold.mjs 318-326). We hold 48px at every width.

      Cost, measured: +14px per button, +28px of section height at 280
      (775 v 747), 300 (764 v 736) and 320 (779 v 751), and the ~9.4% pixel
      figure above. Above 320 the deviation does not exist.

      Why 48: it is the same pill at every width, and 34px is under the 44px
      minimum in WCAG 2.5.5 on a phone-width CTA. Note honestly that 2.5.5 is
      a AAA criterion — the reference's 34x288 already clears 2.5.8 (AA,
      24x24) — so this is a brand-versus-conformance choice and not a
      technical one. It is the founder's to make, so it is in DECISIONS.md
      with the one-line switch either way, not settled inside a CSS comment.

      base.css already restores the reference's 12px inline padding below 321
      (see its @media (max-width: 320px) block), so the label still fits on
      one line: measured 48px tall, not 72px, at 280 through 320 at root 16.

   2. LONG WORDS BREAK INSTEAD OF BEING CLIPPED. Raise the browser's default
      font size and, on the two-column tablet layout, the heading's own words
      outgrow their column. The reference lets them overflow and has
      main{overflow:clip} cut them off, so the reader loses letters
      (_c7-root.mjs, widest word against the box that must hold it):

        768  / root 24  "commercial" 296.3px in a 289.8px box
        768  / root 32  "commercial" 363.8px in a 274.8px box
        1024 / root 32  "commercial" 395.1px in a 349.0px box
        320  / root 32  "commercial" 320.3px in a 256.0px box

      Root 32 is 200% of the default, so this is a WCAG 1.4.4 (Resize Text)
      failure, not a nicety. We break the word and keep every character.

      Cost, and it is only ever height: at root 32, section 1060.1 against
      the reference's 978.1 at 768, and 1008.5 against 951.5 at 1024. Across
      the full 5-width x 5-root grid (320/390/768/1024/1440 x 16/18/20/24/32)
      18 of 25 points are exact; the 7 that are not are the four ≤320 points
      from deviation 1, plus 320/768/1024 at root 32 where this rule fires.

      `hyphens: auto` was NOT added: it changes ordinary line breaking too,
      which would move the rag away from the reference on the signed-off copy
      at normal sizes to buy a nicer hyphen in a case almost nobody reaches.

   3. NOTHING ELSE. There is no third geometric deviation; this entry exists
      so the list cannot be read as "and probably some others".

   TWO CRAFT DECISIONS TAKEN AGAINST THE SECTION, both resolved in favour of
   the comp, both with the cost measured rather than asserted:

   • THE ONE-WORD LAST LINE. The lead ends on "program." alone at 40 of 101
     widths sampled 320-1920 (_c7-widow.mjs), including every desktop width
     from 1440 up. That rag is the reference's own — our rag matches it at
     101 of 101 — so this is inherited, not introduced. `text-wrap: pretty`
     on .br-cover__lead would fix it, and would change our rag at 44 of those
     101 widths (44%), including 320/768/784/800 where there is no widow to
     fix. base.css:255 records the same rejection globally after it cost the
     testimonials section 0.0041% -> 0.1963% at 768. Left alone; if the
     founder ranks craft above rag parity it is a one-line change here and
     the 44% is the number to weigh.

   • THE BUTTON-ROW FLAP AT 1200. Walking 1164-1212 one pixel at a time
     (_c7-fold.mjs), the CTAs stack at 1164-1166, sit side by side at
     1167-1199, stack again at 1200-1207 and unstack at 1208. It looks like a
     bug and it is not ours: the reference does exactly the same thing, 0
     fold mismatches and 0 section-height mismatches across all 49 widths.
     The cause is the container's max-width stepping at 1200, which narrows
     the text column back under the fold threshold. Lowering the container
     query from 445px to 438px removes the 1200-1207 stack (the row is
     441.63px there and the two buttons need 403.06px), at the price of the
     only fold disagreement with the comp on the whole axis. Left alone.

   Where a measured value already exists as a token it is used as a token —
   almost all of them, because this section rides the shared fluid unit
   (--br-u) end to end. Verified with _c7-geom.mjs at 390/768/1440/1920: our
   value equals the reference's to 2dp at every point, largest residual
   0.0001px (section padding, and the panel radius at 1440):

     grid gutter   = --br-flow-md   (4u/3)   32.14 @390 · 37.53 @1440 · 40 @1920
     heading→lead  = --br-flow-xs   (2u/3)   16.06 @390 · 18.77 @1440 · 20 @1920
     button gap    = --br-flow-2xs  (u/2)    12.05 @390 · 14.06 @1440 · 15 @1920
     panel radius  = --br-radius-lg (1u)     24.12 @390 · 28.15 @1440 · 30 @1920
     section pad   = --br-section-y (2u)     48.23 @390 · 56.31 @1440 · 60 @1920

   The three raw numbers that are NOT on the token scale — the 10px / 0.1fr
   spacer column and the 445px fold — are measured constants that describe
   this layout and nothing else on the page. Each is declared once, next to
   the measurement that produced it.
   ========================================================================== */

.br-cover {
  /* ----------------------------------------------------------------------
     Cover-only measured constants.
     ---------------------------------------------------------------------- */

  /* The middle grid track — a deliberate empty column that widens the
     figure/content gutter beyond the plain grid gap. Measured: a flat 10px
     from 768–991, then proportional (0.1fr) from 992 up. Net gutter between
     panel and text: 78.2 @768 · 108.6 @1024 · 130.6 @1440 · 145 @1920. */
  --br-cover-spacer: 10px;
  --br-cover-spacer-fr: 0.1fr;

  padding-block: var(--br-section-y);
  /* Measured: the reference carries an equal outer margin as well as the
     inner padding, and adjacent sections collapse against it — so the gap
     between two sections is 2u, not 4u. Reproduced as a margin so the
     collapse still happens on assembly. */
  margin-block: var(--br-section-y);
}

/* --------------------------------------------------------------------------
   GRID
   Mobile: one column, stack then panel.
   768+:   panel | spacer | text, two rows so the heading block can sit hard
           against the actions row with exactly one gutter between them.
   Both columns are centred against each other; the panel's 4:3 ratio sets
   the row height and the text stack is centred inside it.
   -------------------------------------------------------------------------- */
.br-cover__grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  grid-template-areas:
    "content"
    "actions"
    "figure";
  gap: var(--br-flow-md);
  align-items: center;
}

@media (min-width: 768px) {
  .br-cover__grid {
    grid-template-columns: minmax(0, 1fr) var(--br-cover-spacer) minmax(0, 1fr);
    grid-template-areas:
      "figure . content"
      "figure . actions";
  }
}

@media (min-width: 992px) {
  .br-cover__grid {
    grid-template-columns: minmax(0, 1fr) var(--br-cover-spacer-fr) minmax(0, 1fr);
  }
}

/* --------------------------------------------------------------------------
   TEXT STACK
   Bottom-aligned in the upper row so that the distance from the lead down to
   the buttons is exactly one gutter, whatever the copy does. Measured @1440:
   lead baseline block ends 5435.70, buttons start 5473.23 → 37.53 = 1 gutter.
   -------------------------------------------------------------------------- */
.br-cover__content {
  grid-area: content;
  align-self: end;
  display: flex;
  flex-direction: column;
  gap: var(--br-flow-xs);
}

/* WRAPPING — the two blocks break on DIFFERENT algorithms. An earlier
   revision of this file forced both onto greedy and the comment defending it
   was wrong about the heading; both are corrected here.

   Heading: the reference h2 computes `text-wrap: balance` at every width
   sampled from 320 to 1920. Greedy strands a one-word widow as soon as the
   column is wide enough to fit "Cover for every commercial" on one line — at
   1600 greedy breaks 605/204 where the reference breaks 338/471, at 1920
   648/219 vs 362/505. That band contains 1536/1600/1680/1728/1792/1920, i.e.
   most laptops and desktops in use.

   Lead: the reference p is greedy (computed `wrap`). `pretty` reflows it at
   1440 to avoid the one-word last line — it moves "coherent" down and gives
   "…structured into one / coherent program." where the reference reads
   "…structured into one coherent / program."

   base.css already sets exactly that pair globally — `h1–h6 { balance }` and
   `p { auto }` — so the correct rule here is NO rule. The override is deleted
   rather than restated, so this section cannot drift from the global default.
   Measured line counts now held to: heading 2 @390 · 3 @768 · 2 @1440 · 2
   @1920; lead 5 @390 · 6 @768 · 4 @1440. */

/* WRAP GUARD — one unbreakable token must not move the page.
   A pasted URL, a German compound or an unspaced product name is a single
   token with no break opportunity in it. Without a guard the heading sets
   that token at full width and drags the document with it: measured on this
   section with a 57-character word in the heading, documentElement
   .scrollWidth went to 869 at a 320 viewport, 996 at 390, 1475 at 768 and
   2078 at 1440 — the whole page scrolls sideways, not just the heading. The
   lead does the same with a bare URL, and the lead is the element far more
   likely to receive one.

   The reference has the identical weakness and hides it with overflow:clip
   on <main> — i.e. it keeps the layout still by cutting the word in half and
   never showing the reader the rest. Breaking it is the better answer: the
   text stays whole and legible AND the page stays put.

   Declared here even though base.css carries a global guard, because this
   section has to be correct on its own — a section that only holds together
   while a shared file happens to contain a particular rule is a section that
   breaks the first time somebody edits that file.

   `anywhere`, not `break-word`, and the difference is deliberate. The two
   break lines identically; `anywhere` additionally lets the element report a
   smaller min-content width. base.css picks `break-word` globally because it
   cannot know what its headings sit inside, and a min-content-sized ancestor
   would collapse. Here it can be known: every track in .br-cover__grid is
   minmax(0, 1fr), an explicit zero floor, so there is nothing to collapse —
   which buys the stronger guarantee for free on assembly, where this section
   will be nested inside containers this file does not own.
   Verified: zero line-break changes on the signed-off copy at 280 through
   1920, and scrollWidth back to exactly the viewport with scrollX 0 at every
   width, with and without base.css's global rule present. */
.br-cover__heading,
.br-cover__lead { overflow-wrap: anywhere; }

/* MEASURE — the lead's 604px cap is an md-and-up rule on the reference, not a
   universal one. Below 768 the reference paragraph runs the full column: at a
   740px viewport it is 676px wide, not 604. Capping at every width mis-wrapped
   the lead across 724–764px — [565,595,328] here against [660,668,159] on the
   reference — and iPad mini portrait (744pt) sits inside that band.

   Declared here rather than by putting .br-measure on the element, because the
   breakpoint scoping is specific to this section and other sections depend on
   .br-measure staying unconditional. Measured: 604 only starts to bind above
   ~1590, where it holds the lead at 604 while the heading beside it runs on
   to 648. */
.br-cover__lead { max-width: none; }

@media (min-width: 768px) {
  .br-cover__lead { max-width: 604px; }
}

/* --------------------------------------------------------------------------
   ACTIONS
   Top-aligned in the lower row, mirroring the text stack above it.
   -------------------------------------------------------------------------- */
.br-cover__actions {
  grid-area: actions;
  align-self: start;
  display: flex;
  flex-wrap: wrap;
  gap: var(--br-flow-2xs);
  container: br-cover-actions / inline-size;
}

/* A label can never be wider than the row that holds it, and it can always
   wrap. Both unconditional, and that is the fix for a bug an earlier revision
   of this file introduced while claiming to have solved it.

   That revision released `.br-btn`'s `white-space: nowrap` only INSIDE the
   fold below, reasoning that a full-width button is the only one an
   unbreakable label can escape from. Wrong: it leaves a dead band just above
   the fold threshold where the row is wide enough to stay horizontal but too
   narrow for the label, and there nowrap is still in force with nothing
   containing it. Measured with a 68-character primary label, stepping the
   viewport in 4px increments: documentElement.scrollWidth ran past the
   viewport from 480 (495) to 508 (509) and only closed at 512 — the whole
   page scrolling sideways, which is precisely the failure the old comment
   reasoned about. It was missed because that comment cites measurements at
   390 and 768, and the band sits between them.

   Making both declarations unconditional removes the band rather than moving
   it. The container query below is then responsible for one thing only —
   whether the buttons sit side by side or stack — which is what a fold should
   decide. Verified: no overflow at any width from 280 to 1920 with the long
   label, and today's copy is pixel-identical, because it fits on one line at
   every width regardless. */
.br-cover__actions > .br-btn {
  max-width: 100%;
  white-space: normal;
}

/* The row folds to full-width stacked buttons when the ROW — not the viewport
   — drops below 445px. Measured, and it has to be a container query: the same
   row is 447px wide at a 480px viewport (side by side) and 442px wide at a
   1200px viewport (stacked), because the two-column split halves it. No media
   query can express a fold that reverses twice on the way up. */
@container br-cover-actions (max-width: 445px) {
  .br-cover__actions > .br-btn { width: 100%; }
}

/* Browsers without container queries get the same fold, keyed to the two
   viewport ranges where the row is actually narrow (below 480, and 768–1279
   where the two-column split halves it). Same result, coarser hinge. No
   white-space toggling here either, for the same reason as above — the
   fallback would otherwise carry the dead band the real query no longer has. */
@supports not (container-type: inline-size) {
  .br-cover__actions > .br-btn { width: 100%; }

  @media (min-width: 480px) and (max-width: 767.98px) {
    .br-cover__actions > .br-btn { width: auto; }
  }
  @media (min-width: 1280px) {
    .br-cover__actions > .br-btn { width: auto; }
  }
}

/* --------------------------------------------------------------------------
   PANEL
   Measured: 4:3, full column width, radius 1u, #3a341c (--br-bg-dark-alt).
   Flat by design — no image, no overlay, no border.
   -------------------------------------------------------------------------- */
.br-cover__figure {
  grid-area: figure;
  position: relative;
  overflow: hidden;                 /* photograph and drawing both clip to the corner */
  isolation: isolate;               /* the photo's blend must not reach the section behind */
  width: 100%;
  aspect-ratio: 4 / 3;
  border-radius: var(--br-radius-lg);
  background-color: var(--br-bg-dark-alt);

  /* The panel is empty, so its type is invisible — which is exactly why it
     was wrong. It inherited the body scale (18 / 26 / +0.18px at 1440) while
     the reference's equivalent inherits 14 / 21.7 / -0.084px, flat at every
     width and every root font size. That is our --br-small scale to the
     decimal. Nobody could see the difference today; the first caption, badge
     or "Photography to come" placeholder to land in this box would have set
     one scale step too large and nobody would have known why. Stated as a
     decision rather than left as an accident. */
  font-size: var(--br-small-size);
  line-height: var(--br-small-lh);
  letter-spacing: var(--br-small-ls);
}

/* Windows High Contrast (and any forced-colors mode) discards author
   background-color. Without this the panel becomes an invisible box that
   still occupies its space — 554.72x416.03 at 1440, 288x216 at 320 — so the
   desktop reads as text in the right-hand column beside a large empty half,
   and mobile gets 216-416px of dead white under the buttons. It carries no
   information, so nothing is lost, but the result reads as broken rather
   than as minimal.

   Two things, because either alone still fails somewhere. The fill opts out
   of the override so the brand block survives: this is a decorative colour
   field with no text on it, so there is no contrast pairing to break, which
   is exactly the case forced-color-adjust exists for. But #3a341c sits at
   1.4:1 on a black Canvas, so on a dark forced theme the fill alone would
   disappear all over again — hence the system-coloured hairline, which is
   guaranteed to contrast with whatever background the user chose. Between
   them the panel is a defined shape in every forced theme. */
/* THE PANEL HAS TO STAY DARK, and this is the second attempt at it.

   The first used mix-blend-mode: luminosity against the panel's #3a341c. That
   takes the LUMINANCE of the photograph and the hue of the backdrop, and this
   photograph is a bright one — two men against an overcast sky — so the result
   was a pale gold-brown rectangle. Measured against the page it sits on: the
   panel's top-left corner came out within a few percent of the white section
   background, which meant the rounded corner stopped being visible and the
   block stopped being a block.

   That matters beyond this one panel. The page alternates light and dark
   sections deliberately, and this is the dark beat between two light ones.

   So: no blend, and the darkening is done in the filter where it is
   predictable. brightness() below half sets the value, contrast() puts back
   the separation that darkening costs, and the partial greyscale keeps the
   hi-vis orange from being the loudest thing in a panel whose accent is meant
   to be gold. The panel's own #3a341c still shows at the edges of the cover
   crop, so the box keeps its colour rather than being replaced by one. */
.br-cover__photo {
  position: absolute;
  inset: 0;
  inline-size: 100%;
  block-size: 100%;
  margin: 0;
  border-radius: 0;
  object-fit: cover;
  filter: grayscale(0.62) brightness(0.46) contrast(1.12);
}

/* THE DRAWING. Founder's brief: not just a panel with a photo — a graphical
   element abstractly involved in the picture.

   Vocabulary borrowed from the three sketches in "The Broad Risk difference":
   brand gold, round caps, one weight for structure and a lighter one for the
   echo. What it must NOT borrow is their cream ground and ink outline — those
   are drawings ON a card; this is a figure OVER a photograph.

   preserveAspectRatio="slice" on the <svg>, so the drawing crops with the
   photograph rather than squashing when the panel's 4:3 meets a narrow
   column. */
.br-cover__mark {
  position: absolute;
  inset: 0;
  inline-size: 100%;
  block-size: 100%;
  pointer-events: none;
}
.br-cover__mark-ring,
.br-cover__mark-arc {
  fill: none;
  stroke: var(--br-gold);
  stroke-linecap: round;
}
.br-cover__mark-ring {
  stroke-width: 4;
  opacity: 0.62;
}
/* Heavier and fully opaque: the quadrant that reads as drawn rather than
   generated, which is what stops the ring looking like a border. */
.br-cover__mark-arc { stroke-width: 9; }
.br-cover__mark-dot { fill: var(--br-gold); }
/* Low enough to read as a tint of the panel rather than a gold shape sitting
   on it — it is there to weight the corner, not to be looked at. */
.br-cover__mark-wedge { fill: var(--br-gold); opacity: 0.16; }

@media (forced-colors: active) {
  .br-cover__figure {
    forced-color-adjust: none;
    background-color: var(--br-bg-dark-alt);
    border: 1px solid CanvasText;
  }
  /* The drawing is positioned against the photograph. With the photograph
     gone the ring hangs on nothing, so both leave together. */
  .br-cover__photo,
  .br-cover__mark { display: none; }
}

/* Same reasoning as the renewal block: print the picture, lighter, rather than
   a solid dark rectangle. */
@media print {
  .br-cover__figure {
    background-color: transparent;
    print-color-adjust: economy;
  }
  .br-cover__photo {
    mix-blend-mode: normal;
    filter: none;
    opacity: 1;
  }
  .br-cover__mark { display: none; }
}
