/* =============================================================
   Chemist2U — section components

   One block per part in src/parts/. Everything is scoped under
   .c2u-page and prefixed .c2u-, so nothing here can leak into the
   rest of the Divi site (and Divi cannot easily reach in).

   Deliberately unlayered — see the note in c2u-tokens.css.
   ============================================================= */


/* ── Hero ────────────────────────────────────────────────────────  */

/* The hero sits on the fixed page gradient (see c2u-base.css), so it carries no
   background of its own. The soft radial glow this section used to paint is
   gone — the page gradient already supplies that light, and stacking the two
   muddied it. */
.c2u-hero {
  /* Media geometry. Both values fall between steps of the global scales
     (radius md 14 / lg 24, space-4 16 / space-5 24), so the hero owns them
     locally rather than bending a shared token for one section. */
  --c2u-hero-media-radius: 16px;
  --c2u-hero-media-gap: 20px;

  /* The air above the first thing in the hero. Named rather than written
     into the padding, because two other things are set against it: the
     statement hero's bottom edge and the gap between its headline and the
     photographs, both of which are meant to be this exact figure. */
  --c2u-hero-top: clamp(56px, 3.5rem + 2vw, 88px);

  position: relative;
  padding-block: var(--c2u-hero-top) var(--c2u-section-y);
}

/* Headline block. Held to 8 of 12 columns so the line breaks fall where the
   copy intends and the right-hand third stays open for the circular tagline,
   which floats up into it from the grid below. */
.c2u-hero__top {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  align-items: center;
  gap: var(--c2u-space-6) var(--c2u-space-5);
}

.c2u-hero__intro { grid-column: 1 / span 8; }

.c2u-hero__eyebrow { margin-block-end: var(--c2u-space-5); }

.c2u-hero__headline {
  /* Generous enough that an explicit line ("No extra marketing.") never wraps,
     while still capping a plain string headline on the other pages. */
  max-width: 24ch;
  color: var(--c2u-navy);
}


/* Hero grid — see the layout diagram in parts/hero.php.
   Placement is explicit so DOM order can stay in the mobile order. */

.c2u-hero__grid {
  position: relative;                /* containing block for the circular tagline */
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: var(--c2u-space-7) var(--c2u-hero-media-gap);
  margin-block-start: var(--c2u-space-8);
}

.c2u-hero__media          { grid-row: 1; }
.c2u-hero__media--wide    { grid-column: 1 / span 6; }
.c2u-hero__media:nth-of-type(2) { grid-column: 7 / span 3; }
.c2u-hero__media:nth-of-type(3) { grid-column: 10 / span 3; }

/* Optional media layout — the wide photo centred between the two squares,
   chosen per call with the part's `media_layout: 'wide-center'`. The wide box
   moves to the middle and the first square takes its place on the left; the
   right square stays at 10–12, where the circular tagline is pinned to ride it.
   Placement is explicit, so the wide photo stays DOM-first (the LCP image, the
   only one kept on mobile) while rendering between the two.

   Desktop only, in a min-width query on purpose: below 981px the media stacks
   (see the breakpoints below), and these rules out-specify the stacked ones —
   left unscoped they would keep the centred columns down into the stack. */
@media (min-width: 981px) {
  .c2u-hero--wide-center .c2u-hero__media--wide          { grid-column: 4 / span 6; }
  .c2u-hero--wide-center .c2u-hero__media:nth-of-type(2) { grid-column: 1 / span 3; }
}

.c2u-hero__actions { grid-row: 2; grid-column: 1 / span 3; }
.c2u-hero__subhead { grid-row: 2; grid-column: 7 / span 6; }

.c2u-hero__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: start;
  gap: var(--c2u-space-3);
}

/* The hero CTA is the page's one primary action, so it runs a size above the
   shared button. (0,2,0) clears the base .c2u-btn (0,1,0) and sets nothing the
   .c2u-page .c2u-btn--primary colour rule also sets, so the two compose. */
.c2u-hero__actions .c2u-btn {
  padding: var(--c2u-space-4) 36px;
  font-size: 20px;
  letter-spacing: -0.03rem;
}

.c2u-hero__subhead {
  max-width: none;                 /* the column defines the measure here */
  color: var(--c2u-navy);
  opacity: .82;
}


/* Circular tagline — rides the top edge of the last photo, mostly clear of it
   with the bottom of the ring lapping over the corner.

   It is given a grid placement *and* absolute positioning, which is not a
   contradiction: for an out-of-flow child of a grid container, an explicit
   placement makes that grid area the containing block. So `top: 0` means the
   top edge of that photo and `inset-inline: 0` means its two sides — the
   offsets track the 12-column grid on their own, with none of its maths
   restated here and nothing to re-tune when a column width changes.

   The wrapper stretches across the photo and centres the ring inside itself,
   rather than being positioned by its own edge — the ring's size is fluid, so
   any inset written against it would drift as the viewport changed. */
.c2u-hero__circular {
  /* How much of the ring clears the photo's top edge. Percentage of the ring
     itself, so the overlap holds its proportion at every size. */
  --c2u-hero-circular-rise: 120%;

  position: absolute;
  grid-column: 10 / span 3;
  grid-row: 1;
  top: 0;
  inset-inline: 0;
  z-index: 1;                      /* over the photo, which is not positioned */
  display: flex;
  justify-content: center;
  transform: translateY(calc(-1 * var(--c2u-hero-circular-rise)));
  /* The wrapper is a wide invisible band lying over the photo, so it gives up
     the cursor — but the ring itself keeps it, or the hover speed-up in
     c2u-page.js would never fire. */
  pointer-events: none;
}
.c2u-hero__circular .c2u-circular { pointer-events: auto; }


/* Media */

.c2u-hero__media {
  margin: 0;
  overflow: hidden;
  border-radius: var(--c2u-hero-media-radius);
}

/* Only the narrow items carry an aspect ratio — they set the row height, and
   the wide one stretches to match. Giving all three a ratio would fight. */
.c2u-hero__media:not(.c2u-hero__media--wide) { aspect-ratio: 1 / 1; }

.c2u-hero__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform var(--c2u-base) var(--c2u-ease);
}

/* Hover zoom — the photo scales inside the figure, which already clips to the
   rounded corners, so the frame stays put and only the image moves.

   Scoped to img on purpose: the placeholder <span> is a temporary grey block
   with nothing to zoom. Timed with the interaction tokens rather than the
   entrance ones — --c2u-ease is the curve the buttons and the logo fade use,
   so every hover on the page eases identically.

   The transform is on the image, not on the figure: the figure's own transform
   is spoken for by the reveal animation in c2u-motion.css, and a second one
   here would be overwritten the moment the hero plays in. */
.c2u-hero__media:hover img { transform: scale(1.04); }

/* The wide item is the one with no ratio of its own on desktop, so its photo
   must not be allowed to size it — an in-flow image contributes its intrinsic
   height to the row, and the row would then be set by whatever the photo was
   exported at rather than by the squares. That is not hypothetical: the two
   only agree at one viewport width, because the box is six columns plus five
   fixed gaps against three plus two, and that proportion drifts as the columns
   shrink while the gaps do not. The photo won, by a couple of pixels, and the
   bottom edges stopped lining up.

   Out of flow it contributes nothing, so the squares set the row and the wide
   box stretches to it, as intended above. Below 980px the box has a ratio of
   its own and none of this applies — the rule is harmless there.

   Scoped to img: a placeholder <span> is still in flow, so a hero with no
   photography yet keeps its 200px floor. */
.c2u-hero__media--wide { position: relative; }
.c2u-hero__media--wide img { position: absolute; inset: 0; }

/* TEMPORARY — stands in until real photography is supplied. Delete this rule
   and the <span> in parts/hero.php once every item has a src. */
.c2u-hero__media-placeholder {
  display: block;
  width: 100%;
  height: 100%;
  min-height: 200px;
  background: #d6dade;
}


/* ── Hero photo strip ────────────────────────────────────────────────────
   parts/hero-statement.php — one edge-to-edge row of squares under the
   headline, each sitting at its own height.

   EDGE TO EDGE COSTS NOTHING HERE, because the strip is not in
   .c2u-container: .c2u-hero pads its block edges only, so a block child of
   the section is already the page's full width. That is a real width, not
   100vw — it excludes a classic scrollbar, and 100vw does not (see the card
   wheel's note further down for what that costs).

   THE SQUARES ARE THE COLUMNS. Equal tracks and a fixed gap, so the tile
   size is whatever the screen leaves; aspect-ratio makes it square from
   there and nothing has to be measured. minmax(0, 1fr) rather than a bare
   1fr for the reason the hero grid gives on mobile — auto is the floor
   otherwise, and one item that will not shrink widens every track.

   THE OFFSETS ARE THE COMPOSITION, and they are held as fractions of the
   TILE rather than in the pixels they were drawn at. That is the one
   decision in this block worth defending, because px would be the obvious
   way to write down a design handed over in px.

   The tile is not a fixed size. It is a fifth of the screen above 767px and
   a third of it below, so it runs from about 114px on a phone to 269px at
   the container width and on past it — and it takes a step UP at the
   breakpoint, where five tracks become three. Pixel offsets tuned at one of
   those sizes are a different composition at every other one, and at the
   breakpoint they are a discontinuity: the tiles nearly double and the
   stagger between them does not move. Stated against the tile, the row is
   the same arrangement at every width, and neither the 980px query nor the
   767px one has to say anything about it.

   --c2u-strip-rise is what keeps every margin positive: the highest tile's
   drop, negated. Change a drop above that -.179 and this moves with it, or
   the top of the strip laps back over the headline.

   Spent as margins rather than transforms, so the strip's box knows about
   them — the row is genuinely as tall as its tallest arrangement, and what
   follows clears it — which leaves transform free for the drift in
   c2u-motion.css. One transform per element, no negotiation.             */

.c2u-hero__strip {
  --c2u-strip-cols: 5;
  --c2u-strip-gap: 24px;

  /* Headroom for the tiles that sit ABOVE the baseline, so no margin below
     is negative: -min(--c2u-tile-drop), over the tiles actually being shown.
     Not derivable in CSS, so it is stated — and it is stated per layout,
     because which tiles are shown changes at the phone breakpoint and the
     highest of them changes with it. Get it wrong high and the strip carries
     dead air under the headline; wrong low and the top of the row laps back
     over it. Five up, the third tile is the highest at -.179. */
  --c2u-strip-rise: .179;

  display: grid;
  grid-template-columns: repeat(var(--c2u-strip-cols), minmax(0, 1fr));
  gap: var(--c2u-strip-gap);
  align-items: start;

  /* To the TOPMOST tile, which is the third — the rise above pays the rest.
     The hero's own top padding, so the headline sits in equal air: the same
     gap above it as below it, at every width, since both are one value. */
  margin-block-start: var(--c2u-hero-top);
}

.c2u-hero__tile {
  --c2u-tile-drop: 0;

  margin: 0;
  /* 100% IS ONE TILE, and nothing has to compute that. A grid item's margin
     percentages resolve against the inline size of its containing block,
     which for a grid item is its grid area — here one column, which is the
     tile. So the row minus its gaps over the column count, the obvious way
     to write this, would be resolving that same figure a second time against
     itself. (The drift in c2u-motion.css also says 100% and also means one
     tile, by a different route: a percentage inside a transform resolves
     against the element's own box, and these are square.) */
  margin-block-start: calc(
    (var(--c2u-strip-rise) + var(--c2u-tile-drop)) * 100%
  );
  aspect-ratio: 1 / 1;
}

/* Read as a set: each is the previous one plus or minus the step the design
   names. 1 is the baseline, 2 sits 64 below it, 3 is 112 above 2, 4 is 72
   below 3, 5 is 64 above 4 — the comments are those steps as drawn, against
   the 269px tile the five-up row gives at the 1440px container. */
.c2u-hero__tile:nth-child(1) { --c2u-tile-drop:  0;    }   /*    0px */
.c2u-hero__tile:nth-child(2) { --c2u-tile-drop:  .238; }   /*  +64px */
.c2u-hero__tile:nth-child(3) { --c2u-tile-drop: -.179; }   /*  -48px */
.c2u-hero__tile:nth-child(4) { --c2u-tile-drop:  .089; }   /*  +24px */
.c2u-hero__tile:nth-child(5) { --c2u-tile-drop: -.149; }   /*  -40px */

/* The frame. It clips and it carries the radius, so the tile above is left
   holding nothing but position — which is what lets the drift transform sit
   on the tile and the entrance transform sit here, one each.

   The radius is the hero's own --c2u-hero-media-radius, so these round
   exactly as the photographs on the other three pages do. */
.c2u-hero__tile-in {
  display: block;
  width: 100%;
  height: 100%;
  overflow: hidden;
  border-radius: var(--c2u-hero-media-radius);
}

/* THE TWO ENDS RUN OFF THE PAGE, so they give up the corners that meet the
   screen edge — a rounded corner there reads as a card that has been placed
   short of the edge rather than as a photograph continuing past it.

   The right-hand rule is the column count and not :last-child, which is the
   whole subtlety: below 767px the fourth and fifth tiles are display:none,
   and display:none does not change what :last-child matches — it would keep
   flattening a tile nobody can see while the third one, now at the edge, kept
   its corners. So each layout names its own end tile. */
.c2u-hero__tile:first-child .c2u-hero__tile-in {
  border-start-start-radius: 0;
  border-end-start-radius: 0;
}

.c2u-hero__tile:nth-child(5) .c2u-hero__tile-in {
  border-start-end-radius: 0;
  border-end-end-radius: 0;
}

.c2u-hero__tile-in img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform var(--c2u-base) var(--c2u-ease);
}

/* The hover zoom the hero's photographs already have, for the same reason it
   is on the image rather than the figure there: the figure's transform is
   spoken for — by the entrance on the other pages, by the drift on this one. */
.c2u-hero__tile:hover .c2u-hero__tile-in img { transform: scale(1.04); }

/* Phone — two up. Five across a 390px screen is a 59px thumbnail, which is
   not a photograph of anything; two is 187px and carries a face.

   WHICH TWO IS NAMED HERE, and that is a departure worth being explicit
   about. Everywhere else the call site decides what appears by the order it
   passes things in, and this block used to honour that by keeping the first
   n. It does not any more: the phone shows the row's SECOND and FOURTH
   tiles, so the pair is chosen by position in this file and reordering the
   array at the call site will not change it. The two are photographs 05 and
   03 as the array currently stands; move the array and this moves with it or
   the phone silently shows something else.

   Changing the column count still does most of the work — the tile size is
   derived from it and the offsets from the tile, so the row and the stagger
   both grow on their own. What does not derive is anything that depends on
   WHICH tiles are showing, and each of those is below. */
@media (max-width: 767px) {
  .c2u-hero__strip {
    --c2u-strip-cols: 2;

    /* The two on show drop .238 and .089, so the fourth tile is the higher
       one and the rise is its drop, negated: that tile lands flush with the
       top of the row and the second sits .149 of a tile under it, which is
       the gap the two of them have on desktop, scaled. Left at the five-up
       .179 the strip would open with a tile's worth of empty space where the
       third photograph would have been, and the headline would no longer sit
       in the equal air --c2u-hero-top buys it. */
    --c2u-strip-rise: -.089;

    /* Tighter, because the gap is the one thing in this row that does not
       scale with the screen: at 24px it is an eighth of a phone's tile
       against a tenth of a desktop one, and it is the only seam in a row of
       two, so it is the difference between one row and two pictures. */
    --c2u-strip-gap: 16px;
  }

  .c2u-hero__tile:nth-child(1),
  .c2u-hero__tile:nth-child(3),
  .c2u-hero__tile:nth-child(5) { display: none; }

  /* The ends of the row are now the second and fourth tiles, so they are the
     ones that give up the corners meeting the screen edge. The first and
     fifth keep their rules above and it costs nothing — they are hidden
     here, so their corners are nobody's business. */
  .c2u-hero__tile:nth-child(2) .c2u-hero__tile-in {
    border-start-start-radius: 0;
    border-end-start-radius: 0;
  }
  .c2u-hero__tile:nth-child(4) .c2u-hero__tile-in {
    border-start-end-radius: 0;
    border-end-end-radius: 0;
  }
}


/* ── Hero, arc variant ───────────────────────────────────────────────────

   parts/hero-arc.php. Brand Home's hero: a headline, then the tagline set
   around a huge arc, then a row of photographs on a wider arc still. This
   block holds the first of the three; the two arcs land here as they are
   built, and the drift for both is in c2u-motion.css.                      */

.c2u-hero--arc {
  /* THE MEASURING STICK FOR EVERYTHING BELOW. Both arcs are circles a
     multiple of the viewport wide, and the only way for their curvature to
     read the same at 1440 and at 390 is for every length in them — radius,
     type, tile, gap — to be a share of one width. Declaring the container
     here rather than on an inner wrapper is what lets the arcs sit outside
     .c2u-container (they run past both edges) and still measure against the
     same figure the headline does.

     It also makes this element the containing block for the absolutely
     positioned arcs, which is what keeps two boxes several viewports wide
     from reaching the page and giving it a horizontal scrollbar. */
  container-type: inline-size;

  /* Aim for a screenful, but stop asking at 820px. A hero pinned to 100svh
     has to be re-composed for every short wide laptop; a floor lets the
     composition come to its own height — about 900px at 1440 once both arcs
     are in — and simply hang below the fold where the screen is shorter than
     it. The one thing this guarantees is that the section never collapses
     when the arcs are absent or clipped away. */
  min-block-size: min(100svh, 820px);

  /* Closes as it opens, for the reason .c2u-hero--statement does: this is one
     composition and it reads as one only if the air around it is even. */
  padding-block-end: var(--c2u-hero-top);
}

.c2u-hero__headline--arc {
  /* Not the fit mechanism --c2u-brand-size runs (see below). That exists to
     hold one sentence on one line and sizes the type from how wide the screen
     happens to be; this headline is one sentence deliberately broken across
     two lines, so the measure is fixed and the type is sized against the
     viewport directly. 5.6cqw is ~81px at 1440; the clamp holds it readable
     on a phone and stops it running away on a wide desktop. */
  font-size: clamp(38px, 5.6cqw, 88px);

  /* Where the line breaks. Two lines is the shape the copy wants, and at this
     size 15ch is what puts the break after "the". text-wrap: balance then
     evens the two rather than leaving a short second line; browsers without
     it wrap normally at the same measure, which is the same break for this
     copy. */
  max-width: 15ch;
  text-wrap: balance;

  /* Tight, because two lines of one sentence at this size read as a single
     block and the display scale's 1.04 is what that block is set against.
     See the word-mask correction below — this line-height is only safe with
     it. */
  line-height: 1.08;

  margin-inline: auto;
  text-align: center;
}

/* PHONE — as large as three lines allow.

   The clamp above is written for the two-line shape the copy was broken for,
   and its 38px floor is what a phone gets. But a phone cannot hold that
   sentence on two lines at any readable size — it falls to three — and three
   lines allow far more than 38px: at 390px the break "Don't let life / get in
   the way / of your health" holds to 57px before a fourth line appears.

   THE CEILING IS A SHARE OF THE SCREEN, not a number, because it is the point
   where the longest of the three lines runs out of column. Measured across the
   range it sits at 46px at 320, 52 at 360, 55 at 375, 57 at 390, 64 at 430 —
   between 14.4% and 14.9% of the viewport throughout. 13.4cqw sits a clear
   step under the lowest of those — 52px at 390 against a 57px ceiling — which
   is deliberately not the maximum: the maximum was tried and read as too big
   for the space. Re-measure that percentage if this sentence changes; the
   ceiling is a property of the copy, not of the layout.

   320px IS STILL THE BINDING CASE, at 42.9px against a ceiling between 46 and
   47. That is about three pixels of room, where the ceiling-chasing version of
   this had under one. If the ramp is ever raised again, that is the end that
   runs out first.

   THE CAP IS WHERE THIS STOPS CHASING THE SCREEN. Left uncapped the ramp would
   reach 103px at 767 — past the three-line ceiling there, and a cliff down to
   the clamp's 43px one pixel later. At 56 the step across the breakpoint is
   56 -> 43, which is real but survivable, and it is only ever seen by someone
   dragging a desktop window through 768. The widest phones reach the cap and
   then return to the two-line shape on their own as the column outgrows the
   type: three lines up to 540, two from about 600 on. */
@media (max-width: 767px) {
  .c2u-hero__headline--arc { font-size: min(13.4cqw, 56px); }
}

/* WHAT THE TIGHT LEADING COSTS, AND WHAT PAYS IT.

   Every word is an inline-block clipped flush by .c2u-word (c2u-motion.css),
   and an inline-block is exactly as tall as its line box. Inter's ascent and
   descent together come to about 1.21em, so any line-height under that spills
   the tops of the capitals and the tails of the descenders outside the box the
   mask clips to — at 1.08 that is ~0.065em shaved off each end, which on 'y'
   and 'g' at 81px is plainly visible. It is why .c2u-hero__headline--brand
   carries 1.2 and warns against tightening it.

   So the box is grown at both ends instead of the leading being given back.
   The top is opened by the clip itself, which costs nothing: the words arrive
   from BELOW, so nothing is ever hidden up there and the mask has no work to
   do above the line. The bottom cannot be opened the same way — that edge IS
   the mask — so it is grown with padding and the growth is taken straight back
   out of the layout with a matching negative margin. The line box keeps the
   1.08 spacing; the clip region is 0.18em deeper than it.

   Padding on an inline-block would normally move its baseline to the bottom
   margin edge, which is what the note in c2u-motion.css warns about — but only
   when overflow is not visible. This masks with clip-path, so the baseline is
   still the text's own and the two lines sit where the leading puts them.

   The travel is unaffected: the rise is 125% of the box, and the box is now
   taller, so the word starts further out of sight rather than less. */
