/*
 * Roots 'n' Fruits — offer page redesign (2026-08-06, local only, reversible).
 *
 * Styles the new /non-toxic-guide/ template ONLY. Enqueued from functions.php
 * exclusively when is_page_template('template-offer.php') is true, so it never
 * loads anywhere else on the site.
 *
 * EVERY SELECTOR IN THIS FILE IS SCOPED UNDER .rnf-offer2. Nothing here targets
 * a bare element, a shared class (.rnf-sec, .rnf-card, .rnf-btn, .rnf-site-header
 * …), or the sitewide header/footer. offer.css is NOT edited: this sheet is
 * enqueued with 'rnf-offer' as a dependency so it loads afterwards, and any rule
 * that needs overriding is overridden here rather than changed at the source.
 *
 * To revert the redesign: delete this file, restore template-offer.php from
 * template-offer.php.bak-20260806, and delete the "BEGIN rnf offer2" block in
 * functions.php.
 *
 * Palette (design spec, deliberately literal rather than token-referencing so a
 * later token change cannot silently restyle this page):
 *   forest green  #3c4a2c
 *   cream         #f2ede1
 *   card near-white #fdfcf9
 *   button warm white #fdfbf6
 */

.rnf-offer2 {
	--o2-forest: #3c4a2c;
	--o2-forest-deep: #2b361f;
	--o2-cream: #f2ede1;
	--o2-card: #fdfcf9;
	--o2-warm-white: #fdfbf6;
	--o2-ink: #23291c;
	--o2-muted: #6b7360;
	--o2-line: #ded7c6;

	/*
	 * =====================================================================
	 * OFFER-PAGE FONTS — the display serif lives here and in ONE other place
	 * =====================================================================
	 * ACTIVE 2026-08-06: Cormorant Garamond (display) + Inter (body).
	 *
	 * Changing typeface takes exactly TWO edits: --o2-serif below, and the Google
	 * Fonts url on the 'rnf-offer2-fonts' handle in functions.php. Nothing else
	 * moves — the nine font-family call sites in this file all read these two
	 * variables rather than naming a typeface directly.
	 *
	 * --o2-serif is used by FOUR display elements only: the hero h1, the plans h2,
	 * the card names, and the price figures (both the live price and the struck
	 * "was" price, so the price lockup stays in one typeface). Everything else on
	 * the page inherits --o2-sans from this wrapper.
	 *
	 * Cormorant Garamond is high-contrast and delicate, so the three headings are
	 * set to font-weight 600 rather than 400 — see the rules below. Only 500 and
	 * 600 are loaded; the struck price inherits 400 and therefore resolves to the
	 * nearest loaded weight, 500.
	 *
	 * Superseded (local only, reversible) — earlier values, kept so any is one
	 * un-comment away. Restore the matching font url in functions.php at the same
	 * time, and see the per-rule notes for the heading weights each one used.
	 *     --o2-serif: 'Newsreader', Georgia, serif;                              (immediately prior, headings 400)
	 *     --o2-serif: 'Fraunces', Georgia, serif;                                (soft/light, headings 400)
	 *     --o2-serif: 'Lora', Georgia, serif;                                    (headings 400)
	 *     --o2-serif: "Fraunces", Georgia, "Times New Roman", serif;             (original redesign, headings 600)
	 *     --o2-sans: "Nunito Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
	 */
	/* was: --o2-serif: 'Cormorant Garamond', Georgia, serif; */
	/* Repointed at the global display token 2026-08-08. NOTE: this token has
	 * had ZERO live call sites since the h1 migrated on 2026-08-07 — every
	 * former consumer now reads --font-serif or --o2-sans directly. Kept and
	 * repointed so it cannot reintroduce Cormorant if something starts using
	 * it again. The comment block above is stale; see the per-rule notes. */
	--o2-serif: var(--font-display);

	/*
	 * Body face. Switched to the SITE TOKEN 2026-08-06 (local only, reversible) as
	 * part of consolidating this page onto the two families the footer already uses.
	 * Superseded: --o2-sans: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
	 *
	 * --font-sans is defined in assets/css/tokens.css:31 and is the same stack the
	 * footer's column headings (.rnf-foot-head) and body text use. It is a SYSTEM
	 * stack, so it costs no network request — which is why Inter could be dropped
	 * from the offer-page font enqueue entirely rather than swapped for another
	 * webfont. See the "BEGIN rnf offer2" block in functions.php.
	 *
	 * Kept as a one-line alias rather than replacing the six var(--o2-sans) call
	 * sites, so this stays a single-line change in both directions.
	 */
	--o2-sans: var(--font-sans);

	font-family: var(--o2-sans);
	color: var(--o2-ink);
}

/* ---------------------------------------------------------------------------
 * Shared bits
 * ------------------------------------------------------------------------- */

/*
 * Added 2026-08-06 (local only, reversible). Variable-font tuning for the five
 * display-serif elements. Delete this whole rule to revert.
 *
 * font-optical-sizing: auto — lets the browser track an opsz axis with size where
 * the family has one. Cormorant Garamond does NOT (an opsz request to Google 400s),
 * so this is currently a harmless no-op; it is kept so the behaviour returns for
 * free if the serif is ever swapped back to Fraunces or Newsreader, both of which
 * do have opsz.
 *
 * RETIRED 2026-08-06 with the move to Cormorant Garamond:
 *
 *     font-variation-settings: 'SOFT' 100, 'WONK' 0;
 *
 * SOFT and WONK are Fraunces-only custom axes. Cormorant Garamond has neither, so
 * the declaration had become inert and its presence implied a font that is no
 * longer loaded. Removing it changes nothing visually. Restore the line above if
 * reverting to the Fraunces soft/light url in functions.php.
 */
.rnf-offer2 .rnf-offer2__h1,
.rnf-offer2 .rnf-offer2__h2,
.rnf-offer2 .rnf-offer2__plan-name,
.rnf-offer2 .rnf-offer2__price,
.rnf-offer2 .rnf-offer2__price-was {
	font-optical-sizing: auto;
}

.rnf-offer2 .rnf-offer2__eyebrow {
	margin: 0 0 14px;
	/* was: font-family: var(--o2-sans); — hook eyebrow moves to the display face. */
	font-family: var(--font-display);
	font-size: 11.5px;
	font-weight: 700;
	/* letter-spacing DELIBERATELY LEFT POSITIVE — --track-display is for
	 * headlines only; negative tracking on uppercase text crowds it. */
	letter-spacing: .18em;
	text-transform: uppercase;
	color: var(--o2-muted);
}

/*
 * Hero eyebrow only. The text-shadow below is DELIBERATELY on the --light
 * modifier and not on the base .rnf-offer2__eyebrow, which is shared with the
 * plans heading ("Choose your access") and both card eyebrows ("Targeted start",
 * "Most complete"). Those sit on cream and must not gain a shadow. --light is
 * used exactly once, on the hero.
 */
.rnf-offer2 .rnf-offer2__eyebrow--light {
	color: rgba(242, 237, 225, .78);
	/* Added 2026-08-06 with the lighter hero overlay (template-offer.php). This
	   rule previously had NO text-shadow — delete this line to revert. */
	/*
	 * STRENGTHENED 2026-08-13 with the near-production hero lightening.
	 * Superseded: text-shadow: 0 1px 3px rgba(16,20,10,.55), 0 2px 22px rgba(16,20,10,.6);
	 *
	 * THIS SHADOW IS NOW THE LEGIBILITY MECHANISM, not a polish detail. The hero
	 * scrim dropped from a .80 peak to .18 and the overlay from .42/.32/.50 to
	 * .22/.16/.28 (template-offer.php:433), so there is no longer a dark backdrop
	 * doing this job. Tighter, darker inner shadow (3px/.55 -> 4px/.8) plus a
	 * tighter, denser outer glow (22px/.6 -> 20px/.75).
	 *
	 * THIS ELEMENT IS THE HERO'S WEAKEST — 11.5px at the .78-alpha colour two
	 * lines above, over the brightest part of the photo. It is the reason the
	 * scrim was not removed outright.
	 *
	 * REVERT AS A SET: this line, the same change on .rnf-offer2__lede (:756), and
	 * the background-image at template-offer.php:433. Reverting the background
	 * alone leaves an over-shadowed hero; reverting this alone leaves unreadable
	 * text on a light photo.
	 */
	/* was: text-shadow: 0 1px 3px rgba(16,20,10,.55), 0 2px 22px rgba(16,20,10,.6); */
	/*
	 * STRENGTHENED AGAIN 2026-08-13 — three layers now, and this carries MOST of
	 * the readability gain in that pass.
	 * Superseded: text-shadow: 0 1px 4px rgba(16,20,10,.8), 0 2px 20px rgba(16,20,10,.75);
	 *
	 * Two layers became three:
	 *   0 1px 3px  .92  tight, near-opaque contact shadow — the crisp letter edge
	 *   0 2px 10px .85  NEW mid layer — this is what lifts the text off busy photo
	 *   0 2px 26px .60  wide halo, softens the transition
	 * Ink also went cooler and darker: rgba(16,20,10) -> rgba(12,16,8).
	 *
	 * MUST STAY IDENTICAL TO .rnf-offer2__lede's text-shadow. This rule covers the
	 * anchor; that one covers line A and line B together. Letting the two drift
	 * makes the hero's text sit on visibly different backings.
	 *
	 * THIS ELEMENT IS THE HARDEST CASE IN THE HERO — 11.5px at the .78-alpha
	 * colour above, over the brightest part of the photo — so it is the one to
	 * check first if the shadow is ever weakened.
	 *
	 * PAIRED WITH THE OVERLAY LIFT in template-offer.php, done in the same pass.
	 * Revert together.
	 */
	/* was: text-shadow: 0 1px 4px rgba(16,20,10,.8), 0 2px 20px rgba(16,20,10,.75); */
	text-shadow: 0 1px 3px rgba(12,16,8,.92), 0 2px 10px rgba(12,16,8,.85), 0 2px 26px rgba(12,16,8,.6);
	/*
	 * Added 2026-08-13 with the hero restructure. This rule previously had NO
	 * text-align — delete this line to revert.
	 *
	 * The hero eyebrow is now the page <h1> and sits directly above the paragraph,
	 * which also went text-align: left in the same change. Flush left on both makes
	 * them read as ONE block against a shared edge; centred-over-ragged-left read
	 * as two competing alignments.
	 *
	 * TARGETS --light, NOT THE BASE CLASS — the same trap already documented on the
	 * text-shadow above and again in the 720px block near the end of this file.
	 * .rnf-offer2__eyebrow is shared by the plans heading ("Choose your access",
	 * which also carries --center) and both card eyebrows ("Targeted start", "Most
	 * complete"). Those must stay centred. --light is used exactly once, on the hero.
	 *
	 * This overrides the text-align: center inherited from .rnf-offer2__hero, which
	 * is deliberately left alone — it still governs nothing else in the hero now that
	 * both children set their own alignment.
	 *
	 * APPLIES AT EVERY WIDTH, including phones, where the paragraph fills the
	 * container and both elements simply start at the same left edge.
	 *
	 * ---------------------------------------------------------------------
	 * ^ REVERSED 2026-08-13 (later same day). Superseded: text-align: left;
	 * ---------------------------------------------------------------------
	 * The hero went back to centred for both the anchor and the paragraph. The
	 * "one shared left edge" reasoning above is kept as the record of why they were
	 * ever flush left; it no longer describes the page.
	 *
	 * THE --light SCOPING NOTE ABOVE IS STILL LIVE AND STILL MATTERS. Do not
	 * "simplify" this by moving the declaration onto the base .rnf-offer2__eyebrow
	 * or by deleting the line and relying on inheritance from .rnf-offer2__hero:
	 * the base class is shared with the plans heading and both card eyebrows, and
	 * an explicit value here keeps this rule's intent readable next to its
	 * superseded history.
	 *
	 * DESKTOP-ONLY EDIT BY NECESSITY, AND IT REACHES MOBILE CORRECTLY. There is no
	 * text-align for this element in ANY media query — checked all four (@860,
	 * @720, @520, @400) — so this single declaration governs every width.
	 */
	/* was: text-align: left; */
	text-align: center;
}

.rnf-offer2 .rnf-offer2__eyebrow--center {
	text-align: center;
	/*
	 * Added 2026-08-13 with the removal of the plans <h2> in template-offer.php.
	 * This rule previously had NO margin-bottom — delete this line to revert, and
	 * revert it together with that heading.
	 *
	 * WHY IT IS AN ADDITION AND NOT A "COLLAPSE". Commenting out the <h2> left no
	 * orphaned container, but it took .rnf-offer2__h2's own "margin: 0 0 44px" with
	 * it. Measured, the gap from this line to the cards fell:
	 *     1280px   103px -> 14px
	 *      390px    86px -> 14px
	 * 14px is the base .rnf-offer2__eyebrow margin, which is spacing for a label
	 * sitting ON a heading, not for one standing in as the section heading. So this
	 * needed MORE space, not less.
	 *
	 * 40px is the measured replacement at both widths. Not 44px: this line is much
	 * smaller than the h2 it replaced, so it needs slightly less air beneath it to
	 * read as balanced.
	 *
	 * TARGETS --center, NOT THE BASE CLASS. --center is used exactly once, on the
	 * plans heading. .rnf-offer2__eyebrow is shared with both card eyebrows
	 * ("Targeted start", "Most complete"), which must keep their 14px — the same
	 * scoping trap already documented on --light's text-shadow and text-align.
	 */
	/*
	 * 40px -> 12px 2026-08-13, when the section subheading was added directly
	 * below this line. Superseded: margin-bottom: 40px;
	 *
	 * The 40px existed only because this eyebrow was the last thing before the
	 * cards. It is now a KICKER SITTING ON A HEADING, and those belong tight
	 * together. The 40px did not disappear — it moved to .rnf-offer2__subhead's
	 * bottom margin, so the total distance from this line to the cards is
	 * unchanged.
	 *
	 * REVERT AS A SET with the subhead rule below and both markup changes in
	 * template-offer.php.
	 */
	/* was: margin-bottom: 40px; */
	margin-bottom: 12px;
}

/* ---------------------------------------------------------------------------
 * PROMO BANNER — added 2026-08-13. Sits at the very top of the pricing section,
 * above the "Choose your access" kicker, as a lead-in to the cards.
 *
 * Delete this rule and the block at the top of .rnf-offer2__plans-inner in
 * template-offer.php to revert. Nothing existing was modified.
 *
 * DELIBERATELY NOT A FULL-BLEED BAND. The pricing section already supplies the
 * cream background and its own padding, so a centred pill drops in without a new
 * full-width section, and it matches the chips and ribbon already on the page.
 *
 * PALETTE IS BORROWED FROM .rnf-offer2__chip (#eef0e6 on #dbe0cd with forest
 * text), not invented — the two should stay in step if the chip palette ever
 * changes. A SOFT pill rather than a solid forest one on purpose: a dark filled
 * banner here competes with the UNLOCK ALL button further down the section.
 * ------------------------------------------------------------------------- */
.rnf-offer2 .rnf-offer2__promo {
	display: block;
	width: fit-content;
	/* 28px below, so it reads as a lead-in to the kicker rather than a floating
	   notice. The kicker's own 12px then carries on to the subheading. */
	margin: 0 auto 28px;
	background: #eef0e6;
	border: 1px solid #dbe0cd;
	border-radius: 999px;
	padding: 10px 20px;
	font-size: clamp(14px, 1.15vw, 15.5px);
	font-weight: 600;
	line-height: 1.4;
	color: var(--o2-forest);
	text-align: center;
	/* Keeps it off the screen edges and lets it wrap on a phone rather than
	   forcing one long row. */
	max-width: min(38rem, 92vw);
	text-wrap: balance;
}

/*
 * The code itself. Weight and tracking only — no second background, which would
 * put a chip inside a chip and fight the ribbon above the featured card.
 */
.rnf-offer2 .rnf-offer2__promo-code {
	font-weight: 700;
	letter-spacing: .04em;
}

/* ---------------------------------------------------------------------------
 * PRICING SECTION SUBHEADING — added 2026-08-13. Sits between the "Choose your
 * access" kicker and the two pricing cards, and is the section's <h2>.
 *
 * Delete this rule, delete the <h2> in template-offer.php and restore the
 * eyebrow there to <h2> to revert. All four move together.
 *
 * A NEW CLASS RATHER THAN THE DEAD .rnf-offer2__h2, deliberately: that rule's
 * @media (max-width: 520px) override sets white-space: nowrap for the old SHORT
 * heading, and this line is 62 characters — it would overflow a phone. Those
 * rules are also kept live only to make the old heading's removal revertible.
 * ------------------------------------------------------------------------- */
.rnf-offer2 .rnf-offer2__subhead {
	/*
	 * 24px at 1264px and up, 20px floor — inside the 20-24px brief and clearly
	 * below .rnf-offer2__plan-name (34px), so it does not compete with the card
	 * titles.
	 */
	font-size: clamp(20px, 1.9vw, 24px);
	/* Matches the old section heading's face, weight and tracking. */
	font-family: var(--font-serif);
	font-weight: 700;
	letter-spacing: var(--track-display);
	line-height: 1.25;
	/* Same dark green as the card titles. */
	color: var(--o2-forest);
	text-align: center;
	/*
	 * Keeps it a tidy two-row block and off the screen edges. The 92vw guard is
	 * what stops it running edge to edge on a phone.
	 */
	max-width: min(38rem, 92vw);
	/*
	 * margin: 0 auto 40px — the auto centres the block, and the 40px is the
	 * "modest spacing above the cards" inherited from the eyebrow rule above.
	 */
	margin: 0 auto 40px;
	/*
	 * Without this the copy breaks as "…so there's nothing left" / "to research",
	 * leaving a short orphan row. balance evens the two rows — the same fix
	 * already used on both hero lines.
	 */
	text-wrap: balance;
}

.rnf-offer2 .rnf-offer2__rule {
	height: 0;
	margin: 20px 0;
	border: 0;
	border-top: 1px solid var(--o2-line);
}

/* ---------------------------------------------------------------------------
 * HERO — full bleed. .rnf-main has no width constraint, so 100% is genuinely
 * edge to edge with no negative-margin hack.
 * ------------------------------------------------------------------------- */

.rnf-offer2 .rnf-offer2__hero {
	width: 100%;
	background-color: var(--o2-forest-deep); /* fallback while the photo loads */
	background-size: cover;
	background-position: center;
	background-repeat: no-repeat;
	padding: 96px 24px 104px;
	text-align: center;

	/*
	 * Added 2026-08-07 (local only, reversible). Vertically centres the eyebrow +
	 * H1 + lede as one block inside the photo. This rule previously had NO display,
	 * flex or height properties at all, so deleting the four declarations below
	 * restores the original exactly.
	 *
	 * WHY min-height IS NOT OPTIONAL. Before this change the hero had no height of
	 * its own — it was padding + content and nothing else, so the text was already
	 * centred in its own box by construction and `justify-content: center` alone
	 * would have been a no-op. The min-height is what creates the slack to centre
	 * INTO; the two declarations only work as a pair.
	 *
	 * WHY min-height AND NOT height. With `box-sizing: border-box` (tokens.css:52)
	 * min-height INCLUDES the 200px of padding rather than stacking on top of it,
	 * and if content + padding ever exceeds the band the section simply grows. Text
	 * can therefore never be clipped or overflow — a fixed `height` would clip.
	 *
	 * WHY THE clamp() PX FLOOR. 60vh alone would collapse the band on a short
	 * window. The 420px floor is the short-viewport guard; 620px caps it on very
	 * tall screens so the plans below stay reachable.
	 *
	 * MEASURED EFFECT: natural desktop height today is ~419px (200px padding +
	 * ~219px content), so on a 900px-tall window 60vh = 540px and the band gains
	 * ~120px — more of the photo shows and the text visibly centres. See the
	 * matching mobile min-height in the 720px media query near the end of the file.
	 *
	 * .rnf-offer2__hero-inner is unaffected as a flex item: column flex defaults to
	 * align-items: stretch, so its max-width: 880px still caps the width and its
	 * margin: 0 auto still centres it horizontally.
	 *
	 * NOTE: padding is deliberately left asymmetric (96 top / 104 bottom), which
	 * puts the block ~4px above true geometric centre. Invisible, and it keeps the
	 * diff and the revert minimal.
	 */
	display: flex;
	flex-direction: column;
	justify-content: center;
	/*
	 * BAND SHORTENED 2026-08-13 (later same day; local only, reversible).
	 * Superseded: min-height: clamp(420px, 60vh, 620px);
	 *
	 * All three terms scale down together (~0.81 / 0.77 / 0.77) so the curve keeps
	 * its shape — a floor for short windows, a vh term in the middle, a cap so the
	 * plans below stay reachable. The "MEASURED EFFECT" note above is now historical:
	 * it described a hero that still had the big h1, whose content was ~219px. The
	 * hero content is shorter now, so the old 60vh/620px band left the text floating
	 * in mostly-empty photo.
	 *
	 * MEASURED after this change, 1280x900: natural content height 382px, rendered
	 * band 414px = 46vh. Still slack enough for the centring to read as deliberate.
	 *
	 * justify-content: center is DELIBERATELY UNTOUCHED — vertical centring is
	 * unchanged at every size; only the band it centres within got shorter.
	 *
	 * PAIRED WITH THE MOBILE OVERRIDE in the @media (max-width: 720px) block, which
	 * came down proportionally in the same change. Revert both together or the two
	 * breakpoints disagree.
	 */
	/* was: min-height: clamp(420px, 60vh, 620px); */
	min-height: clamp(340px, 46vh, 480px);
}

.rnf-offer2 .rnf-offer2__hero-inner {
	max-width: 880px;
	margin: 0 auto;
}

.rnf-offer2 .rnf-offer2__h1 {
	margin: 0 0 22px;
	/*
	 * =====================================================================
	 * MOVED TO THE WORDMARK SERIF 2026-08-07 (local only, reversible)
	 * =====================================================================
	 * Superseded: font-family: var(--o2-serif);   (Cormorant Garamond)
	 *
	 * WHAT THIS FIXES, AND WHAT IT DOES NOT. The hook was reported as rendering
	 * "slanted/italic". IT WAS NOT ITALIC — diagnosed before changing anything:
	 *   - No font-style: italic reaches this element. Not here, not in any media
	 *     query, not inherited. The theme's only italic rules are .rnf-quote
	 *     (offer.css), journal.css and portal-category.css; none match. The
	 *     rendered page carries no inline italic and no italic ancestor element.
	 *   - No synthetic italic either. The active Google Fonts request
	 *     (functions.php: family=Cormorant+Garamond:wght@600) has NO ital axis,
	 *     and every @font-face it returns is font-style: normal, weight 600. The
	 *     upright face is the one that was loading.
	 * The apparent slant was Cormorant Garamond's own design — a high-contrast
	 * calligraphic Garamond revival. So a font-style: normal declaration would
	 * have been a no-op and is deliberately NOT added here.
	 *
	 * WHY THIS TOKEN. var(--font-serif) (Georgia, tokens.css) is what the header
	 * wordmark .rnf-brand (offer.css) and the footer brand already use. It is also
	 * where the plans H2, plan name, price and price-was were each moved on
	 * 2026-08-06 — see their own "Superseded: font-family: var(--o2-serif)" notes
	 * below. This h1 was THE LAST live var(--o2-serif) in the file, so this
	 * finishes a migration that was already four-fifths done rather than
	 * introducing a new typeface.
	 *
	 * KNOCK-ON, NOT DONE HERE: nothing on this page uses Cormorant Garamond any
	 * more, so the Google Fonts request in functions.php is now a dead round-trip.
	 * Left in place on purpose — it also owns the preconnect hints, so removing it
	 * is a separate decision.
	 */
	font-family: var(--font-serif);
	/*
	 * Superseded: font-weight: 600;
	 * Superseded comment, kept verbatim because it explains the 600:
	 *   "600 for Cormorant Garamond (high-contrast, needs weight at display size).
	 *    Was 400 under Lora / Fraunces-soft / Newsreader — restore 400 with those."
	 *
	 * DROPPED 600 -> 400 FOR THE SAME REASON THE H2 DID. Georgia ships Regular and
	 * Bold only, so a declared 600 has no matching cut and browsers snap to Bold —
	 * heavier than the Cormorant 600 it replaces. 400 is a real Georgia cut and
	 * matches .rnf-brand and .rnf-foot-brand. Restore 600 only alongside a font
	 * that actually has a semibold.
	 *
	 * 2026-08-08: --font-serif now resolves to Montserrat, which DOES have a real
	 * 700, so the reasoning above no longer applies. This is the page's main hook
	 * line and goes to 700.
	 * was: font-weight: 400;
	 */
	font-weight: 700;
	/*
	 * CLAMP FLOOR LOWERED 2026-08-06 (local only, reversible) so the headline wraps
	 * to TWO lines on mobile instead of three.
	 * Superseded: font-size: clamp(34px, 5.2vw, 60px);
	 *
	 * ONLY THE MINIMUM CHANGED. The preferred value (5.2vw) and the maximum (60px)
	 * are byte-identical, so this is the minimal fix — a competing font-size in a
	 * mobile media query is NOT needed and must not be added.
	 *
	 * WHY THE FLOOR WAS THE WHOLE PROBLEM. 5.2vw only reaches 34px at a 654px
	 * viewport, so on every phone the preferred value was far below the old floor
	 * and clamp() returned a flat 34px. At 400px, 5.2vw = 20.8px — below the old
	 * 34px floor and below the new 27px floor, so the floor is what renders. At
	 * 1200px, 5.2vw = 62.4px, above the 60px cap, so the cap renders: unchanged.
	 *
	 * WHAT ACTUALLY CHANGES, measured against the live Cormorant Garamond 600
	 * metrics (cmap + hmtx, 1000 upem):
	 *   < 519px   34px -> 27px          (the fix)
	 *   519-654px 34px -> 5.2vw, 27-34px (side effect: tracks the viewport instead
	 *                                     of sitting on a flat floor; still two
	 *                                     lines, there is 560px+ of text width)
	 *   >= 654px  identical             (desktop untouched)
	 *
	 * TWO-LINE THRESHOLD: line 1 "You shouldn't need a chemistry" measures 324.8px
	 * at 27px; plus the 40px hero padding that needs a 365px viewport. So 375px and
	 * up wrap to two lines; 360px-class devices are 5px short and still show three.
	 * Drop the floor to 26px if those matter.
	 *
	 * MEASURED AGAINST THE OLD HEADLINE (noted 2026-08-07, value unchanged). The
	 * hook copy was replaced in template-offer.php with "Everyone is making
	 * non-toxic swaps. Have you?" — 44 characters against the old 52 — and this
	 * clamp was NOT touched, per the brief. The threshold above is kept as the
	 * record of why the floor is 27px. The new first line is comparable in width to
	 * the old one, so the two-lines-on-a-phone behaviour it describes still holds;
	 * re-measure before changing the floor rather than trusting these numbers.
	 *
	 * ---------------------------------------------------------------------
	 * ALL THE CORMORANT ARITHMETIC ABOVE IS NOW HISTORICAL (2026-08-07).
	 * ---------------------------------------------------------------------
	 * It described a typeface this rule no longer uses. Kept as the record of how
	 * the 27px floor was originally derived. The floor VALUE survives the switch
	 * by coincidence, not by inheritance — it was re-derived from scratch against
	 * Georgia below. Do not reason from the Cormorant numbers again.
	 *
	 * RE-MEASURED FOR GEORGIA 400, via canvas in the browser (Georgia is a local
	 * system font, so these are real advance widths):
	 *     "Everyone is making non-toxic swaps."   16.329em   <- desktop line 1
	 *     "non-toxic swaps. Have you?"            12.285em   <- mobile longest
	 *     "Everyone is making"                     8.669em
	 *
	 * WHY THE CAP IS 48px, NOT 60px. Desktop line 1 must fit .rnf-offer2__hero-inner
	 * (880px): 16.329em x 48px = 784px, 11% headroom. The old 60px cap would need
	 * 980px and would wrap, breaking the deliberate <br> split. Checked across the
	 * range, because 5.2vw shrinks faster than the container does:
	 *     721px  -> 37.5px -> 612px line vs 673px available   fits
	 *     923px  -> 48px   -> 784px      vs 875px             fits (cap engages)
	 *     1200px -> 48px   -> 784px      vs 880px             fits
	 * One line at every width at or above the 720px breakpoint.
	 *
	 * WHY THE 27px FLOOR STANDS. Below 720px the <br> is hidden and the string
	 * wraps freely, so the binding line is "non-toxic swaps. Have you?" at
	 * 12.285em = 331.7px at 27px. Against available width (viewport - 40px):
	 *     400px -> 360px  two lines, 8% headroom
	 *     390px -> 350px  two lines, 5%
	 *     375px -> 335px  two lines, ~1% — marginal
	 *     360px -> 320px  THREE lines
	 * Drop to 26px if 375/360px-class devices matter.
	 */
	font-size: clamp(27px, 5.2vw, 48px);
	/*
	 * Superseded: line-height: 1.1;
	 *
	 * Georgia has a much larger x-height and taller extenders than Cormorant, so
	 * the 1.1 tuned for Cormorant runs tight on a two-line Georgia heading. 1.15
	 * sits between it and the 1.18 the Georgia .rnf-offer2__h2 already uses.
	 */
	line-height: 1.15;
	/* was: letter-spacing: -.01em; */
	letter-spacing: var(--track-display);
	/*
	 * Added 2026-08-06 (local only, reversible). This rule had NO text-wrap before,
	 * so deleting this line restores the original exactly.
	 *
	 * Evens the two mobile lines instead of stranding "2026" alone on line two.
	 *
	 * NOTE ON WHAT IT CANNOT DO: per CSS Text 4, `balance` redistributes text across
	 * the lines the layout already produced WITHOUT increasing the line count — it
	 * will not turn three lines into two. The clamp floor above is what does that.
	 * Harmless where unsupported (older engines simply ignore it).
	 */
	text-wrap: balance;
	color: #fbf8f0;
	/* Strengthened 2026-08-06 with the lighter hero overlay (template-offer.php).
	   Superseded: text-shadow: 0 2px 18px rgba(16, 22, 12, .55); */
	text-shadow: 0 1px 3px rgba(16,20,10,.55), 0 2px 22px rgba(16,20,10,.6);

	/*
	 * LINING FIGURES — added 2026-08-06 (local only, reversible).
	 *
	 * This rule previously had NO numeral settings at all; the two lines below are
	 * purely additive, so deleting them restores the original exactly.
	 *
	 * WHY: Cormorant Garamond's DEFAULT figures are old-style, so the "2026" in the
	 * headline sat at uneven heights and read small beside the caps. These force
	 * full-height lining figures while keeping the headline in Cormorant Garamond —
	 * family, size, weight and wording are all unchanged.
	 *
	 * VERIFIED the feature actually exists in the file the page loads: the served
	 * woff2 (fonts.gstatic.com/s/cormorantgaramond/v21/…) was brotli-decompressed and
	 * its table data contains 'lnum' and 'tnum'. 'onum' is ABSENT from the subset —
	 * which corroborates the diagnosis, since a subsetter drops features whose
	 * lookups are no-ops, i.e. the default figures already were old-style.
	 *
	 * Both properties are set on purpose: font-variant-numeric is the standards-track
	 * high-level property, font-feature-settings the low-level fallback for older
	 * engines. They express the same intent, so they cannot disagree. The "onum" 0
	 * half names a feature not present in this subset — harmless (absent features are
	 * ignored) and still useful for the Georgia/serif fallback.
	 *
	 * SCOPE: hero H1 only. The plans H2, card names and prices are deliberately not
	 * given these settings.
	 *
	 * STILL CORRECT AFTER THE 2026-08-07 SWITCH TO GEORGIA (value unchanged). The
	 * Cormorant-specific evidence above is historical, but the intent carries:
	 * Georgia's default figures are ALSO oldstyle, so these keep any numerals
	 * full-height. Moot for the current copy either way — the hook no longer
	 * contains digits — and harmless, so left in place rather than removed.
	 */
	font-feature-settings: "lnum" 1, "onum" 0;
	font-variant-numeric: lining-nums;
}