.c2u-hero--arc .c2u-word {
  padding-block-end: 0.18em;
  margin-block-end: -0.18em;
  clip-path: inset(-0.25em -0.5em 0);
}


/* ── The arc ─────────────────────────────────────────────────────────────

   ONE KNOB SETS THE WHOLE DRAWING. parts/hero-arc.php fixes the arc's SHAPE in
   viewBox units — the circle, how many repeats close it, the font-size that
   makes them close, the band's radius — and none of those are screen sizes.
   --c2u-arc-size scales all of it at once. That is the responsiveness: a wider
   drawing is larger type AND a flatter curve, which is one trade and so is one
   number, and the phone below moves that number and nothing else.

   212cqw puts the circle's radius at about one viewport, which is the curvature
   the design draws — a valley shallow enough to read as a line that has been
   bent rather than as part of a circle. At 1440 it sets the type at ~44px.

   The wrapper is what clips: the drawing is over two viewports across and a
   band of it is all that is meant to be seen. Clipping it here rather than at
   the section is also what keeps a box that wide off the page's own scroll —
   the section is the containing block (it declares a container above), so the
   drawing never reaches the document.                                       */

.c2u-hero--arc {
  /* THE DRAWING'S FULL WIDTH — type size and curvature both, because they are
     one number (see above). 212cqw is the design's proportion: the circle's
     radius comes to about one viewport, which is the curve the reference
     draws.

     The bounds are what a pure proportion cannot do. Below about 890px the
     type would keep shrinking with the screen until the phrase stopped being
     readable; above about 1600px it would grow past anything the type scale
     allows. The conversion between the two ends is 2000/--c2u-arc-f ≈ 70px of
     drawing per 1px of type, so 1890px is ~27px type and 3400px is ~49px.

     THE FLOOR IS THE PHONE'S TYPE SIZE, and it is the only way to set it.
     Type and curvature are not two knobs here: the repeats have to keep
     closing the circle, so the font-size is fixed by the count and the only
     thing that can move it is the size of the whole drawing — which is also
     the radius. Bigger phone type is therefore a flatter phone curve, always.
     At 1890px a 390px screen gets 27px type over about 22px of rise, which is
     a shallow curve carrying readable words; the previous 1260px gave 18px
     type over 33px of rise, which was the same trade taken the other way.

     Stated as one clamp rather than as a phone override on purpose: a stepped
     value jumps at the breakpoint, and because a wider drawing is also a
     flatter curve, that jump moves the type AND the curvature at once. Below
     767px it read as a different design rather than the same one on a smaller
     screen. */
  --c2u-arc-size: clamp(1890px, 212cqw, 3400px);

  /* HOW MUCH OF THE CURVE IS ON SCREEN — and it has to hold the whole visible
     arc, because the wrapper clips. What it must clear is the drop from the
     shoulders at the screen edges down to the valley, plus the band's own
     thickness, plus the air the dip leaves under it.

     The floor is why: below about 430px, 24cqw stops covering that and the
     wrapper's top edge starts cutting the tops off the shoulders. Same reason
     the width above needs a floor — a share of the screen is the right shape
     of value until the screen is small enough that the share is smaller than
     the thing it has to contain. */
  --c2u-arc-band: max(24cqw, 130px);

  /* HOW FAR THE ARC IS PULLED UP UNDER THE HEADLINE, and it exists because a
     valley's box lies about where the valley is. The wrapper's top edge is
     level with the arc's HIGHEST point, which is out at the screen edges; the
     part directly under the headline is the lowest point, a full sagitta
     below it. Left alone the headline reads as sitting a whole extra curve's
     depth above the band — about 330px at 1440, against the 88px of air the
     margin actually asks for.

     So the box is lifted by roughly that sagitta and the SHOULDERS of the arc
     come up beside the headline instead, into the gutters either side of it
     where there is nothing to collide with. That is the overlap: the boxes
     cross, the ink does not.

     16cqw tracks the sagitta while the size clamp above is not biting: the
     radius is then a fixed share of the screen, so the sagitta is too. Once
     the clamp pins the drawing the sagitta falls away as the SQUARE of the
     viewport instead — 88px at 767 but only 22px at 390 — and this
     over-corrects. It needs no phone rule of its own even so, because the
     floors on the height and the dip above hold the arc down by more than
     this pulls it up at exactly the widths where that happens. */
  --c2u-arc-lift: 16cqw;

  /* How far the foot of the drawing sits BELOW the band's lower edge. The
     lowest point of the circle is the middle of the valley, so this is what
     decides whether the arc bottoms out inside the band or runs off it.
     Floored with the height above and for the same reason, and at close enough
     to the same width that the two step together. */
  --c2u-arc-dip: max(4cqw, 22px);

  /* Local, and deliberately not a token: this is one band on one page, and it
     is chosen against the page's own pink field rather than from the palette —
     it has to read as a deeper pass of the same colour, which is a relationship
     with the shader behind it and not with the brand reds. --c2u-red-soft, the
     nearest token, is close enough to white here to disappear. */
  --c2u-arc-band-color: #f4ccd1;
}

/* The band itself. Every value it spends is declared above, on the SECTION,
   rather than here — because the photograph ring is a sibling of this element
   and has to read the same geometry to put its circle on the same centre. A
   knob either element needs alone would still belong on that element; these
   are the ones both do. */
.c2u-hero__arc {
  position: relative;
  block-size: var(--c2u-arc-band);
  overflow: hidden;

  /* The air the headline has above it, less the curve's own depth — so what
     the reader sees under the headline is --c2u-hero-top of gap, which is what
     that figure was always meant to buy. Goes negative on a desktop, which is
     the point. */
  margin-block-start: calc(var(--c2u-hero-top) - var(--c2u-arc-lift));
}

/* The headline paints over the arc, not under it. Nothing should ever reach
   the type — the shoulders come up in the gutters either side of it — but the
   lift above is tuned by eye against one headline at one measure, and a longer
   one would find the band before anybody found this rule. */
.c2u-hero--arc .c2u-container {
  position: relative;
  z-index: 1;
}

.c2u-arc {
  position: absolute;
  inset-inline-start: 50%;
  inset-block-end: calc(-1 * var(--c2u-arc-dip));
  inline-size: var(--c2u-arc-size);

  /* The base stylesheet caps every img and svg at max-width:100% so nothing
     can burst its column. This drawing is meant to — it is over two viewports
     across on purpose, and the wrapper above is what stops it reaching the
     page. Without this line --c2u-arc-size is silently ignored above 100% and
     the curve reads far tighter than the number says, which looks exactly
     like a badly chosen radius. */
  max-inline-size: none;
  /* Stated rather than left to the intrinsic ratio the viewBox gives, because
     an <svg> with no height has a 150px fallback in the standard and finding
     that out at a breakpoint is not worth the line it saves. */
  aspect-ratio: 1;
  block-size: auto;
  transform: translateX(-50%);
}

/* The band. A stroked circle, not a shape — the stroke IS the band, so its
   width is the band's thickness and its radius the band's centre line.

   Both are set against --c2u-arc-f, the font-size the part derived, so the
   band grows and shrinks with the type it sits behind and there is only ever
   one thing to retune. 1.9 is the taste: enough air above the capitals and
   below the baseline that the phrase sits IN the band rather than on it. */
.c2u-arc__band {
  fill: none;
  stroke: var(--c2u-arc-band-color);
  stroke-width: calc(var(--c2u-arc-f) * 1.9px);
}

.c2u-arc__text {
  font-family: var(--c2u-font-body);
  font-weight: 600;

  /* 1px is one viewBox unit — the part derived this number, and it is not a
     taste knob: it is the size at which its repeat count closes the circle
     exactly. Change --c2u-arc-size to make the type bigger. */
  font-size: calc(var(--c2u-arc-f) * 1px);

  /* Flat, and it is what arc_fit was measured at. The display scale's -0.05em
     is set for large mixed-case headlines and closes uppercase up too far;
     more to the point, any change here invalidates the measurement and the
     repeats stop closing the circle. */
  letter-spacing: 0;

  /* Uppercased in CSS, not typed in capitals, for the reason
     parts/velocity-text.php gives. The measurement was taken uppercased. */
  text-transform: uppercase;

  fill: var(--c2u-navy);
}

/* No phone rule for the ARC at any width, which is worth stating because it
   was not free: every value it has is either a share of the screen or a floor
   under one, and between them they carry it from 390 to 1920 without a
   breakpoint. The three floors are the whole phone treatment. (The ring below
   does take one, and the note there says why it is a different kind of
   decision.) */


/* ── The photograph ring ─────────────────────────────────────────────────

   A second arc under the first, and the reason it needs no geometry of its own
   is that it borrows the first one's centre. parts/hero-arc.php's header has
   why concentric is the requirement; this block is how.

   EVERY LENGTH HERE IS A SHARE OF --c2u-arc-size, and that is not tidiness. A
   fixed angular step between tiles only holds its spacing if the tile and the
   radius grow together — a step is an angle, and what it buys in pixels is the
   angle times the radius. Tie the tile to the screen and the radius to the
   drawing and the gaps between photographs would open and close across the
   breakpoints. Tie both to the drawing and one step is exact at every width,
   including the phone, where the drawing stops following the screen.

   It also means the ring inherits the arc's floors for free: --c2u-arc-size is
   already clamped, so none of this needs a floor of its own.                */

.c2u-hero--arc {
  /* The tile, and the arc-distance from one tile's centre to the next. The
     difference between them is the gap, so the two are stated rather than a
     size and a gap: it is the PITCH that the step below is derived from.

     The tile is 0.062 x 1.15. The pitch is deliberately NOT scaled with it —
     the photographs were asked to get bigger, not to spread out — so the 15%
     comes out of the gap between them: 0.026 of the drawing to 0.0167, or
     79px to 51px at 1440. That is the whole reason the two are stated as
     size-and-position rather than as size-and-gap; growing one leaves the
     other where it was and the step below never has to be re-derived. Scale
     the pitch too and it does — see the phone block for what that costs. */
  --c2u-ring-tile:  calc(var(--c2u-arc-size) * 0.0713);
  --c2u-ring-pitch: calc(var(--c2u-arc-size) * 0.088);

  /* TWO WAYS TO PUT THE PHOTOGRAPHS BELOW THE BAND, and they are different
     designs rather than different numbers. Both are shares of the drawing.

       sink   moves the photograph circle's CENTRE down. Same radius, so the
              row carries exactly the band's curvature, and the gap between
              them is the same everywhere.
       drop   makes the photograph circle BIGGER about the band's own centre.
              Concentric — but a bigger circle is a flatter one, so the row
              comes out shallower than the band above it, and the gap widens
              towards the screen edges.

     Sink is the default because it is what "the same curve, lower down" means:
     at 1440 the row drops 190px across the screen, matching the band, and it
     does so at any sink, because a translation does not change a curvature.
     Pure drop gives 109px at the distance this was originally set to (0.062)
     and reads as a much straighter row under a curved one. They can be mixed;
     what they must not do is both be zero, which would put the photographs on
     the band.

     0.062 -> 0.0725 puts the row 32px lower at 1440, where the drawing is
     3053px. Worth knowing that the tile grew at the same time and grows about
     its own centre, so the photographs reach 14px further up than they did:
     the row moved 32px, and the air under the band opened by about 18px. Add
     to the sink if the gap rather than the row is what wants the 32. */
  --c2u-ring-sink: 0.0725;
  --c2u-ring-drop: 0;
  --c2u-ring-r: calc(var(--c2u-arc-size) * (var(--c2u-arc-rf) + var(--c2u-ring-drop)));

  /* THE ANGLE BETWEEN TILES, and it is pitch / radius in radians, converted.
     Both are shares of the drawing, so the division is a pure number and holds
     at every width:  0.088 / (0.470 + 0) = 0.18723 rad = 10.727°.
     Re-derive it whenever `drop` or the pitch moves — nothing computes it, and
     getting it wrong changes the spacing, not the seamlessness. */
  --c2u-ring-step: 10.727deg;

  /* WHICH WAY IT TURNS, and it lives here rather than with the animation
     because the placement below depends on it. -1 sends the photographs right,
     against the band above, which is what keeps the two arcs reading as two
     things passing rather than one thick mass sliding. c2u-motion.css only
     spends it. */
  --c2u-ring-dir: -1;

  /* How far the ring's box is raised into the arc's, and it exists because the
     tiles at the screen edges ride HIGHER than the ones in the middle — that
     is what an arc is. Without it the ring's own top edge would clip the outer
     photographs. The arc's box has empty air in its lower corners at exactly
     those points (the band has curved away upwards), so the two boxes overlap
     and nothing collides. */
  --c2u-ring-raise: calc(var(--c2u-arc-size) * 0.075);

  /* Enough to hold the drop from the outer tiles to the middle ones, plus a
     tile, plus the raise above. The middle of the row runs past the fold on a
     short screen, which is the same thing the reference does.

     0.165 -> 0.180 because this is what clips, and it had 29px of room left at
     1440 before the two changes above. Sinking the row 32px and growing the
     tile about its centre take the lowest photograph 46px lower between them;
     0.015 of the drawing is 46px, so the slack is the 29px it always was. Both
     of those knobs have to be paid for here — check this number whenever
     either moves, because nothing derives it and the failure is a row of
     photographs with their bottoms cut off. */
  --c2u-ring-band: calc(var(--c2u-arc-size) * 0.180);
}

.c2u-hero__ring {
  position: relative;
  block-size: var(--c2u-ring-band);
  overflow: hidden;
  margin-block-start: calc(-1 * var(--c2u-ring-raise));
}

/* THE SHARED CENTRE, and this rule is the whole concentricity argument.

   It is a zero-sized point, not a circle: a box two-and-a-half viewports
   across would be a real element for the browser to lay out and clip for no
   reason, when all anything needs from it is an origin to turn about.

   Where it sits is derived, not chosen. The arc's SVG is centred half a
   drawing above its own bottom edge, which sits --c2u-arc-dip below the arc
   box's bottom — and the arc box's bottom is where this box's top would be,
   were it not raised. So the same point, expressed from here, is that dip
   minus half a drawing, plus the raise. Nothing about the arc is restated;
   move the arc and this follows it. */
.c2u-ring {
  position: absolute;
  inset-inline-start: 50%;
  inset-block-start: calc(
    var(--c2u-arc-dip) - var(--c2u-arc-size) / 2 + var(--c2u-ring-raise)
    + var(--c2u-arc-size) * var(--c2u-ring-sink)
  );
  inline-size: 0;
  block-size: 0;
}

/* Placement. Rotate about the centre, then out to the rim — in that order,
   which is why it is one transform and not the `rotate`/`translate` properties
   (those apply translate first and would put the tile on the rim and then spin
   it around its own middle).

   THE ANCHOR is which slot sits at the bottom of the circle — the middle of
   the screen — and it is derived rather than chosen because getting it wrong
   is a hole that walks into frame once a cycle.

   A cycle moves every tile one SET along, so the slots that are filled at both
   ends of it are only the middle count-set of them, and WHICH middle depends
   on which way the ring turns: going one way the safe run is the top of the
   range, going the other it is the bottom. Centring on (count-1)/2 and then
   stepping half a set in the direction of travel lands on the middle of the
   safe run either way — so flipping --c2u-ring-dir above stays a one-character
   change instead of silently costing five tiles off the end. The full
   derivation is in the part's header. */
.c2u-ring__slot {
  --c2u-ring-anchor: calc(
      (var(--c2u-ring-count) - 1) / 2
    + var(--c2u-ring-dir) * var(--c2u-ring-set) / 2
  );

  position: absolute;
  inset-block-start: 0;
  inset-inline-start: 0;
  inline-size: var(--c2u-ring-tile);
  aspect-ratio: 1;

  /* Half its own size back and up, so the box is centred on the point above
     and its own transform-origin lands there too. */
  margin: calc(var(--c2u-ring-tile) / -2);

  transform:
    rotate(calc((var(--c2u-i) - var(--c2u-ring-anchor)) * var(--c2u-ring-step)))
    translateY(var(--c2u-ring-r));
}

/* Takes the placement rotation straight back out, so the square stands square.
   Static, and separate from the tile below only so that the tile's rule — the
   one that has to cancel the ring's TURN — is the same for every photograph
   and can be written once. */
.c2u-ring__plumb {
  block-size: 100%;
  transform: rotate(calc(-1 * (var(--c2u-i) - var(--c2u-ring-anchor)) * var(--c2u-ring-step)));
}

.c2u-ring__tile {
  margin: 0;
  block-size: 100%;
  overflow: hidden;
  border-radius: var(--c2u-hero-media-radius);
}

.c2u-ring__tile img {
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
}

/* Phone — bigger photographs, closer together, further under the band.

   THIS ONE IS TASTE, not geometry, which is why it is a breakpoint where the
   arc above needed none. Below 767px only three photographs are on screen at
   once, and three small ones with wide gaps read as a row that has been
   thinned rather than as a row at this size: the picture is the content here,
   so it takes more of the screen and gives up the air between.

   All four are re-stated together because they are one shape. The step is
   derived from the pitch exactly as it is above — 0.094 / 0.470, which comes
   out at 0.2 radians on the nose — and re-deriving it is not optional: leave
   it at the desktop value and the photographs keep the old spacing at the new
   size, which is to say they overlap.

   The band's height grows to match, because bigger tiles sunk further down
   reach lower and the wrapper is what clips them. It only extends downwards —
   the tiles hang off the wrapper's top edge — so it moves nothing. */
@media (max-width: 767px) {
  .c2u-hero--arc {
    --c2u-ring-tile:  calc(var(--c2u-arc-size) * 0.077);
    --c2u-ring-pitch: calc(var(--c2u-arc-size) * 0.094);
    --c2u-ring-step:  11.459deg;
    /* Sink pays for the air under the band TWICE over here, and that is worth
       knowing before retuning it: a bigger tile grows about its own centre, so
       half the size increase above comes straight off the top of the gap. The
       first 0.0095 of this only cancels that. */
    --c2u-ring-sink:  0.0790;
    --c2u-ring-band:  calc(var(--c2u-arc-size) * 0.195);
  }
}


/* ── Circular text ───────────────────────────────────────────────────────
   Vanilla port of the reactbits CircularText component — see parts/circular-text.php.

   The spin lives here rather than in JS so it runs without scripts. Each letter
   span is stretched over the whole circle and centred, putting its glyph at top
   centre; the per-letter rotateZ (inline, from PHP) then walks it around the
   ring about the circle's midpoint.                                          */

.c2u-circular {
  --c2u-circular-size: clamp(120px, 12vw, 168px);
  --c2u-circular-duration: 20s;

  position: relative;
  width: var(--c2u-circular-size);
  height: var(--c2u-circular-size);
  border-radius: 50%;
  transform-origin: 50% 50%;
  animation: c2u-circular-spin var(--c2u-circular-duration) linear infinite;
  will-change: transform;

  color: var(--c2u-red);
  font-weight: 600;
  /* Sized against the circle, not the page: each glyph sits at the top edge of
     its span, so the ring's radius is fixed by --c2u-circular-size and only the
     font-size controls how tightly the letters pack around it. Too small and
     the ring reads as scattered marks rather than a word. */
  font-size: clamp(17px, 1.6vw, 22px);
  letter-spacing: 0;
  text-transform: uppercase;
  text-align: center;
}

.c2u-circular span {
  position: absolute;
  inset: 0;
  display: inline-block;
  line-height: 1.1;
  /* transform-origin is the circle's centre, since inset:0 makes each span
     fill the whole box */
  transform-origin: 50% 50%;
}

@keyframes c2u-circular-spin {
  from { transform: rotate(0deg); }
  to   { transform: rotate(360deg); }
}

/* Desktop gets a ring about a quarter larger — the hero's right-hand third has
   the room for it there, and at the base size the badge read as an afterthought
   against the photo row. Paired with the 980px tablet query below, so the
   smaller ring stays put wherever the layout is already tight. Both values are
   scaled together: the radius is fixed by the size and the font only sets how
   tightly the letters pack, so moving one alone would re-space the ring. */
@media (min-width: 981px) {
  .c2u-hero__circular .c2u-circular {
    --c2u-circular-size: clamp(153px, 15.3vw, 214px);
    font-size: clamp(21.7px, 2.04vw, 28px);
  }
}

/* Same reasoning as the marquee: the global reduced-motion rule only shortens
   durations, which freezes an infinite spin at an arbitrary angle rather than
   stopping it. */
@media (prefers-reduced-motion: reduce) {
  .c2u-page .c2u-circular { animation: none !important; }
}


/* Tablet — the 6/3/3 photo row gets cramped, so go full-width + half/half,
   and let the CTA and subhead take a row each. */
@media (max-width: 980px) {
  .c2u-hero__intro { grid-column: 1 / span 12; }

  /* Same idea against the wide photo, which is the full width of row 1 here.
     Pushed to one end rather than centred, so the ring lands in the same corner
     of the hero as it does on desktop, and clear of the headline — which now
     runs the full width directly above it. Below 767px it is dropped entirely. */
  .c2u-hero__circular {
    --c2u-hero-circular-rise: 66%;
    grid-column: 1 / span 12;
    justify-content: flex-end;
    padding-inline-end: var(--c2u-space-6);
  }

  .c2u-hero__media--wide          { grid-column: 1 / span 12; aspect-ratio: 16 / 9; }
  .c2u-hero__media:nth-of-type(2) { grid-column: 1 / span 6;  grid-row: 2; }
  .c2u-hero__media:nth-of-type(3) { grid-column: 7 / span 6;  grid-row: 2; }
  .c2u-hero__subhead { grid-row: 3; grid-column: 1 / span 12; }
  .c2u-hero__actions { grid-row: 4; grid-column: 1 / span 12; }
}