.rnf-offer2 .rnf-offer2__lede {
	/*
	 * Widened 2026-08-06 (local only, reversible) so the lede sits on TWO lines on
	 * desktop instead of three. Superseded: max-width: 660px;
	 *
	 * THE ARITHMETIC, because this is easy to get backwards: the copy is 169
	 * characters, so two lines needs ~85 characters per line. 660px at 17px is
	 * ~70ch ~= 75 chars/line, which is why it broke to three. 78ch (~730px) gives
	 * ~85. Anything NARROWER than ~78ch adds a line rather than removing one.
	 *
	 * font-size is deliberately unchanged: `ch` scales with font-size, so shrinking
	 * the type does not buy more characters per line — only the ch value does.
	 *
	 * 730px fits inside .rnf-offer2__hero-inner (880px). On mobile nothing changes:
	 * max-width is a cap, so below ~730px the container governs and it wraps
	 * naturally.
	 *
	 * ARITHMETIC ABOVE IS NOW HISTORICAL (noted 2026-08-07, value unchanged). The
	 * lede's leading sentence was removed in template-offer.php, taking the copy
	 * from 169 to 121 characters. The ~85-chars-per-line conclusion still holds —
	 * 78ch is deliberately KEPT, because `ch` scales with font-size, so the flat
	 * 1rem below shrinks type and measure together. 121 chars now fits two
	 * comfortable desktop lines. Do NOT widen this to "use up" the space: past the
	 * copy length it just strands a short second line.
	 *
	 * ---------------------------------------------------------------------
	 * ALL THE ARITHMETIC ABOVE IS NOW HISTORICAL (2026-08-13, value CHANGED).
	 * ---------------------------------------------------------------------
	 * It was derived to force a TWO-LINE desktop wrap on 121 characters. Both
	 * premises are gone: the lede copy was replaced in template-offer.php and is
	 * now 230 characters, and the brief asks for a 60-70 character measure rather
	 * than the widest wrap that avoids a third line. Kept as the record of how
	 * 78ch was reached; do not reason forward from those numbers.
	 *
	 * Superseded: max-width: 78ch;
	 *
	 * WHY rem AND NOT ch — this reverses the reasoning above, so read it before
	 * changing it back. The `ch` argument was that measure should shrink WITH the
	 * type so characters-per-line stays constant. That is right in principle and
	 * inert in practice here:
	 *   - 78ch renders ~85 chars/line. The target is 60-70. 36rem = 576px, and at
	 *     the 16.5px desktop lede size that is ~35em, i.e. ~70 chars — the top of
	 *     the requested band.
	 *   - The unit only matters where this cap actually binds, which is desktop,
	 *     where the font-size clamp is pinned at its 1.03125rem cap and ch and rem
	 *     therefore track each other anyway.
	 *   - On phones it never binds. Hero padding is 24px a side, so 36rem only
	 *     governs above a ~624px viewport; below that the container is already
	 *     narrower than the cap and wins regardless of unit. The mobile font-size
	 *     clamp at :1230 cannot pull the measure out from under this value.
	 * A rem cap also survives the type scale being retuned again without silently
	 * re-widening the measure, which is what 78ch did when the copy changed.
	 */
	/* was: max-width: 78ch; — 2026-08-13, narrowed for the 230-char lede. */
	/*
	 * WIDENED AND CAPPED TO THE VIEWPORT 2026-08-13 (later same day).
	 * Superseded: max-width: 36rem;
	 *
	 * 40rem (640px) gives the now much larger type somewhere to go. The min() adds
	 * the mobile guard the brief asked for: the paragraph must never run edge to
	 * edge, so it is capped at 90vw as well.
	 *
	 * ONE DECLARATION COVERS BOTH BREAKPOINTS — no media query needed, and none
	 * should be added. min() picks whichever is smaller at the current width:
	 *     390px viewport -> 90vw = 351px wins (measured 350px rendered, 89.7vw)
	 *     720px          -> 90vw = 648px vs 640px, so 40rem wins
	 *     1280px         -> 40rem = 640px wins (50vw)
	 * Measured 87.5-90% of viewport from 320-720px, so the "not edge to edge"
	 * requirement holds at every phone width, and the hero's own 20-24px side
	 * padding sits outside it.
	 *
	 * MEASURE COST, KNOWN AND ACCEPTED: at the 25px desktop cap this box yields
	 * ~56 characters per line, down from ~66. That is the arithmetic of a much
	 * bigger font in a similar box, and it is the trade this change asks for. Do
	 * NOT widen max-width to chase the old measure back — that was the point of
	 * capping it here.
	 */
	/*
	 * WIDENED 2026-08-13 for the two-line hero split.
	 * Superseded: max-width: min(40rem, 90vw);
	 *
	 * This rule is now LINE A only — the large primary line. Line B is
	 * .rnf-offer2__lede--sub immediately below.
	 *
	 * THE WIDTH IS NOT WHAT PRODUCES THE TWO-ROW SPLIT — text-wrap: balance is.
	 * Measured at 1280px, the rendered rows are 627px / 656px at 48rem, 50rem AND
	 * 52rem — byte-identical, because balance picks the break independent of the
	 * box once the box is wide enough. Do NOT tune this value expecting the break
	 * to move; change the copy or the font-size instead.
	 *
	 * 50rem is therefore chosen for headroom, not for the break: the longest
	 * rendered row is 656px against an 800px box, so the copy can grow without
	 * the box becoming the constraint.
	 *
	 * THE 90vw GUARD IS KEPT — it is what stops the line running edge to edge on a
	 * phone, and it is why this is min() and not a bare length.
	 */
	/* was: max-width: 36rem; */
	/* was: max-width: min(40rem, 90vw); */
	max-width: min(50rem, 90vw);
	/*
	 * Added 2026-08-13 with the hero restructure. This rule previously had NO
	 * text-align and inherited center from .rnf-offer2__hero (:175) — delete this
	 * line to revert; do NOT "restore" it by writing text-align: center, which
	 * would pin what used to be inherited.
	 *
	 * WHY. The headline above this paragraph was removed, so this is now the hero's
	 * primary text rather than a supporting line under a hook. Centred ragged-right
	 * is fine for two short lines under a headline; at four lines carrying the whole
	 * message it costs a stable left edge on every line. The eyebrow/<h1> above got
	 * the same treatment (:145) so the two share one edge.
	 *
	 * THE BLOCK ITSELF IS STILL CENTRED IN THE HERO — that is margin: 0 auto below
	 * plus .rnf-offer2__hero-inner's own margin: 0 auto, which are untouched. Only
	 * the text inside this 36rem box is left-aligned. Measured: hero-inner resolves
	 * to exactly 576px with equal left and right margins from 320px to 1920px.
	 *
	 * ---------------------------------------------------------------------
	 * ^ REVERSED 2026-08-13 (later same day). Superseded: text-align: left;
	 * ---------------------------------------------------------------------
	 * Centred again, matching the anchor above it (:190). The left-edge reasoning
	 * above is kept only as the record of why it was ever flush left.
	 *
	 * NO MEDIA QUERY SETS text-align FOR THIS ELEMENT — checked all four (@860,
	 * @720, @520, @400) — so this single declaration governs desktop AND mobile.
	 * The block itself is still centred by margin: 0 auto below; that is unchanged.
	 */
	/* was: text-align: left; */
	text-align: center;
	/*
	 * was: text-wrap: balance; — 2026-08-13.
	 *
	 * "balance" is for short blocks: it equalises EVERY line, which is what the
	 * old two-line lede wanted. At 36rem the new copy runs ~4 lines, which is a
	 * paragraph, and balancing a paragraph narrows all of it to even out the last
	 * row. "pretty" is the paragraph-length tool — it leaves the measure alone and
	 * only suppresses the last-line orphan.
	 *
	 * Progressive enhancement either way: browsers without `pretty` fall back to
	 * normal wrapping, same as they did without `balance`.
	 */
	/*
	 * pretty -> balance 2026-08-13 with the two-line hero split.
	 * Superseded: text-wrap: balance;   (2026-08-13, earlier the same day)
	 * Superseded: text-wrap: pretty;
	 *
	 * Line A is now a SHORT two-row block, which is exactly what balance is for —
	 * it evens the two rows (measured 627px / 656px, a 29px imbalance) instead of
	 * leaving a long row over a short one. "pretty" was correct when this element
	 * was a four-row paragraph; it is not any more.
	 *
	 * LINE B GOES BACK TO pretty in the --sub rule below, because it wraps to two
	 * rows on a phone and balance would narrow both.
	 */
	/* was: text-wrap: pretty; */
	text-wrap: balance;
	/*
	 * 38px -> 1rem 2026-08-13: this is the GAP BETWEEN LINE A AND LINE B.
	 * Superseded: margin: 0 auto 38px;
	 *
	 * THE 38px WAS DORMANT, WHICH IS WHY IT LOOKED LIKE A NO-OP BEFORE. This
	 * element was the last child of .rnf-offer2__hero-inner and
	 * ":last-child { margin-bottom: 0 }" (:808 of this file) zeroed it. Adding
	 * line B made it live for the first time, so it had to come down to the
	 * intended ~1rem gap. Measured 16px between the two lines at every width.
	 *
	 * LINE B NEEDS NO BOTTOM MARGIN OF ITS OWN — it is the last child now, so it
	 * inherits that same :last-child zero.
	 */
	/* was: margin: 0 auto 38px; */
	margin: 0 auto 1rem;
	/*
	 * Stepped down one size 2026-08-07 (local only, reversible) for clearer
	 * contrast against the H1. Restore the two Superseded values to revert.
	 *
	 * Superseded: font-size: 17px;
	 * Superseded: line-height: 1.62;
	 *
	 * WAS A FLAT 17px AT EVERY WIDTH — there was no __lede override in any media
	 * query, and there still must not be one: the clamp below does the responsive
	 * work by itself, so a competing font-size in a breakpoint would fight it.
	 *
	 * THE CURVE is a straight two-point fluid line, 16px at a 375px viewport to
	 * 16.5px at 1280px: slope (16.5-16)/(1280-375) = 0.0552vw, intercept
	 * 16 - 0.000552*375 = 15.79px = 0.987rem. So the step down lands at 17 -> 16.5
	 * on desktop and 17 -> 16 on phones, scaling smoothly in between rather than
	 * sitting on a fixed pixel size.
	 *
	 * THE 1rem FLOOR IS THE POINT: it hard-guarantees the rendered mobile size
	 * never falls below 16px. rem (not px) is used in the floor AND the preferred
	 * term so the whole curve tracks a user's enlarged root font-size; the
	 * 1.03125rem cap is 16.5px at the default root.
	 *
	 * max-width: 78ch ABOVE IS DELIBERATELY UNCHANGED and its arithmetic comment
	 * stays accurate. `ch` scales with font-size, so the type and the measure
	 * shrink together and characters-per-line stays ~85 — the two-line desktop
	 * wrap is preserved. Do NOT "compensate" by widening it; that would ADD a line.
	 *
	 * ^ THAT PARAGRAPH IS OUT OF DATE (noted 2026-08-13; the font-size curve it
	 * documents is UNCHANGED and everything else here still applies). The cap is
	 * no longer 78ch — it is 36rem, and the "~85 chars / two desktop lines" target
	 * it protected was retired with the copy rewrite. See the 2026-08-13 note on
	 * max-width above for why the ch->rem swap does not disturb this curve: the cap
	 * only binds above ~624px, where this clamp is pinned at its 1.03125rem cap.
	 *
	 * 1.55 is the slight tightening to match the smaller size, and is already the
	 * line-height used elsewhere in this file (.rnf-offer2__hero-note,
	 * .rnf-offer2__plan-desc).
	 */
	/*
	 * SECOND PASS 2026-08-07 (local only, reversible). The clamp above is flattened
	 * to a hard 1rem. This is a SECOND LINK in the revert chain, not a replacement
	 * of the first — the "Superseded: font-size: 17px" / "line-height: 1.62" lines
	 * above are the original values and must stay.
	 *
	 * Superseded: font-size: clamp(1rem, 0.987rem + 0.055vw, 1.03125rem);
	 * Superseded: line-height: 1.55;
	 *
	 * WHY THE CURVE WENT AWAY. Its floor was already governing every phone width:
	 * at 400px the preferred term computes to 0.987rem + 0.22px = 16.01px, i.e.
	 * effectively the floor. So the only thing the curve bought was ~0.5px of extra
	 * size on DESKTOP — exactly where the paragraph most needed to be smaller.
	 * Flattening takes desktop 16.5px -> 16px and leaves mobile unchanged.
	 *
	 * 1rem, NOT px: the size must track a user's enlarged root font-size, and this
	 * hard-guarantees the rendered size never falls below 16px at the default root.
	 * That is the accessibility line this change must not cross.
	 *
	 * MOBILE CONTRAST IS AT ITS LIMIT AND THAT IS DELIBERATE, NOT AN OVERSIGHT.
	 * At 400px the H1 sits on its own 27px clamp floor and this paragraph on its
	 * 1rem floor, so the ratio is pinned at 27/16 = 1.69x. It cannot be improved
	 * without either taking this below 16px or raising the H1 floor — both ruled
	 * out. Desktop is where the gain lands: 60/16 = 3.75x, up from 3.64x. The rest
	 * of the perceived hierarchy on phones comes from the shorter copy.
	 *
	 * STILL NO MEDIA-QUERY OVERRIDE, same as the first pass: one declaration governs
	 * every width. Do NOT "fix" mobile by adding a __lede font-size to a breakpoint —
	 * it would fight this rule and reintroduce the problem the clamp was written to
	 * avoid.
	 *
	 * 1.45 tightens the leading to suit the smaller size and the now-shorter copy;
	 * 1.55 was tuned for a 169-character paragraph running ~7 lines on a phone.
	 */
	/*
	 * STEPPED UP 2026-08-13 with the hero restructure. Superseded: font-size: 1rem;
	 *
	 * WHY. The .rnf-offer2__h1 hook above was commented out, so this paragraph is
	 * now the hero's PRIMARY text, not a subhead. At 1rem it read as supporting copy
	 * with nothing to support.
	 *
	 * WHY 1.125rem AND NOT 1.25rem — the measure decides it, not taste. max-width is
	 * 36rem, so characters-per-line falls as the type grows. Measured on the
	 * rendered page in headless Chrome (Montserrat, canvas advance widths):
	 *
	 *     1rem     (16px)   3 lines   ~72 chars/line   too wide
	 *     1.125rem (18px)   4 lines   ~66 chars/line   <- inside the 60-70 target
	 *     1.25rem  (20px)   4 lines   ~58 chars/line   below the target
	 *
	 * So 1.125rem is the ONLY step that both raises the type and holds the measure.
	 * Do NOT "round up" to 1.25rem: it costs ~8 characters a line and buys no extra
	 * line count. If the type must grow further, widen max-width in step or the
	 * measure goes with it.
	 *
	 * NEW RUNG IN THE SCALE, KNOWINGLY. This file previously went 16px -> 21px with
	 * nothing between (see .rnf-offer2__faux-btn at 16px and .rnf-offer2__price-was
	 * at 21px). 18px is a natural intermediate and is used only here.
	 *
	 * rem, NOT px, is kept from the previous value so the size still tracks a user's
	 * enlarged root font-size. That was the accessibility line the 2026-08-07 note
	 * below drew, and this change does not cross it — it raises the floor, it does
	 * not lower it.
	 */
	/* was: font-size: 1rem; */
	/*
	 * STEPPED UP AGAIN 2026-08-13 (later same day; local only, reversible).
	 * Superseded: font-size: 1.125rem;
	 * Superseded: line-height: 1.45;
	 *
	 * The paragraph becomes the hero's dominant element, so it moves from a flat
	 * 18px to a fluid 19-25px. 1.5 leading suits the larger size.
	 *
	 * THIS ONE CLAMP GOVERNS BOTH BREAKPOINTS. The @media (max-width: 720px) block
	 * used to hard-set font-size and line-height for this element; BOTH ARE NOW
	 * COMMENTED OUT there so nothing competes with this declaration. If you restore
	 * either, restore both, and expect them to win below 720px.
	 *
	 * MEASURED, rendered page, headless Chrome:
	 *      320px  19px    (floor)   8 lines
	 *      390px  19px    (floor)   6 lines
	 *      430px  19px    (floor)   5 lines
	 *      720px  19px    (floor)   3 lines
	 *     1024px  22.5px            4 lines
	 *     1280px  25px    (cap)     4 lines   ~56 chars/line
	 * 2.2vw reaches the 25px cap at a 1136px viewport and does not touch the 19px
	 * floor until 864px, so the floor governs every phone and tablet width. Zero
	 * horizontal overflow from 320px to 1920px.
	 *
	 * WHY A px FLOOR AND NOT rem HERE — this is a deliberate break from the
	 * "1rem floor" accessibility note further up, and it does NOT weaken it: 19px
	 * is well above the 16px that note was protecting. The px floor is what keeps
	 * the phone rendering predictable against the 2.2vw term.
	 */
	/*
	 * STEPPED UP 2026-08-13 for the two-line hero split — this is now LINE A, the
	 * hero's largest text.
	 * Superseded: font-size: clamp(19px, 2.2vw, 25px);
	 *
	 * The whole curve moves up together (floor 19 -> 20px, slope 2.2 -> 2.4vw,
	 * cap 25 -> 27px) so it keeps its shape. 2.4vw reaches the 27px cap at a
	 * 1125px viewport and holds the 20px floor below ~833px.
	 *
	 * Measured: 2 rows at every desktop width from 721px to 1920px, 3 rows at
	 * 390px. Line B sits at roughly half this size — see --sub below.
	 */
	/* was: font-size: 1.125rem; */
	/* was: font-size: clamp(19px, 2.2vw, 25px); */
	font-size: clamp(20px, 2.4vw, 27px);
	/* was: line-height: 1.45; */
	line-height: 1.5;
	color: rgba(247, 243, 232, .92);
	/* Strengthened 2026-08-06 with the lighter hero overlay (template-offer.php).
	   Superseded: text-shadow: 0 1px 12px rgba(16, 22, 12, .45); */
	/*
	 * STRENGTHENED AGAIN 2026-08-13 with the near-production hero lightening.
	 * Superseded: text-shadow: 0 1px 3px rgba(16,20,10,.55), 0 2px 22px rgba(16,20,10,.6);
	 *
	 * Matched exactly to the anchor's shadow at :149 — the two must stay identical
	 * or the hero's two text elements sit on visibly different backings.
	 *
	 * This shadow is now the legibility mechanism: the hero scrim dropped to a .18
	 * peak and the overlay to .22/.16/.28 (template-offer.php:433), so there is no
	 * dark backdrop doing the work any more.
	 *
	 * REVERT AS A SET: this line, :149, and template-offer.php:433.
	 */
	/* was: text-shadow: 0 1px 3px rgba(16,20,10,.55), 0 2px 22px rgba(16,20,10,.6); */
	/*
	 * STRENGTHENED AGAIN 2026-08-13 — three layers now, and this carries MOST of
	 * the readability gain in that pass.
	 * Superseded: text-shadow: 0 1px 4px rgba(16,20,10,.8), 0 2px 20px rgba(16,20,10,.75);
	 *
	 * Two layers became three:
	 *   0 1px 3px  .92  tight, near-opaque contact shadow — the crisp letter edge
	 *   0 2px 10px .85  NEW mid layer — this is what lifts the text off busy photo
	 *   0 2px 26px .60  wide halo, softens the transition
	 * Ink also went cooler and darker: rgba(16,20,10) -> rgba(12,16,8).
	 *
	 * THIS RULE AND .rnf-offer2__eyebrow--light MUST STAY IDENTICAL. Between them
	 * they cover all three hero elements — LINE A AND LINE B HERE (line B carries
	 * no text-shadow of its own and inherits this one, see --sub below), and the
	 * anchor in the eyebrow--light rule. Letting the two drift makes the hero's
	 * text sit on visibly different backings.
	 *
	 * PAIRED WITH THE OVERLAY LIFT in template-offer.php, done in the same pass.
	 * Revert together — a stronger shadow on the older lighter overlay, or the
	 * lifted overlay with the older weaker shadow, is worse than either end state.
	 */
	/* was: text-shadow: 0 1px 4px rgba(16,20,10,.8), 0 2px 20px rgba(16,20,10,.75); */
	text-shadow: 0 1px 3px rgba(12,16,8,.92), 0 2px 10px rgba(12,16,8,.85), 0 2px 26px rgba(12,16,8,.6);
}