/* Mobile — one column, one photo. All explicit placement is dropped so the
   DOM order renders directly: media 1, subhead, CTA. */
@media (max-width: 767px) {
  .c2u-hero__grid {
    /* minmax(0, …) rather than a bare 1fr, which means minmax(auto, 1fr): that
       auto floor is the widest min-content in the column, so a single item that
       cannot shrink — a nowrap CTA label, most easily — widens the whole track
       and carries the photo and the subhead off the right edge with it. Pinned
       to 0 the track is the container width, and an oversized item is the only
       thing that overflows. */
    grid-template-columns: minmax(0, 1fr);
    gap: var(--c2u-space-6);
    /* Tighter than the 56px elsewhere. Nothing stands in this gap now that the
       ring is gone, and the fitted headline sits directly above the photo. */
    margin-block-start: var(--c2u-space-6);
  }
  .c2u-hero__grid > * { grid-column: auto; grid-row: auto; }

  .c2u-hero__media:not(.c2u-hero__media--wide) { display: none; }
  .c2u-hero__media--wide { aspect-ratio: 4 / 3; }

  /* The hero CTA is the one button on these pages big enough to outgrow the
     column it sits in, and its side padding is the difference. At 20px type
     "Talk to our partnerships team" needs ~275px of label and icon, which
     clears the 335px column of a 375px phone on its own — but not with the
     72px the 36px-a-side rule above adds to it. 16px a side puts the button at
     ~307px and holds it on one line down to roughly a 362px viewport.

     Narrower than that it wraps, so the two rules that make wrapping safe stay.
     The nowrap on .c2u-btn is right for a pill everywhere else and is lifted
     here only. The leading has to come with it: .c2u-btn runs line-height at
     the label token, 20px against 20px type, set for a single line where the
     glyph box overhanging its line box by 4px costs nothing. Wrapped, that
     overhang is an overlap — the lines advance 20px while each occupies 24, so
     the second rides into the first. */
  .c2u-hero__actions .c2u-btn {
    padding-inline: 16px;
    white-space: normal;
    line-height: 1.25;
  }

  /* The ring goes too. At this width the headline runs the full column and the
     photo is the only one left, so the ring has no clear ground to stand on
     between them — it would either sit on the copy or be pushed so far down the
     photo that it stops reading as a flourish laid over the corner. */
  .c2u-hero__circular { display: none; }

  /* Headline fitted to its own longest line — opt-in, via headline_fit in
     parts/hero.php.

     A headline written as separate sentences wants one line each, and
     .c2u-line--hard holds those breaks here instead of reflowing them. But at
     the global display size the longest sentence needs two lines of its own,
     and three sentences land as five. So the size comes from the line rather
     than from the scale: --c2u-hero-headline-ratio is that sentence's width
     divided by its font-size — a constant of the typeface, measured, not
     guessed — so the available width divided by it is the largest size that
     still fits on one line.

     That constant is not only about the glyphs: --c2u-ls-display is part of it,
     because tracking set in em scales with the type. Nineteen characters at
     -0.05em came to 8.59 and at -0.03em to 8.97, so a change to the display
     tracking silently invalidates every ratio and the longest line starts
     wrapping again. Re-measure when it moves — the recipe is in parts/hero.php.

     min() against the token means this can only ever make the headline
     smaller. Past roughly 450px the scale's own size already fits and wins, so
     the rule bows out on its own with no second breakpoint to keep in sync.

     The width comes from a container query, not 100vw: cqw is the intro's real
     content box, so the gutter is already subtracted and a classic scrollbar
     cannot throw it off the way it does 100vw. If a browser lacks container
     queries the declaration is simply dropped and the headline reflows as it
     did before — the same outcome, not a broken one. */
  .c2u-hero__intro { container-type: inline-size; }

  .c2u-hero__headline--fit {
    font-size: min(
      var(--c2u-fs-display),
      calc(100cqw / var(--c2u-hero-headline-ratio, 9.1))
    );
  }

  /* Opt-in fixed phone size — headline_mobile in parts/hero.php, carried on the
     element as --c2u-hero-headline-mobile. For a headline too long to sit at the
     display scale here (the fit rule above needs hard line breaks this one has
     none of), the page names a plain size instead. Only heroes that ask for it
     carry the class, so every other headline keeps the display scale. */
  .c2u-hero__headline--mobile {
    font-size: var(--c2u-hero-headline-mobile);
  }
}


/* Two equally-wide hero photos — media_layout: 'split' in parts/hero.php.
   Gathered here, after every base and responsive media rule above, so each of
   these wins on source order rather than reaching for extra specificity weight.

   The pair is passed as exactly two media items. The circular tagline is left
   untouched: it is still pinned to columns 10–12, so it rides the top-right
   corner of the second photo exactly as it does over the default layout. */

/* Desktop — six columns each, both on one landscape ratio so the row is set by
   the photos rather than by the squares the default row leans on. Giving the
   wide one a ratio also settles the absolute-image trick from its note above —
   that img stays absolutely positioned and simply fills the now-definite box. */
@media (min-width: 981px) {
  .c2u-hero--split .c2u-hero__media--wide          { grid-column: 1 / span 6; }
  .c2u-hero--split .c2u-hero__media:nth-of-type(2) { grid-column: 7 / span 6; }
  .c2u-hero--split .c2u-hero__media                { aspect-ratio: 3 / 2; }
}

/* Tablet — hold the two side by side rather than letting the base rule send the
   wide photo full-width and the second down to a row of its own. A little
   taller, to suit the narrower six-column box. */
@media (min-width: 768px) and (max-width: 980px) {
  .c2u-hero--split .c2u-hero__media--wide          { grid-column: 1 / span 6; grid-row: 1; aspect-ratio: 4 / 3; }
  .c2u-hero--split .c2u-hero__media:nth-of-type(2) { grid-column: 7 / span 6; grid-row: 1; aspect-ratio: 4 / 3; }
}

/* Mobile — deliberately nothing here. The split pair follows the default hero
   below 767px: one column, the first photo only, at that layout's 4/3.

   This used to keep the second photo visible and stack the two. It carried two
   workarounds that both existed only to support that, and both go with it — the
   grid-column reset the second photo needed to stop forcing the single-column
   grid back to multiple tracks, and the minmax(0, 1fr) track floor its in-flow
   image needed to stop the column bleeding past the right gutter. Neither
   applies once the photo is display:none: the base rule above (0,2,0) hides it,
   and the wide photo's own image is absolutely positioned, so nothing in the
   column has a min-content width to overflow from. Re-showing the second photo
   here means bringing both workarounds back. */


/* Brand Home heroes — parts/hero-brand.php and parts/hero-statement.php. Only
   the differences are written here; both sections carry .c2u-hero, so
   everything not restated below is that hero's own rule.

   Gathered after the responsive blocks above for the same reason the split
   layout is: source order settles it, so nothing needs extra weight.

   Neither takes any section geometry of its own. The brand hero briefly set a
   minimum height and a symmetric padding, both of which existed only because
   nothing sat below the headline to give the section its size; .c2u-hero's own
   padding and grid do that job unaltered now. What is left is the headline
   treatment below, which is the only thing these two actually change — and they
   share it, which is why it hangs off the headline's own class rather than off
   either section's. The word-by-word reveal that only the statement hero runs
   is in c2u-motion.css, with the rest of the choreography. */

/* A little more air than the 24px above, at the size the headline runs here. */
.c2u-hero--brand .c2u-hero__eyebrow { margin-block-end: var(--c2u-space-6); }

/* Headline sized from its own longest line, not from the display scale.

   Each sentence is meant to occupy exactly one line here, and the type scale
   cannot promise that: at the display size the first sentence needs two lines,
   so the statement lands as three lines split mid-clause. So the size comes
   from the line instead — --c2u-hero-headline-ratio is that sentence's rendered
   width divided by its font-size, measured rather than guessed (the recipe is
   in parts/hero.php), which makes the available width divided by it the largest
   size that still fits on one line.

   This is the same mechanism .c2u-hero__headline--fit runs above, with one real
   difference: there it is a phone-only fallback under a max-width query, and
   here it is how the headline is sized at every width down to the phone
   breakpoint. The caveats carry over unchanged. The constant is not only about
   the glyphs — --c2u-ls-display is part of it, because tracking set in em
   scales with the type — so a change to the display tracking, the typeface or
   the copy silently invalidates it and the longest line starts wrapping again.

   min() against the token means this can only make the headline smaller, never
   larger than the scale allows. The width comes from a container query rather
   than 100vw, so the gutter is already subtracted and a classic scrollbar
   cannot throw it off; a browser without container queries simply drops the
   declaration and gets the scale's own size, which wraps — the old outcome,
   not a broken one.

   The default in the var() is this page's own measured value (17.80 rounded up
   to 18.10 for headroom), so the part still fits its copy if a caller forgets
   to pass headline_fit. The measure is dropped: the fit is the measure now, and
   a max-width would only reintroduce the wrap it exists to prevent.

   Both selectors are single classes the parts opt into, not descendants of a
   section modifier, so the two Brand Home heroes read off one copy of this. The
   container query needs a container, and .c2u-hero__intro cannot simply become
   one for every hero — containment makes it a formatting context, which would
   change how the eyebrow's margins collapse on the three built pages. So the
   part asks for it by class instead.

   The size is held as an expression rather than applied directly, because the
   statement section below the hero runs at a fraction of it and the two have to
   move together. An expression is the right shape for that: 100cqw and the two
   var()s inside it are not resolved here, they are resolved wherever the
   property is finally used — so each user reads its own container's width, and
   the headline's own inline ratio, without any of it being restated.

   The catch to know: the ratio and the phone size are inline on the H1, put
   there by the page, and nothing else on the page can see them. The statement
   below therefore falls back to the defaults written here. They currently match
   what src/brand-home.php passes; change headline_fit or headline_mobile there
   and these have to move with it, or the two sizes quietly stop being 65% and
   100% of one thing. */
.c2u-hero__intro--fit { container-type: inline-size; }

.c2u-page {
  --c2u-brand-size: min(
    var(--c2u-fs-display),
    calc(100cqw / var(--c2u-hero-headline-ratio, 18.10) * var(--c2u-hero-brand-fill, 0.86))
  );
}

.c2u-hero__headline--brand {
  /* Share of the column the longest line is allowed to take. The fit on its own
     sizes that line to the full column, which sets the type by how wide the
     screen happens to be and leaves the headline running into the right gutter;
     holding it to a fraction is what pulls the size back while keeping the
     one-line-per-sentence guarantee intact. This is the knob to turn to make
     the headline bigger or smaller — the ratio beside it is measured and must
     not be traded against it. */
  --c2u-hero-brand-fill: 0.86;

  /* Looser than the display scale's 1.04, which is set for a headline of two or
     three short lines where tight leading reads as one block. These are full
     sentences at close to the column's width, so the eye has to travel the
     whole line and back — 1.2 is the gap that makes finding the next one
     effortless.

     It is also what makes the word masks safe to clip flush: at 1.2 the line
     box clears Inter's ascent and descent, so no tail is shaved. See the note
     in c2u-motion.css before tightening it. */
  line-height: 1.2;

  max-width: none;
  font-size: var(--c2u-brand-size);
}

/* Phone — one sentence per line stops being possible at any size worth reading:
   at 375px the fit would put the headline at about 19px, smaller than the body
   copy it is supposed to open above. So the fit gives way to a plain size and
   each sentence wraps inside its own hard line — two lines each, the sentence
   break still held.

   36px is the default rather than a fixed value; headline_mobile overrides it.
   It is also close to where the fit rule leaves off (about 39px at 768px), so
   nothing jumps at the breakpoint. */
@media (max-width: 767px) {
  .c2u-page { --c2u-brand-size: var(--c2u-hero-headline-mobile, 36px); }
}


/* ── Statement ───────────────────────────────────────────────────

   parts/statement.php — one large paragraph under the hero, revealed a word at
   a time once it scrolls in. The reveal itself is in c2u-motion.css; what is
   here is the type and the measure. */

/* The container the type size is measured against. It has to be this box and
   not the paragraph: the paragraph's width is capped below, and a capped
   element measuring itself would feed its own size back in. This one fills the
   page container, which is also what the hero's headline measures against, so
   the two sizes are read off the same width. */
.c2u-statement__inner { container-type: inline-size; }

.c2u-statement__text {
  /* Two thirds of the headline above it, near enough — sized as a fraction of
     the same expression rather than from the type scale, so the pair holds its
     proportion at every width instead of only at the ends. See the note on
     --c2u-brand-size above for the one way the two can drift apart. */
  font-size: calc(var(--c2u-brand-size) * 0.65);

  /* 30 characters is a deliberately narrow measure for prose — around a third
     of what --c2u-measure allows — which at this size is the point: the
     paragraph reads as three short stacked statements rather than as body copy
     that happens to be large. */
  max-width: 30ch;

  /* And that measure sits in the middle of the page. The block is centred, not
     the lines inside it: text-align would give every line its own centre and
     turn three stacked statements into a poem — the left edge is what makes
     them read as a list of three. So the paragraph keeps its flush left edge
     and the spare width either side of the 30ch column is split evenly.
     Nothing below 767px, where the cap is dropped and the block already fills
     the column. */
  margin-inline: auto;

  /* Looser than the headline's 1.2, because these lines are short and there are
     many of them; also comfortably clear of the ascent-plus-descent the flush
     word masks need, which 1.2 only just makes. */
  line-height: 1.3;

  /* The display tracking, -0.05em — the headline's, not the lead paragraph's
     -0.01em. This is display-sized type, and tracking set in em scales with it,
     so at 41px the looser figure reads as gappy. The token rather than the
     number, so the pair stays locked if the scale is ever retuned. It is also
     the reason the word masks leave their sides open: negative tracking is
     applied after a word's last glyph too, so the box is narrower than the ink.
     See c2u-motion.css. */
  letter-spacing: var(--c2u-ls-display);
  color: var(--c2u-navy);
}

/* A blank line between blocks, when the copy is passed as an array rather than
   as one string. One line, not an arbitrary gap — 1lh is this element's own
   line-height, so the space is exactly the empty line it stands for and it
   tracks the leading instead of having to be re-tuned against it. */
.c2u-statement__text .c2u-line + .c2u-line { margin-block-start: 1lh; }

/* Phone — the measure goes. At this size 30ch is wider than the column anyway,
   so the cap only ever fought the gutter for control of the same edge. */
@media (max-width: 767px) {
  .c2u-statement__text { max-width: none; }
}


/* Pinned scroll geometry. Every constant lives here; c2u-page.js reads them and
   writes back one number. The reveal they drive is in c2u-motion.css.

   Nothing below applies until JS adds .is-live, which it does only once it has
   checked reduced motion and that the window can hold the pinned paragraph. */

.c2u-statement {
  /* Where the pinned scene sits — the card wheel's clearance, so two pinned
     sections on one site stop at the same line under the header. */
  --c2u-statement-top: 104px;
  --c2u-statement-scene: calc(100svh - var(--c2u-statement-top));

  /* How much scrolling one word costs. This is the whole feel of the effect:
     the reveal has no pace of its own any more, only an exchange rate. Around
     a wheel notch buys three or four words, which keeps a deliberate scroll
     roughly at reading speed without making a flick feel like it broke it.
     Forty-three words at 32px is about 1400px of runway — one and a half
     screens, which is the honest cost of the whole paragraph. */
  --c2u-statement-run: 32px;

  /* Holds at each end, as fractions of the runway.

     The lead is zero on purpose, and should stay there. The section arrives
     with nothing showing — see the note in c2u-motion.css — so any lead at all
     is a stretch of scrolling where the pin has caught, the reader is pushing,
     and the screen is still blank. The first word has to move on the first
     pixel past the pin.

     The tail is the opposite case and wants its beat: it leaves the finished
     paragraph still and readable before the pin lets go, which is the moment
     the whole section exists for. */
  --c2u-statement-lead: 0;
  --c2u-statement-tail: .14;
}

.c2u-statement.is-live {
  height: calc(
    var(--c2u-statement-scene)
    + var(--c2u-word-count, 1) * var(--c2u-statement-run)
      / (1 - var(--c2u-statement-lead) - var(--c2u-statement-tail))
  );
  padding-block: 0;
}

.c2u-statement.is-live .c2u-statement__scene {
  position: sticky;
  top: var(--c2u-statement-top);
  height: var(--c2u-statement-scene);
  display: flex;
  align-items: center;
}


/* Closes as it opens. The hero's shared bottom edge is --c2u-section-y, which
   is the spacing between two sections; this one is a headline and a row of
   photographs with nothing else in it, and it reads as a single composition
   only if the air around that composition is even.

   This replaces a temporary 1500px runway, which existed to push the section
   below the section that follows it out of the first screen. That was written
   when the paragraph below played a scroll-in reveal that had to be armed
   off-screen; it is scrubbed by scroll now (see .c2u-statement above), and a
   scrub has no arming to miss — it reads the scroll position it is given
   wherever the section starts. The runway had been dead weight since. */
.c2u-hero--statement { padding-block-end: var(--c2u-hero-top); }

/* Centred. The fit holds the longest sentence to 86% of the container
   (--c2u-hero-brand-fill above), so there is always spare width — this splits
   it evenly either side instead of leaving it all in the right gutter, and the
   headline then sits on the same axis as the photograph row under it, which is
   the full page width. Below 767px each sentence wraps to two lines and those
   centre against each other.

   On the section rather than on .c2u-hero__headline--brand: that class is
   shared with parts/hero-brand.php, whose hero has an eyebrow, a subhead and a
   CTA stacked with it and reads from the left. Each .c2u-line is a block and
   each .c2u-word an inline-block (c2u-motion.css), so this moves the words
   within their own line box and leaves the masks and the stagger alone. */
.c2u-hero--statement .c2u-hero__headline { text-align: center; }


/* Tagline lockup — set apart from the subhead by a rule and small caps feel. */
.c2u-lockup {
  display: flex;
  align-items: center;
  gap: var(--c2u-space-4);
  margin-block-start: var(--c2u-space-8);
  font-size: var(--c2u-fs-heading-4);
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--c2u-red);
}
.c2u-lockup::before {
  content: '';
  width: 40px;
  height: 2px;
  flex-shrink: 0;
  background: var(--c2u-red);
}


/* ── Velocity text ───────────────────────────────────────────────────────

   parts/velocity-text.php — the tagline as three bands of moving type, ported
   from reactbits' ScrollVelocity. That file describes the effect; what is here
   is the type, the fit and the geometry the loop needs. The movement itself is
   c2u-page.js, which reads the five physics knobs below off this stylesheet and
   writes one transform per row per frame.

   Every default the component has lives here, under the names the original
   uses, so a page only states what it wants changed.                        */

.c2u-velocity {
  /* ── The original's props ──────────────────────────────────────────────
     Its defaults exactly: velocity 100, damping 50, stiffness 400, and the
     mapping {input: [0, 1000], output: [0, 5]} written as its far end, since
     both ranges start at zero and the map is linear. Read by c2u-page.js.

     `velocity` is split in two: the magnitude here, and the sign as
     --c2u-velocity-dir on each row, which is how the original's alternation
     (`index % 2 !== 0 ? -velocity : velocity`) is expressed without the part
     having to restate the default to be able to negate it. */
  --c2u-velocity-base: 100;
  --c2u-velocity-dir: 1;
  --c2u-velocity-damping: 50;
  --c2u-velocity-stiffness: 400;
  --c2u-velocity-map-in: 1000;
  --c2u-velocity-map-out: 5;

  /* ── The fit ───────────────────────────────────────────────────────────
     How many font-sizes wide the line's own ink is, and nothing else. Measured,
     not guessed; parts/hero.php carries the recipe, and the part's header
     carries what invalidates it — the copy, the typeface, the tracking and the
     uppercasing, all of which are properties of the line itself.

     The spacing and the separator are deliberately NOT inside this number.
     One repeat is the line plus the mark and its air, and the row works that
     total out below from the parts — so the gap and the mark can be retuned,
     including at a breakpoint, without the measurement going stale. Fold them
     in here and every such change silently becomes a lie.

     The default is Brand Home's own measured value, the same arrangement
     .c2u-hero__headline--brand has: the one page using this today still works
     if a caller forgets to pass it, and any other copy must measure its own.

     Unlike the headline's, this one is not rounded up for headroom. The
     headline's spare is there to stop a line wrapping; nothing wraps here
     (.c2u-velocity__copy is nowrap), so the only thing headroom would buy is
     type slightly smaller than the promise. */
  --c2u-velocity-fit: 9.332;

  /* Share of the container one repeat is allowed to take. 1 is the promise
     exactly: one phrase, one screen. It exists for the phone, where the line at
     exactly one screen wide comes out too small against the rest of the page —
     see the breakpoint at the bottom of this block. */
  --c2u-velocity-fill: 1;

  /* The air either side of the separator, in em of the line, so it scales with
     the type. Added to the fit by the row rather than measured into it. */
  --c2u-velocity-gap: 0.34;

  /* What the mark adds to a repeat: its own advance plus the air in front of it
     (the air behind it is the copy's trailing padding, counted separately). Zero
     here because a separator is opt-in — .c2u-velocity--marked, set by the part
     when it is given one, fills this in. */
  --c2u-velocity-mark: 0;

  /* The rows either side of the middle. The middle line is the one being read;
     these two give the band its depth without competing for it. */
  --c2u-velocity-fade: 0.32;

  /* Line height, and with it the whole block's rhythm. 1 sets the rows a cap
     height and a bit apart, which is what makes three lines read as one mass
     rather than as a list. */
  --c2u-velocity-leading: 1;

  /* Headroom for the clip. Each row hides its own overflow to cut the track off
     at the screen edge, and that clip is the padding box — so at a leading this
     tight, ink that sits outside the line box (Inter's ascender and descender
     together are about 1.21em) would be shaved off. The padding buys the room
     back horizontally-clipped type still needs vertically. */
  --c2u-velocity-bleed: 0.12em;
}

/* ── One screen, and nothing else on it ──────────────────────────────────
   parts/velocity-text.php's `screen`. The band is given the whole viewport and
   centred in it. Height only — the page scrolls through this section like any
   other, and nothing takes hold of the reader's scroll on the way past.

   Centred rather than stacked from the top, and centred by the box rather than
   by a margin, which is what keeps the air above the band equal to the air
   below it: .c2u-section sets the same --c2u-section-y on both edges, the box
   is border-box (c2u-base.css), so the height below is the outside of the
   section and the padding is inside it. Nothing here reaches for a top offset
   to clear the sticky header — it is translucent-white over a band that starts
   a section's padding down, and buying it room would spend the symmetry.

   min-block-size, not block-size: the phone sets this type half again as large
   at a looser leading, and a fixed height would crop the band rather than grow
   for it. The overflow is horizontal — .c2u-velocity__row hides its own — so a
   band that outgrows the screen scrolls like anything else.

   100svh for the reason every full-screen scene in this file uses it: vh on
   iOS is measured against the collapsed address bar, so a section promised the
   screen would arrive taller than the screen it was promised. */
.c2u-velocity--screen {
  display: flex;
  flex-direction: column;
  justify-content: center;
  min-block-size: 100svh;
}

/* The box the fit measures against. It has to be an ancestor of the row rather
   than the row itself — an element cannot be its own container — and it is the
   full section width, which is the full viewport, because nothing here is
   inside .c2u-container. That is the point of the section. */
.c2u-velocity__rows { container-type: inline-size; }

.c2u-velocity__row {
  /* One repeat per container width. The repeat is the line, the air after it,
     and whatever the mark adds — assembled here from the three so that none of
     them has to be measured against the others. See --c2u-velocity-fit above. */
  font-size: calc(
    100cqw
    / (var(--c2u-velocity-fit) + var(--c2u-velocity-gap) + var(--c2u-velocity-mark))
    * var(--c2u-velocity-fill)
  );
  line-height: var(--c2u-velocity-leading);

  /* The display weight, which is 600 — and 600 is as bold as this band can
     honestly get: c2u-base.css loads Inter at 400, 500 and 600 upright only, so
     asking for 700 would not reach a heavier file, it would have the browser
     synthesise one by smearing the 600. At a hundred and fifty pixels that is
     not a bolder cut, it is a distorted one. Drop an Inter 700 woff2 in beside
     the others and add its @font-face, and this line is where it gets used. */
  font-weight: var(--c2u-fw-display);

  letter-spacing: var(--c2u-ls-display);
  color: var(--c2u-navy);
  opacity: var(--c2u-velocity-o, 1);

  /* Set here and not in the copy: a string typed in capitals is spelled out
     letter by letter by several screen readers. The part's header has the whole
     note — and this is part of what the fit is measured against. */
  text-transform: uppercase;

  overflow: hidden;
  padding-block: var(--c2u-velocity-bleed);
}

/* The padding above is clip headroom, not spacing, so it is given straight back
   between rows — leaving the rows exactly one leading apart, which is what
   --c2u-velocity-leading is supposed to mean. */
.c2u-velocity__row + .c2u-velocity__row {
  margin-block-start: calc(-2 * var(--c2u-velocity-bleed));
}

.c2u-velocity__track {
  display: flex;
  width: max-content;
}

/* One repeat: the line, then the space, the separator and the space again. The
   trailing half of that pair is padding on this box rather than a margin on the
   separator, so the whole repeat is one border-box — which is the box the fit is
   measured against, and the box c2u-page.js wraps the loop on. */
.c2u-velocity__copy {
  flex-shrink: 0;
  white-space: nowrap;
  padding-inline-end: calc(var(--c2u-velocity-gap) * 1em);
}

/* The mark between repeats. Set smaller and lighter than the line, because at
   the line's own weight and size it competes with the words instead of
   punctuating them.

   ITS WIDTH IS PINNED, and that is not cosmetic. Inter does not carry ✦ (U+2726)
   — nor most of the marks anyone would reach for here — so the glyph is drawn by
   whatever the operating system falls back to, at whatever advance width that
   font gives it. Left free, one repeat would be a different width on Windows
   than on the Mac it was measured on, and the fit above is a promise about
   exactly that width. Fixing the box makes the repeat font-independent: the
   fallback still draws the glyph, but it no longer gets a say in the layout.

   EVERY LENGTH ON IT IS DIVIDED BY ITS OWN SIZE, and that is not decoration.
   This element sets its own font-size, so a bare `em` here resolves against
   that and not against the line — which is how the mark ended up with 0.21em of
   air in front of it and 0.34em behind, from the one figure that was supposed to
   give it both. Stating each length as a fraction of the line and dividing by
   the size puts them back in the line's terms, so --c2u-velocity-gap means the
   same thing on either side of the mark and the row can add it up. */
.c2u-velocity--marked {
  --c2u-velocity-sep-size: 0.62;   /* glyph size, as a fraction of the line */
  --c2u-velocity-sep-box: 0.5;     /* advance width, same fraction */
  --c2u-velocity-mark: calc(var(--c2u-velocity-sep-box) + var(--c2u-velocity-gap));
}

.c2u-velocity__sep {
  display: inline-block;
  inline-size: calc(var(--c2u-velocity-sep-box) / var(--c2u-velocity-sep-size) * 1em);
  text-align: center;

  margin-inline-start: calc(var(--c2u-velocity-gap) / var(--c2u-velocity-sep-size) * 1em);
  font-size: calc(var(--c2u-velocity-sep-size) * 1em);
  font-weight: 400;
  letter-spacing: 0;
  color: var(--c2u-red);

  /* Optically centred on the line rather than sitting on the baseline: it is a
     small mark between two runs of caps, so the baseline puts it low. In the
     element's own em on purpose — it is centring the glyph, so it should track
     the glyph's size rather than the line's. */
  vertical-align: 0.22em;
}

/* Promoted only while it is actually being driven — c2u-page.js adds the class
   when it takes the section over, and never under reduced motion. Three
   screen-sized layers is not something to hint at on a band that is going to
   sit still. */
.c2u-velocity.is-live .c2u-velocity__track { will-change: transform; }

/* On the navy field. The page background crossfades from pink to navy as the
   band arrives and back on the way out — the shift* parameters at the
   brand-home call site — and the type, which is navy ink, has to come back the
   other way with it. The same arrangement the EOI section further down this
   file makes, and for the same reasons:

   The transition is set on the row unconditionally rather than inside the
   shifted state, or the colour would ease onto the navy and snap back off it.
   800ms is c2u-grainient.js's SHIFT_MS — the type and the field behind it are
   one movement and have to take the same time; move one and move the other.

   `is-bg-shifted` is set by the shader path in that file and only by it, so a
   browser that never painted the navy is never left with white type over the
   pink it did paint.

   The separator keeps its red on both fields. It is the one thing on the band
   that is not the sentence, and the field moving under it does not change
   that. */
.c2u-velocity__row { transition: color 800ms var(--c2u-ease); }

.c2u-velocity.is-bg-shifted .c2u-velocity__row { color: var(--c2u-paper); }

/* The shader snaps between palettes under this preference rather than
   crossfading, and type still easing its way to white against a background
   that arrived instantly is the two halves coming apart. */
@media (prefers-reduced-motion: reduce) {
  .c2u-page .c2u-velocity__row { transition: none; }
}

/* Phone. The section is the only thing on screen here, and every desktop
   proportion leaves it looking incidental at 390px.

   The type goes well past one screen per repeat. The promise the fit makes is
   worth keeping exactly where a 1440px line is already 137px tall, and worth
   breaking where the same rule gives 37px and reads as a caption. At 1.5 the
   line lands around 54px and the band is the page's loudest thing, which is
   what it is for. Over-filling costs nothing structurally: the line simply runs
   off both edges, which is what it does anyway.

   The rows are given air to match — at a leading of 1 three lines pack into a
   block that works at display size and turns into a smudge at phone size — and
   between them the band takes noticeably more of the screen, which is the
   point.

   The mark grows faster than the type, and its air closes in. Scaled with
   everything else the mark would come out around 34px against a 54px line, and
   at that size on a phone it reads as a speck rather than as punctuation; a
   fraction of the line is the right way to state it and the wrong fraction to
   keep. The gap goes the other way for the same reason — a bigger mark needs
   less room around it to read as separate, and at the desktop 0.34 the phone
   band came apart into three pieces instead of running as one line.

   Both feed back into the repeat through --c2u-velocity-mark, which the row
   adds to the fit, so nothing here needs re-measuring. The type does come out a
   little larger as a result: a narrower repeat fills the same 1.5 screens at a
   bigger size (about 56px at 390px rather than 54.5px). That is the mechanism
   working, not a second decision. */
@media (max-width: 767px) {
  .c2u-velocity {
    --c2u-velocity-fill: 1.5;
    --c2u-velocity-leading: 1.3;
    --c2u-velocity-gap: 0.2;
  }

  .c2u-velocity--marked {
    --c2u-velocity-sep-size: 0.88;
    --c2u-velocity-sep-box: 0.72;
  }
}


/* ── Steps ───────────────────────────────────────────────────────  */

/* Columns sit flush (no column-gap) and each item pads itself instead, so the
   connector rails in adjacent columns meet and read as one continuous line.
   A gap would break the line into segments. */
.c2u-steps__list {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  row-gap: var(--c2u-space-9);
  counter-reset: c2u-step;

  /* One dot size for the whole component. The rail is exactly this tall so
     the dot centres itself on the line, and the spark measures its start
     offset off it — change it here and the three stay registered. */
  --c2u-steps-dot: 10px;
  --c2u-steps-spark: 6px;
}

/* Flush left, so the numerals line up with the section head above. The gutter
   between columns is trailing padding only — the item's content starts on the
   column edge and the rail is widened back over the padding below. */
.c2u-steps__item {
  counter-increment: c2u-step;
  display: flex;
  flex-direction: column;
  align-items: start;
  text-align: start;
  padding-inline: 0 var(--c2u-space-7);
}

.c2u-steps__num {
  font-size: clamp(56px, 2.5rem + 3.4vw, 96px);
  font-weight: 500;
  line-height: 1;
  letter-spacing: -0.03em;
  color: var(--c2u-red);
  font-variant-numeric: tabular-nums lining-nums;
}
.c2u-steps__num::before { content: counter(c2u-step); }

/* Rail — dot on the column's left edge, line running from it to the next
   column's dot. The last item in a row has nothing to join, so its line is
   dropped and the run reads dot-to-dot rather than overhanging the row.
   Whether a line is there is also the answer to "can the spark travel from
   here", which is why c2u-page.js reads it back off ::before rather than
   working the row ends out a second time in script. */
.c2u-steps__rail {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: start;
  width: 100%;
  height: var(--c2u-steps-dot);
  margin-block: var(--c2u-space-7) var(--c2u-space-6);
}

/* Two lines on one geometry: ::before is the rail, ::after the red trail the
   idle cycle draws over it as the spark runs (timed in c2u-motion.css). The
   insets have to stay identical — the trail is meant to replace the rail for
   the length it covers, and a pixel of disagreement reads as a double line. */
.c2u-steps__rail::before,
.c2u-steps__rail::after {
  content: '';
  position: absolute;
  left: 0;
  /* the overhang is on the line, not the rail box: it reaches across the
     item's trailing padding to the next column's dot, and on the item that
     ends a row there is no line at all, so nothing hangs past the grid */
  right: calc(-1 * var(--c2u-space-7));
  height: 1px;
}
.c2u-steps__rail::before {
  /* Not --c2u-line: the rail sits on the page's pink gradient rather than a
     flat surface, and a translucent black holds an even weight across it. */
  background: rgba(0, 0, 0, 0.1);
}
.c2u-steps__rail::after {
  background: var(--c2u-red);
  transform-origin: left center;
  /* Idle state — drawn only while the cycle is running it. */
  transform: scaleX(0);
  opacity: 0;
}
.c2u-steps__item:last-child .c2u-steps__rail::before,
.c2u-steps__item:last-child .c2u-steps__rail::after { content: none; }

.c2u-steps__dot {
  position: relative;
  width: var(--c2u-steps-dot);
  height: var(--c2u-steps-dot);
  border-radius: var(--c2u-radius-pill);
  background: var(--c2u-red);
  /* Grown and shrunk by the idle cycle; from the middle, so the dot stays on
     the line and on its column edge at every size. */
  transform-origin: center center;
}

/* Spark — the mark that carries the highlight to the next step.
   The element itself is an invisible carrier, sized to the exact run between
   two dot centres: one column, since every column is the same width and the
   dot sits at the same offset in each. That is what lets the travel be
   written as translateX(0 → 100%) and land on the next dot without any
   measurement in script. The visible mark is its ::after, offset by the dot's
   own radius so it starts life concentric with the dot it leaves. */
.c2u-steps__spark {
  position: absolute;
  top: 50%;
  left: 0;
  right: calc(-1 * var(--c2u-space-7));
  height: 0;
  opacity: 0;
  pointer-events: none;
}
.c2u-steps__spark::after {
  content: '';
  position: absolute;
  top: 0;
  left: calc(var(--c2u-steps-dot) / 2);
  width: var(--c2u-steps-spark);
  height: var(--c2u-steps-spark);
  margin: calc(var(--c2u-steps-spark) / -2) 0 0 calc(var(--c2u-steps-spark) / -2);
  border-radius: var(--c2u-radius-pill);
  background: var(--c2u-red);
}

.c2u-steps__title {
  font-size: var(--c2u-fs-heading-2);
  font-weight: var(--c2u-fw-heading-2);
  line-height: var(--c2u-lh-heading-2);
  letter-spacing: var(--c2u-ls-heading-2);
  color: var(--c2u-navy);
  margin-block-end: var(--c2u-space-4);
}

.c2u-steps__body {
  color: var(--c2u-muted);
  font-size: var(--c2u-fs-body);
  line-height: var(--c2u-lh-body);
  max-width: 34ch;
}

/* Two columns — each row gets its own dot-to-dot rail, so the line is dropped
   on the right-hand item of every row instead of only on the last. */
@media (max-width: 980px) {
  .c2u-steps__list { grid-template-columns: repeat(2, 1fr); }
  .c2u-steps__item:nth-child(odd)  .c2u-steps__rail::before,
  .c2u-steps__item:nth-child(odd)  .c2u-steps__rail::after  { content: ''; }
  .c2u-steps__item:nth-child(even) .c2u-steps__rail::before,
  .c2u-steps__item:nth-child(even) .c2u-steps__rail::after  { content: none; }
}

/* Single column — a dot-to-dot rail would have no length, so drop the line and
   let the numerals carry the sequence. */
@media (max-width: 600px) {
  .c2u-steps__list { grid-template-columns: 1fr; row-gap: var(--c2u-space-8); }
  .c2u-steps__item { padding-inline: 0; }
  .c2u-steps__rail { display: none; }
  .c2u-steps__num { margin-block-end: var(--c2u-space-4); }
}


/* ── Labelled rows ───────────────────────────────────────────────  */

.c2u-rows__list {
  /* dl is outside the scoped reset in c2u-base.css, which covers ul/ol only,
     so its UA margin is cleared here. Same for dt/dd below — a class beats
     Divi's bare element rules, which is what those margins would otherwise
     come back as. */
  margin: 0;
}

/* Ruled on the top edge, so the run ends on content rather than on a line
   hanging under the last row. */
.c2u-rows__row {
  display: grid;
  grid-template-columns: minmax(0, 3fr) minmax(0, 2fr);
  gap: var(--c2u-space-7);
  padding-block: var(--c2u-space-7) var(--c2u-space-9);
  /* Same hairline as the steps rail, and the same reason it is a translucent
     black rather than --c2u-line: it sits on the page's pink gradient rather
     than on a flat surface, and a solid grey shifts against it. Keep the two
     in step — they are read as one line running down the page. */
  border-block-start: 1px solid rgba(0, 0, 0, 0.1);
}

/* A row's bottom padding is clearance for the next rule. The last row has none
   to clear, so it would only stack onto the section's own padding and leave the
   section ending on a gap. Specificity carries this over the stacked rule
   below without needing to be repeated there. */
.c2u-rows__row:last-child { padding-block-end: 0; }

.c2u-rows__label {
  margin: 0;
  font-size: var(--c2u-fs-heading-2);
  font-weight: var(--c2u-fw-heading-2);
  line-height: var(--c2u-lh-heading-2);
  letter-spacing: var(--c2u-ls-heading-2);
  color: var(--c2u-navy);
}

.c2u-rows__content {
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: var(--c2u-space-4);
  color: var(--c2u-muted);
  font-size: var(--c2u-fs-body);
  line-height: var(--c2u-lh-body);
}

.c2u-rows__items {
  display: flex;
  flex-direction: column;
  gap: var(--c2u-space-4);
}

/* The marker is the steps dot at list scale, which is where this page's
   vocabulary of small red marks comes from. Positioned off the text's own
   line-height so it stays on the first line's optical centre as the type
   scales, rather than being nudged by a fixed offset. */
.c2u-rows__items li {
  position: relative;
  padding-inline-start: var(--c2u-space-5);
}
.c2u-rows__items li::before {
  content: '';
  position: absolute;
  inset-inline-start: 0;
  inset-block-start: calc(var(--c2u-lh-body) * 0.5em);
  width: 6px;
  height: 6px;
  margin-block-start: -3px;
  border-radius: var(--c2u-radius-pill);
  background: var(--c2u-red);
}

/* Even columns. The desktop split leaves the label deliberately short of its
   column — that space is the layout. Below about 1000px there is no longer
   enough width to spend on it: the content drops to ~250px and sets four-word
   lines beside an empty half-row, so the two columns share the width instead.  */
@media (max-width: 980px) {
  .c2u-rows__row {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: var(--c2u-space-6);
  }
}

/* Stacked — the label sits above its content, and the rule is what keeps the
   rows apart. The gap between the two columns becomes the gap between them. */
@media (max-width: 767px) {
  .c2u-rows__row {
    grid-template-columns: 1fr;
    gap: var(--c2u-space-5);
    padding-block: var(--c2u-space-6) var(--c2u-space-8);
  }
}


/* ── Labelled rows, beside a sticky picture ──────────────────────
   Switched on by the part's `media` arg — see the layout diagram in
   parts/rows.php. The plain layout above is untouched: .c2u-rows__grid
   is an ordinary block wrapper until this modifier makes it a grid.  */

.c2u-rows--aside {
  /* Where the picture parks. The site header is sticky at the top of the
     viewport, so this has to clear it: 16px + the tallest thing in the bar
     + 16px + its 1px rule, rounded up to 80 because the bar's search field
     comes from a plugin and is not ours to measure. The rest is a step of
     air. One number to retune if the header bar ever changes height. */
  --c2u-rows-aside-top: calc(80px + var(--c2u-space-5));
}

.c2u-rows--aside .c2u-rows__grid {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: var(--c2u-space-9) var(--c2u-space-5);
  /* start, not the default stretch. A stretched item fills its whole grid
     area, which leaves the picture nowhere to travel and silently turns the
     sticky below into a no-op — the failure looks like a CSS typo and isn't. */
  align-items: start;
}

.c2u-rows--aside .c2u-rows__head {
  grid-row: 1;
  grid-column: 1 / span 6;
  /* The grid's row-gap now separates the head from the list; the block's own
     margin would stack a second gap on top of it. Same for the measure cap —
     the column is the measure here, as it is in the media-split's intro. */
  margin-block-end: 0;
  max-width: none;
}

.c2u-rows--aside .c2u-rows__list {
  grid-row: 2;
  grid-column: 1 / span 6;
}

/* Column 7 is left empty on purpose — the same open column the media-split
   keeps, and for the same reason: at this scale a gap alone does not read as
   a division, and the text has to stop well short of the picture. */
.c2u-rows--aside .c2u-rows__aside {
  /* Spanning both rows is what makes the sticky release at the right moment.
     A sticky box travels within its containing block, which for a grid item
     is its grid area — so an area covering the head AND the list gives the
     picture exactly the section's own height to travel, and it unsticks on
     the last row rather than on the first. */
  grid-row: 1 / span 2;
  grid-column: 8 / span 5;
  position: sticky;
  top: var(--c2u-rows-aside-top);
  align-self: start;
}

.c2u-rows--aside .c2u-rows__media {
  margin: 0;
  overflow: hidden;
  border-radius: var(--c2u-radius-lg);
  /* Same 4:5 frame as the media-split, so a page running both keeps one set
     of proportions. A call site can override it with the part's `ratio`. */
  aspect-ratio: var(--c2u-rows-ratio, 4 / 5);
  /* A sticky picture taller than the screen can never be seen whole: it
     scrolls its own bottom edge into view and reads as drifting rather than
     as parked. Capped to what is left under the header, and the cover crop
     below absorbs the difference. svh rather than vh so a mobile browser's
     retracting toolbar cannot resize it mid-scroll; the vh line is the
     fallback for anything that does not know the unit. */
  max-height: calc(100vh - var(--c2u-rows-aside-top) - var(--c2u-space-6));
  max-height: calc(100svh - var(--c2u-rows-aside-top) - var(--c2u-space-6));
}

.c2u-rows--aside .c2u-rows__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform var(--c2u-base) var(--c2u-ease);
}

/* The same hover the split's pictures have, scoped to img for the same
   reason: the figure clips to the rounded corners, so the frame stays put
   and only the picture moves. */