/* ---------------------------------------------------------------------------
 * HERO LINE B — the smaller supporting line. Added 2026-08-13 with the two-line
 * hero split. Delete this whole rule and the second <p> in template-offer.php to
 * revert.
 *
 * A MODIFIER ON .rnf-offer2__lede, NOT A STANDALONE CLASS. The element carries
 * both classes, so it inherits colour, line-height, text-align: center and the
 * text-shadow from the base rule above and overrides only what differs. That is
 * what keeps the two hero lines guaranteed-consistent in colour and shadow.
 *
 * IT MUST STAY AFTER THE BASE RULE. Both selectors are two classes, so they tie
 * on specificity and SOURCE ORDER is the only tie-breaker. Moving this block
 * above .rnf-offer2__lede silently disables every declaration in it.
 * ------------------------------------------------------------------------- */
.rnf-offer2 .rnf-offer2__lede--sub {
	/*
	 * Wide enough to hold ONE row across the whole desktop range — measured one
	 * row from 1440px down to 721px, at 630px of text against a 736px box.
	 * The 90vw guard matches the base rule and keeps it off the screen edges.
	 */
	max-width: min(46rem, 90vw);
	/*
	 * Roughly half line A, so the two read as clearly different levels rather
	 * than two similar paragraphs. 1.35vw reaches the 16px cap at ~1185px.
	 *
	 * THE 14px FLOOR IS DELIBERATE AND MUST NOT BE LOWERED. At 390px this line
	 * cannot fit one row at any readable size, so it is allowed to wrap to two —
	 * one row is a DESKTOP-ONLY target. Shrinking below 14px to force one row on
	 * a phone was explicitly ruled out.
	 */
	font-size: clamp(14px, 1.35vw, 16px);
	/*
	 * Back to pretty, overriding the base rule's balance. Balance is for the
	 * short two-row block that line A is; this line is one row on desktop (where
	 * balance is inert anyway) and two on mobile, where balance would narrow both
	 * rows for no gain. pretty just suppresses a last-line orphan.
	 *
	 * ---------------------------------------------------------------------
	 * ^ THAT REASONING WAS WRONG AND IS SUPERSEDED (2026-08-13).
	 * Superseded: text-wrap: pretty;
	 * ---------------------------------------------------------------------
	 * "balance would narrow both rows for no gain" was the mistake — on this
	 * two-row mobile block balance is exactly the gain. pretty only suppresses a
	 * last-line orphan; it does nothing to even the rows, which left a long first
	 * row over a short second. Measured, rendered row widths:
	 *
	 *                  pretty            balance
	 *     390px    [348, 200]  148px   [269, 279]  10px
	 *     430px    [379, 168]  211px   [269, 279]  10px
	 *     320px    [269, 279]   10px   [269, 279]  10px  (already even)
	 *    1280px    one row, 630px      one row, 630px    (inert)
	 *
	 * The split becomes "A swap is a healthier version of a product" /
	 * "you already buy, with less toxic ingredients".
	 *
	 * GLOBAL, NOT SCOPED TO A BREAKPOINT — deliberate. Line B is a single row at
	 * every desktop width and balance is inert on a one-row block (630px either
	 * way, measured), so a @media wrapper would add a breakpoint for no
	 * behavioural difference.
	 *
	 * THIS NOW MATCHES THE BASE RULE'S text-wrap, so the override is technically
	 * redundant. Kept explicit rather than deleted so line B's intent stays
	 * readable beside its other overrides, and so the revert is a one-word flip.
	 *
	 * DO NOT REACH FOR &nbsp; IF THIS EVER REGRESSES. Gluing "you already"
	 * together was measured and does NOTHING: output is byte-identical to pretty
	 * at 390 / 430 / 320px, because the browser breaks AFTER "already", not
	 * between the two words.
	 */
	/* was: text-wrap: pretty; */
	text-wrap: balance;
	/*
	 * No bottom margin: this is the last child of .rnf-offer2__hero-inner, so the
	 * :last-child rule directly below already zeroes it. Stated so the omission
	 * reads as deliberate rather than forgotten.
	 */
	margin: 0 auto;
}