.c2u-rows--aside .c2u-rows__media:hover img { transform: scale(1.04); }

/* TEMPORARY — stands in until photography for this section is supplied.
   Delete this rule and the <span> in parts/rows.php once every use has a src.
   Matches .c2u-split__placeholder, which it will be deleted alongside. */
.c2u-rows__placeholder {
  display: block;
  width: 100%;
  height: 100%;
  background: #d6dade;
}

/* Six columns is already past the width at which a row's own two-column
   split works — the plain layout gives it up at 980px, and this column is
   narrower than that at every size. So the label sits above its content
   here at all widths, and the 767px rule below has nothing left to do. */
.c2u-rows--aside .c2u-rows__row {
  grid-template-columns: 1fr;
  gap: var(--c2u-space-5);
}

/* The open column is the first thing to go, exactly as in the media-split:
   below about 1000px it is width the text needs more than the layout does.
   The picture keeps its five columns, so only the text column grows. */
@media (max-width: 980px) {
  .c2u-rows--aside .c2u-rows__head,
  .c2u-rows--aside .c2u-rows__list { grid-column: 1 / span 7; }
  .c2u-rows--aside .c2u-rows__aside { grid-column: 8 / span 5; }
}

/* Stacked, and the picture lands between the subhead and the first row —
   which is the DOM order, so nothing is reordered to get it. The sticky
   goes with the second column: with the picture in the reading flow there
   is no longer a column beside it to hold it against, and a box that parks
   over the text it interrupts would be in the way rather than alongside. */
@media (max-width: 767px) {
  .c2u-rows--aside .c2u-rows__grid {
    grid-template-columns: 1fr;
    row-gap: var(--c2u-space-7);
  }

  .c2u-rows--aside .c2u-rows__head,
  .c2u-rows--aside .c2u-rows__aside,
  .c2u-rows--aside .c2u-rows__list { grid-row: auto; grid-column: 1; }

  .c2u-rows--aside .c2u-rows__aside {
    position: static;
    top: auto;
  }

  .c2u-rows--aside .c2u-rows__media { max-height: none; }
}


/* ── Text beside a picture ───────────────────────────────────────
   See the layout diagram in parts/media-split.php.                */

.c2u-split__grid {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  /* Centred rather than top-aligned: the picture is much the taller of the
     two, so aligning the tops would hang the text off the top of a long
     column of photograph. */
  align-items: center;
  gap: var(--c2u-space-8) var(--c2u-space-5);
}

/* Placement is explicit so DOM order can stay the mobile order, and so the
   flipped variant is a swap of two values rather than a reordering. Both are
   pinned to row 1: with only a column named, auto-placement would push the
   flipped picture to a second row, since the cursor has already passed the
   columns it asks for. */
.c2u-split__intro { grid-row: 1; grid-column: 1 / span 6; }
.c2u-split__media { grid-row: 1; grid-column: 8 / span 5; }

.c2u-split--flip .c2u-split__media { grid-column: 1 / span 5; }
.c2u-split--flip .c2u-split__intro { grid-column: 7 / span 6; }

/* Same rhythm as .c2u-section-head, which this is not: that block caps its
   measure and carries the margin that separates a heading from the section
   under it. Here the column is the measure and there is nothing below. */
.c2u-split__intro {
  display: flex;
  flex-direction: column;
  gap: var(--c2u-space-4);
}

.c2u-split__intro .c2u-h1 { color: var(--c2u-navy); }

/* One step more air under the heading than the flex gap gives everything else
   (16 + 16 = 32). The eyebrow belongs to the heading and should sit close to
   it; the body is the next thing to read and wants the break. Written as a
   margin on the paragraph rather than on the heading so a section with no body
   does not end on a trailing gap. */
.c2u-split__intro .c2u-h1 + .c2u-split__body {
  margin-block-start: var(--c2u-space-4);
}

/* .c2u-lead caps itself at 68ch, which is wider than this column ever is —
   the cap would only bite at the top of the type scale and shorten one
   section's lines and not another's. The column sets the measure. */
.c2u-split__body { max-width: none; }

/* Optional bullet list under the body — see the note in parts/media-split.php.
   Sits in the intro's flex column, so the space above and below it is the
   column's own gap; a step more air on top sets the list apart from the
   paragraph it follows, the way the CTA is set apart below. */
.c2u-split__points {
  list-style: none;
  margin: var(--c2u-space-2) 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--c2u-space-4);
  color: var(--c2u-navy);
}

/* The name half of a "name — what it is" point, when the section opts in with
   points_lead. Semibold rather than bold: <strong> defaults to 700, which at
   this size reads as a heading dropped into a sentence, and 600 is the weight
   the rest of the page already uses for a label. Colour is inherited — the
   list is navy already, so the weight is the only thing that changes. */
.c2u-split__lead { font-weight: var(--c2u-fw-label); }

/* Same small red dot as the rows list, positioned off the text's own
   line-height so it holds the first line's optical centre as the type scales —
   see the fuller note on .c2u-rows__items li::before. */
.c2u-split__points li {
  position: relative;
  padding-inline-start: var(--c2u-space-5);
}
.c2u-split__points li::before {
  content: '';
  position: absolute;
  inset-inline-start: 0;
  inset-block-start: calc(var(--c2u-lh-body) * 0.5em);
  width: 6px;
  height: 6px;
  margin-block-start: -3px;
  border-radius: var(--c2u-radius-pill);
  background: var(--c2u-red);
}

/* Optional CTA under the prose. A flex row so the button hugs its content and
   sits at the start of the column, the way .c2u-hero__actions does — a bare
   .c2u-btn is a stretch child of the intro's flex column and would run the full
   width. A step more air above it than the column's flex gap gives, to set the
   action apart from the paragraph it follows. It wraps, so an accompanying note
   drops below the button when the column is narrow — and on mobile, where the
   button goes full width by the base rule, the note always sits on its own row. */
.c2u-split__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--c2u-space-3) var(--c2u-space-4);
  margin-block-start: var(--c2u-space-2);
}

/* The address in full beside the button, to be read and copied without opening
   a mail client. A single click selects the whole address, since a part of an
   email is no use — the same reason it is not broken across lines. */
.c2u-split__note {
  color: var(--c2u-navy);
  font-size: var(--c2u-fs-label);
  opacity: .82;
  white-space: nowrap;
  user-select: all;
}

.c2u-split__media {
  margin: 0;
  overflow: hidden;
  border-radius: var(--c2u-radius-lg);
  /* 4:5 by default — the frame that keeps a section's proportions when the
     photography is swapped. A call site can override it via the part's `ratio`
     to match a source of its own, e.g. a square portrait. */
  aspect-ratio: var(--c2u-split-ratio, 4 / 5);
}

.c2u-split__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform var(--c2u-base) var(--c2u-ease);
}

/* The same hover the hero photos have, for the same reason it is scoped to
   img there: the figure already clips to the rounded corners, so the frame
   stays put and only the picture moves. */
.c2u-split__media:hover img { transform: scale(1.04); }

/* TEMPORARY — stands in until real photography is supplied. Delete this rule
   and the <span> in parts/media-split.php once every use has a src. */
.c2u-split__placeholder {
  display: block;
  width: 100%;
  height: 100%;
  background: #d6dade;
}

/* The open column is the first thing to go: below about 1000px it is width the
   text needs more than the layout does. The picture keeps its five columns, so
   its proportions are unchanged and only the text column grows. */
@media (max-width: 980px) {
  .c2u-split__intro { grid-column: 1 / span 7; }
  .c2u-split__media { grid-column: 8 / span 5; }

  .c2u-split--flip .c2u-split__media { grid-column: 1 / span 5; }
  .c2u-split--flip .c2u-split__intro { grid-column: 6 / span 7; }
}

/* Stacked, picture last — including when flipped, which has no meaning in one
   column. These carry the same specificity as the --flip rules above and win
   on order, so the variant does not have to be named again. */
@media (max-width: 767px) {
  .c2u-split__grid {
    grid-template-columns: 1fr;
    row-gap: var(--c2u-space-7);
  }

  .c2u-split .c2u-split__intro,
  .c2u-split .c2u-split__media { grid-row: auto; grid-column: 1; }

  /* The extra space under the heading is desktop-only: in one narrow column
     the heading is already two or three lines, and the break is legible on
     the flex gap alone. */
  .c2u-split__intro .c2u-h1 + .c2u-split__body { margin-block-start: 0; }
}


/* ── Benefits ────────────────────────────────────────────────────  */

.c2u-benefits__grid {
  display: grid;
  gap: var(--c2u-space-5);
}
.c2u-benefits__grid--2 { grid-template-columns: repeat(2, 1fr); }
.c2u-benefits__grid--3 { grid-template-columns: repeat(3, 1fr); }

.c2u-benefits__card {
  display: flex;
  flex-direction: column;
  padding: var(--c2u-space-7);
  background: var(--c2u-paper);
  border: 1px solid var(--c2u-line);
  border-radius: var(--c2u-radius-lg);
  box-shadow: var(--c2u-shadow-sm);
}

.c2u-benefits__mark {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  margin-block-end: var(--c2u-space-5);
  border-radius: var(--c2u-radius-pill);
  background: var(--c2u-red-soft);
  color: var(--c2u-red-deep);
}
.c2u-benefits__mark svg { width: 20px; height: 20px; }

.c2u-benefits__title {
  color: var(--c2u-navy);
  margin-block-end: var(--c2u-space-3);
}

.c2u-benefits__body {
  color: var(--c2u-muted);
  font-size: var(--c2u-fs-body-large);
  line-height: 1.6;
  text-wrap: pretty;
}

/* No lead-in title — let the body carry the card at heading weight-ish size. */
.c2u-benefits__card--untitled .c2u-benefits__body {
  color: var(--c2u-ink);
}

@media (max-width: 980px) {
  .c2u-benefits__grid--2,
  .c2u-benefits__grid--3 { grid-template-columns: 1fr; }
  .c2u-benefits__card { padding: var(--c2u-space-6); }
}


/* ── Benefits, plain grid variant ────────────────────────────────────────
   See parts/benefits-grid.php. The same paper card the wheel rides, sat
   still in a 2- or 3-up row: icon disc at the top-left, title and copy at the
   bottom. justify-content pins the two ends apart, and the row stretches every
   card to the tallest, so the headings line up along one edge no matter how
   uneven the copy. */

.c2u-cardgrid__list {
  display: grid;
  gap: var(--c2u-space-5);
}
.c2u-cardgrid__list--2 { grid-template-columns: repeat(2, 1fr); }
.c2u-cardgrid__list--3 { grid-template-columns: repeat(3, 1fr); }

.c2u-cardgrid__card {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: var(--c2u-space-7);
  min-height: clamp(280px, 24vw, 340px);
  padding: clamp(24px, 2.4vw, 38px);
  border: 1px solid var(--c2u-line);
  border-radius: var(--c2u-radius-md);
  background: var(--c2u-paper);
  color: var(--c2u-navy);
  box-shadow: var(--c2u-shadow-lg);
}

.c2u-cardgrid__mark {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: none;
  align-self: start;
  width: 48px;
  height: 48px;
  border-radius: var(--c2u-radius-pill);
  background: var(--c2u-red-soft);
  color: var(--c2u-red-deep);
}
.c2u-cardgrid__mark svg { width: 22px; height: 22px; }

/* An illustration brings its own tinted disc, so the card's disc gets out of
   its way and the box just letterboxes the artwork — square, so an icon drawn
   on a shorter canvas still lands its disc at the same size as the others. */
.c2u-cardgrid__mark--art {
  width: 64px;
  height: 64px;
  background: none;
}
.c2u-cardgrid__mark--art img {
  width: 100%;
  height: 100%;
  object-fit: contain;
}

.c2u-cardgrid__body {
  display: grid;
  gap: var(--c2u-space-3);
}

.c2u-cardgrid__title { color: var(--c2u-navy); }

.c2u-cardgrid__text {
  max-width: 46ch;
  color: var(--c2u-muted);
  font-size: var(--c2u-fs-body-large);
  line-height: 1.6;
  text-wrap: pretty;
}

/* No lead-in title — let the body carry the card at heading-ish size. */
.c2u-cardgrid__card--untitled .c2u-cardgrid__text {
  color: var(--c2u-ink);
  font-size: var(--c2u-fs-heading-3);
  line-height: 1.3;
}

@media (max-width: 980px) {
  .c2u-cardgrid__list--3 { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 680px) {
  .c2u-cardgrid__list--2,
  .c2u-cardgrid__list--3 { grid-template-columns: 1fr; }
  .c2u-cardgrid__card { min-height: 0; }
}


/* ── Bento ───────────────────────────────────────────────────────────────
   See parts/bento.php for the layout diagram and for why the placement is
   written out card by card rather than left to auto-flow.

   Three columns, two rows, and one card down the first of them across both.
   The card itself is the cardgrid's — paper, icon disc pinned top-left, copy
   sat at the bottom — with a CTA under the copy and the whole box clickable. */

.c2u-bento {
  /* The feature's column, as a fraction of the two beside it. It is already
     twice the height of a side card; this is how much wider it also reads.
     Below ~1.1 the layout stops looking composed and starts looking like a
     three-up row that lost a card. */
  --c2u-bento-feature-w: 1.2fr;
  --c2u-bento-gap: var(--c2u-space-5);
}

.c2u-bento__grid {
  display: grid;
  grid-template-columns: minmax(0, var(--c2u-bento-feature-w)) minmax(0, 1fr) minmax(0, 1fr);
  /* Equal rows, so the feature is exactly two side cards plus the gap and the
     two cards beside it line up with its top and bottom edges. The height
     comes from the tallest side card's content; the min() floor stops a short
     set collapsing into a band of letterboxes. */
  grid-auto-rows: minmax(clamp(230px, 17vw, 280px), 1fr);
  gap: var(--c2u-bento-gap);
}

/* Coordinates come from the part as custom properties. The `auto` fallbacks
   are what a sixth card lands on — see the note at the $slots list. */
.c2u-bento__card {
  position: relative;                /* containing block for the stretched link */
  display: flex;
  flex-direction: column;
  justify-content: space-between;    /* mark to the top, body to the bottom */
  gap: var(--c2u-space-7);
  grid-column: var(--c2u-bento-col, auto);
  grid-row: var(--c2u-bento-row, auto) / span var(--c2u-bento-span, 1);
  padding: clamp(24px, 2.4vw, 38px);
  border: 1px solid var(--c2u-line);
  border-radius: var(--c2u-radius-lg);
  background: var(--c2u-paper);
  color: var(--c2u-navy);
  box-shadow: var(--c2u-shadow-lg);
  transition:
    transform  var(--c2u-base) var(--c2u-ease),
    box-shadow var(--c2u-base) var(--c2u-ease);
}

/* The whole card lifts, because the whole card is the link. Guarded on hover
   support so it never sticks on a touch device, and expressed as a transform
   so it cannot move the grid around it.

   :has() is what lets the card react to a state on its own descendant. Its
   fallback is simply no lift — the card is still a card, and the CTA still
   has the arrow nudge below, so nothing about the affordance depends on it. */
@media (hover: hover) {
  .c2u-bento__card:has(.c2u-bento__cta:hover) {
    transform: translateY(-4px);
    box-shadow: 0 26px 56px -14px rgba(12, 52, 74, .28);
  }
}

/* The focus ring belongs on the card, not on the invisible stretched box — a
   2px outline around a link that covers the whole card would trace the card's
   edge anyway, but square, and inside its own rounded border. Drawn here it
   follows the radius. The link's own ring is suppressed for the same reason:
   there would otherwise be two. */
.c2u-bento__card:has(.c2u-bento__cta:focus-visible) {
  outline: 2px solid var(--c2u-red);
  outline-offset: 3px;
}
.c2u-page .c2u-bento__cta:focus-visible { outline: none; }

/* Icon, top-left. The artwork brings its own tinted disc, so the box only
   letterboxes it — square, so an icon drawn on a shorter canvas (icon4 is
   72x64) still lands its disc at the same size as the others.

   align-self keeps it at its own width instead of stretching across the card,
   and flex:none keeps it off the space-between distribution — the mark stays
   at the top and only the gap below it grows. */
.c2u-bento__mark {
  flex: none;
  align-self: start;
  width: 64px;
  height: 64px;
}
.c2u-bento__mark img {
  width: 100%;
  height: 100%;
  object-fit: contain;
}

.c2u-bento__body {
  display: grid;
  gap: var(--c2u-space-3);
  justify-items: start;              /* copy and CTA to the left edge */
}

.c2u-bento__title { color: var(--c2u-navy); }

.c2u-bento__text {
  max-width: 42ch;
  color: var(--c2u-muted);
  font-size: var(--c2u-fs-body);
  line-height: 1.6;
  text-wrap: pretty;
}

/* A text link rather than a pill. Five buttons in one grid would read as five
   equally weighted asks and would fight the feature for the eye; the card is
   the button. */
.c2u-page .c2u-bento__cta {
  display: inline-flex;
  align-items: center;
  gap: var(--c2u-space-2);
  margin-block-start: var(--c2u-space-2);
  color: var(--c2u-red);
  font-size: var(--c2u-fs-body);
  font-weight: 600;
  line-height: 1.3;
  text-decoration: none;
}

/* This is what makes the card clickable. The card is the containing block, so
   the layer covers it exactly, and it sits above the card's own content but
   below nothing — there is no other interactive element inside a card, which
   is the condition this pattern is only safe under. */
.c2u-bento__cta::after {
  content: "";
  position: absolute;
  inset: 0;
}

.c2u-bento__arrow {
  width: 1.15em;
  height: 1.15em;
  transition: transform var(--c2u-base) var(--c2u-ease);
}
.c2u-bento__card:has(.c2u-bento__cta:hover) .c2u-bento__arrow,
.c2u-bento__cta:focus-visible .c2u-bento__arrow { transform: translateX(3px); }

/* The label is underlined on hover rather than always, so five cards do not
   arrive as five underlined runs of text. */
.c2u-bento__card:has(.c2u-bento__cta:hover) .c2u-bento__cta-label,
.c2u-bento__cta:focus-visible .c2u-bento__cta-label { text-decoration: underline; }


/* The feature. It is not a different card — same paper, same border, same
   corner — only a bigger one, and its copy is set up a step to match. Giving
   it a tone of its own is a trap worth naming: the icon artwork is drawn in
   navy line work that runs past its own tinted disc, so an ink card loses
   every stroke outside that disc. Same hazard as the wheel's tone cycle. */
.c2u-bento__card--feature {
  gap: var(--c2u-space-8);
}
.c2u-bento__card--feature .c2u-bento__mark {
  width: 80px;
  height: 80px;
}
.c2u-bento__card--feature .c2u-bento__text {
  max-width: 34ch;
  font-size: var(--c2u-fs-lead);
  line-height: var(--c2u-lh-lead);
}
.c2u-bento__card--feature .c2u-bento__cta { font-size: var(--c2u-fs-label); }


/* Two columns. Three cards abreast plus a wider first one needs more width
   than this, so the feature gives up its column and takes the full first row —
   still first, still the biggest, and the other four fall into a 2x2 beneath
   it in the order they are written. Coordinates are dropped wholesale here
   rather than restated, which is why every one of them is `revert`-able:
   nothing below this breakpoint reads --c2u-bento-col at all. */
@media (max-width: 1080px) {
  .c2u-bento__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }

  .c2u-bento__card {
    grid-column: auto;
    grid-row: auto;
  }
  .c2u-bento__card--feature {
    grid-column: 1 / -1;
    /* Side by side inside the full-width card — at this width a stacked
       feature would be a very tall box holding two short lines. */
    flex-direction: row;
    align-items: center;
    gap: var(--c2u-space-7);
  }
  .c2u-bento__card--feature .c2u-bento__body { flex: 1; }
}

/* One column, and the DOM order takes over — which is the order the part
   writes the cards in, feature first. The row floor goes with the grid: a
   phone card should be as tall as its copy and no taller. */
@media (max-width: 680px) {
  .c2u-bento__grid {
    grid-template-columns: 1fr;
    grid-auto-rows: auto;
  }
  .c2u-bento__card--feature {
    flex-direction: column;
    align-items: stretch;
    gap: var(--c2u-space-6);
  }
  .c2u-bento__card--feature .c2u-bento__mark {
    width: 64px;
    height: 64px;
  }
}



/* ── People ──────────────────────────────────────────────────────────────
   See parts/people.php for the row-split argument and the layout diagram.

   Twelve columns, and the only thing that changes from one row to the next is
   how many of them a person takes. n spans of 12/n plus the gaps between them
   comes to exactly the full width for any n that divides 12, so a 3-up line
   and a 4-up line sit flush to the same two edges without either being told
   what the other is doing.

   NO CARD, on purpose. The portraits sit straight on the page's own field:
   seven paper boxes under the bento's five would read as more of the same
   section, and this one is a set of people rather than a set of doors. It also
   means the only thing drawing a box here is the photograph itself, which is
   what the section is for. */

.c2u-people__grid {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  /* Rows are spaced further apart than columns: the gap below a bio has to
     read as the end of that person rather than as the space beside them. */
  gap: var(--c2u-space-8) var(--c2u-space-5);
}

/* The span comes from the part as a custom property. Its fallback is the 3-up
   the part falls back to when no row shape is passed, and it is also what the
   breakpoints below overwrite — they set grid-column outright rather than
   redefining the property, so the split is dropped rather than recalculated. */
.c2u-people__person {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  grid-column: span var(--c2u-people-span, 4);
}

/* Full width in the column layout, so the bio's own 42ch measure is what
   decides where it wraps rather than the widest word in the name. */
.c2u-people__copy { align-self: stretch; }