/*
 * Added 2026-08-06 (local only, reversible) with the removal of the hero CTA
 * block from template-offer.php. Kills the trailing margin on whatever element
 * now ends the hero — today the lede, whose "margin: 0 auto 38px" existed only
 * to separate it from the buttons. Without this the 38px stacks on the hero's
 * 104px bottom padding and leaves a dangling gap.
 *
 * DELIBERATELY :last-child RATHER THAN TARGETING .rnf-offer2__lede. This is
 * self-correcting: if the CTA block is un-commented, the lede stops being the
 * last child and its 38px returns automatically, while this rule falls through
 * to the restored container (which already has margin: 0 auto, so no effect).
 * That is what makes the revert markup-only. Do not "simplify" this to
 * .rnf-offer2__lede { margin-bottom: 0 } — that would break the spacing on
 * restore, silently.
 */
.rnf-offer2 .rnf-offer2__hero-inner > :last-child {
	margin-bottom: 0;
}

/*
 * Hero CTA grid. Four children in DOM order: button, button, note, note.
 * Because the two buttons occupy grid row 1 and the two notes row 2, the buttons
 * stay aligned to each other however the notes wrap underneath.
 *
 * CURRENTLY UNUSED (2026-08-06): the markup this styles is commented out in
 * template-offer.php. Kept intact — along with .rnf-offer2__faux-btn,
 * .rnf-offer2__hero-note and the @media (max-width: 720px) rules that stack this
 * grid — so un-commenting that block restores the design with no CSS work.
 */
.rnf-offer2 .rnf-offer2__hero-cta {
	display: grid;
	grid-template-columns: 1fr 1fr;
	column-gap: 26px;
	row-gap: 14px;
	align-items: start;
	max-width: 720px;
	margin: 0 auto;
}

/*
 * DECORATIVE ONLY — these are <span>s, not links or buttons. pointer-events:none
 * guarantees a click can never do anything even if a future stylesheet gives
 * them a cursor. Do not add href/tabindex/role here without also making them
 * genuinely interactive.
 */
.rnf-offer2 .rnf-offer2__faux-btn {
	display: block;
	background: var(--o2-warm-white);
	color: var(--o2-forest);
	font-family: var(--o2-sans);
	font-size: 16px;
	font-weight: 700;
	line-height: 1.25;
	text-align: center;
	padding: 16px 20px;
	border-radius: 10px;
	box-shadow: 0 6px 22px rgba(12, 18, 8, .28);
	pointer-events: none;
	user-select: none;
}

.rnf-offer2 .rnf-offer2__hero-note {
	margin: 0;
	font-size: 13.5px;
	line-height: 1.55;
	color: rgba(240, 236, 224, .84);
	text-shadow: 0 1px 10px rgba(16, 22, 12, .4);
}

/* ---------------------------------------------------------------------------
 * PLANS
 * ------------------------------------------------------------------------- */

.rnf-offer2 .rnf-offer2__plans {
	background: var(--o2-cream);
	padding: 76px 24px 88px;
}

.rnf-offer2 .rnf-offer2__plans-inner {
	max-width: 1000px;
	margin: 0 auto;
}

.rnf-offer2 .rnf-offer2__h2 {
	margin: 0 0 44px;
	/*
	 * Moved to the FOOTER SERIF 2026-08-06 (local only, reversible) — the same
	 * var(--font-serif) token the footer's "Roots 'n' Fruits" heading uses
	 * (.rnf-foot-brand, offer.css:131; token at tokens.css:30).
	 * Superseded: font-family: var(--o2-serif);   (Cormorant Garamond)
	 *
	 * WEIGHT DROPPED 600 -> 400 DELIBERATELY. Georgia ships Regular and Bold only,
	 * so a declared 600 has no matching cut and browsers snap to Bold — heavier than
	 * the Cormorant 600 it replaces. 400 is a real Georgia cut and matches
	 * .rnf-foot-brand, which renders Regular. Restore 600 only alongside a font that
	 * actually has a semibold.
	 * Superseded: font-weight: 600;
	 *
	 * 2026-08-08: --font-serif now resolves to Montserrat, which has a real 700.
	 * This is a main hook line and goes to 700.
	 * was: font-weight: 400;
	 * was: (no letter-spacing declared)
	 */
	font-family: var(--font-serif);
	font-weight: 700;
	letter-spacing: var(--track-display);
	font-size: clamp(27px, 3.4vw, 38px);
	line-height: 1.18;
	text-align: center;
	color: var(--o2-forest);
}

.rnf-offer2 .rnf-offer2__cards {
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: 26px;
	align-items: start;
}

.rnf-offer2 .rnf-offer2__card {
	position: relative;
	background: var(--o2-card);
	border: 1px solid var(--o2-line);
	border-radius: 16px;
	padding: 30px 28px;
}

.rnf-offer2 .rnf-offer2__card--featured {
	border: 2px solid var(--o2-forest);
	padding: 29px 27px; /* keeps the inner box the same size despite the 2px border */
}

/* Ribbon overlapping the top-left edge of the featured card. */
.rnf-offer2 .rnf-offer2__ribbon {
	position: absolute;
	top: -13px;
	left: -8px;
	background: var(--o2-forest);
	color: #f6f2e8;
	/*
	 * Scaled up ~20% 2026-08-06 (local only, reversible) to hold its own against the
	 * now-larger plan title. Text and colours unchanged.
	 * Superseded: font-size: 11.5px;
	 * Superseded: padding: 7px 14px;
	 *
	 * CLEARANCE (measured): this ribbon is absolutely positioned over the card's
	 * top-left corner, NOT in flow above the title, so growing it cannot push or
	 * overlap the title. Its bottom edge moves from 14.8px to 19.6px below the card
	 * top; the "Most complete" eyebrow starts at the card's 29px padding-top, leaving
	 * 9.4px clear. Width grows 206px -> 247px inside a card that is 487px wide on
	 * desktop and 360px at a 400px viewport, so `white-space: nowrap` below is safe.
	 */
	font-size: 13.8px;
	font-weight: 700;
	letter-spacing: .08em;
	text-transform: uppercase;
	padding: 8px 17px;
	border-radius: 7px;
	box-shadow: 0 4px 14px rgba(28, 38, 20, .26);
	white-space: nowrap;
}

.rnf-offer2 .rnf-offer2__plan-name {
	margin: 0 0 12px;
	/* Moved to the FOOTER SERIF 2026-08-06, and 600 -> 400, for the same reasons as
	   .rnf-offer2__h2 above (Georgia has no semibold cut).
	   Superseded: font-family: var(--o2-serif);
	   Superseded: font-weight: 600; */
	/* was: font-family: var(--font-serif); */
	/* Card name — a label in the price lockup, not a page heading, so it is held
	 * on the body face rather than following --font-serif into Montserrat. The
	 * 600 below is a real Open Sans cut and is loaded. */
	font-family: var(--font-body);
	/*
	 * Promoted to the card head's anchor 2026-08-06 (local only, reversible).
	 * Superseded: font-weight: 400;
	 * Superseded: font-size: 26px;
	 *
	 * WHY 600 AND NOT 500: Georgia ships Regular(400) and Bold(700) only — no medium.
	 * Under CSS font matching a desired 500 falls back to 400, so "one step up" would
	 * have been a visual no-op here. 600 resolves upward to Georgia Bold, which is a
	 * real cut, not a synthetic smear. (The 600 -> 400 note above is the earlier
	 * font-family move and is unrelated to this decision.)
	 *
	 * WHY 34px: measured, not estimated. Georgia's cap-height is 0.6929 em and the
	 * price's SF Pro is 0.7046 em, so at 34px vs the price's 36px the two caps land at
	 * 23.6px and 25.4px — near level. The title then wins on weight and serif contrast
	 * rather than raw size. At the originally proposed 30px the price would still have
	 * read 22% taller and stayed the anchor.
	 *
	 * KNOWN, ACCEPTED: "Whole-house bundle" is 362px at this size against a 302px inner
	 * card width at a 400px viewport, so it wraps to two lines there. Cards stack below
	 * 860px, so it is never seen beside the one-line "Single guide". Desktop inner width
	 * is 429px, so both titles stay on one line there.
	 */
	font-weight: 600;
	font-size: 34px;
	line-height: 1.2;
	color: var(--o2-forest);
}

.rnf-offer2 .rnf-offer2__price-row {
	display: flex;
	align-items: baseline;
	flex-wrap: wrap;
	gap: 9px;
	margin: 0 0 4px;
}

/*
 * THIS ONE RULE STYLES BOTH AMOUNTS — the $17 on the single-guide card and the
 * $47 on the whole-house card use the same class. There is no --featured
 * override; changing this changes both.
 */
.rnf-offer2 .rnf-offer2__price {
	/*
	 * Moved to Inter 2026-08-06 (local only, reversible). Cormorant Garamond's
	 * default figures are old-style, so the amounts sat at uneven heights — most
	 * visibly on "17", where a short 1 meets a descending 7.
	 * Superseded: font-family: var(--o2-serif);
	 *
	 * var(--o2-sans) resolves to exactly
	 * 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif
	 * and is used rather than re-typing that stack so the prices cannot drift from
	 * the rest of the page's body type.
	 */
	font-family: var(--o2-sans);
	/* Defensive, not load-bearing: Inter's figures are already lining, so this is a
	   no-op there. It covers the -apple-system / sans-serif fallbacks. */
	font-variant-numeric: lining-nums;
	/*
	 * Medium 2026-08-06 (local only, reversible) — clean and substantial without
	 * reading bold. History: 600 (too heavy) -> 400 (too light) -> 500.
	 * Superseded: font-weight: 600;
	 * Superseded: font-weight: 400;
	 *
	 * CAVEAT: this is now a SYSTEM stack (var(--font-sans)), not a webfont, so a true
	 * Medium is not guaranteed on every platform — macOS/SF has one, some Windows
	 * setups snap 500 to Regular. The $47 / $102 hierarchy therefore does not rest on
	 * weight alone: size (42px vs 21px), colour (forest vs muted) and the strike
	 * carry it regardless.
	 */
	/*
	 * Stepped DOWN to secondary 2026-08-06 (local only, reversible) so the plan title
	 * above can be the anchor the eye lands on first. Deliberately gentle — the price
	 * must stay easy to find.
	 * Superseded: font-weight: 500;
	 * Superseded: font-size: 42px;
	 *
	 * One weight step (500 -> 400) and -15% on size. Per the CAVEAT above this is a
	 * smaller real-world change than it looks: 500 already snapped to Regular on some
	 * platforms, so on those nothing moves but the size. At 36px the amount is still
	 * large and highly legible.
	 *
	 * Cap-height check against the title (Georgia 0.6929 em, SF Pro 0.7046 em, SF digits
	 * are cap-height): title 34px -> 23.6px, price 36px -> 25.4px. Was 18.0px vs 29.6px,
	 * i.e. the price used to read 64% taller and now reads 7.7% taller — near level, with
	 * the title carrying the hierarchy on weight and typeface instead.
	 */
	font-weight: 400;
	font-size: 36px;
	line-height: 1;
	color: var(--o2-forest);
}

.rnf-offer2 .rnf-offer2__price-was {
	/* Moved to Inter 2026-08-06 (local only, reversible), matching .rnf-offer2__price
	   so the whole price lockup reads in one typeface.
	   Superseded: font-family: var(--o2-serif); */
	font-family: var(--o2-sans);
	/* Defensive, as on .rnf-offer2__price — Inter is already lining. */
	font-variant-numeric: lining-nums;
	/*
	 * Made EXPLICIT 2026-08-06 (local only, reversible). This rule previously
	 * declared no font-weight and merely inherited 400; it is now stated outright so
	 * the intended contrast with .rnf-offer2__price (500) is visible in the code
	 * rather than implied. Delete this line to return to inheriting.
	 *
	 * Kept LIGHTER than the live price on purpose: a struck-through "was" figure
	 * should read as subordinate to the price it is being compared against.
	 */
	font-weight: 400;
	font-size: 21px;
	color: var(--o2-muted);
	text-decoration: line-through;
}