.c2u-people__photo {
  width: 100%;
  aspect-ratio: 1;
  margin-block-end: var(--c2u-space-5);
  border-radius: var(--c2u-radius-lg);
  object-fit: cover;
  /* Holds the frame while the image is still coming. The portraits are lazy
     and below the fold, so this is what is on screen for the first moment of
     the section rather than a hole in the grid. */
  background: var(--c2u-surface-mist);
}

.c2u-people__name { color: var(--c2u-navy); }

.c2u-people__role {
  margin-block-start: var(--c2u-space-1);
  color: var(--c2u-red);
  font-size: var(--c2u-fs-body-small);
  font-weight: 600;
  line-height: 1.4;
}

.c2u-people__bio {
  margin-block-start: var(--c2u-space-4);
  max-width: 42ch;
  color: var(--c2u-muted);
  font-size: var(--c2u-fs-body);
  line-height: var(--c2u-lh-body);
  text-wrap: pretty;
}

/* ── The lead row ────────────────────────────────────────────────────────
   A person alone on a line, turned sideways. parts/people.php has the reason
   in prose; this is the geometry.

   IT IS THE SPLIT'S PHOTOGRAPH, on this section's own square. Five of twelve
   columns is the width .c2u-split__media takes above, which is what makes the
   founder's portrait bigger than the four-column ones below it; the 4:5 frame
   that comes with it is not borrowed, because every other portrait in this
   section is square and the odd one out would be reading as a different kind
   of picture rather than as a larger one of the same kind. So: the split's
   width, the section's ratio.

   A NESTED GRID RATHER THAN SUBGRID, and the tracks still line up: the person
   spans all twelve columns of .c2u-people__grid, so a twelve-column grid at the
   same column gap resolves to tracks in the same places. `1 / span 5` inside
   means the same thing it means outside. Subgrid would say it more directly and
   nothing else in this file uses it yet; the arithmetic here is exact, so that
   is a swap to make on its own terms rather than as part of this.

   NO OPEN COLUMN BETWEEN THEM. The split leaves one standing empty between its
   picture and its text; here the copy starts in column 6, immediately after the
   photograph, so the two sit the single column-gap apart — the same 24px that
   separates any two portraits in the rows below. The section already spaces its
   people that way, and a wider trough would make the founder's photograph and
   his own bio look less related than he and Tim do.

   THE PHOTOGRAPH OVERSTEPS the portrait below it — five columns against four —
   so only its left edge lines up with the grid underneath, where before both
   did. That is the price of it being bigger, and the left edge is the one that
   carries it: every portrait in the section starts on the same line, and the
   founder's is the only one that runs past four columns.

   WHAT THE COPY GETS is one rung up the type scale for each of its three lines
   — heading-3 → heading-2, small → body, body → large. One rung each rather
   than one big jump on the name: the block has to read as the same three lines
   everyone else has, said a little louder, and moving them by different amounts
   would make it a different lockup instead.

   NOTHING TOUCHES THE ROW GAP. The grid's own row-gap is the space under this
   row as much as under any other, and it is left alone so all three rows sit
   the same distance apart. A negative bottom margin here does close the gap,
   but not by moving the row: a grid track is sized from the item's margin box,
   so the track ends up shorter than the photograph in it and the photograph
   hangs into the gap below. The measured space then reads smaller than the
   row-gap says it is, which is a confusing thing to leave behind for whoever
   next wonders why 56px looks like 32. If this gap ever does need to be
   different, it should come from the grid — a row-gap on the grid itself, or
   grid-template-rows — and not from the item hanging out of its own track. */
.c2u-people__person--lead {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  align-items: center;
  gap: var(--c2u-space-5);
}

.c2u-people__person--lead .c2u-people__photo {
  grid-column: 1 / span 5;
  /* Square, like every other portrait here — the base rule already says so,
     and this only has to undo the bottom margin that separates a photograph
     from the copy stacked under it. Nothing is stacked under this one. */
  margin-block-end: 0;
}

.c2u-people__person--lead .c2u-people__copy {
  grid-column: 6 / span 7;
  /* min-width:0 so the copy wraps inside its seven columns rather than pushing
     the track wider than the photograph's. */
  min-width: 0;
  align-self: center;
}

.c2u-people__person--lead .c2u-people__name { font-size: var(--c2u-fs-heading-2); }
.c2u-people__person--lead .c2u-people__role { font-size: var(--c2u-fs-body); }

.c2u-people__person--lead .c2u-people__bio {
  /* The column is the measure here — seven columns at 18px is a little past
     the 58ch this would otherwise cap at, so the cap is lifted and the grid
     decides. Same as .c2u-split__body, for the same reason. */
  max-width: none;
  font-size: var(--c2u-fs-body-large);
}

/* The split is dropped rather than narrowed: a row of four is already the
   tightest column a bio reads in at 1080px, and the split only exists to fit
   seven people onto two lines — it is not a ranking, so nothing is lost by
   letting the set wrap 3-up on its own and leaving the seventh on a line of
   its own. 1080px is the bento's breakpoint above.

   THERE IS NO 2-UP STEP, and that is the interesting part. Every column a
   layout gives up is width handed to the columns that remain, so the obvious
   3-2-1 ladder makes the portraits GROW as the screen shrinks — 2-up at 980px
   puts them at 446px, larger than the 426px they are at 1440px, and the
   section turns into a three-thousand-pixel scroll of faces at the exact width
   where there is least room for it. Going 3-up straight to one column skips
   that: the widest a portrait ever gets is its 1440px size, and the only step
   that could break the rule is the one below, which is why the photograph is
   capped there rather than left to fill.

   THE LEAD ROW IS EXEMPT, because none of that applies to it: its photograph
   is pinned to five of the twelve columns, so it tracks the container the same
   way every other portrait does and never grows as the screen shrinks. Folding
   it into the 3-up here would shrink it while everything else stayed put — and
   would throw the copy back underneath at the exact widths where there is
   still room for it to sit alongside.

   It is exempted by restating its span after the general one rather than by
   a :not() on the general one, and that is not a style preference. Both of
   these media queries are still live at 390px, so a :not() would make the
   3-up rule the more specific of the two and it would beat the one-column rule
   below at every phone width — seven portraits stuck three across a 390px
   screen. Equal specificity keeps the ladder working the way the rest of the
   file's breakpoints do: whichever block is written last wins. */
@media (max-width: 1080px) {
  .c2u-people__person { grid-column: span 4; }
  .c2u-people__person--lead { grid-column: span 12; }
}

/* One column, and the portrait fills it. The cap that used to sit here left
   the photograph short of the right gutter while the text below it ran the
   full width, which reads as a misalignment rather than as a smaller picture —
   the one edge a single column has to hold is its right one.

   THE LEAD ROW STOPS BEING ONE. Five columns of a phone is a thumbnail and the
   copy beside it would be a column of two-word lines, so the person goes back
   to the flex column everyone else is in — square portrait, full width, copy
   underneath — and the type goes back down the scale with it. That last part is
   the difference from the wider screens: one column is already the whole width
   the phone has, so the lead has no more room than anybody else to say
   something in, and type a rung larger than its neighbours' would just be a
   louder version of the same line. Above 767px the extra size is paid for by
   the layout; here there is nothing to pay with.

   Every one of these is a straight revert, which is why they read as a list of
   undos rather than as a design. */
@media (max-width: 767px) {
  .c2u-people__grid { gap: var(--c2u-space-7) 0; }
  .c2u-people__person { grid-column: span 12; }

  .c2u-people__person--lead {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 0;
  }
  .c2u-people__person--lead .c2u-people__photo {
    margin-block-end: var(--c2u-space-5);
  }
  .c2u-people__person--lead .c2u-people__copy { align-self: stretch; }

  .c2u-people__person--lead .c2u-people__name { font-size: var(--c2u-fs-heading-3); }
  .c2u-people__person--lead .c2u-people__role { font-size: var(--c2u-fs-body-small); }
  .c2u-people__person--lead .c2u-people__bio {
    max-width: 42ch;
    font-size: var(--c2u-fs-body);
  }
}


/* ── Benefits, wheel variant ─────────────────────────────────────────────
   See parts/benefits-wheel.php for what the effect is and why it departs from
   the component it is adapted from.

   Split in two:
     · the base rules render a plain card list — what ships to no-JS,
       prefers-reduced-motion, and viewports too short to turn a card through
       (c2u-page.js measures that one);
     · the `.is-live` rules, which JS opts into, pin the scene and hand the
       card positions over to the script.

   The arc itself cannot be expressed in CSS: every card's offset depends on
   its distance from a focus point that moves with the scroll. So the
   stylesheet owns the *shape* of the wheel — every constant below is read by
   c2u-page.js through getComputedStyle — and the script owns only the
   per-frame arithmetic. That keeps the whole effect tunable per breakpoint
   here, in the stylesheet.                                                 */

.c2u-cardwheel {
  /* Where the pinned scene sits. Clears the sticky site header, with the same
     breathing room the heading above it needs for the same reason. */
  --c2u-cardwheel-top: 104px;

  /* ── Wheel shape ──────────────────────────────────────────────────────
     Angle between two neighbouring cards, in degrees. This is the whole
     curl: the radius is derived from it (R = rowH / tilt in radians) so that
     the arc length between neighbours stays exactly one row, whatever the
     cards measure. Higher curls tighter.

     The original's default is 6°, tuned for single-line text labels a couple
     of rem tall. A card is an order of magnitude bigger, and at 6° the radius
     comes out so large that the arc is indistinguishable from a straight
     column — the curve only reads once the cards are a decent fraction of the
     radius. */
  --c2u-cardwheel-tilt: 15;
  /* Depth of the curve; 0 flattens the wheel into a straight column. */
  --c2u-cardwheel-curve: 1;
  /* Row height as a multiple of card height — the gap between cards on the
     arc, and with it how much of a neighbour shows.

     This is the number the whole thing reads on, because the neighbour's
     distance from the focus is essentially the row height: the radius is
     rowH / tilt, so R·sin(tilt) comes back to rowH for any tilt this small.
     Turning the curl up does not bring the neighbours closer — only this and
     the card's own height do. Just over 1, so neighbours clear each other
     while still sitting well inside the window. */
  --c2u-cardwheel-spacing: 1.06;
  /* How much of its arc angle a card actually turns through. The original
     turns items the full angle, which is right for a word and wrong for a
     paragraph: a card at a full 15° is legible but reads as fallen over. At
     0.6 the card clearly belongs to the curve without the copy fighting it. */
  --c2u-cardwheel-rot: .6;

  /* ── Falloff ──────────────────────────────────────────────────────────
     Deliberately mild, and with no blur at all — see the part's header. One
     step off the focus lands at 0.72, and the floor stops a four-card wheel
     ever dropping a card below legibility. */
  --c2u-cardwheel-fade: .28;
  --c2u-cardwheel-min-opacity: .55;
  /* Size lost per step away from the focus, and the floor on it. Depth the
     dim alone cannot carry now that the blur is gone. */
  --c2u-cardwheel-scale: .07;
  --c2u-cardwheel-min-scale: .82;

  /* ── Runway ───────────────────────────────────────────────────────────
     Scroll distance that turns the wheel by one card, and the share of the
     whole runway spent holding still at each end so the first and last cards
     are not already moving when the section arrives and leaves. */
  --c2u-cardwheel-run: 58vh;
  --c2u-cardwheel-lead: .1;
  --c2u-cardwheel-tail: .1;

  /* Card shape, width ÷ height — landscape, since a card on the wheel is
     read one at a time rather than as a pile. */
  --c2u-cardwheel-ar: 1.6;

  /* The container's own gutter, restated as a local token.

     The wheel's column runs off the right edge of the page, so the grid below
     cannot be a .c2u-container — a box centred by `margin-inline: auto` ends
     where the container ends, which is the hard edge the cards were being
     trimmed against. It becomes full width with the container's left padding
     applied by hand instead, and this is the half of .c2u-container that has
     to come with it. The breakpoints match c2u-base.css; they are the
     deployed header's, so they cannot drift on their own. */
  --c2u-cardwheel-pad: var(--c2u-gutter);

  /* Clip room to the left of the card, for its shadow.

     The window has to clip — a card leaving the arc runs off the page, and
     unclipped it would widen it. But the left side has nothing to clip: the
     cards only ever travel right. All that edge was cutting was the focus
     card's own shadow, at every size where the card fills its column and its
     left edge lands exactly on it.

     So the window is widened leftwards by this much and the card's width cap
     gives the same amount back, which leaves the card where it was and the
     clip further out. Zero unless the wheel is live, so the fallback's plain
     card list is not quietly narrowed by it. */
  --c2u-cardwheel-air: 0px;

  /* The size below which a card stops tracking the window.

     Without it the card is a straight share of the window height, so a short
     one shrinks the card until the copy no longer fits it — and because the
     fit test then hands that viewport the plain list, the wheel disappeared on
     exactly the sizes most people have: a 13" laptop and a phone in Safari
     were both a dozen px the wrong side of it.

     Below this the neighbours give up room instead of the copy. They have room
     to give — a card at the floor still leaves most of a window to its
     neighbours — and losing a little of the arc is a far better trade than
     losing the section. The fit test still catches windows too short to hold
     even this. */
  --c2u-cardwheel-floor: 430px;
  /* Card count, set by the part. */
  --c2u-cardwheel-n: 4;

  /* Height of the pinned scene, and the card size that fits inside it.

     The card is sized against --c2u-cardwheel-vh — the wheel's own window,
     which c2u-page.js measures and sets — rather than against the scene. The
     two are the same thing above the split, but below it the heading sits
     inside the scene and takes a share of it that only a measurement knows.
     The fallback keeps the sizing sane for the frame before the script runs.

     A card takes a little over half its window, so its neighbours still show
     above and below it at the focus point. */
  --c2u-cardwheel-scene: calc(100svh - var(--c2u-cardwheel-top));
  --c2u-cardwheel-size: min(
    calc(100% - var(--c2u-cardwheel-inset, 0px) - var(--c2u-cardwheel-air)),
    max(var(--c2u-cardwheel-floor), calc((var(--c2u-cardwheel-vh, var(--c2u-cardwheel-scene)) - 96px)
                                         * .62 * var(--c2u-cardwheel-ar)))
  );
}

@media (max-width: 980px) { .c2u-cardwheel { --c2u-cardwheel-pad: var(--c2u-gutter-tablet); } }
@media (max-width: 767px) { .c2u-cardwheel { --c2u-cardwheel-pad: var(--c2u-gutter-mobile); } }

.c2u-cardwheel__scene { position: relative; }

.c2u-cardwheel__list {
  display: grid;
  gap: var(--c2u-space-5);
  max-width: var(--c2u-cardwheel-size);
  margin-inline: auto;
  margin-block: 0;
  padding: 0;
  list-style: none;
}


/* Cards. The tone palette and the card interior, sized for a box that is read
   one at a time. */

.c2u-cardwheel__card {
  --c2u-cardwheel-bg: var(--c2u-paper);
  --c2u-cardwheel-fg: var(--c2u-navy);
  --c2u-cardwheel-dim: var(--c2u-muted);
  --c2u-cardwheel-edge: var(--c2u-line);
  --c2u-cardwheel-mark-bg: var(--c2u-red-soft);
  --c2u-cardwheel-mark-fg: var(--c2u-red-deep);

  /* Everything inside the card is sized against the card, not the viewport —
     the box swings a long way between a phone and a tall desktop, and type in
     vw would keep its own scale while the box moved under it. */
  container-type: inline-size;

  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: 4cqi;
  aspect-ratio: var(--c2u-cardwheel-ar);
  min-width: 0;
  min-height: 0;
  padding: clamp(20px, 4.6cqi, 38px);
  border: 1px solid var(--c2u-cardwheel-edge);
  border-radius: var(--c2u-radius-xl);
  background: var(--c2u-cardwheel-bg);
  color: var(--c2u-cardwheel-fg);
  box-shadow: var(--c2u-shadow-lg);
}

/* Tones cycle paper → sky → soft → ink. Each tinted tone takes its edge and
   its body colour from its own hue rather than the neutral line grey, which is
   what stops the tint reading as a wash laid over a grey card. */
.c2u-cardwheel__card--mist { --c2u-cardwheel-bg: var(--c2u-surface-mist); }

.c2u-cardwheel__card--sky {
  --c2u-cardwheel-bg: #eaf7ff;
  --c2u-cardwheel-edge: rgba(14, 165, 233, .22);
  --c2u-cardwheel-dim: #4a6b7e;
  --c2u-cardwheel-mark-bg: rgba(255, 255, 255, .8);
}

.c2u-cardwheel__card--soft {
  --c2u-cardwheel-bg: var(--c2u-surface-soft);
  --c2u-cardwheel-edge: rgba(217, 32, 80, .18);
  --c2u-cardwheel-dim: #8a5563;
  --c2u-cardwheel-mark-bg: rgba(255, 255, 255, .72);
}

.c2u-cardwheel__card--ink {
  --c2u-cardwheel-bg: var(--c2u-navy);
  --c2u-cardwheel-fg: var(--c2u-paper);
  --c2u-cardwheel-dim: rgba(255, 255, 255, .74);
  --c2u-cardwheel-edge: rgba(255, 255, 255, .14);
  --c2u-cardwheel-mark-bg: rgba(255, 255, 255, .14);
  --c2u-cardwheel-mark-fg: var(--c2u-paper);
}

.c2u-cardwheel__mark {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: none;
  align-self: start;
  width: 8cqi;
  height: 8cqi;
  border-radius: var(--c2u-radius-pill);
  background: var(--c2u-cardwheel-mark-bg);
  color: var(--c2u-cardwheel-mark-fg);
}
.c2u-cardwheel__mark svg { width: 3.6cqi; height: 3.6cqi; }

/* An illustration brings its own tinted disc, so the card's disc gets out of
   its way and the box becomes a plain frame for the artwork. Square, with the
   artwork letterboxed inside, so an icon drawn on a shorter canvas still lands
   its disc at the same size as the others. */
.c2u-cardwheel__mark--art {
  width: 12cqi;
  height: 12cqi;
  background: none;
}
.c2u-cardwheel__mark--art img {
  width: 100%;
  height: 100%;
  object-fit: contain;
}

.c2u-cardwheel__card-body {
  display: grid;
  gap: var(--c2u-space-3);
}

/* The heading colour has to come from the tone, not the base reset's navy, or
   the title disappears on the ink card. */
.c2u-page .c2u-cardwheel__title {
  color: var(--c2u-cardwheel-fg);
  font-size: clamp(20px, 4.4cqi, 34px);
  text-wrap: balance;
}

.c2u-cardwheel__text {
  max-width: 52ch;
  color: var(--c2u-cardwheel-dim);
  font-size: clamp(15px, 2.6cqi, 18px);
  line-height: var(--c2u-lh-body-large);
  text-wrap: pretty;
}

.c2u-cardwheel__card--untitled .c2u-cardwheel__text {
  max-width: 46ch;
  color: var(--c2u-cardwheel-fg);
  font-size: var(--c2u-fs-heading-3);
  line-height: 1.3;
}


/* ── Live: the same markup, on the wheel ──────────────────────────────────
   JS adds .is-live once it has checked viewport size and reduced-motion. */

/* The section is the runway: one `run` per card, plus the lead and tail holds,
   on top of the scene that pins inside it. Stated as a height rather than
   min-height so the runway is exactly what the geometry above asks for — the
   section's own padding is inside it, box-sizing being border-box globally. */
.c2u-cardwheel.is-live {
  /* Enough for the shadow (blur 44, spread -12, so ~10px of horizontal
     reach), never more than the page gutter — so the widened window cannot
     cross the left edge of the page — and always under the 32px column gap,
     so at the split it stops in the gutter rather than reaching across into
     the heading. */
  --c2u-cardwheel-air: min(24px, var(--c2u-cardwheel-pad));

  height: calc(
    var(--c2u-cardwheel-scene)
    + (var(--c2u-cardwheel-n) - 1) * var(--c2u-cardwheel-run)
      / (1 - var(--c2u-cardwheel-lead) - var(--c2u-cardwheel-tail))
  );
  padding-block: 0;
}

.c2u-cardwheel.is-live .c2u-cardwheel__scene {
  position: sticky;
  top: var(--c2u-cardwheel-top);
  height: var(--c2u-cardwheel-scene);
  display: flex;
  align-items: center;
}

/* Full-bleed to the right, container-aligned on the left.

   The grid drops .c2u-container's max-width and auto margins and pays the left
   padding itself, so its right edge is the page's rather than the container's —
   which is what lets a card on the far side of the arc run off the screen the
   way the logo wall's rows do, instead of being cut against an invisible box
   edge halfway across the page.

   The percentage is deliberate, and is not the same thing as 100vw: it
   resolves against the scene, a block box whose width already excludes a
   classic scrollbar. 100vw does not, and would push the wheel a scrollbar's
   width past the viewport and give the whole page a horizontal scroll. The
   max() is what holds the left edge on the container line once the page is
   wider than --c2u-container, and falls back to the plain gutter below it.

   Not applied to the fallback: a plain card list wants both gutters. */
.c2u-cardwheel.is-live .c2u-cardwheel__grid {
  width: 100%;
  max-width: none;
  margin-inline: 0;
  padding-left: max(
    var(--c2u-cardwheel-pad),
    calc((100% - var(--c2u-container)) / 2 + var(--c2u-cardwheel-pad))
  );
  padding-right: 0;
}

/* The wheel's window. Clipping is not cosmetic: a card at the far end of the
   arc has swung most of its width off the column, and unclipped it would widen
   the page. The mask feathers the top and bottom so cards arrive and leave
   rather than being cut off by a hard edge — the same read the original gets
   from its opacity falloff, which is turned right down here.

   Safe for the sticky scene above: the scene is this box's ancestor, not its
   descendant, so the clip cannot trap it. */