.rnf-offer2 .rnf-offer2__price-unit {
	font-size: 11px;
	font-weight: 700;
	letter-spacing: .13em;
	text-transform: uppercase;
	color: var(--o2-muted);
}

.rnf-offer2 .rnf-offer2__tax {
	margin: 0 0 16px;
	font-size: 12.5px;
	color: var(--o2-muted);
}

.rnf-offer2 .rnf-offer2__plan-desc {
	margin: 0 0 16px;
	font-size: 15px;
	line-height: 1.55;
	color: var(--o2-ink);
}

/* Chips ------------------------------------------------------------------- */

.rnf-offer2 .rnf-offer2__chips {
	display: flex;
	/*
	 * flex-wrap: wrap IS DELIBERATE AND MUST STAY. It is the safety net: a future
	 * fourth category wraps to a second row instead of overflowing the card. Do
	 * NOT "fix" chip wrapping with nowrap — the three chips are made to fit by
	 * their labels and sizing (see .rnf-offer2__chip below), not by forbidding
	 * the wrap.
	 */
	flex-wrap: wrap;
	/* Tightened 2026-08-07 with the chip resize below (local only, reversible).
	   Superseded: gap: 8px; */
	gap: 6px;
}

/* Whole-house card chips: two grouped columns on every screen.
   Column-major fill, so $rnf_o2_all_chips runs down the left column then the right —
   left = single-guide-eligible, right = whole-house-only. */
.rnf-offer2 .rnf-offer2__chips--grid {
	display: grid;
	/* Superseded 2026-08-06 (local only, reversible): grid-template-columns: repeat(3, 1fr); */
	grid-template-columns: repeat(2, 1fr);
	grid-template-rows: repeat(3, auto);
	grid-auto-flow: column;
	gap: 8px;
	justify-items: center;
}

.rnf-offer2 .rnf-offer2__chip {
	display: inline-block;
	background: #eef0e6;
	border: 1px solid #dbe0cd;
	border-radius: 999px;
	/*
	 * Horizontal padding trimmed 2026-08-07 (local only, reversible). VERTICAL IS
	 * UNCHANGED at 6px, so chip height only grows with the type below.
	 * Superseded: padding: 6px 13px;
	 */
	padding: 6px 10px;
	/*
	 * RAISED 2026-08-07 (local only, reversible) — note the direction.
	 * Superseded: font-size: 12.5px;
	 *
	 * This goes UP, not down. 12.5px was below the 14px readability floor set for
	 * this work, so the chips could not be shrunk to fit; they had to grow to
	 * reach the floor. The one-row fit comes entirely from the shortened labels in
	 * template-offer.php, not from smaller type.
	 *
	 * THE BUDGET, at a 360px viewport (the tightest case). Card interior is
	 * 360 - 40 (plans padding) - 40 (card padding) - 2 (card border) = 278px.
	 *     before: 260.9 text + 3x28 + 2x8 gap = 360.9px  -> overflowed, wrapped
	 *     after:  174.4 text + 3x22 + 2x6 gap = 252.4px  -> fits, 25.6px spare
	 * At 400px the interior is 318px, so the same row leaves 65.6px spare.
	 *
	 * SHARED WITH THE WHOLE-HOUSE GRID. This rule also styles .rnf-offer2__chips--grid,
	 * where a 360px cell is 135px; the widest label there is now "Personal Care"
	 * at 115.9px. That is why BOTH chip arrays were shortened — at 14px the old
	 * "Kitchen & Dining" came to 134px against that 135px cell.
	 */
	font-size: 14px;
	font-weight: 600;
	line-height: 1.3;
	color: var(--o2-forest);
	text-align: center;
	white-space: nowrap;
}

.rnf-offer2 .rnf-offer2__pill {
	display: block;
	width: fit-content;
	margin: 14px auto 0;
	background: var(--o2-forest);
	color: #f4f1e6;
	border-radius: 999px;
	padding: 6px 15px;
	font-size: 12px;
	font-weight: 600;
	letter-spacing: .02em;
}

/* Checklist --------------------------------------------------------------- */

.rnf-offer2 .rnf-offer2__list {
	list-style: none;
	margin: 0 0 24px;
	padding: 0;
}

.rnf-offer2 .rnf-offer2__list-item {
	display: flex;
	align-items: flex-start;
	gap: 10px;
	margin-bottom: 10px;
	font-size: 14.5px;
	line-height: 1.5;
	color: var(--o2-ink);
}

.rnf-offer2 .rnf-offer2__list-item:last-child {
	margin-bottom: 0;
}

/* Colors the shared rnf_icon_check() SVG, which draws with currentColor. */
.rnf-offer2 .rnf-offer2__check {
	flex: 0 0 auto;
	margin-top: 2px;
	color: var(--o2-forest);
}

/* Buttons — the only two clickable controls on the page ------------------- */

.rnf-offer2 .rnf-offer2__btn {
	display: block;
	width: 100%;
	margin-top: 24px;
	padding: 15px 18px;
	border-radius: 10px;
	font-family: var(--o2-sans);
	font-size: 12.5px;
	font-weight: 700;
	letter-spacing: .12em;
	text-transform: uppercase;
	text-align: center;
	text-decoration: none;
	cursor: pointer;
	transition: background-color .15s ease, color .15s ease, border-color .15s ease;
}

.rnf-offer2 .rnf-offer2__btn:focus-visible {
	outline: 2px solid var(--o2-forest);
	outline-offset: 3px;
}

/* Outlined green. Colour is restated because tokens.css sets a global `a` color. */
.rnf-offer2 .rnf-offer2__btn--ghost {
	background: transparent;
	color: var(--o2-forest);
	border: 2px solid var(--o2-forest);
}

.rnf-offer2 .rnf-offer2__btn--ghost:hover {
	background: var(--o2-forest);
	color: var(--o2-warm-white);
}

/* Solid green. */
.rnf-offer2 .rnf-offer2__btn--solid {
	background: var(--o2-forest);
	color: var(--o2-warm-white);
	border: 2px solid var(--o2-forest);
}

.rnf-offer2 .rnf-offer2__btn--solid:hover {
	background: var(--o2-forest-deep);
	border-color: var(--o2-forest-deep);
}

.rnf-offer2 .rnf-offer2__closing {
	margin: 34px auto 0;
	max-width: 640px;
	text-align: center;
	font-size: 14px;
	line-height: 1.6;
	color: var(--o2-muted);
	/*
	 * Added 2026-08-06 (local only, reversible). PURELY ADDITIVE — nothing was
	 * superseded, so there is no old value to restore; deleting this line reverts it.
	 *
	 * The 70-character line was stranding a fragment on its own row: at a 400px
	 * viewport (360px available — __plans has 20px side padding below 860px, so the
	 * max-width above does not bind) it wrapped to THREE lines as 322 / 356 / 66px,
	 * leaving "inbox." alone. Desktop was no better: 640 / 118px, stranding
	 * "your inbox.". Balancing evens both out — mobile to 256 / 240 / 248px (spread
	 * 291px -> 17px) and desktop to 382 / 375px (spread 522px -> 7px).
	 *
	 * ONE LINE WAS REJECTED, NOT OVERLOOKED: the string measures 770px at 14px in
	 * SF Pro, i.e. 2.14x the 360px available, so a single line at 400px would need
	 * 6.5px type. Font-size, colour and copy are therefore all unchanged.
	 *
	 * No media query governs this rule, so this one declaration covers every width.
	 * Unsupported browsers ignore it and render exactly as before. Same technique as
	 * .rnf-offer2__h1.
	 */
	text-wrap: balance;
}

/* ---------------------------------------------------------------------------
 * Responsive
 * ------------------------------------------------------------------------- */

/* Cards stack before they get too narrow for a 3-column chip grid. */
@media (max-width: 860px) {
	.rnf-offer2 .rnf-offer2__cards {
		grid-template-columns: 1fr;
	}

	.rnf-offer2 .rnf-offer2__plans {
		padding: 60px 20px 70px;
	}
}

/* Below 720px the headline wraps naturally, so the forced break is removed. */
@media (max-width: 720px) {
	.rnf-offer2 .rnf-offer2__h1-br {
		display: none;
	}

	.rnf-offer2 .rnf-offer2__hero {
		padding: 68px 20px 74px;
		/*
		 * Added 2026-08-07 with the hero centring in the base rule (local only,
		 * reversible). This rule previously held ONLY the padding above — delete
		 * this one declaration to revert. The padding is untouched.
		 *
		 * Smaller floor than desktop's 420px because the phone hero is naturally
		 * ~445px already (142px padding + ~303px content, the lede running ~7
		 * lines). So on most handsets 52vh lands at or below the natural height and
		 * this is inert — the block stays centred by its own padding. That is the
		 * intended safe behaviour, not a missing effect: it guarantees the band on
		 * short/landscape phones without inflating the hero and pushing the plans
		 * down on ordinary ones.
		 *
		 * If more visible breathing room on phones is ever wanted, raise this to
		 * clamp(420px, 62vh, 560px) — one value, nothing else changes.
		 *
		 * NATURAL-HEIGHT ESTIMATE IS NOW STALE (noted 2026-08-07, value unchanged).
		 * The lede lost its leading sentence, so it runs fewer than the ~7 lines
		 * assumed above and the natural phone hero is shorter than ~445px. This floor
		 * is therefore MORE likely to be the thing setting the height rather than
		 * sitting inert — which is the intended safe behaviour either way. Left at
		 * clamp(360px, 52vh, 480px) on purpose.
		 *
		 * ---------------------------------------------------------------------
		 * BROUGHT DOWN 2026-08-13 (later same day; local only, reversible).
		 * Superseded: min-height: clamp(360px, 52vh, 480px);
		 * ---------------------------------------------------------------------
		 * PAIRED WITH THE DESKTOP min-height, which shrank in the same change from
		 * clamp(420px, 60vh, 620px) to clamp(340px, 46vh, 480px). All three terms
		 * here scale by the same ~0.83/0.85/0.87 so the two breakpoints stay in
		 * proportion. Revert both together or they disagree.
		 *
		 * WHY. The brief asked that the hero not be mostly empty photo on a phone.
		 * Measured natural content height on a 390x844 device is 345px against the
		 * old 52vh = 439px band, so ~95px of the hero was slack.
		 *
		 * MEASURED after this change, 390x844: band 371px = 44% of viewport height,
		 * comfortably inside the 60-70vh ceiling the brief set, with ~26px of slack
		 * left so the vertical centring still reads as intentional rather than
		 * cramped.
		 *
		 * justify-content: center on the base rule is UNTOUCHED — content stays
		 * vertically centred at both sizes.
		 */
		/* was: min-height: clamp(360px, 52vh, 480px); */
		min-height: clamp(300px, 44vh, 420px);
	}

	/*
	 * One column: each button is immediately followed by its own note, so the
	 * pairing stays clear. Explicit row placement keeps DOM order (btn, btn,
	 * note, note) rendering as btn/note, btn/note.
	 */
	.rnf-offer2 .rnf-offer2__hero-cta {
		grid-template-columns: 1fr;
		row-gap: 10px;
	}

	.rnf-offer2 .rnf-offer2__faux-btn:nth-of-type(1) { grid-row: 1; }
	.rnf-offer2 .rnf-offer2__hero-note:nth-of-type(1) { grid-row: 2; margin-bottom: 12px; }
	.rnf-offer2 .rnf-offer2__faux-btn:nth-of-type(2) { grid-row: 3; }
	.rnf-offer2 .rnf-offer2__hero-note:nth-of-type(2) { grid-row: 4; }

	/*
	 * =====================================================================
	 * MOBILE HERO TYPE PASS — added 2026-08-07 (local only, reversible)
	 * =====================================================================
	 * Four overrides, all inside this ONE existing breakpoint. NO BASE RULE WAS
	 * EDITED, so desktop is untouched by construction — deleting the four rules
	 * below reverts this pass completely, with nothing to restore elsewhere.
	 *
	 * THE PROBLEM. On phones the hook sat on its 27px clamp floor, close enough to
	 * a 700-weight uppercase eyebrow and a 16px lede that none of the three read as
	 * a distinct level.
	 *
	 * WHY THE HOOK DOES ALL THE WORK. The other two were already at the floors set
	 * for this work: the eyebrow at 11.5px against an 11px limit (0.5px of room, a
	 * 4% change — invisible), and the lede at exactly 1rem, which must not go below
	 * 16px. Neither could be "reduced noticeably". So the contrast is bought by
	 * raising the hook:
	 *     hook : lede     27/16   = 1.69x  ->  33/16 = 2.06x
	 *     hook : eyebrow  27/11.5 = 2.35x  ->  33/11 = 3.00x
	 */

	/*
	 * Hook floor raised 27px -> 33px.
	 *
	 * Superseded: no mobile override existed — the base rule's
	 * clamp(27px, 5.2vw, 60px) at .rnf-offer2__h1 governed every width, and that
	 * base rule is UNCHANGED.
	 *
	 * WHY THE CLAMP IS REPEATED INSTEAD OF A FLAT 33px. 5.2vw crosses 33px at a
	 * 634.6px viewport, so between ~635px and this 720px breakpoint the base
	 * already renders LARGER than 33px (36.4px at 700px, 37.4px at 720px). A flat
	 * value would shrink the headline on small tablets in portrait. Repeating the
	 * clamp with only the minimum changed raises phones to 33px and leaves the
	 * 635-720px band computing exactly as before. The preferred value and the
	 * maximum are byte-identical to the base rule on purpose.
	 */
	/*
	 * RETIRED 2026-08-07 with the switch to Georgia (local only, reversible).
	 * Superseded:
	 *     .rnf-offer2 .rnf-offer2__h1 {
	 *         font-size: clamp(33px, 5.2vw, 60px);
	 *     }
	 *
	 * WHY IT HAD TO GO. That 33px floor was derived from Cormorant's narrower
	 * metrics. In Georgia the binding mobile line "non-toxic swaps. Have you?"
	 * measures 12.285em, so 33px x 12.285 = 405px — it OVERFLOWS the 360px of text
	 * width a 400px phone has. The rule existed only to lift the floor above 27px,
	 * which Georgia cannot support at this measure, so the base rule's
	 * clamp(27px, 5.2vw, 48px) now governs mobile too.
	 *
	 * The 27px that mobile lands on is NOT the old Cormorant floor carried over —
	 * it was re-derived against Georgia; see the base rule for the per-viewport
	 * line counts. Restoring this block requires restoring the Cormorant family
	 * with it, or the hook will overflow on phones.
	 */

	/*
	 * Paired with the <span class="rnf-offer2__nowrap"> added around "non-toxic" in
	 * template-offer.php. Below this breakpoint .rnf-offer2__h1-br is display:none
	 * (above) and the h1 keeps text-wrap: balance from its base rule, so the hook
	 * is one continuous string the browser may break anywhere — including at the
	 * hyphen, which is a legal wrap opportunity. This pins the compound together so
	 * the break falls before or after it.
	 *
	 * DELIBERATELY SCOPED INSIDE THIS MEDIA QUERY, not the base, so the change is
	 * provably mobile-only; on desktop the span is inert.
	 *
	 * STILL LOAD-BEARING AFTER THE 2026-08-07 GEORGIA SWITCH (value unchanged).
	 * The hyphen is a wrap opportunity in any typeface; only the surrounding size
	 * arithmetic was re-derived, not this. The mobile split it protects is
	 * "Everyone is making" / "non-toxic swaps. Have you?" (8.669em / 12.285em in
	 * Georgia).
	 */
	.rnf-offer2 .rnf-offer2__nowrap {
		white-space: nowrap;
	}

	/*
	 * Hero eyebrow.
	 *
	 * Superseded: font-size: 11.5px; letter-spacing: .18em;
	 * (both inherited from the base .rnf-offer2__eyebrow at the top of this file,
	 * which is UNCHANGED and still governs desktop and the plans/card eyebrows.)
	 *
	 * TARGETS --light, NOT THE BASE CLASS. .rnf-offer2__eyebrow is shared by the
	 * plans heading ("Choose your access") and both card eyebrows ("Targeted
	 * start", "Most complete"), which must keep their sizing; --light is used
	 * exactly once, on the hero. Same reasoning already documented for the hero
	 * text-shadow further up this file. Specificity ties at two classes, and this
	 * block is later in source order, so it wins.
	 *
	 * TRACKING IS THE REAL LEVER, NOT SIZE. 11px is all the size reduction the 11px
	 * floor allows (a 4% step down, not perceptible on its own). What made this
	 * line read as a second headline is .18em of tracking across a 41-character
	 * uppercase string — wide enough to wrap to two lines on a phone. .12em is the
	 * proportional reduction that aims it back onto one line while keeping the
	 * spaced-caps label look. If it still wraps on a 360px-class device, .10em is
	 * the next step; do not go below 11px.
	 */
	.rnf-offer2 .rnf-offer2__eyebrow--light {
		font-size: 11px;
		letter-spacing: .12em;
	}

	/*
	 * Hero lede.
	 *
	 * Superseded: line-height: 1.45; (base rule, UNCHANGED.)
	 *
	 * ---------------------------------------------------------------------
	 * THE "DO NOT ADD A FONT-SIZE" RULE BELOW WAS DELIBERATELY REVERSED
	 * 2026-08-08. Read this before restoring it.
	 * ---------------------------------------------------------------------
	 * Superseded guidance, kept verbatim because it explains the original intent:
	 *
	 *   "font-size IS DELIBERATELY ABSENT. The base rule is already a flat 1rem,
	 *    which is the hard floor for this work — there is no reduction available
	 *    here, and adding a smaller value would break the 16px guarantee. The
	 *    contrast comes from the bigger hook above. 1.4 is the leading tightened
	 *    to suit the now clearly-subordinate role. Do NOT add a font-size to
	 *    this rule."
	 *
	 * WHY IT NO LONGER HOLDS. That note assumed "the bigger hook above" carries
	 * the contrast. That stopped being true on 2026-08-08, when the hook was
	 * re-clamped to clamp(17px, 4.55vw, 42px) so each sentence holds one row.
	 * Measured on the live page:
	 *
	 *     1280px : hook 42px    / lede 16px = 2.625x   <- the desktop reference
	 *      430px : hook 19.57px / lede 16px = 1.223x
	 *      400px : hook 18.20px / lede 16px = 1.137x
	 *      390px : hook 17.75px / lede 16px = 1.109x   <- hook and lede nearly equal
	 *      380px : hook 17.29px / lede 16px = 1.081x
	 *
	 * The hook is no longer bigger in any meaningful sense between 380 and 430px,
	 * so the premise of the old note is gone and the lede is the only remaining
	 * lever. Reproducing the 2.625x desktop ratio at 390px would need a 6.76px
	 * lede, so that target is unreachable; 12px is the accepted floor and yields
	 * ~1.47x. Requested and approved explicitly.
	 *
	 * THE 16px GUARANTEE IS PRESERVED WHERE IT MATTERS. This is a clamp, not a
	 * flat reduction: it returns to the full 16px by ~516px and never touches the
	 * base rule at line 503, so tablets (521-720px) and desktop are byte-for-byte
	 * unchanged. Only phones drop below 16px.
	 *
	 *   3.1vw is the coefficient where 12/390 and 16/520 coincide (both 3.08vw),
	 *   so one value pins the floor across the problem band AND restores the base
	 *   size exactly where contrast stops being a problem.
	 *
	 *     320-387px : 12px      (floor)   hook 27px      -> 2.25x
	 *          390px : 12.09px            hook 17.75px   -> 1.47x
	 *          400px : 12.40px            hook 18.20px   -> 1.47x
	 *          430px : 13.33px            hook 19.57px   -> 1.47x
	 *      516px+    : 16px      (cap)    unchanged from base
	 *
	 * IF YOU WANT THE 16px FLOOR BACK, the correct fix is to raise the hook, not
	 * to delete this clamp — deleting it returns mobile to the 1.08-1.22x collapse.
	 */
	/*
	 * ---------------------------------------------------------------------
	 * THE 12px FLOOR WAS RAISED TO 14px ON 2026-08-13. Read this before
	 * restoring it. Requested and approved explicitly.
	 * ---------------------------------------------------------------------
	 * Superseded: font-size: clamp(12px, 3.1vw, 16px);
	 *
	 * WHY THE 2026-08-08 REASONING NO LONGER DECIDES IT. Everything above is a
	 * ratio argument: 12px was the accepted floor because it bought ~1.47x
	 * hook-to-lede contrast on a phone. That was measured against a 121-character
	 * lede, where the paragraph was short enough that the small type cost little.
	 * The lede is now 230 characters (template-offer.php, 2026-08-13), and 12px
	 * across 230 characters on a 320-390px screen is a readability regression —
	 * which is the opposite of what that rewrite was for. Length now outweighs
	 * ratio; the ratio argument itself is still sound, it just lost the trade.
	 *
	 * THE COST, STATED SO IT IS NOT REDISCOVERED AS A BUG:
	 *
	 *     320-451px : 14px      (floor)   hook 27px      -> 1.93x
	 *          390px : 14px               hook 17.75px   -> 1.27x   (was 1.47x)
	 *          400px : 14px               hook 18.20px   -> 1.30x   (was 1.47x)
	 *          430px : 14px               hook 19.57px   -> 1.40x   (was 1.47x)
	 *      516px+    : 16px      (cap)    unchanged from base
	 *
	 * Contrast in the 380-430px band is genuinely weaker than it was. That is the
	 * accepted trade, not an oversight.
	 *
	 * 3.1vw AND THE 16px CAP ARE BOTH UNTOUCHED, so the curve is identical
	 * wherever it was already above 14px: 3.1vw crosses 14px at a 451px viewport
	 * and still restores the full 16px by ~516px. Tablets (521-720px) and desktop
	 * remain byte-for-byte unchanged, and the base rule is still not touched.
	 *
	 * IF YOU WANT THE OLD CONTRAST BACK, raise the hook rather than dropping this
	 * floor again — same conclusion the 2026-08-08 note reached.
	 */
	.rnf-offer2 .rnf-offer2__lede {
		/* was: (no font-size — see the superseded guidance above) */
		/* was: font-size: clamp(12px, 3.1vw, 16px); — 2026-08-13, floor raised for the 230-char lede. */
		/*
		 * SCALED UP 2026-08-13 (later same day) with the hero restructure.
		 * Superseded: font-size: clamp(14px, 3.1vw, 16px);
		 *
		 * This tracks the base rule going 1rem -> 1.125rem. The whole clamp moves in
		 * proportion rather than only the cap, so the curve keeps its shape:
		 *   floor 14 -> 15px, slope 3.1 -> 3.4vw, cap 16 -> 18px.
		 *
		 * MEASURED CONTINUOUS THROUGH THE BREAKPOINT — this is the thing to check if
		 * you retune either value. 3.4vw reaches the 18px cap at a 530px viewport, so
		 * by 720px this override is already sitting at 18px and hands over to the
		 * base rule's 18px at 721px with NO jump:
		 *
		 *     320px  15px    (floor)   6 lines
		 *     390px  15px    (floor)   5 lines
		 *     430px  15px    (floor)   4 lines
		 *     520px  17.7px            4 lines
		 *     720px  18px    (cap)     4 lines
		 *     721px  18px    (base)    4 lines   <- no discontinuity
		 *
		 * The 15px floor is deliberately BELOW the base size: this paragraph is the
		 * hero's primary text now and runs to 6 lines on a 320px screen, where 18px
		 * would push it to 8. Zero horizontal overflow at every width from 320px up.
		 */
		/*
		 * ---------------------------------------------------------------------
		 * BOTH DECLARATIONS IN THIS RULE ARE COMMENTED OUT 2026-08-13 (later same
		 * day; local only, reversible). THE RULE IS NOW EMPTY BY DESIGN.
		 * ---------------------------------------------------------------------
		 * Superseded: font-size: clamp(15px, 3.4vw, 18px);
		 * Superseded: line-height: 1.45;
		 *
		 * The base rule's new font-size: clamp(19px, 2.2vw, 25px) and line-height:
		 * 1.5 are intended to govern EVERY width. This override existed only to give
		 * phones a smaller size than the desktop flat value; with a fluid clamp on
		 * the base rule there is nothing left for it to do, and leaving it in place
		 * would silently cap phones at 18px and defeat the change.
		 *
		 * THE EMPTY RULE AND ITS SELECTOR ARE DELIBERATELY LEFT IN PLACE so the
		 * revert is "uncomment two lines" rather than "reconstruct the block". It
		 * emits nothing. Do not delete it, and do not add a competing font-size here
		 * — see the paired note on the base rule.
		 *
		 * VERIFIED CONTINUOUS ACROSS THE BREAKPOINT after commenting out: 19px at
		 * 720px and 19px at 721px, because 2.2vw only leaves the 19px floor at an
		 * 864px viewport. No jump.
		 */
		/* was: font-size: clamp(15px, 3.4vw, 18px); */
		/* was: line-height: 1.4; — nudged up because the smaller type reads tight. */
		/* was: line-height: 1.45; — 2026-08-13, base rule's 1.5 now governs all widths. */
	}
}