.c2u-cardwheel.is-live .c2u-cardwheel__viewport {
  position: relative;
  margin-left: calc(-1 * var(--c2u-cardwheel-air));
  overflow: hidden;
  -webkit-mask-image: linear-gradient(to bottom, transparent 0, #000 11%, #000 89%, transparent 100%);
          mask-image: linear-gradient(to bottom, transparent 0, #000 11%, #000 89%, transparent 100%);
}

.c2u-cardwheel.is-live .c2u-cardwheel__list {
  display: block;
  position: absolute;
  inset: 0;
  max-width: none;
}

/* Every card is stacked at the same anchor — the middle of the viewport's
   right edge — and the script moves it onto the arc from there. The right edge
   is the pivot, so a card turns and shrinks about the point it curls around
   rather than swinging its far corner across the column.

   All five values default to a no-op, so a script error leaves a neat stack of
   cards at the focus point rather than a broken scatter. */
.c2u-cardwheel.is-live .c2u-cardwheel__card {
  position: absolute;
  top: 50%;
  /* Set by c2u-page.js — the container line, so the card in focus ends where
     the rest of the page ends and only its neighbours run off the edge. */
  right: var(--c2u-cardwheel-inset, 0px);
  width: var(--c2u-cardwheel-size);
  transform:
    translate(var(--c2u-cardwheel-x, 0px), calc(var(--c2u-cardwheel-y, 0px) - 50%))
    rotate(var(--c2u-cardwheel-a, 0deg))
    scale(var(--c2u-cardwheel-s, 1));
  transform-origin: right center;
  opacity: var(--c2u-cardwheel-o, 1);
  will-change: transform, opacity;
}


/* ── Live, split across two columns (≥1024px) ─────────────────────────────
   Laptop and up the heading moves out of the wheel's way: it takes the left
   45% and the wheel turns in the right 55%. */

@media (min-width: 1024px) {
  .c2u-cardwheel {
    /* No flag for the layout switch: the script never branches on it. It
       measures the window the wheel actually
       got and sizes the cards from that, which comes out right whether the
       heading is beside the wheel or above it. */

    /* No column width restated here. The card is
       `width: var(--c2u-cardwheel-size)` inside the wheel's window, so the
       `min(100%, …)` in the base rule already caps it at the column it is in —
       there is nothing for a second, hand-computed copy of that width to do
       except disagree with the grid. */
  }

  /* The wheel takes the larger share, and the columns sit close together. Both
     are the same adjustment: the card is anchored to the
     right of its column, so every px the column has and the card does not
     opens up between the heading and the cards. */
  .c2u-cardwheel.is-live .c2u-cardwheel__grid {
    display: grid;
    grid-template-columns: 40fr 60fr;
    column-gap: var(--c2u-space-6);
    align-items: center;
  }

  /* Nothing above it in this layout, so the wheel's window is the whole
     scene. */
  .c2u-cardwheel.is-live .c2u-cardwheel__viewport { height: var(--c2u-cardwheel-scene); }

  /* Left-aligned and vertically centred against the wheel beside it. Centred
     type in a 40% column reads as a caption for the cards rather than the
     section's own heading.

     align-items is the one that actually matters and the one easy to miss.
     .c2u-section-head is a flex column, and its --center modifier centres the
     eyebrow and the heading two different ways: text-align for the lines
     inside each box, align-items for the boxes themselves. Undoing only
     text-align leaves the eyebrow — a short box in a wide column — still
     parked in the middle of it, sitting off the heading's left edge with
     nothing to explain why. */
  .c2u-cardwheel.is-live .c2u-section-head {
    align-items: start;
    margin-block: 0;
    margin-inline: 0;
    max-width: none;
    text-align: left;
  }
}

@media (max-width: 1023px) {
  /* Heading above the wheel, both inside the pinned scene — so the heading
     stays with the cards for the whole turn instead of scrolling off before
     the first one has arrived, without needing a sticky box of its own.

     The wheel then takes whatever height the heading leaves, which is what
     c2u-page.js measures back into --c2u-cardwheel-vh to size the cards. A
     column flex with min-height:0 is what lets it: the default min-height
     auto on a flex item would floor the wheel at its content height, and its
     content is absolutely positioned, so that floor is zero on some passes
     and the card height on others. */
  .c2u-cardwheel.is-live .c2u-cardwheel__grid {
    display: flex;
    flex-direction: column;
    height: 100%;
  }
  /* The grid pays no right padding now that the wheel runs off that edge, so
     the heading — the one thing in this layout that is not meant to bleed —
     puts its own back. */
  .c2u-cardwheel.is-live .c2u-section-head {
    flex: none;
    margin-block: 0 var(--c2u-space-6);
    padding-right: var(--c2u-cardwheel-pad);
  }
  .c2u-cardwheel.is-live .c2u-cardwheel__viewport {
    flex: 1;
    min-height: 0;
  }
}

@media (max-width: 767px) {
  /* Phone geometry. Same effect, retuned around a viewport a third of the
     height and a quarter of the width:

       · the scene pins higher, because the header is shorter here;
       · the curl is tighter and the cards nearly square — a 1.5 landscape card
         at phone width is too short to hold its copy;
       · the runway is shorter, so the section is a few flicks rather than a
         minute of thumb. */
  .c2u-cardwheel {
    --c2u-cardwheel-top: 84px;
    --c2u-cardwheel-tilt: 19;
    --c2u-cardwheel-rot: .5;
    --c2u-cardwheel-scale: .05;
    --c2u-cardwheel-run: 46vh;
    --c2u-cardwheel-ar: 1.05;

    /* The card takes the whole column here rather than the share the desktop
       rule works out. A card is anchored to the right edge of its window, so
       any width it gives up comes off one side only — which on a 350px column
       reads as the wheel having slipped sideways, not as margin. Filling the
       column also buys back the line length: at the desktop share the title
       was wrapping mid-phrase. */
    --c2u-cardwheel-size: calc(100% - var(--c2u-cardwheel-inset, 0px) - var(--c2u-cardwheel-air));
    /* Tighter than the desktop's, to win back the neighbour the taller card
       above would otherwise push out of the window. */
    --c2u-cardwheel-spacing: 1.04;
  }

  .c2u-cardwheel__card {
    gap: var(--c2u-space-4);
    padding: 24px 20px;
    border-radius: var(--c2u-radius-lg);
  }
  .c2u-cardwheel__mark { width: 42px; height: 42px; }
  .c2u-cardwheel__mark svg { width: 20px; height: 20px; }
  /* Fixed, and larger than the cqi rule would give here — that shrinks the
     drawing below the size it was drawn at and the finer line work stops
     reading. */
  .c2u-cardwheel__mark--art { width: 64px; height: 64px; }
  .c2u-cardwheel__text { font-size: var(--c2u-fs-body); }
  .c2u-cardwheel__card--untitled .c2u-cardwheel__text {
    font-size: var(--c2u-fs-body-large);
    line-height: var(--c2u-lh-body-large);
  }

  /* Air above the eyebrow, which on a phone is the first thing under the site
     header once the scene pins — the desktop layout gets its breathing room
     from centring the heading against the wheel, and there is nothing doing
     that job here.

     Padding on the heading rather than a larger --c2u-cardwheel-top: the pin
     offset moves the whole scene down and takes the same height off the wheel's
     window, so the cards would shrink to buy the gap. This takes it from the
     window alone, which c2u-page.js already measures — the cards resize to
     what is left and the fit test still has the last word.

     Only part of the gap, though. This padding travels with the scene, so
     whatever it buys on the way in is still there once the scene pins, holding
     the eyebrow that far below the header for the whole turn. The rest of the
     gap is paid by the section above instead — see the next rule — where it
     scrolls away like any other section break. */
  .c2u-cardwheel.is-live .c2u-section-head { padding-block-start: var(--c2u-space-6); }

  /* The other 40px, on the section that precedes a live wheel.

     It has to sit there rather than here: a live wheel sets `padding-block: 0`,
     since its own box is the runway, so the section break above it is whatever
     the previous section's bottom padding is and nothing else. Keyed off
     `.is-live` so the fallback — which keeps its section padding — is not given
     a second helping of it. */
  .c2u-section:has(+ .c2u-cardwheel.is-live) { padding-block-end: calc(var(--c2u-section-y) + var(--c2u-space-7)); }
}


/* ── Logo wall ───────────────────────────────────────────────────  */

/* Two columns, edge to edge: eyebrow and heading flush left over 6 of 12,
   subhead flush right over the last 5. The two blocks are set to the outer
   edges and read inward, so the gutter between them is the section's own
   whitespace and neither block needs a max-width. */
.c2u-logos__head {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  align-items: start;
  gap: var(--c2u-space-5);
  margin-block-end: var(--c2u-space-9);
}

.c2u-logos__eyebrow { grid-row: 1; grid-column: 1 / span 6; }
.c2u-logos__heading { grid-row: 1; grid-column: 1 / span 6; }

/* Bottom of the right column meets the bottom of the heading, so the two
   blocks sit on a shared line however many lines each one runs to. */
.c2u-logos__subhead {
  grid-row: 1;
  grid-column: 8 / span 5;
  align-self: end;
  justify-self: end;
  text-align: end;
}

/* The rows are numbered from whatever is actually there. Reserving row 1 for
   an eyebrow unconditionally would leave an empty row — zero-height, but the
   grid's own row-gap still sits either side of it, so a head without one would
   carry a stray gap above the heading. */
.c2u-logos__head:has(> .c2u-logos__eyebrow) .c2u-logos__heading { grid-row: 2; }
.c2u-logos__head:has(> .c2u-logos__eyebrow) .c2u-logos__subhead { grid-row: 1 / span 2; }

/* Even line lengths on both blocks. The subhead needs this explicitly:
   .c2u-lead sets text-wrap:pretty, which only tidies the last line. */
.c2u-logos__heading,
.c2u-logos__subhead { text-wrap: balance; }

/* Below the two-column split the subhead stacks under the heading and both
   read flush left — right-aligned type only holds up against a facing column. */
@media (max-width: 980px) {
  .c2u-logos__eyebrow,
  .c2u-logos__heading { grid-column: 1 / span 12; }
  .c2u-logos__subhead {
    grid-column: 1 / span 10;
    justify-self: start;
    text-align: start;
  }
  .c2u-logos__head:has(> .c2u-logos__eyebrow) .c2u-logos__subhead { grid-row: 3; }
  .c2u-logos__head:not(:has(> .c2u-logos__eyebrow)) .c2u-logos__subhead { grid-row: 2; }
}

@media (max-width: 767px) {
  .c2u-logos__subhead { grid-column: 1 / span 12; }
}


/* ── Marquee ─────────────────────────────────────────────────────────────
   Each track holds N identical sets side by side and slides by exactly one
   set's width — 100%/N — so the frame at the end of the animation is pixel-
   identical to the frame at the start and the loop is invisible. Change the
   copy count in parts/logo-wall.php and --c2u-marquee-shift must change with
   it (4 copies -> 25%).

   Repeating the set rather than duplicating it once also guarantees the track
   is wider than any viewport; a single duplicated set of five logos is only
   ~1100px and would show a gap on a wide screen.                          */

.c2u-logos__rows {
  display: flex;
  flex-direction: column;
  gap: var(--c2u-space-7);
}

.c2u-marquee {
  --c2u-marquee-shift: 25%;
  --c2u-marquee-duration: 60s;
  overflow: hidden;
}

.c2u-marquee__track {
  display: flex;
  width: max-content;
  animation: c2u-marquee-rtl var(--c2u-marquee-duration) linear infinite;
  will-change: transform;
}

.c2u-marquee--ltr .c2u-marquee__track { animation-name: c2u-marquee-ltr; }

.c2u-marquee__set {
  display: flex;
  flex-shrink: 0;
  align-items: center;
}

.c2u-marquee__item {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  padding-inline: clamp(28px, 3vw, 64px);
  min-height: 72px;
}

@keyframes c2u-marquee-rtl {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(calc(-1 * var(--c2u-marquee-shift)), 0, 0); }
}
@keyframes c2u-marquee-ltr {
  from { transform: translate3d(calc(-1 * var(--c2u-marquee-shift)), 0, 0); }
  to   { transform: translate3d(0, 0, 0); }
}

/* An endlessly moving band is exactly what this preference is for. Overrides
   the global reduced-motion rule, which only shortens the duration — that
   would freeze the track mid-loop instead of stopping it cleanly. */
@media (prefers-reduced-motion: reduce) {
  .c2u-page .c2u-marquee__track { animation: none !important; }
}

/* Logos themselves — knocked well back so the rows read as one texture, and
   brought up under the cursor so a single brand can be picked out of it.
   The target is the image rather than its slot: the slots carry up to 64px of
   padding each side, so hovering one would light a logo up while the cursor
   was still nowhere near it. */
/* THE KNOCK-BACK RIDES IN THE FILTER CHAIN, NOT ON `opacity`, and that is not a
   style choice. The live site runs WP Smush's lazy loader, which rewrites every
   one of these images — real URL moved to data-src, a 1x1 base64 placeholder in
   its place, class `lazyload` until it arrives and `lazyloaded` after — and
   prints this from an inline <style> in the head:

       .lazyloaded { opacity: 1; transition: opacity 400ms; }

   That is (0,1,0), exactly what `.c2u-logos__img` scores, and it lands AFTER our
   stylesheets in the document. A specificity tie is decided by source order, so
   it won and every logo rendered at full strength.

   `filter: opacity()` is not a property it touches, and for a flat SVG it
   composites identically. No !important, no specificity escalation, and it
   behaves the same locally where no plugin is involved.

   Before moving this back to `opacity`, check that rule is actually gone — it is
   the plugin's, not Divi's, so the scoping patch has no bearing on it. */
.c2u-logos__img {
  max-height: 38px;
  width: auto;
  filter: grayscale(1) opacity(.4);
  transition: filter var(--c2u-fast) var(--c2u-ease);
}

.c2u-logos__img:hover { filter: grayscale(1) opacity(.6); }

/* Placeholder wordmark, used until the real asset is dropped in. */
.c2u-logos__placeholder {
  font-size: clamp(18px, 1.4vw, 24px);
  font-weight: 600;
  letter-spacing: -0.02em;
  white-space: nowrap;
  color: #aba6a3;
  opacity: 1;
}

@media (max-width: 767px) {
  .c2u-logos__rows { gap: var(--c2u-space-5); }
  .c2u-marquee__item { min-height: 56px; }
}


/* ── Trust statement ─────────────────────────────────────────────
   See the layout diagram in parts/trust.php.                       */

/* The same edge-to-edge two-column split as the logo wall's head: the section
   name flush left over 6 of 12, the claim and its endorsement strip in the
   facing column over the last 5. Both are text, so the tops align — unlike the
   picture split, which centres against a tall photograph. */
.c2u-trust__grid {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  align-items: start;
  gap: var(--c2u-space-8) var(--c2u-space-5);
}

.c2u-trust__intro {
  grid-column: 1 / span 6;
  display: flex;
  flex-direction: column;
  gap: var(--c2u-space-4);
}

.c2u-trust__aside {
  grid-column: 8 / span 5;
  display: flex;
  flex-direction: column;
  gap: var(--c2u-space-4);
}

/* The column sets the measure, so drop .c2u-lead's own 68ch cap — same reason
   as .c2u-split__body. */
.c2u-trust__body { max-width: none; }

/* Static by design: only three logos, so a marquee would read as a loop of the
   same handful rather than a settled list. They hold a single row (see the slot
   note below) and sit well clear of the paragraph — the endorsement reads as
   its own beat under the claim rather than as a run-on of it. */
.c2u-trust__logos {
  display: flex;
  flex-wrap: nowrap;
  align-items: center;
  gap: clamp(16px, 2.5vw, 40px);
  margin: 0;
  margin-block-start: var(--c2u-space-8);
  padding: 0;
  list-style: none;
}

/* Each slot's width is proportional to its logo's aspect ratio (--c2u-logo-ar,
   set inline from the file's w/h). The three share a native height, so slots in
   proportion to width make every logo fill to the same height — a plain equal
   third would leave the wider marks shorter. The whole strip then scales as one
   to hold a single line at every width, down to the narrow right column on
   desktop and the full width on a phone. min-width:0 lets a slot shrink below
   the image's own intrinsic width, which is what would otherwise force a wrap. */
.c2u-trust__logo {
  flex: var(--c2u-logo-ar, 1) 1 0;
  min-width: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* Standing alone they are set larger than the wall's knocked-back 38px — but
   they keep that tone: .c2u-logos__img still supplies the grayscale and the .4
   knock-back, and only the size is lifted here. The 52px is a ceiling; in a narrow
   column the third-of-a-row width brings them under it. */
.c2u-trust__logos .c2u-trust__img {
  max-height: 52px;
  max-width: 100%;
  width: auto;
  height: auto;
}

/* Below the split the two columns stack and both read flush left. */
@media (max-width: 980px) {
  .c2u-trust__intro,
  .c2u-trust__aside { grid-column: 1 / span 12; }
}


/* ── Expression of interest ──────────────────────────────────────  */

/* One centred column straight on the page background — no card. The section is
   the end of the page's argument rather than a boxed-off form, so the only
   thing separating it from the sections above is the heading and the white of
   the inputs themselves.

   Heading above, form under it, both on the page's centre line: a single axis
   at every width, so nothing about the composition changes on a phone. */
.c2u-eoi__panel {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(32px, 3.5vw, 56px);
  text-align: center;
}

.c2u-eoi__intro { max-width: 760px; }
.c2u-eoi__intro .c2u-eyebrow { margin-block-end: var(--c2u-space-4); }
.c2u-eoi__intro .c2u-lead {
  margin-block-start: var(--c2u-space-5);
  margin-inline: auto;   /* .c2u-lead caps its own measure; centre what's left */
}

/* On the navy field. The page background crossfades from pink to navy as this
   section arrives (the shift* parameters at the pharmacy-partners call site),
   so everything written in navy ink sinks into the background it is sitting
   on and has to come back the other way.

   Three things so far: the heading, the subhead under it and the labels over
   the form's fields. The eyebrow, the help text and the legal blocks are
   still on their light-background colours and are next to be judged.

   `is-bg-shifted` is set by the shader path in c2u-grainient.js and only by
   it, so a browser that never painted the navy never gets white text either.
   800ms is that file's SHIFT_MS: the text and the background behind it are
   one movement and have to last the same length of time. The transitions are
   set on the elements unconditionally, not inside the shifted state, or the
   colours would ease onto the navy and snap back off it.

   The accent line inside the heading sets its own colour and stays red, as
   does the asterisk on a required field. */
.c2u-eoi__heading,
.c2u-eoi__intro .c2u-lead,
.c2u-eoi .c2u-hs .hs-form-field > label {
  transition: color 800ms var(--c2u-ease);
}

.c2u-eoi.is-bg-shifted .c2u-eoi__heading { color: var(--c2u-paper); }

/* The subhead keeps its step back from the heading rather than going white
   with it — the hierarchy between the two is the same one --c2u-muted draws
   on the light background, and white on navy for both would flatten it. Held
   off the field rather than mixed against it so the one value covers the pink
   it crosses on the way as well. */
.c2u-eoi.is-bg-shifted .c2u-eoi__intro .c2u-lead { color: rgba(255, 255, 255, .78); }

/* Labels go the whole way to white. They sit directly above the field they
   name, against the white of the input itself, and anything softer next to
   that much white reads as a disabled field rather than a quieter one.

   Higher specificity than the label rule further down this file, so the two
   are not order-dependent — HubSpot's own injected styles sit between them. */
.c2u-eoi.is-bg-shifted .c2u-hs .hs-form-field > label { color: var(--c2u-paper); }

/* The shader snaps between palettes under this preference rather than
   crossfading, and text still easing its way to white against a background
   that arrived instantly is the two halves coming apart. */
@media (prefers-reduced-motion: reduce) {
  .c2u-page .c2u-eoi__heading,
  .c2u-page .c2u-eoi__intro .c2u-lead,
  .c2u-page .c2u-eoi .c2u-hs .hs-form-field > label { transition: none; }
}

/* Narrower than the intro above it. A form centred at the intro's width would
   set fields far wider than the text they're under, and a long input is harder
   to scan than a long line of prose, not easier.

   The box is centred; its contents are not. Centring is the section's, set on
   the panel and inherited — but a label centred over its own field detaches
   from the field it names and leaves the column with no edge to read down. So
   the form takes the alignment back here, once, rather than each control
   fighting the inheritance separately. The submit button is the exception and
   re-centres itself, down in the HubSpot rules. */
.c2u-eoi__form {
  width: 100%;
  max-width: 520px;
  text-align: start;
}


/* ── HubSpot embed overrides ─────────────────────────────────────
   HubSpot injects its own markup and its own CSS. c2u-page.js passes
   `css: ''` to the embed, which suppresses the theme stylesheet — the
   one that would fight every rule below over borders, type and
   colour. So these rules mostly dress markup that arrives unstyled,
   and the resets below cover what that stylesheet used to supply.

   What `css: ''` does NOT suppress is a small per-instance <style>
   block, injected at runtime, that carries HubSpot's column layout.
   It is scoped to a .hs-form-<form guid>_<instance guid> class on the
   <form>, which makes its selectors (0,3,1) — enough to beat a
   three-class rule of ours — and the instance guid is regenerated per
   page load, so it cannot be named here. Anything that block sets is
   overridden by out-specifying it generically instead; see the
   `form fieldset` selectors below, which exist for that reason alone.

   Rules also have to out-specify Divi's global form styling, hence
   the .c2u-page prefix on anything Divi also targets.                */

.c2u-hs { min-height: 320px; }

/* HubSpot groups fields in <fieldset>. With its stylesheet gone these would
   otherwise render with the browser's default border and inset padding. */
.c2u-hs fieldset {
  max-width: none;
  margin: 0;
  padding: 0;
  border: 0;
}

.c2u-hs.is-loading::before {
  content: 'Loading form…';
  display: block;
  padding: var(--c2u-space-6) 0;
  color: var(--c2u-muted);
  font-size: var(--c2u-fs-body-small);
}
.c2u-hs.is-ready { min-height: 0; }

.c2u-hs .hs-form-field { margin-block-end: var(--c2u-space-5); }

/* Layout — one field per row at every width. HubSpot decides its own column
   split in the form editor and ships it as `width: 50%; float: left` from the
   per-instance block described above; forcing the stack here means the
   section's single centred axis holds however the form is later edited, rather
   than depending on a HubSpot setting nobody on this side can see.

   The redundant-looking `form fieldset` is doing real work: it is what carries
   these to (0,3,2), over the (0,3,1) of the rules they replace. Dropping either
   element from the selector puts the columns back. */
.c2u-page .c2u-hs form fieldset .hs-form-field {
  width: 100%;
  float: none;
}

/* The gutter between side-by-side fields, meaningless once they stack and
   visible as a ragged right edge if left in place. */
.c2u-page .c2u-hs form fieldset .hs-form-field > .input { margin: 0; }

/* …except the first row, which pairs up again.

   Grid on the fieldset rather than giving the fields back their 50% float: the
   rule above still applies to them, so they stay `width: 100%` and simply fill
   a half-width track. That means the pairing is stated in one place — this
   fieldset is two columns — instead of depending on HubSpot's own float
   widths, which come from a form-editor setting nobody on this side can see
   and which is what the stacking rule above exists to be independent of.

   Scoped with .form-columns-2:first-of-type so it can only ever affect a row
   HubSpot itself built as a pair. If the form is later edited so the first row
   is a single field, the selector stops matching and the field stays full
   width — a no-op rather than a half-width box with a gap beside it.

   The gap the rule above strips is put back as a column-gap, which unlike a
   margin on .input does not survive into the rows that stack. */
.c2u-page .c2u-hs form fieldset.form-columns-2:first-of-type {
  display: grid;
  grid-template-columns: 1fr 1fr;
  column-gap: var(--c2u-space-5);
}

/* Fields run the full column. HubSpot sets 95% on a single-column row, which
   leaves every input short of the edge its label and the button both sit on. */
.c2u-page .c2u-hs form fieldset .hs-input:not([type="checkbox"]):not([type="radio"]) {
  width: 100%;
  max-width: 100%;
}

.c2u-hs .hs-form-field > label {
  display: block;
  margin-block-end: var(--c2u-space-2);
  font-size: var(--c2u-fs-body-small);
  font-weight: 600;
  color: var(--c2u-navy);
}
.c2u-hs .hs-form-required { color: var(--c2u-red); margin-inline-start: 2px; }

/* Help text under a label */
.c2u-hs .hs-field-desc {
  margin-block-end: var(--c2u-space-2);
  font-size: var(--c2u-fs-body-small);
  color: var(--c2u-muted);
}

/* Inputs — .c2u-page prefix so these beat Divi's global input rules.

   The two !important flags are aimed at one rule in the per-instance block,
   which sizes every text field itself:

     .hs-custom-style > div input:not([type="image"]):not([type="submit"])
       :not([type="button"]):not([type="radio"]):not([type="checkbox"])
       :not([type="file"]) { padding: 0 15px; min-height: 27px }

   Six chained :not([type]) put that at (0,7,2), and it is injected after this
   stylesheet, so a tie on specificity still loses. Out-specifying it would take
   a selector longer than the rule it beats and one HubSpot release away from
   breaking; !important on the two properties it claims is both shorter and
   steadier. Nothing else here needs it — the rest of the field's look comes
   through untouched. */
.c2u-page .c2u-hs input[type="text"],
.c2u-page .c2u-hs input[type="email"],
.c2u-page .c2u-hs input[type="tel"],
.c2u-page .c2u-hs input[type="number"],
.c2u-page .c2u-hs input[type="url"],
.c2u-page .c2u-hs textarea,
.c2u-page .c2u-hs select {
  width: 100%;
  max-width: 100%;
  /* Floor rather than a fixed height: a select renders a couple of pixels
     shorter than a text input at the same padding, and a field that grows —
     a multi-line error, a larger text size — still grows from here. */
  min-height: 48px !important;
  padding: 13px 16px !important;
  background: var(--c2u-paper);
  border: 1px solid var(--c2u-input-border);
  border-radius: var(--c2u-radius-sm);
  font: 400 16px/1.4 var(--c2u-font-body); /* 16px avoids iOS zoom-on-focus */
  color: var(--c2u-ink);
  transition: border-color var(--c2u-fast) var(--c2u-ease),
              box-shadow   var(--c2u-fast) var(--c2u-ease);
  -webkit-appearance: none;
  appearance: none;
}

/* !important only to restate the floor above, which carries the flag. */
.c2u-page .c2u-hs textarea { min-height: 128px !important; resize: vertical; }

.c2u-page .c2u-hs select {
  /* re-add a chevron, since appearance:none removed the native one */
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%235a6b78' stroke-width='2' stroke-linecap='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 14px center;
  background-size: 18px;
  padding-inline-end: 42px;
}

.c2u-page .c2u-hs input:focus,
.c2u-page .c2u-hs textarea:focus,
.c2u-page .c2u-hs select:focus {
  outline: none;
  border-color: var(--c2u-navy);
  box-shadow: 0 0 0 3px rgba(12, 52, 74, .12);
}

.c2u-hs input::placeholder,
.c2u-hs textarea::placeholder { color: var(--c2u-muted); }

/* Checkboxes / radios */
.c2u-hs .inputs-list { list-style: none; margin: 0; padding: 0; }
.c2u-hs .inputs-list li { margin-block-end: var(--c2u-space-2); }
.c2u-hs .inputs-list label {
  display: flex;
  align-items: flex-start;
  gap: var(--c2u-space-3);
  font-size: var(--c2u-fs-body-small);
  color: var(--c2u-ink);
  cursor: pointer;
}
.c2u-page .c2u-hs .inputs-list input[type="checkbox"],
.c2u-page .c2u-hs .inputs-list input[type="radio"] {
  width: 18px;
  height: 18px;
  margin: 2px 0 0;
  flex-shrink: 0;
  accent-color: var(--c2u-red);
}

/* Legal / rich text blocks */
.c2u-hs .hs-richtext,
.c2u-hs .legal-consent-container {
  font-size: var(--c2u-fs-body-small);
  line-height: 1.55;
  color: var(--c2u-muted);
}
.c2u-hs .hs-richtext p { margin-block-end: var(--c2u-space-3); }
.c2u-page .c2u-hs .hs-richtext a { color: var(--c2u-red); text-decoration: underline; }

/* Submit — the same pill as .c2u-btn + .c2u-btn--primary, restated rather than
   shared because HubSpot renders an <input type=submit> we can't put our class
   on. Every value below is the button's, read from the same tokens, so the two
   move together when the tokens do; the one thing an input can't copy is the
   flex centring, and with no icon to place, padding gives the same result.

   Full width, unlike the page's other CTAs: it is the end of a 520px column of
   fields, and a pill sized to its own label would be the one element in that
   column not meeting both edges. */
.c2u-page .c2u-hs .hs-button,
.c2u-page .c2u-hs input[type="submit"] {
  display: block;
  width: 100%;
  padding: 16px 28px;
  background: var(--c2u-red);
  border: 1px solid transparent;
  border-radius: var(--c2u-radius-pill);
  font-family: var(--c2u-font-body);
  font-size: var(--c2u-fs-label);
  font-weight: var(--c2u-fw-label);
  line-height: var(--c2u-lh-label);
  color: #fff;
  text-align: center;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  box-shadow: var(--c2u-shadow-sm);
  transition:
    background-color var(--c2u-base) var(--c2u-ease),
    border-color     var(--c2u-base) var(--c2u-ease),
    color            var(--c2u-base) var(--c2u-ease),
    transform        var(--c2u-fast) var(--c2u-ease),
    box-shadow       var(--c2u-base) var(--c2u-ease);
  -webkit-appearance: none;
  appearance: none;
}
.c2u-page .c2u-hs .hs-button:hover,
.c2u-page .c2u-hs input[type="submit"]:hover {
  background: var(--c2u-red-deep);
  color: #fff;
  box-shadow: var(--c2u-shadow-lg);
}
.c2u-page .c2u-hs .hs-button:active,
.c2u-page .c2u-hs input[type="submit"]:active { transform: translateY(1px); }

/* The button sits in .hs_submit > .actions; the gap above it belongs there so
   it survives the button being swapped for HubSpot's submitting state. */
.c2u-hs .hs_submit .actions { margin-block-start: var(--c2u-space-6); }

/* Validation */
.c2u-hs .hs-error-msgs,
.c2u-hs ul.hs-error-msgs {
  list-style: none;
  margin: var(--c2u-space-2) 0 0;
  padding: 0;
}
.c2u-page .c2u-hs .hs-error-msgs label,
.c2u-page .c2u-hs .hs-error-msg {
  display: block;
  font-size: var(--c2u-fs-body-small);
  font-weight: 400;
  color: var(--c2u-red-deep);
}
.c2u-page .c2u-hs .hs-input.invalid,
.c2u-page .c2u-hs .hs-input.error { border-color: var(--c2u-red); }

/* Thank-you state — HubSpot swaps the whole form for this, so it is what the
   section is once it has been used.

   No panel of its own: it sits on the page background like everything else in
   the section, and centres to pick the axis back up from the heading above it,
   which is now the only other thing left in view. The left edge it would
   otherwise inherit from .c2u-eoi__form belonged to a column of fields that no
   longer exists. */
.c2u-hs .submitted-message {
  padding-block: var(--c2u-space-4);
  font-size: var(--c2u-fs-body-large);
  line-height: 1.6;
  text-align: center;
  color: var(--c2u-paper);
}
.c2u-hs .submitted-message p:last-child { margin-block-end: 0; }

/* Fallback shown when the embed script never loads */
.c2u-hs-fallback {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--c2u-space-4);
  padding: var(--c2u-space-6);
  background: var(--c2u-surface-mist);
  border: 1px dashed var(--c2u-input-border);
  border-radius: var(--c2u-radius-lg);
}
.c2u-hs-fallback[hidden] { display: none; }
.c2u-hs-fallback__msg {
  font-size: var(--c2u-fs-body-small);
  color: var(--c2u-muted);
}


/* ── Promise ─────────────────────────────────────────────────────────────

   parts/promise.php — an eyebrow, one sentence at heading size, and a line
   under it. Centred, and held to a measure well inside the container: the
   claim is the whole section, and a claim that runs the full width of a wide
   screen is read as a paragraph.                                             */

/* The box the claim's size is measured against, and it has to be this one
   rather than the claim itself: the claim caps its own width below, and a
   capped element measuring itself would feed its own size back in. This one
   fills the page container, which is the width the hero's headline is measured
   against too, so the two sizes are read off the same number. Exactly the
   arrangement .c2u-statement__inner makes, for exactly the same reason. */
.c2u-promise__inner {
  container-type: inline-size;

  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
}

.c2u-promise__eyebrow { margin-block-end: var(--c2u-space-5); }

.c2u-promise__claim {
  /* THE HERO'S SIZE, not the heading scale's. This is the page's second big
     statement and it should land at the size the first one did — 54px against
     the hero's 63px at the top of the range read as a smaller claim, which is
     the opposite of what this section is for.

     Taken as the expression rather than as a number: --c2u-brand-size is the
     hero's own fit, published on .c2u-page for this (the statement section
     under the hero already runs at 65% of it), and it resolves against the
     container above. So the two move together at every width and through the
     phone override, and nothing here restates a size measured for a different
     sentence. The note above --c2u-brand-size has the one way they can drift.

     The class is .c2u-display rather than .c2u-h1 for the same reason: at this
     size the display tracking is the right one, and the size is the only thing
     the token gives that has to be overridden.

     AND NEVER UNDER A SECTION HEADING. The hero's fit is a long sentence
     pulled into a narrow column, so between about 767px and 1100px it drops to
     the heading scale and just below it — 36px at the phone breakpoint against
     the bento's 40px. That is right for the hero, which is buying one sentence
     per line with it, and wrong here, where the claim wraps freely and has no
     such guarantee to pay for. Tracking the hero down would leave the page's
     second-loudest statement quieter than the headings either side of it. The
     max() is the floor, and above about 1100px the fit is the larger of the
     two and this does nothing. */
  font-size: max(var(--c2u-brand-size), var(--c2u-fs-heading-1));

  /* Between the display scale's 1.04, set for short stacked lines, and the
     hero's 1.2, set for full sentences running the whole column. This is a
     full sentence over two lines at two thirds of the column — close enough to
     the hero to need more air than 1.04, short enough not to need all of it. */
  line-height: 1.12;

  /* Two lines at the top of the range, and the number is the size's: it was
     800px while the claim was 54px, and it moves with the type or the sentence
     that used to break in the middle starts landing on three lines. Not shared
     with .c2u-closing__heading any more — that one is still at the heading
     scale, and a shared measure across two different sizes is a coincidence
     rather than a rule. */
  max-width: 940px;
}

.c2u-promise__subtext {
  margin-block-start: var(--c2u-space-6);
  margin-inline: auto;   /* .c2u-lead caps its own measure; centre what's left */
}
.c2u-promise__subtext + .c2u-promise__subtext { margin-block-start: var(--c2u-space-4); }


/* ── Trust band ──────────────────────────────────────────────────────────

   parts/trust-band.php — four figures in a row, each over the line that says
   what it counts. Ported from the live homepage's .c2u-trustband; the part's
   header says what changed and what did not. Here it sits under the promise,
   as the evidence for it.                                                      */

/* Follows the promise directly, and the two are one statement: the claim, then
   the numbers behind it. The promise section already closes with a full
   section's padding, so the band takes only the bottom half of its own and
   lets the promise pay for the top — the gap between them is then smaller than
   the gap to whatever comes next, which is what makes them read as a pair.
   Same idiom as `.c2u-section + .c2u-section--paper` in c2u-base.css, scoped
   to the pairing it is written for. */
.c2u-promise + .c2u-trustband { padding-block-start: 0; }

.c2u-trustband__list {
  list-style: none;
  margin: 0;
  padding: 0;

  /* A grid rather than a wrapping flex row, because the hairlines are borders
     on the items: with four fixed columns, "which items start a row" is known,
     so the rule can go on the ones that do not. A wrapped flex row would put
     one at the start of the second line. */
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--c2u-space-6);
}