@media (max-width: 520px) {
	/*
	 * Added 2026-08-06 (local only, reversible). Keeps the plans heading
	 * "One room, or the whole home" on ONE line on phones. Delete this whole block
	 * to revert — the base rule's clamp was never modified.
	 *
	 * WHY A MEDIA QUERY AND NOT THE CLAMP FLOOR (the technique used on the H1):
	 * the base size is clamp(27px, 3.4vw, 38px), and 3.4vw only reaches 27px at a
	 * 794px viewport — so the floor governs everything below 794px, INCLUDING tablet
	 * portrait at 768px. Lowering the floor would shrink the heading on tablets.
	 * Overriding here keeps >=521px byte-identical.
	 *
	 * WHY 24px: measured against Georgia (the --font-serif stack this heading uses,
	 * NOT Cormorant) from the system font file, cmap + hmtx, 2048 upem. The string
	 * is 13.135em wide, so it needs:
	 *     27px -> 355px  (overflows 360/375/390 phones)
	 *     25px -> 328px  (still overflows 360px)
	 *     24px -> 315px  (fits every phone down to a 355px viewport)
	 * 24px is the largest size with NO nowrap overflow risk on any common phone.
	 *
	 * ABOUT nowrap: at 24px the text already fits on one line unaided, so this is
	 * belt-and-braces rather than load-bearing. It matters most where Georgia is
	 * absent (Android falls through to a generic serif with different metrics).
	 * There is ~35px of headroom at 390px, so a fallback would need to be >11% wider
	 * than Georgia to overflow. If you would rather have graceful wrapping than a
	 * guaranteed single line on unknown fallbacks, delete just the nowrap line.
	 */
	.rnf-offer2 .rnf-offer2__h2 {
		font-size: 24px;
		white-space: nowrap;
	}

	/* No-op since 2026-08-06: the base rule is now repeat(2, 1fr) too.
	   Kept as the revert anchor — if the base goes back to 3 columns, this
	   line is what restores 2 columns on phones. */
	.rnf-offer2 .rnf-offer2__chips--grid {
		grid-template-columns: repeat(2, 1fr);
	}

	/*
	 * white-space OVERRIDE WITHDRAWN 2026-08-07 (local only, reversible).
	 * Commented out, not deleted — uncomment this rule to restore the old behaviour.
	 *
	 * WHY: "normal" let a chip break mid-label, so "Kitchen & Dining" could split
	 * across two lines inside its own pill. With it gone the chip inherits the base
	 * white-space: nowrap (line 860), which is what guarantees no word split. Row
	 * wrapping is now handled deterministically by the order/centering rules below
	 * instead of by letting text reflow inside pills.
	 *
	 * Superseded:
	 * .rnf-offer2 .rnf-offer2__chip {
	 * 	white-space: normal;
	 * }
	 */

	/*
	 * SINGLE EFFECTIVE MOBILE CHIP SIZE, ADDED 2026-08-07 (local only, reversible).
	 * This is now the ONLY font-size/padding declaration for chips below 521px — the
	 * competing pair in the @media (max-width: 400px) block at the end of this file
	 * was commented out in the same pass, so there is no duplicate and no cascade
	 * race. VERTICAL PADDING STAYS 6px, so chip height is unchanged from the 12px
	 * step it replaces except for the type.
	 */
	.rnf-offer2 .rnf-offer2__chip {
		font-size: 13px;
		padding: 6px 6px;
	}

	/*
	 * DETERMINISTIC TWO-ROW SINGLE-GUIDE CHIP LAYOUT, ADDED 2026-08-07
	 * (local only, reversible). Purely additive — delete these two rules to revert.
	 *
	 * SCOPED AWAY FROM THE WHOLE-HOUSE GRID ON PURPOSE. The :not(.rnf-offer2__chips--grid)
	 * guard means neither rule can reach the bundle card: its grid keeps its own
	 * column-major flow, its 2x3 shape and its justify-items: center. `order` has no
	 * effect there anyway once the selector excludes it.
	 *
	 * WHAT order: 3 DOES. The row is flex with flex-wrap: wrap. Giving the FIRST chip
	 * ("Kitchen & Dining", the longest) order: 3 moves it visually last while the other
	 * two keep the default order: 0, so the rendered sequence becomes
	 * Living Spaces, Motherhood, Kitchen & Dining. The two short chips therefore pair
	 * up on line one and the long one drops alone to line two, instead of the browser
	 * breaking the row wherever it happens to run out of width.
	 *
	 * justify-content: center centres BOTH resulting lines.
	 *
	 * DOM ORDER IS UNCHANGED — this is a visual reorder only, so assistive tech and
	 * copy-paste still read Kitchen & Dining, Living Spaces, Motherhood.
	 */
	.rnf-offer2__chips:not(.rnf-offer2__chips--grid) {
		justify-content: center;
	}

	.rnf-offer2__chips:not(.rnf-offer2__chips--grid) .rnf-offer2__chip:first-child {
		order: 3;
	}

	.rnf-offer2 .rnf-offer2__card,
	.rnf-offer2 .rnf-offer2__card--featured {
		padding: 26px 20px;
	}
}

/* ---------------------------------------------------------------------------
 * Narrowest phones — chip fit for the full "Kitchen & Dining" label.
 *
 * ADDED 2026-08-07 (local only, reversible). PURELY ADDITIVE: no rule above this
 * point was edited, and deleting this whole block reverts it. Revert together
 * with the 'Kitchen & Dining' label lines in template-offer.php.
 *
 * VERTICAL PADDING STAYS 6px, so chip height tracks the type only.
 *
 * WHY THE SELECTORS CARRY THE ".rnf-offer2 " PREFIX. The base rules are
 * ".rnf-offer2 .rnf-offer2__chip" (0,2,0). A bare ".rnf-offer2__chip" here would be
 * (0,1,0), and MEDIA QUERIES ADD NO SPECIFICITY — the base rule would keep winning
 * and this whole block would silently do nothing. Verified: at 360px the chips still
 * computed to 14px / 6px 10px until the prefix was added. Same trap already
 * documented at offer.css:499-508. Do not drop the prefix.
 *
 * WHY 12px / 7px AND NOT 13px / 8px (13/8 was tried first and MEASURED TO FAIL).
 * Card interior at a 360px viewport is 360 - 40 (plans padding) - 40 (card padding)
 * - 2 (border) = 278px. Measured in headless Chrome, SF Pro, weight 600:
 *     14px / 10px : 133.95 + 62.39 + 104.55 + 2x6 gap = 312.89  -> wrapped
 *     13px /  8px : 122.98 + 55.89 +  95.30 + 2x4 gap = 282.17  -> wrapped, by 4.17px
 *     12px /  7px : 114.03 + 51.39 +  88.05 + 2x4 gap = 261.47  -> FITS, 16.5px spare
 *
 * KNOWN LIMIT: at a 320px viewport (interior 238px) the single-guide row still wraps
 * — 261.47px does not fit. 320px was out of scope for this pass; the target was 360px.
 * Every phone from 360px up is clear.
 *
 * SIDE EFFECT, DELIBERATE AND CHECKED: the gap rule below matches the whole-house
 * grid too (it also carries .rnf-offer2__chips), so that grid's 8px gap becomes 4px
 * under 400px. This makes each grid cell WIDER (134px -> 136px at 360px), which helps
 * "Kitchen & Dining" clear its cell. Verified one line, equal height, at 320-400px.
 * ------------------------------------------------------------------------- */
@media (max-width: 400px) {
	/*
	 * CHIP SIZING WITHDRAWN FROM THIS BLOCK 2026-08-07 (local only, reversible).
	 * Commented out, not deleted.
	 *
	 * WHY: mobile chip sizing was reconciled to ONE value — 13px / 6px 6px, declared
	 * once in the @media (max-width: 520px) block above. This block sits LATER in the
	 * file, so leaving 12px / 6px 7px here would have out-cascaded that 13px below
	 * 401px and produced two different chip sizes across the mobile range. The row
	 * now fits at 13px because the shortest two chips are paired on line one by the
	 * order rule above, so the old 12px squeeze is no longer needed.
	 *
	 * Superseded:
	 * .rnf-offer2 .rnf-offer2__chip {
	 * 	font-size: 12px;
	 * 	padding: 6px 7px;
	 * }
	 */

	.rnf-offer2 .rnf-offer2__chips {
		gap: 4px;
	}
}

/* ---------------------------------------------------------------------------
 * HERO HOOK — one sentence per line.
 *
 * ADDED 2026-08-08 (local only, fully reversible). PURELY ADDITIVE: no rule above
 * this point was edited. Deleting this whole block plus restoring the <br> markup
 * in template-offer.php reverts it.
 *
 * Target:
 *     Everyone is making non-toxic swaps.
 *     Have you?
 *
 * The old approach put a <br class="rnf-offer2__h1-br"> between the sentences and
 * hid it below 720px, so mobile fell back to natural wrapping and the hook ran to
 * THREE ragged lines. Each sentence is now its own block span, so the break is
 * structural and does not depend on a breakpoint.
 *
 * PLACED AT THE END OF THE FILE ON PURPOSE. Media queries add no specificity, and
 * this block is (0,2,0) — exactly the same as the base rule at line 222 and as the
 * max-width blocks at 1023 / 1191 / 1326. Source order is the only tie-breaker, so
 * it has to come last to win at 380-720px. Same prefix trap documented at 1303-1308
 * and offer.css:499-508: the ".rnf-offer2 " prefix is mandatory.
 *
 * WHY 380px AND NOT 390px. Line 1 is 35 characters and needs 18.673x its font-size
 * in width (Montserrat 700 at letter-spacing -0.02em, measured in headless Chrome
 * — every Georgia-based width figure in the comments above this point is STALE,
 * --font-serif was repointed to Montserrat on 2026-08-08). The h1 box is
 * viewport - 40px below 720px. So the largest font-size that keeps line 1 on one
 * row is 15.0px at 320px, 17.1px at 360px, 18.7px at 390px.
 *
 * Holding line 1 on one row at 360px therefore caps the hook at ~16.4px against a
 * 16px lede — a 1.02x ratio, versus 1.69x at the current 27px. The hook would read
 * as body copy. DELIBERATE TRADE, APPROVED: below 380px line 1 is allowed to wrap
 * (3 rows total) and keeps its 27px headline scale; from 380px up each sentence
 * holds one row. 380 rather than 390 so 384px-wide Androids land on the two-line
 * side.
 *
 * WHY clamp(17px, 4.55vw, 42px):
 *   - 4.55vw — the binding width is the SMALLEST viewport in the nowrap range, not
 *     the largest. 380px allows at most 4.79vw, so 4.55vw leaves ~5% margin. 4.7vw
 *     was tried and leaves only 1.3% at 360px and overflows outright at 320px.
 *   - 17px floor is a GUARD ONLY. It binds below 373.6px, which is under the
 *     breakpoint, so it never actually renders. It exists so a future breakpoint
 *     change cannot silently produce a clipping floor.
 *   - 42px cap is reached at 923px and uses 784px of the 880px hero-inner — 96px
 *     spare. The true ceiling is 47.1px, so 45px is available if the desktop hook
 *     should be larger.
 *
 * THE BASE clamp(27px, 5.2vw, 48px) AT LINE 344 IS DELIBERATELY LEFT LIVE. It is
 * what governs below 380px and renders the 27px that keeps narrow phones at
 * headline scale. Do not "tidy" it away — doing so drops the smallest phones onto
 * the small clamp and defeats this entire block.
 *
 * line-height 1.08 is scoped HERE rather than applied to the base rule: below
 * 380px line 1 wraps to two rows, and 1.08 on wrapped 27px text is uncomfortably
 * tight. The base 1.15 stays for that case.
 *
 * text-wrap: balance (line 366) is left alone. Above 380px it is inert under
 * nowrap; below it, it usefully evens the two wrapped rows of line 1.
 *
 * MEASURED, proposed markup + these rules, headless Chrome:
 *     320px  27.0px  3 rows  text 268 / box 280
 *     360px  27.0px  3 rows  text 268 / box 320
 *     379px  27.0px  3 rows  text 268 / box 339
 *     380px  17.3px  2 rows  text 323 / box 340   (17px margin)
 *     390px  17.7px  2 rows  text 331 / box 350   (19px margin)
 *     400px  18.2px  2 rows  text 340 / box 360   (20px margin)
 *     430px  19.6px  2 rows  text 365 / box 390   (25px margin)
 *     720px  32.8px  2 rows  text 612 / box 680
 *     721px  32.8px  2 rows  text 612 / box 673   (hero padding 40->48 jump)
 *    1280px  42.0px  2 rows  text 784 / box 880   (96px margin)
 * No clipping and no h1-driven page overflow anywhere from 320px to 1920px.
 *
 * ^ THAT TABLE IS FOR THE SUPERSEDED HOOK (noted 2026-08-13). It described
 * "Everyone is making non-toxic swaps. / Have you?" (44 chars). The hook was
 * replaced in template-offer.php on 2026-08-13 with "This isn't an e-book or
 * PDF / that gets lost in your inbox." (57 chars). NEITHER RULE IN THIS BLOCK
 * WAS CHANGED — only the copy — so the table is kept as the record of how the
 * 380px breakpoint and 4.55vw were derived. Re-measured against the new copy,
 * same method:
 *
 *     320px  27.0px  4 rows  text 196 / box 280
 *     360px  27.0px  4 rows  text 196 / box 320
 *     379px  27.0px  4 rows  text 196 / box 339
 *     380px  17.3px  2 rows  text 238 / box 340   (102px margin)
 *     390px  17.7px  2 rows  text 244 / box 350   (106px margin)
 *     400px  18.2px  2 rows  text 250 / box 360   (110px margin)
 *     430px  19.6px  2 rows  text 269 / box 390   (121px margin)
 *     720px  32.8px  2 rows  text 451 / box 576
 *     721px  32.8px  2 rows  text 451 / box 576
 *    1280px  42.0px  2 rows  text 578 / box 578
 * Still 0 page overflow at every width from 320px to 1920px, and the nowrap span
 * holds "e-book" on one row throughout.
 *
 * TWO DIFFERENCES WORTH KNOWING:
 *   - Below 380px the hook is now 4 rows, not 3 — both spans wrap instead of just
 *     line 1, because the copy is 13 characters longer. Accepted: no clipping, and
 *     the hero has the room (468px tall at those widths).
 *   - From 380px up the margin is far larger than it was (102px spare at 380px vs
 *     17px). The new lines are much shorter, so 4.55vw is now conservative rather
 *     than tight. Do NOT raise it without re-deriving: the 4.55vw ceiling was set
 *     by the OLD line 1, and the note at :1513 explains the trap.
 *
 * SIDE EFFECT, CHECKED AND INERT: .rnf-offer2__hero-inner narrows from 880px to
 * 784px at desktop once the h1 goes nowrap, because its width now tracks the h1's
 * max-content. Nothing depends on the difference — .rnf-offer2__lede is capped by
 * its own max-width:78ch (714px) and measures 714px wide / 2 rows either way.
 *
 * ^ THOSE TWO FIGURES MOVED WITH THE 2026-08-13 COPY CHANGE, conclusion UNCHANGED:
 * hero-inner now tracks to 578px (the new line 2), and the lede is capped by its
 * own max-width: 36rem (576px) and measures 576px / 3 rows. Still nothing depends
 * on the difference.
 * ------------------------------------------------------------------------- */
.rnf-offer2 .rnf-offer2__h1-line {
	display: block;
}

@media (min-width: 380px) {
	.rnf-offer2 .rnf-offer2__h1-line {
		white-space: nowrap;
	}

	.rnf-offer2 .rnf-offer2__h1 {
		/* was (STILL LIVE at line 344 and governing below 380px): font-size: clamp(27px, 5.2vw, 48px); */
		font-size: clamp(17px, 4.55vw, 42px);
		/* was: line-height: 1.15; */
		line-height: 1.08;
	}
}