.c2u-trustband__item {
  display: flex;
  flex-direction: column;
  gap: var(--c2u-space-2);
  padding-inline: var(--c2u-space-5);
  text-align: center;
}

/* The hairline between each pair. On the item's leading edge rather than as
   elements of its own, the way the homepage draws them — one rule per column
   that starts inside a row, and nothing to hide when the grid changes shape. */
.c2u-trustband__item + .c2u-trustband__item {
  border-inline-start: 1px solid #f7cdcd;
}

/* The figure and the stars sit on one line and centre against each other. */
.c2u-trustband__figure {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: var(--c2u-space-2);

  font-size: var(--c2u-fs-heading-3);
  font-weight: var(--c2u-fw-heading-3);
  line-height: var(--c2u-lh-heading-3);
  letter-spacing: var(--c2u-ls-heading-3);
  color: var(--c2u-navy);
  text-wrap: balance;
}

.c2u-trustband__label {
  font-size: var(--c2u-fs-body-small);
  line-height: var(--c2u-lh-body-small);
  color: var(--c2u-muted);
  text-wrap: pretty;
}

/* Sized against the figure beside it rather than in px, so the row of stars
   keeps its proportion to the number at every step of that clamp. */
.c2u-trustband__stars {
  display: inline-flex;
  gap: 1px;
  color: #f5a623;              /* the homepage's own gold, transcribed */
}

.c2u-trustband__star {
  width: 0.75em;
  height: 0.75em;
  flex: none;
}

/* Filled to floor(rating) in the part, so the row never claims more than the
   number beside it. The rest are the same glyph in the page's hairline grey —
   drawn rather than dropped, because five positions is what makes four read as
   four out of five. */
.c2u-trustband__star--off { color: #f7cdcd; }

/* Tablet. Two across, which puts the rule between the pairs in each row and
   nowhere else — the third item starts the second row and gives its up. */
@media (max-width: 980px) {
  .c2u-trustband__list { grid-template-columns: repeat(2, minmax(0, 1fr)); }

  .c2u-trustband__item + .c2u-trustband__item { border-inline-start: none; }
  .c2u-trustband__item:nth-child(even) {
    border-inline-start: 1px solid #f7cdcd;
  }
}

/* Phone. One column and no rules at all — a vertical hairline needs something
   beside it, and stacked items are separated by the gap instead. The gap grows
   to do that job, and each item keeps its own two lines centred. */
@media (max-width: 767px) {
  .c2u-trustband__list {
    grid-template-columns: minmax(0, 1fr);
    gap: var(--c2u-space-7);
  }

  .c2u-trustband__item:nth-child(even) { border-inline-start: none; }
  .c2u-trustband__item { padding-inline: 0; }
}


/* ── Closing ─────────────────────────────────────────────────────────────

   parts/closing.php — the heading and the two links a page ends on. Centred,
   and mostly air: see the part's header for why there is nothing else in it.  */

.c2u-closing {
  /* Generous, and derived rather than typed: 1.75 of the page's own section
     rhythm, so this section reads as the end of the page at every width the
     clamp covers and does not have to be retuned when that clamp is. Roughly
     126px on a phone and 224px on a wide screen. */
  padding-block: calc(var(--c2u-section-y) * 1.75);
}

.c2u-closing__inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(32px, 3.5vw, 56px);
  text-align: center;
}

/* Held well inside the container. The heading is balanced by the base
   stylesheet, so this is not choosing where the line breaks — it is choosing
   how many there are, and 800px puts this page's closing line on two at the
   top of the clamp rather than one very long one. */
.c2u-closing__heading { max-width: 800px; }

.c2u-closing__subhead {
  margin-inline: auto;   /* .c2u-lead caps its own measure; centre what's left */
}

.c2u-closing__actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--c2u-space-4);
}

/* On the navy field. The page background crossfades to navy as this section
   arrives (the shift* parameters at the page's grainient call), so the heading,
   which is navy ink, sinks into the background it is sitting on and has to come
   back the other way — the third place this file makes that arrangement, after
   the tagline band and the EOI section, and for the same reasons.

   `is-bg-shifted` is set by the shader path in c2u-grainient.js and only by it,
   so a browser that never painted the navy never gets white text either. 800ms
   is that file's SHIFT_MS: the type and the field behind it are one movement
   and have to take the same time. The transitions are set unconditionally
   rather than inside the shifted state, or the colours would ease onto the navy
   and snap back off it.

   The primary button is red on both fields and is left alone. The secondary is
   the one thing here that has a hover as well as a shift, and the two want
   different speeds out of the same three properties. Hover wins on the way in —
   the :hover rule below restores the button's own timing, so pointing at it
   still answers immediately — and the 800ms applies on the way out. A slow
   release is a fair price for the button never being white on pink. */
.c2u-closing__heading,
.c2u-closing .c2u-btn--secondary {
  transition:
    background-color 800ms var(--c2u-ease),
    border-color     800ms var(--c2u-ease),
    color            800ms var(--c2u-ease);
}
.c2u-closing .c2u-btn--secondary:hover,
.c2u-closing .c2u-btn--secondary:focus-visible {
  transition:
    background-color var(--c2u-base) var(--c2u-ease),
    border-color     var(--c2u-base) var(--c2u-ease),
    color            var(--c2u-base) var(--c2u-ease);
}

.c2u-closing.is-bg-shifted .c2u-closing__heading { color: var(--c2u-paper); }

/* The subhead keeps its step back from the heading rather than going white
   with it, as the EOI's does — held off the field rather than mixed against
   it, so the one value covers the pink it crosses on the way as well. */
.c2u-closing.is-bg-shifted .c2u-closing__subhead { color: rgba(255, 255, 255, .78); }

/* Outlined rather than filled. A solid white pill beside the red one would
   read as the louder of the two and invert the emphasis the order sets.
   Two classes deep so it out-specifies `.c2u-page .c2u-btn--secondary` in
   c2u-base.css, and the hover a level deeper again for the same reason. */
.c2u-closing.is-bg-shifted .c2u-btn--secondary {
  border-color: rgba(255, 255, 255, .55);
  color: var(--c2u-paper);
}
.c2u-closing.is-bg-shifted .c2u-btn--secondary:hover {
  background: var(--c2u-paper);
  border-color: var(--c2u-paper);
  color: var(--c2u-navy);
}

/* The shader snaps between palettes under this preference rather than
   crossfading, and type still easing its way to white against a background
   that arrived instantly is the two halves coming apart. */
@media (prefers-reduced-motion: reduce) {
  .c2u-page .c2u-closing__heading,
  .c2u-page .c2u-closing__subhead { transition: none; }
}

/* Phone. The padding is left where it is — 1.75 of a 72px section is 126px,
   which puts the section at around 500px of an 844px screen rather than at the
   screenful the same multiplier gives on a wide one, so there is nothing to
   claw back here.

   The buttons stack and go full width. Two pills side by side at 390px either
   wrap into a ragged pair or squeeze the labels; stacked, neither is the wider
   of the two and the order alone carries the emphasis, which is what the
   variants are already saying. */
@media (max-width: 767px) {
  .c2u-closing__actions { width: 100%; }
  .c2u-closing__actions .c2u-btn { width: 100%; }
}
