/**
 * Rolex Bespoke design tokens + shell components.
 * Every rule is scoped under body.rolex-section — an unscoped selector here
 * restyles the whole site. Token names mirror Rolex's own template-JPG
 * annotations (Headline50, Body20, Fixed14 …) so a mockup annotation maps
 * 1:1 to a variable.
 */
body.rolex-section {
	/* HELVETICA NEUE IS THE RATIFIED FACE (client decision, 2026-09-15).

	   PREMISE CORRECTED 2026-09-19. This comment used to say Rolex's mockups
	   are set in "their own licensed typeface". They are not: the Brand
	   Centre's Design specifications name **Helvetica** bold and light. So
	   there is no proprietary face to acquire, and nobody should go looking
	   for one.

	   The 6-9% width delta below is real and was measured; what is now known
	   is that it is NOT recoverable by changing this stack. Measured
	   2026-09-18: Helvetica Neue against Helvetica differs by -0.19% to
	   +0.68% at weights 400 and 700, and on this machine Helvetica resolves
	   to Arial metrics anyway. Whatever produces the delta -- the comps'
	   own rendering, tracking, or a version of Helvetica we do not have --
	   swapping the family does not close it. The conclusion below is
	   therefore unchanged; only the reason for it is.

	   Rolex's mockups run 6-9% NARROWER per line than this stack at
	   identical cap heights. The
	   2026-09-15 comp-parity audit measured that on every page type: matched
	   cap heights with mismatched advance widths, e.g. an H2 run of 313px in
	   the comp against 333px live, and "Learn more" at 70px against 75px.
	   That costs an extra line on a handful of headings and body blocks.
	   The client has confirmed we continue on Helvetica Neue, so those wrap
	   points are ACCEPTED, not outstanding.
	   Consequence for future audits: a comp/live delta that is a WIDTH at a
	   matching cap height is this typeface and is not a defect. A delta in
	   cap HEIGHT is a real size difference and still is. Do not chase line
	   counts or measure-widths back to the comp by adjusting font-size --
	   that would break the type ramp the spec sheet defines. */
	--rlx-font-sans: "Helvetica Neue", Helvetica, Arial, sans-serif;
	--rlx-font-serif: Georgia, "Times New Roman", serif;

	--rlx-headline70: 70px; /* Headline70 — the SLIDER hero tagline, the largest size in the spec's whole type ramp; added 2026-08-20 with the Discover slider (design-specs audit: Slider was the single `high`-severity NOT BUILT item). Joins the SHARED responsive ramp below at its existing four breakpoints. */
	--rlx-headline50: 50px;
	--rlx-headline36: 36px;
	--rlx-headline26: 26px; /* Headline26 — the SLIDER hero kicker; added 2026-08-20 alongside Headline70. Same shared ramp. */
	--rlx-body24: 24px;
	--rlx-body20: 20px;
	--rlx-fixed16: 16px;
	--rlx-fixed14: 14px;
	--rlx-fixed22: 22px; /* Fixed22 (Navigation elements, spec p14/p18) — mobile-open-state nav list typography; added 2026-08-17, was flagged NOT BUILT in design-specs audit §0.4/§1.2 */
	--rlx-legend16: 16px;
	--rlx-quote50: 50px; /* Quote50 (Georgia), added 2026-08-17 per design-specs audit §0.4 — see the responsive-ramp block below */

	/* Headline leading. CORRECTED 2026-09-12 from 1.1, which matched neither
	   source. Rolex's own spec sheet (Bespoke section-Design-Specs.pdf pp.5-6,
	   read at all four breakpoint columns) states Line-height 1.2 for
	   Headline50/36/30/26 and 1.1 for Headline70 alone -- hence the separate
	   token below.

	   CONFLICT RESOLVED 2026-09-16 in favour of the mockups. They measure an
	   ink-top-to-ink-top pitch of 58 on a 50px face -- re-measured across
	   seven pages (1908, daytona, datejust, day-date, deepsea, explorer,
	   explorer-II), 15 samples, unanimously 58 -- against the spec's 60.
	   This token followed the spec on the stated grounds that "the spec
	   defines the type system"; the client has since ratified the opposite
	   precedence (15-16 Sep 2026, "JPG governs"), so the measured value
	   wins. 58/50 = 1.16, the same figure already used for the quote. The
	   residual it removes is 2px per line, which compounds over a
	   four-line statement. */
	--rlx-lh-headline: 1.16;
	--rlx-lh-headline70: 1.1;
	/* 1.16, NOT the spec PDF's 1.3. The datejust mockup sets four quote
	   lines on a 58px pitch at 50px (ink runs y455-503, 513-561, 571-619,
	   629-677 in the quote crop -- 49px of ink, 58px apart), and the
	   subheading under it measures the same 58. 1.3 would be 65px.
	   Client ruling, 15 Sep 2026: the JPG mockups govern over the spec
	   PDF where the two disagree. */
	--rlx-lh-quote: 1.16; /* spec pp.5-6 says 1.3; mockup overrides */ /* spec pp.5-6: Headline70 is the one headline step at 1.1 */
	/* 1.6, per the design spec's own "Body20 ... lh 1.6" and the comps: the
	   section body copy measures a 32px ink-top-to-ink-top pitch on a 20px
	   face across the article, collection, model, accessories and servicing
	   mockups. (The two-column intro blocks measure 30 = 1.5; one token
	   cannot be both, and 1.6 is what the spec states and what nearly all
	   multi-paragraph copy uses.) */
	--rlx-lh-body: 1.6;
	/* Body24 is 1.2, NOT --rlx-lh-body. Both read one token until 2026-09-11,
	   which was harmless while it was 1.5 and wrong the moment Body20 went to
	   its spec value of 1.6: card names and accordion labels jumped to a
	   38.4px line box. Spec p.6 lists them separately -- "Body24 bold /
	   Helvetica bold 24px - Line-height 1.2" against "Body20 bold /
	   Helvetica bold 20px - Line-height 1.6". */
	--rlx-lh-body24: 1.2;
	--rlx-lh-fixed: 1.4;

	/* Colours (Styleguide > Colours, spec p2 — design-specs audit §0.1/0.2,
	   2026-08-17): --rlx-green was off by one hex digit (#127449, 4th digit
	   should be 7 → #127749, confirmed against the spec's own swatch and
	   this repo's style.css:685 .rlx__button, which already had it right).
	   --rlx-brown is new: spec's dominant headline/label colour across
	   Model + Contact components, previously missing entirely (everything
	   that should be Brown rendered as Black/--rlx-ink instead). */
	--rlx-green: #127749;
	--rlx-brown: #452C1E;
	--rlx-bg: #F9F7F4;
	--rlx-surface: #FFFFFF;
	/* Body ink. Confirmed 2026-09-12: the comps sample body copy at (32,32,32),
	   so this value is right FOR BODY -- what was wrong was the four headline
	   tokens pointing at it. Task 1's "inconclusive" sampling is now resolved:
	   five independent comp audits plus a darkest-decile glyph-band measurement
	   all read headings as (67..69, 42..44, 28..30) = --rlx-brown #452C1E, on
	   collection, article, model, hub and retailer comps alike. The headline
	   tokens below therefore take --rlx-brown; body24/body20/legend16 keep this. */
	--rlx-ink: #212121;
	--rlx-panel: #F4EFEA; /* specs panel; corrected 2026-08-17 from #F4EFEB (1 hex digit off) per design-specs audit §0.1. NOTE: the delivered _collection packshots (card.php) bake the OLD #f4efeb into their own corners — a 1-unit blue-channel delta vs this new tile colour, imperceptible, not chased here (see rlx-card__media comment below, unchanged). */

	/* THE LAST THREE UNTOKENISED SPEC COLOURS (2026-09-19). All three are
	   Rolex's own, all three were pasted as literals at 8 declaration sites,
	   and this file has ALREADY shipped two one-hex-digit colour typos that
	   took an audit to find (--rlx-green was #127449, --rlx-panel was
	   #F4EFEB). A literal repeated eight times is that bug waiting to happen
	   an eighth time, so they get names.
	   Comment prose below still quotes the literal values on purpose -- the
	   contrast measurements recorded there are about specific numbers, and
	   several guards match that prose. */
	--rlx-green-rolex: #006039; /* Rolex green -- the CTA hover fill and the "Rolex Retailer" tag. NOT --rlx-green (#127749), which is the lighter interface green. */
	--rlx-green-ocean: #9BF9CE; /* Ocean green -- dark-background focus rings, the green band's current-page crumb. Fails contrast on light backgrounds; see the notes at each site. */
	/* THE ROOM A HOVER/FOCUS RING NEEDS OUTSIDE ITS CARD: 2px outline at 3px
	   offset (Accessibility spec p132). Scroll rows reserve exactly this much
	   so the ring is not clipped -- see the .rlx-*__row block below. */
	--rlx-ring-room: 5px;
	--rlx-track: #D4D4D4;       /* Inactive slider track. ~1.4:1 on --rlx-bg, acceptable only because it is decoration with a text/label alternative. */

	--rlx-gap: clamp(45px, 10vh, 90px);
	--rlx-gap-half: clamp(24px, 5vh, 45px);
	/* HEADING-TO-CONTENT, not section-to-section. Measured off Rolex's own
	   Discover comps 2026-09-21: an .rlx-headline36 sits 25px (desktop) /
	   30px (mobile) of INK above the block beneath it. Those two blocks --
	   the promo rows and the Discover trio -- were using --rlx-gap-half, the
	   SECTION rhythm token, which renders 45px desktop / 40px mobile, i.e.
	   nearly double. The two are different rhythms and must not share a
	   token; that conflation is what the client saw as "Rolex watches has
	   more bottom margin than Our Rolex selection".
	   The carousel rows keep their own 24px: the comp genuinely draws that
	   heading looser (31px ink, vs 25 for the promos), so this is NOT a
	   single value applied everywhere. */
	--rlx-heading-gap: 16px;
	/* EVERY card/tile gutter in the section. Measured 8px in every comp that
	   has one — collection cards (3 x 402, gutter 8, verified on datejust,
	   submariner and accessories), the Discover carousel (4 x 402, gutter 8),
	   keep-exploring (4 x 400, gutter 8), the selection grid (3 x 402,
	   gutter 8) and the new-watches hub tiles (2 x 808, gutter 9). Row gaps
	   on the card grids measure 8 too (datejust row 1 ends y1537, row 2
	   starts y1546). The build previously used 45/32/40/16px, which is why
	   every card came out 20-30% narrow. */
	--rlx-card-gap: 8px;
	--rlx-keep-gap: var(--rlx-card-gap);
	/* DASH END RADIUS (2026-09-22, Ernie: ".25rem, from the referenced sites
	   -- and I see the border radius in all the templates"). Every progress
	   track in this section draws rounded ends, and they were all shipping
	   square. ONE token because there are FIVE independent dash families
	   (banner / keep-hub-carousel / new-watches keep / model gallery /
	   lightbox) that a future change must not be able to drift apart -- the
	   same mistake the 26px dash gutter made when it was written per
	   component.

	   MIND THE ROOT: this site sets `html { font-size: 10px }`, so 0.25rem
	   is 2.5px HERE and 4px on a 16px-root site like the reference. It makes
	   no visible difference today -- every bar in this section is 3 or 4px
	   tall and the CSS spec clamps a radius to half the side it sits on, so
	   2.5 and 4 both render the same true pill. It WOULD matter if a future
	   track were taller than 5px: 0.25rem would stop being a pill here while
	   still being one on the reference. Kept as the rem value Ernie gave
	   (2026-09-22) rather than silently converted to 4px. */
	--rlx-dash-radius: 0.25rem;
	--rlx-container-max: 1620px; /* mockup well: text x=150–1770 at 1920 (measured 2026-08-16) */
	/* Page gutter. 24px a side down to 768, but the mobile comps are
	   unanimous at 27: card boxes and photo edges land on device x54 of 780
	   (= 27 CSS at a 390 viewport) in the collection, discover, watches,
	   watchmaking, contact and oyster-story mockups, with text ink ~2px
	   further in on glyph side bearing. The mobile well is 336, not 342 --
	   the same number the .rlx-article__video comment below already recorded
	   ("x54-726 of 780 = 336") without it reaching the declaration. */
	/* PERCENTAGE, not pixels, since 2026-09-17 — this is Rolex's own rule.
	   Brand Centre > Bespoke section > Design specifications > Styleguide >
	   Layout publishes three CSS grids:
	       S  0-767px    6 columns,  6px gutter,  7% side margin
	       M  768-1024   12 columns, 8px gutter,  8% side margin
	       L  1025px +   12 columns, 8px gutter,  8% side margin
	   The token is the BOTH-SIDES total, so 8% a side is 16% here (14% at S).

	   It was 48px, and that was right at exactly one width. 1920 x 0.84 =
	   1612.8, which is why --rlx-container-max's 1620 (measured off the 1920
	   comp) looked correct: 1620 IS the 8% rule, frozen. Below 1920 the fixed
	   48px took over and the margin collapsed — measured 1.67% at 1440,
	   1.50% at 1600, against a specified 8%, i.e. every component ran ~180px
	   wide on any laptop. --rlx-container-max stays as the cap so the well
	   never exceeds the 1620 the comp draws. */
	--rlx-container-inset: 16%;
	/* --rlx-cover-ar / --rlx-cover-ar-mobile used to default to 7/2 and 3/2
	   here and crop every .rlx-cover. Both defaults are gone: the cover now
	   renders its delivered asset uncropped (see .rlx-cover img), and the
	   ONLY consumer left is the Discover slider, which declares both values
	   on .rlx-banner__slide itself because its cross-fading slides must
	   share one height. No root default means a future consumer that forgets
	   to set one gets `aspect-ratio: auto` — the asset's own shape — rather
	   than silently inheriting a crop measured for a different page. */
	/* Sticky band (2026-08-17): the site's own <nav class="fixed"> height,
	   measured live via getBoundingClientRect() on ddev, NOT assumed —
	   75px at >=991px desktop, 70px at <=990px (the same breakpoint the
	   legacy functions.php bare-<nav> rule uses, where the nav's own height
	   changes to 70px). Overridden for mobile below. */
	--rlx-sticky-top: 75px;
}

/* ---- shell type primitives -------------------------------------------- */
body.rolex-section .rlx-headline70 {
	font-family: var(--rlx-font-sans);
	font-size: var(--rlx-headline70);
	line-height: var(--rlx-lh-headline70);
	font-weight: 700;
	color: var(--rlx-brown);
	letter-spacing: 0;
	text-transform: none;
}
body.rolex-section .rlx-headline50 {
	font-family: var(--rlx-font-sans);
	font-size: var(--rlx-headline50);
	line-height: var(--rlx-lh-headline);
	font-weight: 700;
	color: var(--rlx-brown);
	letter-spacing: 0;
	text-transform: none;
}
body.rolex-section .rlx-headline36 {
	font-family: var(--rlx-font-sans);
	font-size: var(--rlx-headline36);
	line-height: var(--rlx-lh-headline);
	font-weight: 700;
	color: var(--rlx-brown);
}
body.rolex-section .rlx-headline26 {
	font-family: var(--rlx-font-sans);
	font-size: var(--rlx-headline26);
	line-height: var(--rlx-lh-headline);
	font-weight: 700;
	color: var(--rlx-brown);
}
body.rolex-section .rlx-body24 {
	font-family: var(--rlx-font-sans);
	font-size: var(--rlx-body24);
	line-height: var(--rlx-lh-body24);
	font-weight: 400;
	color: var(--rlx-ink);
}
body.rolex-section .rlx-body20 {
	font-family: var(--rlx-font-sans);
	font-size: var(--rlx-body20);
	line-height: var(--rlx-lh-body);
	font-weight: 400;
	color: var(--rlx-ink);
}
body.rolex-section .rlx-fixed16,
body.rolex-section .rlx-fixed14,
body.rolex-section .rlx-fixed22,
body.rolex-section .rlx-legend16 {
	font-family: var(--rlx-font-sans);
	line-height: var(--rlx-lh-fixed);
	font-weight: 400;
	color: var(--rlx-ink);
}
body.rolex-section .rlx-fixed16 { font-size: var(--rlx-fixed16); }
body.rolex-section .rlx-fixed14 { font-size: var(--rlx-fixed14); }
body.rolex-section .rlx-fixed22 { font-size: var(--rlx-fixed22); }
body.rolex-section .rlx-legend16 { font-size: var(--rlx-legend16); }

/* Responsive type ramp (Styleguide > Typography, spec p4–7 — design-specs
   audit §0.4, 2026-08-17). Spec gives 4 breakpoint columns per token
   (col1 smallest → col4 largest); the base declarations above already
   equal col4 (the spec's largest value for every token here — confirmed,
   no numeric change needed there). This block supplies col1–col3.
   Custom-property architecture preserved per the rollout note: only the
   TOKEN VALUES change per breakpoint, not a single consumer rule.
   Breakpoint WIDTHS: spec's own Layout section (p3) confirms exactly 3
   tiers — Mobile 0–767 / Tablet 768–1023 / Desktop 1024+ (verified
   directly against the PDF, not just the audit's best-effort read — the
   tablet upper bound reads clearly as 1023, resolving the audit's
   767/990/1023 ambiguity). The type table itself has 4 columns, one more
   than the layout's 3 tiers, and its own column-header row is blank in the
   source (confirmed both by the audit and this same direct read — not a
   clipping artifact, genuinely absent). col1/col2 use the two spec-
   confirmed widths (767, 1023). col3/col4's split at 1620px is an
   IMPLEMENTER CHOICE, not a spec value: tied to this file's own
   --rlx-container-max, on the reasoning that a further type-size step past
   the point where the layout well itself stops growing is the most
   defensible place to draw a line the spec doesn't draw. Disclosed here,
   and in the task report, as an assumption — not presented as fact. */
/* Quote50 col3 (this block, the 1024–1619 tier) is illegible in the spec
   source itself (page-break seam clip, per the audit's appendix); col1=40
   and col4=50 are both directly read from the PDF, col2=50 too. col3 is
   inferred here, not read, from the monotonic-ascending constraint: col2
   already equals col4 at 50, so col3 (sitting between them) cannot be
   lower than 50 and cannot exceed col4's 50 either — it can only be 50. */
/* Headline70 / Headline26 (added 2026-08-20 with the Discover slider) join
   this SHARED ramp at its four EXISTING breakpoint columns — base (>=1620),
   1619, 1023, 767. No new breakpoint is introduced and no existing token's
   value changed; other components read these same three blocks.
   Steps: 70 -> 58 -> 48 -> 40 and 26 -> 24 -> 22 -> 20. The spec's type
   table gives the col4 base values (70 / 26); the three smaller steps are
   scaled PROPORTIONALLY to the ramp Headline50 already establishes in this
   same file (50 -> 42 -> 36 -> 30, i.e. ~0.84 / ~0.72 / ~0.60 of base),
   rounded to whole px and held monotonic — an IMPLEMENTER CHOICE consistent
   with the neighbouring tokens, disclosed here and in the task report, not
   presented as a directly-read spec value. */
@media (max-width: 1619px) {
	body.rolex-section {
		--rlx-headline70: 58px;
		--rlx-headline50: 42px;
		--rlx-headline36: 32px;
		--rlx-headline26: 24px;
		--rlx-body24: 22px;
		--rlx-body20: 19px;
		--rlx-legend16: 15px;
		--rlx-quote50: 50px;
	}
}
@media (max-width: 1024px) {
	body.rolex-section {
		--rlx-headline70: 48px;
		--rlx-headline50: 36px;
		--rlx-headline36: 28px;
		--rlx-headline26: 22px;
		--rlx-body24: 20px;
		--rlx-body20: 19px;
		--rlx-legend16: 13px;
		--rlx-quote50: 50px;
	}
}
@media (max-width: 767px) {
	body.rolex-section {
		/* The MOBILE template states its own rhythm, and it is not the desktop's:
		   7vh / 60px between blocks, 4vh / 40px from a heading+body to its image
		   (desktop: 10vh/90px, 5vh/45px). The clamps in :root resolve 10vh/5vh
		   against a phone's ~844px height to 84px/42px, so mobile was rendering a
		   shrunk desktop rhythm rather than its own spec. Measured 2026-08-25:
		   block gaps 84px, should be 60px. These live in THIS block, not a second
		   767px block — a rival block shadows the type ramp for anything matching
		   on the first @media hit. */
		/* 14% = 7% a side, the S-breakpoint spec value. Was 54px, which on a
		   390 viewport is 6.92% — so this changes the mobile well by 0.6px
		   (336 -> 335.4) and corroborates rather than overturns
		   `rolex-mobile-gutter-is-27`: 27px WAS 7%, measured from the comp. */
		--rlx-container-inset: 14%;
		--rlx-gap: 60px;
		--rlx-gap-half: 40px;
		/* The heading gap is NOT one value across the ramp either, measured the
		   same day on the same comps: the promo heading sits 25px of ink above
		   its image at desktop and 30px at mobile. 16 lands 25 at desktop but
		   22.5 here, because the smaller face leaves less room under the
		   baseline (the ink-to-box offset measures 9px desktop, 6.5px mobile).
		   24 lands 30.5 -- and 24 is also the .rlx-headline36 default, so at
		   this breakpoint the promos simply stop being an exception. */
		--rlx-heading-gap: 24px;
		/* Headline leading is NOT one ratio across the ramp. The desktop
		   comps set a 58px pitch on a 50px face (1.16); the mobile comps set
		   38px on a 30px face (1.267) -- measured across six mobile mockups,
		   25 samples, 38.0 in every one. Restated here rather than in :root
		   so the desktop value stays exactly 1.16. The two middle columns
		   have no delivered comp, so they keep the desktop ratio. */
		--rlx-lh-headline: 1.267;
		--rlx-headline70: 40px;
		--rlx-headline50: 30px;
		--rlx-headline36: 24px;
		--rlx-headline26: 20px;
		--rlx-body24: 18px;
		--rlx-body20: 18px;
		--rlx-legend16: 12px;
		--rlx-quote50: 40px;
	}
}

/* ---- CTAs -------------------------------------------------------------- */
body.rolex-section .rlx-cta-primary {
	display: inline-block;
	font-family: var(--rlx-font-sans);
	font-size: var(--rlx-fixed14);
	font-weight: 700;
	color: #fff;
	background: var(--rlx-green);
	border: 0;
	border-radius: 9999px;
	/* The spec draws this button as `35px | Label | 35px`, height 44, radius
	   22, label 16px bold -- and both comps that carry one agree: "View all"
	   measures 118x44 and "+ More results" 171x44, each with 35px of padding
	   a side and a semicircular end. Width is therefore auto, never a fixed
	   number (so the backlog's "134" is a label-width coincidence). We
	   shipped 49 tall on 24px padding at 14px. Mobile is 30px / 40 / 20 in
	   the same spec. */
	font-size: var(--rlx-fixed16);
	line-height: 1.1;
	min-height: 44px;
	padding: 0 35px;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	text-decoration: none;
	cursor: pointer;
}
/* CTA hover (Styleguide > Call to action, spec p8-11 — design-specs audit
   §1.1, 2026-08-17): spec's exact value is Rolex green #006039, which
   already existed correctly elsewhere in this same codebase
   (bespoke-light.css's .wpb_wrapper.is-active p, style.css's .rlx__button)
   but was never reused here — this token system invented an ad hoc
   #0e5c3a instead. Corrected to reuse the spec's actual value. */
body.rolex-section .rlx-cta-primary:hover { background: var(--rlx-green-rolex); color: #fff; }
@media (max-width: 767px) {
	body.rolex-section .rlx-cta-primary { min-height: 40px; padding: 0 30px; }
}
body.rolex-section .rlx-cta-secondary {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	font-family: var(--rlx-font-sans);
	font-size: var(--rlx-fixed14);
	font-weight: 700;
	color: var(--rlx-green);
	text-decoration: none;
}
body.rolex-section .rlx-cta-secondary:hover { text-decoration: underline; color: var(--rlx-green); }
/* A <button> CARRYING THIS CLASS HAS TO SHED THE BROWSER'S CHROME
   (2026-09-24, Ernie on an iPhone: the filter rail's Apply rendered as a blue
   pill with green text). The rule above was written for an <a> and sets
   only type and colour, so on a <button> every UA default survived: 54x31,
   appearance:button, a 2px border, a #EFEFEF fill in desktop Chrome and a
   blue fill on iOS. Restated property by property -- the theme's own button
   rules are beaten by counter-declaration, never by omission. */
body.rolex-section button.rlx-cta-secondary {
	-webkit-appearance: none;
	appearance: none;
	background: none;
	border: 0;
	border-radius: 0;
	padding: 0;
	margin: 0;
	min-height: 0;
	line-height: 1.2;
	text-transform: none;
	letter-spacing: normal;
	box-shadow: none;
	cursor: pointer;
}

/* AN INLINE LINK IS NOT A SECONDARY CTA (2026-09-22, client: "on the
   /rolex/watches/ page in the intro text there is a contact us link that is a
   smaller font size then the copy block").

   The "contact us" phrase inside the collection intro was carrying
   `.rlx-cta-secondary`, which is a STANDALONE control: it sets its own
   14px, its own 700 weight and `display: inline-flex`. Dropped into a
   Body20 sentence that rendered 14/700 against the paragraph's 20/400 --
   measured, both pages, both breakpoints:

       desktop  paragraph 20px/30 w400   link 14px/21 w700   (-6px)
       mobile   paragraph 18px/27 w400   link 14px/21 w700   (-4px)

   `display: inline-flex` was the quieter half of the same mistake: a flex
   container cannot break across lines, so a longer linked phrase would have
   been pushed whole onto its own line rather than wrapping with the sentence.

   `font: inherit` rather than a second set of numbers -- the point is that
   this link IS the copy, so it tracks the Body20 ramp at every breakpoint
   for free and can never drift from it again.

   THE UNDERLINE IS REQUIRED, not a preference. Measured: this green on the
   page ground is 5.22:1, comfortably over the 4.5:1 body floor -- but
   against the SURROUNDING ink it is only 2.88:1, under the 3:1 that WCAG
   technique G183 asks for when colour alone marks a link inside a block of
   text. So it carries a permanent underline, which is the conventional cue
   and the one that removes the question entirely. The standalone
   `.rlx-cta-secondary` above is unaffected: it is not inside a sentence, and
   its arrow icon and placement already distinguish it. */
body.rolex-section .rlx-inline-link {
	font: inherit;
	color: var(--rlx-green);
	text-decoration: underline;
	text-underline-offset: 0.2em;
	text-decoration-thickness: from-font;
}
body.rolex-section .rlx-inline-link:hover { color: var(--rlx-green-rolex); }
/* THE BUBBLE IS ON THE ICON, NOT THE CONTROL (2026-09-14, Rolex staging
   review): "No bubbles should be around the CTAs. The icons should be in a
   bubble, while the text is against the backing of the page."

   This used to draw a white 1px-bordered pill around the whole link. The
   accessories model-page mockup draws each CTA as a WHITE CIRCLE holding a
   brown icon, with brown label text sitting directly on the page ground --
   measured off that comp, the circles are 36x36 (white runs x148-184 and
   x325-361 in the CTA block). So the pill moves onto the icon and the link
   itself carries no chrome at all. */
body.rolex-section .rlx-cta-tertiary {
	display: inline-flex;
	align-items: center;
	gap: 12px;
	font-family: var(--rlx-font-sans);
	font-size: var(--rlx-fixed14);
	font-weight: 700;
	color: var(--rlx-brown);
	background: none;
	border: 0;
	border-radius: 0;
	padding: 0;
	text-decoration: none;
}
body.rolex-section .rlx-cta-tertiary .rlx-icon {
	flex: 0 0 auto;
	width: 36px;
	height: 36px;
	padding: 11px;
	border-radius: 50%;
	background: var(--rlx-surface);
	color: var(--rlx-brown);
	box-sizing: border-box;
}

/* ---- section layout ----------------------------------------------------- */
body.rolex-section .rlx-main {
	background: var(--rlx-bg);
	/* BOTTOM OF THE BAND (2026-09-09, reported: "the discover rolex section
	   on the discover rolex page need bottom padding under learn more").
	   On /rolex/ the last section is .rlx-ed-trio and the beige band ended
	   flush with its final "Learn more"; every other section only looks
	   right because its neighbour's margin supplies the gap.
	   Measured before choosing the fix: the last section's computed
	   margin-bottom is 0px — .rlx-block's `margin-block: var(--rlx-gap)` is
	   overridden by the parent theme's own compiled section rules — so
	   containing a margin (display: flow-root) would have added nothing.
	   `flow-root` is kept anyway: it costs nothing, and if a future last
	   child does carry a bottom margin the band contains it instead of
	   letting it collapse out. The padding is what actually creates the
	   space, and it uses the same --rlx-gap token as every other vertical
	   step in the section so it tracks that clamp. */
	display: flow-root;
	padding-bottom: var(--rlx-gap);
}

/* P1 parity fix (2026-08-17): the parent theme's own compiled LESS
   (roneous-theme-styles.css, selector `section, footer`) forces
   `padding: 72px 0` on EVERY <section> element site-wide, plus a
   `margin-bottom: 0 !important` that (harmlessly, since sibling margins
   still collapse to whichever side is non-zero) zeroes each section's own
   bottom margin. That 72px padding is INSIDE each section's border box, on
   top of — not instead of — this file's own margin-driven --rlx-gap
   rhythm below: measured on the live watches-hub page (DevTools computed
   style), two adjacent Bespoke sections showed marginTop:90px/
   marginBottom:0px (ours, correct single-token collapse) but ALSO
   paddingTop:72px/paddingBottom:72px each (the legacy rule, never
   anticipated by any Bespoke component here), for a real content-to-
   content gap of 72+90+72 = 234px — 2.6x the mockup's single 90px rhythm.
   Reset scoped to descendants of .rlx-main (never site-wide: header/
   footer/widget-area sections outside our own content region may still
   want the legacy padding) so every Bespoke <section> starts from 0 and
   the real gap is controlled by exactly one thing: each component's own
   margin/padding rule below.
   Fix round 2 (review, 2026-08-17): most of those components (.rlx-block,
   .rlx-hub-tiles, etc.) are safe from this reset regardless of specificity
   because they use MARGIN, a different physical property untouched by a
   padding-block reset. .rlx-keep is likewise unaffected, but for an
   entirely different, non-cascade reason: keep-exploring.php always
   renders it as a SIBLING of <main> (after </main>, right before
   band-footer in every caller) — `.rlx-main section` never matches it in
   the first place, since it isn't a descendant of .rlx-main at all.
   .rlx-availability is the ONE real exception: it's both a descendant of
   .rlx-main AND the only such <section> that drives its OWN vertical
   rhythm through padding-block rather than margin — and its selector
   (body.rolex-section .rlx-availability -- 1 type, 2 classes) is LESS
   specific than this reset (body.rolex-section .rlx-main section -- 2
   types, 2 classes: the extra `section` type selector tips it), so
   without this :not() it silently lost the fight regardless of source
   order, zeroing its own top/bottom padding (live-verified regression on
   a model page: computed paddingTop/Bottom went to 0px). Excluded here
   rather than fixed via a specificity/order trick, since a :not() carve-
   out doesn't depend on which rule happens to load first in a future
   stylesheet reorganization. */
/* .rlx-ed-trio joins .rlx-availability in the carve-out (2026-09-09): the
   Discover Rolex band paints --rlx-panel edge to edge and needs its OWN
   padding-block for the colour to stand off the heading and the last "Learn
   more" (Rolex's comp measures ~71px above / ~123px below). This reset is
   (0,3,2) and beat the component's own (0,2,1) rule, so padding-block
   computed 0px and the panel hugged the text. Extending the existing
   :not() list is what the comment above prescribes for exactly this case,
   in preference to a specificity or ordering trick. */
body.rolex-section .rlx-main section:not(.rlx-availability):not(.rlx-ed-trio):not(.rlx-editorial--panel):not(.rlx-ed-store):not(.rlx-facade-section--panel) { padding-block: 0; }

body.rolex-section .rlx-block { margin-block: var(--rlx-gap); }
/* ---- paragraph spacing ---------------------------------------------------
   The parent stack's reboot ships `p { margin: 0 0 10px }` and nothing in
   this file overrode it for body copy, so consecutive paragraphs sat 10px
   apart where every comp puts a full blank line.

   ONE LINE-HEIGHT, not 64px. 64 is the measured baseline-to-baseline across
   the break on the 32px-pitch body style -- the RESULT, not the margin. A
   64px margin would open it to 96. Expressed in `lh` so it tracks the pitch
   of whatever it is applied to: the same rule gives 32 on section body copy
   and 30 in the two-column intros, which is what the comps measure (2.00x
   pitch in 14 of 14 blocks, at both breakpoints).

   Adjacent margins collapse, so the reboot's 10px bottom margin is absorbed
   rather than added.

   NAMED PROSE CONTAINERS, never `.rlx-main p + p`. That broader selector is
   specificity (0,2,3) and outranks every component caption rule at (0,2,1):
   it put 38px between a card's name and its attribute, and 62px between a
   hub tile's kicker and its name where the comp measures 23. A card caption
   is a stack of <p>s, not prose. */
body.rolex-section .rlx-editorial__copy p + p,
body.rolex-section .rlx-overview__copy p + p,
body.rolex-section .rlx-accordion__panel p + p,
body.rolex-section .rlx-availability__copy p + p,
body.rolex-section .rlx-article__intro-body p + p,
body.rolex-section .rlx-contact__form p + p,
body.rolex-section .rlx-nw-intro__body + .rlx-nw-intro__body,
body.rolex-section .rlx-coll-intro__body + .rlx-coll-intro__body {
	/* `1.6em` first for browsers without `lh` (Safari < 16.4), which would
	   otherwise drop the declaration and fall back to the reboot's 10px. */
	margin-top: 1.6em;
	margin-top: 1lh;
}
/* ...EXCEPT where the comp runs the two straight on. The collection comps
   draw a one-line gap after the bold lede (Deepsea mobile: 112px of pitch
   against a 56px line); the contact comp's pitch is a uniform 56, so its
   lede ends and the rest starts on the very next line. Set by the partial's
   `intro_tight` flag. */
body.rolex-section .rlx-coll-intro--tight .rlx-coll-intro__body + .rlx-coll-intro__body {
	margin-top: 0;
}
body.rolex-section .rlx-block--half { margin-block: var(--rlx-gap-half); }
body.rolex-section .rlx-container {
	/*
	 * 1620px of CONTENT, not a 1620px box with the gutter inside it.
	 *
	 * `max-width: 1620px; padding-inline: 24px` with border-box sizing put
	 * the box at x150-1770 but its children at x174-1746 = 1572. Every comp
	 * in the section puts full-width ink at x148-151 and reaches x1771, so
	 * every heading, section label, intro column, grid well and
	 * keep-exploring row was 48px narrow and shifted 24px right.
	 *
	 * `width: min(1620px, 100% - 48px)` gives the full 1620 once the
	 * viewport can afford it and keeps the 24px gutter below 1668px, where
	 * the gutter is actually wanted. This is the same pattern .rlx-hero,
	 * .rlx-push and .rlx-editorial__media each had to apply individually to
	 * escape it — now it is the container's own behaviour rather than a
	 * workaround every block repeats.
	 */
	width: min(var(--rlx-container-max), 100% - var(--rlx-container-inset));
	max-width: none;
	margin-inline: auto;
	padding-inline: 0;
}

/* THE COVER IS NOT CROPPED. It renders its delivered asset at that asset's
   own ratio.

   This used to impose a house band — 7/2 by default, 16/5 on collection
   pages — with `object-fit: cover`. Measured against Rolex's own comps, that
   was wrong on almost every page in the section. Each comp's hero band, and
   each page's delivered cover:

     collection pages   560px  3.429   assets 2880x840 (all 17)      3.429
     watches hub        500px  3.840   asset                          3.840
     watches-selection  500px  3.840                                  3.840
     new watches hub    500px  3.840                                  3.840
     new watches child  560px  3.429                                  3.429
     accessories        500px  3.840                                  3.840
     retailer hub       500px  3.840                                  3.840
     contact            500px  3.840                                  3.840

   Every comp equals its asset's own ratio, and nothing equals 7/2 (3.500) or
   16/5 (3.200). Live, that meant ten of thirteen heroes were cover-cropped —
   /rolex/watches/ and the retailer pages lost ~9% of the photograph's width,
   /rolex/ collection heroes were 40px too tall and cropped the other way.
   Reported by the client on /rolex/datejust/.

   So the box follows the asset (project memory: rolex-image-box-follows-asset)
   and there is now ONE mechanism rather than a per-page-type constant that
   each new page had to remember to override. Mobile needs no rule either:
   every delivered portrait cover is 1170x780 or 780x520, i.e. exactly the
   3/2 the old token hardcoded.

   --rlx-cover-ar / --rlx-cover-ar-mobile are NOT removed: the Discover
   slider still needs a fixed box, because its slides cross-fade and must
   share one height, and it sets its own value. See .rlx-banner__slide. */
body.rolex-section .rlx-cover img {
	width: 100%;
	height: auto;
	display: block;
}
/* The slider is the one place a fixed box is correct — cross-fading slides
   must share a height — so it opts back in. */
body.rolex-section .rlx-banner__slide.rlx-cover img {
	aspect-ratio: var(--rlx-cover-ar);
	object-fit: cover;
	object-position: center;
}
/* Per-slide crop edge, desktop only (RLX_Discover_Slider::ALIGNS). The file
   is never altered; this chooses which part of the cover crop is kept. */
@media (min-width: 768px) {
	body.rolex-section .rlx-banner__slide.rlx-cover[data-rlx-img-align="right"] img { object-position: right center; }
}
@media (max-width: 767px) {
	body.rolex-section .rlx-banner__slide.rlx-cover img { aspect-ratio: var(--rlx-cover-ar-mobile); }
}

/* ---- bands -------------------------------------------------------------- */
/* Navigation gradient (Styleguide > Colours > Gradient, spec p2 —
   design-specs audit §0.2, 2026-08-17): spec is `linear-gradient(90deg,
   #0b3e27, #197149)`. Both the angle (was 135deg) and the end colour were
   wrong — #197149 is NOT the same as --rlx-green (#127749): the green
   channel differs by more than a typo, so this stays two literal hex
   values rather than reusing the --rlx-green token (unlike most of this
   file's other green usages, which correctly do reuse the token). */
body.rolex-section .rlx-band {
	background: linear-gradient(90deg, #0b3e27, #197149);
	color: #fff;
}
body.rolex-section .rlx-band a { color: #fff; text-decoration: none; }

/* Sticky band (design feedback, 2026-08-17): pins directly beneath the
   site's own fixed main nav (position:fixed, z-index:999, top:0) as the
   page scrolls. z-index 998 is deliberately one below the main nav's 999
   -- band stacks under it, never over it. --rlx-sticky-top is 75px on
   desktop and overridden to 70px at <=990px below (both measured live off
   the real nav, not assumed -- see the token comment at the top of this
   file). position:sticky was verified to actually work here (not silently
   inert) despite body { overflow-x: hidden } from the parent theme
   (roneous/style.css:34): that rule makes body's COMPUTED overflow-y
   resolve to `auto` per the CSS overflow-x/overflow-y interaction, which
   spec-wise makes body "an ancestor with a scrolling mechanism" -- the
   textbook way position:sticky silently breaks. But body never actually
   scrolls here (document.body.scrollTop stays 0 on scroll; the real
   scrolling element is <html>, confirmed live), so it never becomes the
   sticky containing block in practice. Confirmed with an actual scroll
   test after implementing (see the commit message / report), not assumed
   from the overflow value alone -- this is exactly the case the rollout
   note called out to verify rather than guess. */
body.rolex-section .rlx-band-header {
	position: sticky;
	top: var(--rlx-sticky-top, 75px);
	z-index: 998;
	/*
	 * THE MARGIN IS WHAT STOPS THE BAND EATING THE TOP OF EVERY HERO.
	 *
	 * `position: sticky; top: 75px` clamps the band to at least 75px from
	 * the viewport top — and at scroll 0 its flow position is y0, which is
	 * above that clamp, so sticky displaces it DOWNWARD by 75px. Its flow
	 * SLOT stayed at y0-140 while it painted at y75-215, and .rlx-main
	 * began at y140. Net effect: the band covered the first 75px of
	 * whatever followed it, on every page in the section.
	 *
	 * Measured before the fix, on /rolex/watches/:
	 *   band painted  y75-215      hero box y140-640 (500px, correct)
	 *   hero VISIBLE  y215-640 = 425px against the comp's 500
	 *   elementFromPoint() at the hero's own top row returned
	 *   .rlx-band-nav__link, not the image.
	 * Mobile was the same, 70px: hero visible 190px against 260.
	 *
	 * Every hero BOX matched its comp exactly, which is why the geometry
	 * probes passed throughout — they measured boxes, and the loss was in
	 * paint. (memory: measure-ink-not-boxes, again.)
	 *
	 * Reserving the clamp distance in flow makes the displacement zero:
	 * the band's slot becomes 75-215, it paints in the same place it
	 * already did, and content starts at 215 instead of 140. The site's own
	 * nav is `position: fixed` AND transparent by theme design — the
	 * homepage deliberately runs content under it — so this margin is the
	 * only place that height gets reserved, and only inside this section,
	 * where the band below it is opaque.
	 */
	margin-top: var(--rlx-sticky-top, 75px);
}

/* HIDE ON SCROLL DOWN, REAPPEAR ON SCROLL UP -- Ashton item 3: "The Rolex top
   navigation can disappear as the user scrolls down to allow more screen
   space for the Rolex page. When the user scrolls back up, the Rolex header
   can reappear."

   TRANSFORM, never display/visibility/hidden. The band's sticky slot and its
   margin-top reservation are what stop it eating the top 75px of every hero
   (see the long note above); a transform moves paint only and leaves that
   layout exactly as it is. Removing it from flow would re-open that bug.

   Translated by its own height PLUS the sticky offset so it clears the
   viewport outright. It is NOT enough to slide it under the site's own fixed
   nav at z-998: that nav is transparent by theme design, so a band parked
   behind it would still show through on any page that runs content up there.

   rolex-bespoke.js owns when the class goes on. prefers-reduced-motion drops
   the ANIMATION, not the behaviour -- the band still hides, it just cuts
   rather than slides. */
body.rolex-section .rlx-band-header {
	transition: transform 240ms ease;
	will-change: transform;
}
body.rolex-section .rlx-band-header.rlx-band-header--hidden {
	transform: translateY(calc(-100% - var(--rlx-sticky-top, 75px)));
}
@media (prefers-reduced-motion: reduce) {
	body.rolex-section .rlx-band-header { transition: none; }
}
/* Header height + plaque→nav gap (Navigation elements, spec p12, Large
   breakpoint — design-specs audit §1.2, 2026-08-17 follow-up): spec's
   dimensioned diagram gives 110px bar height and a fixed 50px gap between
   the plaque and the first nav item. `gap` (not a hard margin) is used
   alongside the existing `justify-content: space-between` deliberately:
   at real content width (9 nav items) space-between already produces far
   more than 50px between plaque and nav, so `gap` acts as a floor
   guaranteeing the spec's minimum rather than visibly changing the
   edge-aligned layout — confirmed live at 1920px, see report. Mobile
   (<=990px) height drops to 80px, matching the spec's Small breakpoint
   (p12) — the spec's separate Medium/tablet value (100px) is not
   implemented as its own breakpoint; this codebase has a single
   desktop/mobile split at 990px (audit §0.3 already flags the
   3-tier-spec-vs-2-tier-implementation breakpoint mismatch as a pre-existing,
   low-severity delta — not newly introduced here). */
body.rolex-section .rlx-band-header__inner {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 50px;
	min-height: 110px;
}

/* ---- plaque (restyle slice): official co-branded artwork
   (official-rolex-dealer-grand-rapids-jeweler.jpg, 500x250, uploads 2024/05).
   Sized to the spec's Navigation elements plaque dimensions (p12): 120x60px
   at Large/Medium breakpoints, 100x50px at Small (<=990px, below) — both
   exactly 2:1, matching the source asset's native 500x250 ratio, so
   object-fit: contain never crops. Previously fixed at height:56px only
   (a DELTA per design-specs audit §1.2); corrected 2026-08-17. */
body.rolex-section .rlx-plaque img {
	display: block;
	width: 120px;
	height: 60px;
	max-width: none;   /* see the flex note below */
	object-fit: contain;
}

/* The plaque must never shrink. It is a flex item in .rlx-band-header__inner,
   and it was `flex: 0 1 auto` with the image inheriting a global
   `img { max-width: 100% }`. Between them the plaque absorbed ALL the overflow
   pressure from the 9-item nav, so the declared 120px above never actually
   rendered: measured 2026-08-25 at 0px (1291), 58.9px (1366), 112.3px (1600)
   and 68.3px (1920) — correct at exactly one viewport, 1470px.
   `max-width: none` lets the declared width hold; `flex: 0 0 auto` stops the
   row stealing it back. The nav now yields instead — see the breakpoints. */
body.rolex-section .rlx-plaque {
	flex: 0 0 auto;
}

/* ---- section nav (restyle slice): 9-item list + mobile disclosure.
   Deliberately class-scoped (.rlx-band-nav / .rlx-band-nav-toggle) — NEVER
   a bare <nav> element selector. functions.php's legacy custom-CSS emits
   `@media (max-width: 990px) { nav.absolute, nav.fixed, nav {
   position:fixed!important; background:#fff!important; z-index:99999; } }`
   which hard-fixes ANY bare <nav> at <=990px (the same trap band-header.php's
   own FIX 3 comment documents for the breadcrumb row below); a class-scoped
   <ul> never matches that selector regardless of viewport. */
/* Menu toggle (Navigation elements, spec p12, Medium/Small breakpoints):
   "Fixed16 — Menu ▾ 10px 12x12px icon" — text-to-icon gap 10px (was 6px),
   icon 12x12px (was 10x10px). Label itself is now rlx-fixed16 in the
   markup (was rlx-fixed14 — a font-token DELTA the audit's own table
   didn't catch, found on direct spec re-read 2026-08-17). */
body.rolex-section .rlx-band-nav-toggle {
	display: none;
	align-items: center;
	gap: 10px;
	font-family: var(--rlx-font-sans);
	background: none;
	border: 0;
	color: #fff;
	cursor: pointer;
}
body.rolex-section .rlx-band-nav-toggle .rlx-icon { width: 12px; height: 12px; }
/* Item gap (spec p12, Large breakpoint): "2,5vw" between nav items —
   European-decimal-comma read as 2.5vw, confirmed 3x zoom. Live-verified
   at 1920px this does not overflow/wrap the 9-item row inside the 1620px
   container (see report); replaces the previous flat 28px. */
body.rolex-section .rlx-band-nav {
	display: flex;
	align-items: center;
	gap: 2.5vw;
	list-style: none;
	margin: 0;
	padding: 0;
}
body.rolex-section .rlx-band-nav__link {
	display: inline-block;
	white-space: nowrap;
	color: #fff;
	border-bottom: 2px solid transparent;
	padding-bottom: 4px;
}
/* Hover/current (Navigation elements, spec p12/p14/p15 — Large, Medium,
   AND the mobile open-state all independently state "Hover/Current: Ocean
   green"; this is the spec's single most-repeated nav accent and, per
   design-specs audit §1.2, was previously ZERO occurrences of #9BF9CE
   anywhere in this file's nav rules — the underline stayed white on
   hover/active. Fixed 2026-08-17: text + underline both switch to Ocean
   green, default state stays White (#fff, spec-confirmed, unchanged). */
body.rolex-section .rlx-band-nav__link.is-active,
body.rolex-section .rlx-band-nav__link:hover {
	color: var(--rlx-green-ocean);
	border-bottom: 2px solid var(--rlx-green-ocean);
	padding-bottom: 4px;
}
/* Nav-disclosure breakpoint (batch review fix, HIGH -- nav items wrapped
   2-3 lines from 991px up to ~1490px under the shipped CSS: the Fixed16
   bump widened the row past the old ~1340 natural fit-point, and
   Chromium's flex-shrink algorithm compounded it -- shrinking multi-word
   labels below their own single-line width even where the AGGREGATE row
   still had room, because flex-basis:auto's hypothetical size assumes
   wrapping is available and shrinks toward each item's word-level floor
   rather than only shrinking once the row's true nowrap total exceeds the
   container (confirmed live: single-word items like "Servicing" never
   wrapped, every multi-word label did, at the same nominal row width).
   white-space:nowrap above removes that instability entirely -- text can
   no longer wrap under shrink pressure -- which changes the failure mode
   from "wraps early" to "overflows/clips exactly at the true fit
   boundary", live-measured with the REAL nowrap CSS applied (not a JS
   simulation).

   RE-MEASURED (feat/rolex-nav-consistency, 2026-08-18): the "Rolex at Paul
   Medawar" nav item became "Rolex at Paul Medawar Fine Jewelry" (label
   parity with the legacy nav + Rolex's own retailer-name convention), which
   widens the row -- the old ~1315-1320px fit-point no longer applies. Live
   binary-search against the real content (plaque 120 + 50px gap + 9
   Fixed16 items incl. the new longer label + 2.5vw gaps), forcing the nav
   flex row to render at full width at each candidate viewport (bypassing
   the disclosure media query purely for measurement, via a temporary
   override stylesheet -- not a JS simulation of the layout), found the row
   first fits with zero overflow at exactly 1429px (1428px still overflowed
   by 1px) AT FIXED16. This 1429px number is why Fixed16 is gated to
   >=1500px below (col4/Large tier, spec-true) rather than applying all the
   way down to the disclosure breakpoint -- 1500px carries a safe ~70px
   margin above it.

   RE-MEASURED AGAIN (user decision, 2026-08-19): 1440x900 (a common laptop
   width) fit at Fixed16 with only ~11px of raw margin under the 1429px
   onset above -- not enough to also carry the original ~30px cross-browser
   safety margin, which is why the very first pass of this fix (2026-08-18,
   see above) pushed the breakpoint to 1460px and let 1440 fall into
   Menu-toggle mode. The user then asked for 1440 to keep the full row
   instead. DELIBERATE SPEC DEVIATION: below 1500px, the 9 nav items now
   render at Fixed14 (14px, `--rlx-fixed14` -- an EXISTING spec token, not
   an invented size) instead of the spec's Fixed16 for the section nav --
   narrower text needs less width, which is the whole point. This is a
   conscious drift from the Navigation elements spec (p12 gives Fixed16 for
   both Large AND Medium), made on the user's explicit instruction to keep
   1440x900 on the full single-line row rather than the Menu-toggle -- flag
   this as an intentional decision, not an unnoticed regression, on any
   future design-specs audit pass.
   Re-measured the fit-point at Fixed14 with the SAME live binary-search
   technique (real nowrap CSS, real viewport resizes, not simulated), gap
   left UNCHANGED at 2.5vw (type-only tried first, per instruction): the row
   first fits with zero overflow at exactly 1262px (1261px still overflowed
   by 1px). Type-only was sufficient -- 1262px clears 1366px by 104px, so no
   gap-tightening was needed. Breakpoint moved 1460px -> 1290px -- ~28px of
   margin above the 1262px onset, the same ~30px-margin philosophy as
   both earlier numbers, for the same cross-browser font-rendering
   variance reason.
   RESULT: 1366x768, 1440x900, 1500x900 and 1920x1080 all now show the full,
   single-line nav (1366/1440/1500 at Fixed14; 1920, and everything
   >=1500px, at spec-true Fixed16) -- live-verified, no wrapping at any of
   the four -- see nav-consistency-report.md. Only viewports <=1290px show
   the Menu-toggle, which still roughly lines up with the spec's own
   Medium-breakpoint diagram (p12: Menu toggle, not the 9-item row) even
   though the exact boundary is now an implementer choice rather than a
   spec-matched one.
   DELIBERATELY scoped to ONLY the toggle/nav-visibility/flex-wrap
   mechanism, not the whole former single breakpoint: --rlx-sticky-top,
   the 80px header height, and the 100x50px plaque are Small-breakpoint-
   SPECIFIC spec numbers (p12) that do NOT apply to Medium (Medium's own
   plaque is 120x60, same as Large) -- moving them here too would wrongly
   shrink the plaque/header across 991-1290px, which the spec never asks
   for. Those three stay on the original 990px boundary below. The mobile
   breadcrumb back-link swap (previous pass) also stays at 990px: the full
   crumb trail has no wrapping problem in the 991-1290px range (live-
   confirmed, see report), so there is no functional reason to move it. */
/* NAV BAND BREAKPOINTS RECALCULATED 2026-09-17, when --rlx-container-inset
   became Rolex's 8% rather than a fixed 48px and the well lost ~180px at
   every laptop width. The three bounds below were tuned on 2026-08-25
   against the OLD well and each sat inside an overflow zone afterwards;
   measured overflow at 1400-1450 and again at 1600-1700.

   The plaque is PINNED, so it offsets where the nav starts but the nav may
   spill into the page margin; what actually overflows is the nav's right
   edge against the VIEWPORT, not against the container. Modelled from live
   measurements at eleven widths (nav width is fluid, ~0.2 x viewport):
       Fixed16 + 50px gap fits from ~1722  -> band starts 1750
       Fixed14 + 24px gap fits from ~1500  -> band is 1500-1749
       below that the row cannot fit at all -> disclosure (burger)

   THEN RESTORED to 1399 / 1400-1599 / 1600+ on 2026-09-18, when the nav's
   longest label was shortened ("Rolex at Paul Medawar Fine Jewelry" ->
   "Rolex at Paul Medawar", RLX_Shell::nav_items). That removed ~90px at
   Fixed14 and ~105px at Fixed16 — enough for the row to clear the viewport
   at the original bounds again, which is what keeps the 2026-08-19
   instruction (1440x900 shows the full single line) true alongside the 8%
   gutter. Re-verified by sweep: no horizontal overflow at any width. */
@media (max-width: 1399px) {
	/* Upper bound moved 1290 -> 1399 (2026-08-25); briefly 1499 under the 8%
	   gutter, back to 1399 once the label shortened (see the note above):
	   with the plaque pinned to
	   its spec 120px, the full 9-item row no longer fits below 1400px without
	   horizontal overflow. It previously "fit" only by crushing the plaque.
	   row-gap:0 is deliberate and load-bearing, not decorative: the header
	   row's own `gap:50px` (plaque->nav floor, Large breakpoint, above) is
	   a SHORTHAND -- once flex-wrap:wrap is active it also becomes a
	   50px ROW-gap between the wrapped toggle row and the open nav list,
	   an accidental side-effect discovered while live-measuring the
	   open-state spacing fix below (63px toggle-to-first-item traced back
	   to this, not to the link's own box model). column-gap (plaque<->
	   toggle spacing) is untouched -- only the wrap-created row-gap is
	   zeroed, since the open state's own margin-top below now owns that
	   spacing instead. */
	body.rolex-section .rlx-band-header__inner { flex-wrap: wrap; row-gap: 0; }
	body.rolex-section .rlx-band-nav-toggle { display: inline-flex; }
	body.rolex-section .rlx-band-nav { display: none; }
	/* flex-basis/width: 100% used to live here, to make the open list wrap
	   onto its own flex line. That IS the bug fixed below (the wrap grew the
	   header row and displaced the page), and the panel rule now sets
	   position/left/right/width itself -- so these two were dead
	   declarations that still read like the layout mechanism. Removed. */
	body.rolex-section .rlx-band-nav.is-open { display: block; }
	body.rolex-section .rlx-band-nav.is-open li { width: 100%; }
	/* THE OPEN LIST OVERLAYS THE PAGE. IT DOES NOT PUSH IT (2026-09-21,
	   client report: "the .rlx-band-header__inner is being pushed up ... the
	   rolex plaque is pushed to the bottom of the sticky header ... the
	   mobile nav is pushing the page content down and the breadcrumb is
	   displaying at the bottom of the open mobile nav").

	   All three symptoms were ONE cause. The open list was a wrapped flex
	   item (flex-basis: 100%) inside .rlx-band-header__inner, so opening it
	   grew the inner from 80px to 652px. Measured at 390 before this fix:
	   the plaque moved from y85-135 (centred in the 80px row) to y70-120
	   (flush to the top, because align-items: center now centres it against
	   a 652px row and the flex line it sits on is only the toggle's height);
	   the crumb row moved from y150 to y722, i.e. to the BOTTOM of the open
	   list; and .rlx-main moved from y180 to y752 -- 572px of page content
	   displaced by opening a menu.

	   Taking the list out of flow fixes all three at once, and matches the
	   spec's own Small-breakpoint open state (p14), which draws the plaque
	   row at its normal height with the list on the green below it.

	   top is a TOKEN, not 100%: the containing block is .rlx-band-header
	   (sticky, so already a positioning context) and 100% of that is BELOW
	   the crumb row. --rlx-band-row is the inner's own min-height -- 110px
	   through this whole collapsed range, 80px at <=990 -- so the panel
	   starts exactly where the plaque row ends and covers the crumb row
	   while open, which is what the spec's open state shows (it draws no
	   crumb row at all) and what stops the crumbs appearing under the list.

	   THE WHOLE COLLAPSED RANGE, not just phones. The report was about
	   mobile, but the toggle appears from 1399px down and the wrapped-flex
	   push was identical at every width below that -- iPad landscape
	   included. Fixing only <=990 would have left the same bug live on the
	   tier above it.

	   padding-inline restates .rlx-container's own sizing rather than a
	   literal 27px: the panel is full-bleed so its background is the band's,
	   but its links must still line up with the plaque above them. Same
	   expression .rlx-banner__controls uses for the same reason.

	   max-height + overflow-y: nine items at Fixed22 with 35px between them
	   is ~600px, which does not fit under the bar on a short phone. */
	body.rolex-section .rlx-band-nav.is-open {
		position: absolute;
		top: var(--rlx-band-row, 110px);
		left: 0;
		right: 0;
		width: auto;
		/* z-index 1, and it is NOT decorative. The crumb row sits under this
		   panel and is entirely static, so a positioned element at
		   z-index:auto should paint over it -- except .rlx-crumbs__back's
		   chevron carries transform: scaleX(-1) to point left, and a
		   transform creates a stacking context, which promotes that icon to
		   paint like z-index:0. Without this the back arrow showed THROUGH
		   the green, floating over "Discover Rolex". */
		z-index: 1;
		background: linear-gradient(90deg, #0b3e27, #197149);
		padding-inline: calc((100% - min(var(--rlx-container-max), 100% - var(--rlx-container-inset))) / 2);
		/* The spec's 40px from the TOGGLE ROW to "Discover Rolex" (p14's
		   dimensioned diagram) is now the panel's own padding-top, tuned per
		   tier below, because the toggle is vertically centred in the row and
		   a taller row leaves more empty space under it before the panel
		   starts. This replaces the old margin on the first <li>, which was
		   tuned against the wrapped-flex geometry that no longer exists. */
		padding-bottom: 40px;
		max-height: calc(100vh - var(--rlx-sticky-top, 75px) - var(--rlx-band-row, 110px));
		overflow-y: auto;
		overscroll-behavior: contain;
	}
	/* The 40px toggle-row-to-first-item gap (spec p14) is now the panel's own
	   padding-top, not a margin on the first <li>. It used to be 27px, tuned
	   against the empty space left under the vertically-centred toggle in the
	   wrapped flex line; with the panel out of flow that leftover space no
	   longer exists, so the same 27 would have measured short. Re-derived
	   live below. */
	body.rolex-section .rlx-band-nav.is-open li:first-child { margin-top: 0; }

	/* Open-state typography (spec p14/p18, "Open state specifications" --
	   Medium AND Small breakpoints both give Fixed22, Default White,
	   Hover/Current Ocean green, on the Navigation gradient background).
	   Fixed22 was flagged NOT BUILT in design-specs audit §0.4; the
	   color/background parts were already correct (band bg + the
	   hover/current rule above now covers this too -- this rule only needs
	   to bump the font-size for the expanded list). */
	body.rolex-section .rlx-band-nav.is-open .rlx-band-nav__link {
		display: block;
		font-size: var(--rlx-fixed22);
		padding-block: 0;
	}
	/* Open-state spacing (batch review fix, spec p14 dimensioned diagram,
	   re-read directly: 40px from the toggle row to "Discover Rolex", 35px
	   between every subsequent row). Was a single padding-block:10px on
	   every link, conflating row HEIGHT with row GAP -- measured live at
	   63px to the first item / 53px row-to-row (line-height 30.8px + 10+10
	   padding), nowhere near spec. Row-to-row is now a pure margin between
	   <li>s (independent of font metrics) and is IDENTICAL at every width
	   in this breakpoint (live-confirmed 35px at both 390px and 1100px --
	   it doesn't depend on the toggle row's own height). The toggle-row gap
	   is a DIFFERENT story: it's margin-top on the first <li> alone, and
	   that one DOES depend on the toggle row's height, because the toggle
	   is vertically centered (align-items:center) inside a row whose
	   min-height differs by tier (110px above 990px, still Large's height
	   since this block deliberately doesn't touch it; 80px at/below 990px,
	   Small's height) -- a taller row centers the toggle with more empty
	   space below it before the flex-wrap point, so the SAME margin-top
	   produced 40px at 390px but 45px at 1100px (live-measured). Split
	   below per sub-range so both land on the exact 40px spec number
	   rather than accepting a several-px drift between them. */
	body.rolex-section .rlx-band-nav.is-open li + li { margin-top: 35px; }
}
@media (min-width: 991px) and (max-width: 1399px) {
	/* 991-1290px sub-range (upper bound moved with the disclosure
	   breakpoint above, 2026-08-19): nav is collapsed (rule above) but the header
	   row is still Large's 110px height (untouched -- Medium's plaque/
	   height match Large, see the big comment above), so the toggle sits
	   centered higher/lower than at <=990px and needs its own margin-top
	   to hit the same 40px gap. */
	/* 110px row: the toggle is centred in it, so 43px of empty space is
	   already below the toggle by the time the panel starts -- 3px MORE than
	   the spec's 40, which no padding-top can take back. A -3px margin on the
	   panel does, and is measured, not guessed (live: 43 -> 40 at 1100).
	   The <=990 tier is the other way round, 28px, and pays the difference in
	   padding-top instead. Same 40px target both sides, same split the old
	   22/27 first-child margins made for the same reason. */
	body.rolex-section .rlx-band-nav.is-open { margin-top: -3px; padding-top: 0; }
}
@media (max-width: 990px) {
	body.rolex-section { --rlx-sticky-top: 70px; } /* live-measured fixed nav height at this breakpoint */
	body.rolex-section { --rlx-band-row: 80px; } /* the open panel starts here; same number as the min-height below */
	body.rolex-section .rlx-band-nav.is-open { margin-top: 0; padding-top: 12px; } /* 80px row leaves 28px under the centred toggle; 28 + 12 = the spec's 40 */
	/* FULL HEIGHT ON PHONES (2026-09-21, client). The panel used to be as
	   tall as its nine items and stopped there, leaving a strip of page
	   content visible under it; it now runs from the plaque row to the
	   bottom of the viewport, which is also how the spec's Small open state
	   draws it (p14: the green fills to the bottom of the frame).

	   height, not min-height: with overflow-y: auto already set, a fixed
	   height is what makes the panel scroll INSIDE itself on a short phone
	   instead of growing past the viewport.

	   100dvh first, 100vh as the fallback for browsers without dynamic
	   viewport units: on iOS Safari 100vh is the ADDRESS-BAR-HIDDEN height,
	   so a vh-only panel is taller than the visible viewport whenever the
	   bar is showing and its last item sits under it.

	   Scoped to <=990. The 991-1399 tier still collapses to a toggle, but
	   the spec's Medium open state does not run the panel to the bottom and
	   the report was about phones. */
	body.rolex-section .rlx-band-nav.is-open {
		height: calc(100vh - var(--rlx-sticky-top, 70px) - var(--rlx-band-row, 80px));
		height: calc(100dvh - var(--rlx-sticky-top, 70px) - var(--rlx-band-row, 80px));
		max-height: none;
	}
	body.rolex-section .rlx-band-header__inner { min-height: 80px; } /* Small breakpoint header height, spec p12 */
	body.rolex-section .rlx-plaque img { width: 100px; height: 50px; } /* Small breakpoint plaque, spec p12 */
}

/* Mid-tier nav type (user decision, 2026-08-19) -- see the big disclosure
   comment above for the full re-measurement narrative. DELIBERATE SPEC
   DEVIATION: the spec's Navigation elements page (p12) gives Fixed16 for
   the section nav at BOTH the Large and Medium breakpoints; from 1291px up
   to 1499px this instead renders the nav links at Fixed14
   (`--rlx-fixed14`, an existing spec token reused here, not an invented
   size), on the user's explicit instruction, so that 1440x900 (a common
   laptop width) keeps the full single-line row instead of falling into the
   Menu-toggle. Fixed16 (`.rlx-fixed16`'s own base rule, above) still
   applies untouched at >=1500px -- the spec-true Large tier. A future
   design-specs-style audit should read this comment as the documented
   REASON for the delta, not flag it as unnoticed drift.
   Bounded explicitly to 1291-1499px (not a bare `max-width: 1499px`) so the
   range this deviation covers is unambiguous in the source; the upper
   bound of the disclosure breakpoint above (1290px, where `.rlx-band-nav`
   is `display:none`) makes 1291px the first pixel the full row is ever
   visible at. Targets `.rlx-band-nav__link.rlx-fixed16` (both classes, not
   just `.rlx-fixed16`) so this rule's specificity (0,3,1) only affects the
   nav link and never the OTHER `.rlx-fixed16` consumers in this file
   (`.rlx-push__kicker`, the contact form controls) -- deliberately not a
   `--rlx-fixed16` token override, which would have shrunk all of those too.
   The open (mobile-disclosure) state's own Fixed22 override
   (`.rlx-band-nav.is-open .rlx-band-nav__link`, specificity (0,4,1), higher
   than this rule's) still wins whenever the nav is open, unaffected. */
@media (min-width: 1400px) and (max-width: 1599px) {
	/* Band is 1400-1599 again as of 2026-09-18 — it went to 1500-1749 for a
	   day under the 8% gutter, and came back when the retailer label was
	   shortened. Fixed14 is what makes the full row fit here; Fixed16
	   resumes at 1600. */
	body.rolex-section .rlx-band-nav__link.rlx-fixed16 { font-size: var(--rlx-fixed14); }
	body.rolex-section .rlx-band-header__inner { gap: 24px; }
}

/* Nav-consistency fix (feat/rolex-nav-consistency, 2026-08-18): the four
   retained legacy-builder pages (watchmaking, servicing, servicing-
   procedure, oyster-story) now get OUR band prepended ahead of their own
   post_content (see RLX_Shell::maybe_prepend_band_for_retained_pages), but
   their post_content itself is untouched — Rolex-approved builder content,
   never edited for this fix — so it still carries the OLD Bespoke-Lite
   green nav (`section.wtp-rlx-hybrid-header`) and its own breadcrumb row
   (`section.wtp-rlx-bc-wrapper`) right below ours. Hidden here, scoped to
   the `body.rlx-retained-legacy-page` class functions.php's add_body_class()
   adds ONLY on these four IDs (RLX_Shell::is_retained_legacy_page()) —
   DELIBERATELY not a bare `.wtp-rlx-hybrid-header`/`.wtp-rlx-bc-wrapper`
   selector: a DB query (`wp db query "SELECT ID FROM wp_posts WHERE
   post_content LIKE '%wtp-rlx-hybrid-header%'"`) turned up 40 published
   pages carrying these same classes, most of them legacy family pages
   (datejust, day-date, etc.) that are NOT part of this fix and still
   render their own nav via this exact markup — a global hide would have
   blanked their nav entirely.
   The hybrid-header row is targeted by ID (`#hybird_header`, the same
   literal id="hybird_header" all four pages' WPBakery rows carry — verified
   live via `wp db query`), not by its `.wtp-rlx-hybrid-header` class:
   bespoke-light.css (a pre-existing stylesheet this fix does not touch)
   carries `body.rolex-section #hybird_header { display: flex; }` — an
   ID selector, specificity (1,1,1) — which silently WON against a
   class-only `body.rolex-section.rlx-retained-legacy-page
   .wtp-rlx-hybrid-header` rule, specificity (0,3,1) (confirmed live: the
   row stayed visible). Matching bespoke-light.css's own ID selector, with
   one extra scoping class, gives specificity (1,2,1) — beats theirs on
   class count once the ID tier ties, cascade order no longer matters. The
   breadcrumb row has no id in the builder markup and hides correctly via
   its class alone (no competing ID rule exists for it). */
body.rolex-section.rlx-retained-legacy-page #hybird_header,
body.rolex-section.rlx-retained-legacy-page .wtp-rlx-bc-wrapper {
	display: none;
}

/* Design feedback (2026-08-17): moved INSIDE the green band (see
   band-header.php) as a second row below the plaque/nav row — was
   previously a light-background row below the band, hence the color
   updates here (was relying on inherited dark ink text + the theme's
   default link color; both are wrong against the green field now). */
/* Breadcrumb (Navigation elements, spec p15 "Specifications" — confirmed
   both Large AND Small breakpoints, identical values): row height 30px,
   Fixed14 (already correct — unchanged), Current: Ocean green / Previous:
   White, separator a 10x10px icon. Row was previously padding-driven
   (~10px+14px+text ≈ 38-44px, a DELTA); now a flex row with a literal
   30px min-height, vertically centering the Fixed14 content to hit the
   spec number exactly. */
body.rolex-section .rlx-crumbs {
	font-size: var(--rlx-fixed14);
	color: #fff;
	display: flex;
	align-items: center;
	min-height: 30px;
}
/* Current: Ocean green (spec p15) — was opacity:0.75 on white (a dimmed
   white, not Ocean green at all); design-specs audit §1.2 flagged this
   exact DELTA ("visually similar via opacity, wrong mechanism/color"). */
body.rolex-section .rlx-crumbs [aria-current="page"] { color: var(--rlx-green-ocean); }
body.rolex-section .rlx-crumbs ol {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	flex-wrap: wrap;
	gap: 4px;
}
/* Separator: spec p15 shows a 10x10px icon between crumbs (not a text
   glyph). Implemented as a CSS mask of the same sprite's #rlx-arrow path
   (assets/img/rolex-icons.svg — the theme's existing chevron, reused
   rather than re-derived) so the true icon renders at the exact spec size
   with no markup change: `mask` + `background: currentColor` recolors an
   arbitrary SVG shape via CSS alone. Kept at reduced opacity (0.7, an
   implementer choice carried over from the previous text-glyph rule, not
   a spec value — the spec's own diagram doesn't give the separator's
   opacity) so it reads as a subdued divider rather than a third crumb. */
body.rolex-section .rlx-crumbs li + li::before {
	content: "";
	display: inline-block;
	width: 10px;
	height: 10px;
	margin-inline: 4px;
	background: currentColor;
	opacity: 0.7;
	vertical-align: middle;
	-webkit-mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 15 15'><path d='M12,7.5l-1.3,1.4L4.6,15l-1.5-1.5l6.1-6.1L3,1.4L4.5,0l6.1,6.1l0,0L12,7.5z'/></svg>") center / contain no-repeat;
	mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 15 15'><path d='M12,7.5l-1.3,1.4L4.6,15l-1.5-1.5l6.1-6.1L3,1.4L4.5,0l6.1,6.1l0,0L12,7.5z'/></svg>") center / contain no-repeat;
}
/* Mobile breadcrumb collapse (Navigation elements, spec p15, Small
   breakpoint): the spec's mockup shows a single "< [Previous page]"
   back-link, not the full crumb trail — a real deviation disclosed in the
   earlier pass of this file (band-spec-report.md, "Assumptions" #2):
   deep-page rows were hitting 79px on mobile against the spec's flat 30px
   figure (p15 states the SAME 30px for both Large and Small breakpoints).
   Approach: band-header.php now renders BOTH the back-link anchor
   (.rlx-crumbs__back, server-computed from the existing $crumbs array —
   no JS) and the untouched full <ol> trail; only one is ever visible per
   breakpoint via this CSS swap, same pattern as the nav disclosure toggle
   above (display:none / display:flex pair, no interaction-mechanism
   change). Desktop is completely unaffected — the <ol> stays exactly as
   it was. Root/1-crumb pages never get a .rlx-crumbs__back element in the
   markup at all (band-header.php), so on those pages this rule simply
   shows nothing — an empty but still min-height:30px row — rather than a
   self-link. */
body.rolex-section .rlx-crumbs__back {
	display: none;
	align-items: center;
	gap: 6px;
	color: #fff;
}
/* Reuses the SAME right-pointing #rlx-arrow source glyph as the crumb
   separator above (and .rlx-lightbox__arrow--prev below, in this file's
   established "flip the one shipped arrow via scaleX(-1)" pattern) rather
   than adding a second sprite symbol for a mirror-image shape. Sized to
   match the separator (10x10px) for visual consistency — the spec's
   diagram gives the back-link's icon+label pairing but no explicit icon
   size of its own, so this is an implementer choice, not a spec number. */
body.rolex-section .rlx-crumbs__back .rlx-icon {
	width: 10px;
	height: 10px;
	transform: scaleX(-1);
}
@media (max-width: 990px) {
	body.rolex-section .rlx-crumbs__back { display: inline-flex; }
	body.rolex-section .rlx-crumbs ol { display: none; }
}
body.rolex-section .rlx-band-footer {
	text-align: center;
	padding-block: var(--rlx-gap-half);
}
body.rolex-section .rlx-band-footer .rlx-backtotop {
	display: inline-flex;
	flex-direction: column;
	align-items: center;
	gap: 4px;
	font-size: var(--rlx-legend16);
	background: none;
	border: 0;
	color: #fff;
	cursor: pointer;
}
/* "BACK TO TOP" LABEL WAS DARK (2026-09-09, reported against
   https://staging.shopmedawar.com/rolex/ — "the back to top text needs to be
   the approved white color"). The button above already declares #fff and the
   glyph inherited it, but the LABEL did not: .rlx-legend16 is a TYPOGRAPHY
   utility that also carries `color: var(--rlx-ink)` (grouped with
   .rlx-fixed16/14/22 near the top of this file), and at (0,2,1) it beat the
   button's inherited colour on the span. So the arrow rendered white and the
   words rendered #212121 on the band's #0B3E27→#197149 gradient — measured
   1.29:1, far under WCAG's 4.5:1, i.e. an accessibility failure and not only
   a visual one.
   Fixed by making the label inherit the control's own colour rather than by
   stripping `color` off the shared type utility, which would silently
   restyle every .rlx-fixed / .rlx-legend16 consumer on light surfaces. */
body.rolex-section .rlx-band-footer .rlx-backtotop .rlx-legend16 { color: inherit; }

/* ---- push banner --------------------------------------------------------- */
body.rolex-section .rlx-push__media img { display: block; width: 100%; height: auto; }
body.rolex-section .rlx-push__kicker { font-size: var(--rlx-fixed16); margin-block: 12px 4px; }
body.rolex-section .rlx-push__title { margin: 0 0 8px; }

/* ---- keep exploring ------------------------------------------------------- */
body.rolex-section .rlx-keep {
	background: var(--rlx-surface);
	padding-block: var(--rlx-gap);
}
body.rolex-section .rlx-keep__row {
	display: grid;
	grid-auto-flow: column;
	/* Mobile shows exactly TWO tiles and no peek of a third: comp tiles are
	   332 device / 166 CSS with an 8 device / 4 CSS gutter, filling the 672
	   well. minmax(260px, 1fr) showed 1.3 tiles. The 4px gutter is genuinely
	   narrower than the card grid's 6 -- it reads 332/8 in six comps, and
	   the hub tiles beside them read a clean 330/12, so it is not edge
	   anti-aliasing. */
	grid-auto-columns: calc((100% - var(--rlx-keep-gap)) / 2);
	gap: var(--rlx-keep-gap);
	overflow-x: auto;
	scroll-snap-type: x mandatory;
	scrollbar-width: none;
	margin-top: 24px;
}
@media (min-width: 768px) {
	body.rolex-section .rlx-keep__row {
		grid-auto-columns: calc((100% - 3 * var(--rlx-keep-gap)) / 4);
	}
}
body.rolex-section .rlx-keep__row::-webkit-scrollbar { display: none; }
body.rolex-section .rlx-keep__card {
	scroll-snap-align: start;
	text-decoration: none;
	color: var(--rlx-ink);
}
/* NO forced ratio. Every keep-exploring delivery is 3:2 — 600x400, 1200x800,
   780x520 — and every comp renders the card at 400x266 = 1.504, uncropped.
   The 4/3 box cover-cropped ~11% off the width of every card on every page
   in the section. Same defect as the hero cover, one component along.
   Uniform sources, so removing the box cannot make a row ragged: measured
   1.500 on every card across /rolex/, /rolex/watches/,
   /rolex/watches-selection/, /rolex/datejust/, /rolex/accessories/ and
   /rolex/new-watches/, at both breakpoints. */
body.rolex-section .rlx-keep__card img { display: block; width: 100%; height: auto; }
body.rolex-section .rlx-keep__caption { font-size: var(--rlx-body20); margin-top: 8px; color: var(--rlx-brown); }

/* THE CURRENT PAGE'S CARD (2026-09-10, on instruction: "all three rows").
   Every one of these rows now carries a card pointing at the page the
   visitor is already on — /rolex/ shows a "Discover Rolex" card,
   /rolex/datejust/ a "Datejust" card — because the client asked for every
   delivered image on every page. Until now that card looked exactly like
   the four that go somewhere. Rolex's New watches comps show the current
   card's caption in the brand green, and this is that treatment applied to
   the generic and family rows too, so the marking is consistent everywhere
   a self card appears rather than only on five pages.

   --rlx-green (#127749) is 5.58:1 on --rlx-surface and 5.22:1 on --rlx-bg,
   both clear of the 4.5:1 body-text floor. Not colour-alone: the template
   emits aria-current="page" and drops the href on this card. */
body.rolex-section .rlx-keep__card--current .rlx-keep__caption { color: var(--rlx-green); }
/* PROGRESS DASHES. All three comps that show this row -- Discover, the
   collection pages and the accessory model pages -- put a centred dash track
   under the tiles, one long green dash for the current page and shorter grey
   ones beside it. We rendered none. Geometry mirrors .rlx-nw-keep__dash
   exactly rather than inventing a second treatment. */
body.rolex-section .rlx-keep__dots,
body.rolex-section .rlx-hub__dots,
body.rolex-section .rlx-ed-carousel__dots {
	display: flex;
	justify-content: center;
	align-items: center;
	gap: 8px;
	margin-top: 24px;
}
body.rolex-section .rlx-keep__dash,
body.rolex-section .rlx-hub__dash,
body.rolex-section .rlx-ed-carousel__dash {
	appearance: none;
	-webkit-appearance: none;
	border: 0;
	background: none;
	padding: 0;
	width: 24px;
	height: 24px;
	display: grid;
	place-items: center;
	cursor: pointer;
	transition: width 200ms ease;
}
/* THE BAR MOVES WITH ITS SLOT (2026-09-29, animation audit). Only the button's
   width was transitioned, so the visible bar snapped 24 <-> 50px on one frame
   while the slot took ~150ms to follow: the new green bar overflowed its slot
   and the neighbours slid under it. Same property, duration and curve as the
   slot, so the two move as one; the Discover banner dash already transitions
   its ::before the same way. */
body.rolex-section .rlx-keep__dash::before,
body.rolex-section .rlx-hub__dash::before,
body.rolex-section .rlx-ed-carousel__dash::before {
	content: "";
	display: block;
	width: 24px;
	height: 4px;
	border-radius: var(--rlx-dash-radius);
	background: rgba(33, 33, 33, 0.5);
	transition: width 200ms ease, background-color 200ms ease;
}
body.rolex-section .rlx-keep__dash[aria-current="true"],
body.rolex-section .rlx-hub__dash[aria-current="true"],
body.rolex-section .rlx-ed-carousel__dash[aria-current="true"] { width: 50px; }
body.rolex-section .rlx-keep__dash[aria-current="true"]::before,
body.rolex-section .rlx-hub__dash[aria-current="true"]::before,
body.rolex-section .rlx-ed-carousel__dash[aria-current="true"]::before {
	width: 50px;
	background: var(--rlx-green);
}
@media (prefers-reduced-motion: reduce) {
	body.rolex-section .rlx-keep__dash,
	body.rolex-section .rlx-hub__dash,
	body.rolex-section .rlx-ed-carousel__dash,
	body.rolex-section .rlx-keep__dash::before,
	body.rolex-section .rlx-hub__dash::before,
	body.rolex-section .rlx-ed-carousel__dash::before { transition: none; }
}
body.rolex-section .rlx-keep__nav {
	display: flex;
	gap: 8px;
	/* RIGHT-ALIGNED, which is also what Rolex's own Discover comp
	   (discover-rolex-with-grid-mockup-desktop.jpg) shows for this row.
	   Briefly centred earlier on 2026-09-09 when "the chevrons need to be
	   centered" was read as horizontal placement; the user clarified the
	   same day that the row stays right and it was the GLYPH that needed
	   centring inside the button — see the flex rule on the three arrow
	   primitives below. Do not re-centre this row. */
	justify-content: flex-end;
}
body.rolex-section .rlx-keep__arrow {
	width: 40px;
	height: 40px;
	border-radius: 50%;
	border: 1px solid rgba(33, 33, 33, 0.2);
	background: var(--rlx-surface);
	cursor: pointer;
}
body.rolex-section .rlx-keep__arrow[disabled] { visibility: hidden; }

/* ---- availability block ----------------------------------------------------- */
body.rolex-section .rlx-availability {
	background: var(--rlx-panel); /* was #F0EEE9 — a near-miss for the spec's
	   #F4EFEA, which --rlx-panel already held. Corrected 2026-08-25 after the
	   Tappers Bespoke reference rendered rgb(244,239,234) here. */
	text-align: center;
	/* Longhand (was the `padding` shorthand): the P1 reset above competes
	   on padding-block specifically (it's excluded via :not() there too,
	   belt-and-suspenders), so stating this rule on the same physical
	   longhand property keeps intent explicit rather than relying on
	   shorthand-vs-longhand equivalence. */
	padding-block: var(--rlx-gap);
	padding-inline: 24px;
}
/* THE CORONET IS NOT SQUARE AND IS NOT 28px.
   Measured on the model-page comp: 59 x 66 (x931-989, y6281-6346). The
   #rlx-crown symbol's own viewBox is 456.6 x 494.7 = 0.923, so 61 x 66 is
   both the comp's height and the artwork's true proportion; 28 x 28 was
   less than half size AND squashed a taller-than-wide glyph into a square.
   Scoped to the crown so any other icon in this panel keeps its own size. */
body.rolex-section .rlx-availability .rlx-icon { width: 28px; height: 28px; }
body.rolex-section .rlx-availability .rlx-icon--crown { width: 61px; height: 66px; }
/* 60px BELOW THE CROWN (2026-09-19). Rolex's Model availability spec (p77)
   marks 60px between the coronet and the Headline50, and the model-page
   mockup agrees: the crown bottoms at y6345 and the headline's box starts
   about y6402. We rendered EIGHT -- the h2's own default margin and nothing
   else -- so the coronet sat almost on the heading.

   The gap lives on the crown and the headline's top margin is zeroed, so the
   two cannot add up to something neither of them states. The crown becomes a
   block to carry a bottom margin at all; `margin-inline: auto` keeps it
   centred exactly as `text-align: center` did. */
body.rolex-section .rlx-availability .rlx-icon--crown { display: block; margin: 0 auto 60px; }
body.rolex-section .rlx-availability .rlx-headline50 { margin-top: 0; }
/* Design-specs audit §1.6 (2026-08-17): spec's Model availability headline
   is Brown, not Black/--rlx-ink (the default every .rlx-headline50 inherits
   site-wide). Scoped to this component only — never a global
   .rlx-headline50 recolour, which would over-apply Brown to unrelated
   Headline50 usages the spec doesn't call Brown (Quote50's own subheading,
   collection-intro titles, etc.). */
body.rolex-section .rlx-availability .rlx-headline50 { color: var(--rlx-brown); }

/* ---- accordion (shared: model spec/contact blocks consume in B) --------------
   DIVIDER AND ICON FOLLOW THE SPEC (2026-09-19). Rolex's Watch key selling
   points, p71, annotates the accordion rows "1px line Brown Opacity20%" and
   "Icon 12x12px Brown".

   The divider was `rgba(33, 33, 33, 0.15)` -- INK at 15%, not brown at 20%.
   That also made this file internally inconsistent: `.rlx-specs__rule` and
   `.rlx-rail__item` already drew the same Rolex divider as brown at 20%, so
   three renderings of one treatment disagreed. They agree now.

   The icon had no size here and fell back to the 22px `.rlx-icon` base.
   `.rlx-rail` had already overridden it to 12px for the same control, so
   that rule is now redundant rather than load-bearing -- it stays only
   because removing it changes nothing and its comment explains the rail. */
body.rolex-section .rlx-accordion__item { border-top: 1px solid rgba(69, 44, 30, 0.2); }
body.rolex-section .rlx-accordion__button .rlx-icon { width: 12px; height: 12px; color: var(--rlx-brown); }
body.rolex-section .rlx-accordion__button {
	display: flex;
	width: 100%;
	align-items: center;
	justify-content: space-between;
	background: none;
	border: 0;
	font-family: var(--rlx-font-sans);
	font-size: var(--rlx-body24);
	color: var(--rlx-ink);
	padding-block: 16px;
	cursor: pointer;
	text-align: left;
}
body.rolex-section .rlx-accordion__panel[hidden] { display: none; }

/* ---- icons ---------------------------------------------------------------------
   FIX 2 (final-review fix wave): .rlx-icon carried no base size, so the
   inline <svg> fell back to its intrinsic 300×150 default in every context —
   on a 390px viewport that alone pushed document.scrollWidth to 633px. Give
   every icon a sane 1em default, then size each context explicitly (the
   token annotations from the mockup review: plaque crown ~40px, availability
   crown 28px, CTA arrows 14px, carousel arrows 16px, footer crown 40px,
   back-to-top 20px). */
body.rolex-section .rlx-icon {
	width: 1em;
	height: 1em;
	fill: currentColor;
	flex: none;
}

body.rolex-section .rlx-cta-primary .rlx-icon,
body.rolex-section .rlx-cta-secondary .rlx-icon,
/* SUPERSEDED 2026-09-14: the icon is now a 36px circle with 11px of padding,
   which leaves the glyph itself at 14px -- the same size this rule set, now
   expressed as the circle's inner box rather than the element's outer one. */

body.rolex-section .rlx-keep__arrow .rlx-icon { width: 16px; height: 16px; }
/* The New watches keep row's arrows need this too. Without it the inline SVG
   fell back to its intrinsic 14px while .rlx-keep, .rlx-hub and
   .rlx-ed-carousel all declare 16px — measured at 14px on 2026-09-10, before
   this rule existed. The four carousels are meant to be the same control. */
body.rolex-section .rlx-nw-keep__arrow .rlx-icon { width: 16px; height: 16px; }

body.rolex-section .rlx-band-footer > .rlx-icon { width: 40px; height: 40px; }

body.rolex-section .rlx-backtotop .rlx-icon { width: 20px; height: 20px; }

/* The shipped source for the arrow glyph points right; rlx-icons.svg reuses
   that same geometry (verbatim, per source) for both #rlx-arrow and
   #rlx-back-to-top rather than shipping a distinct upward arrow. Rotate it
   here so the "back to top" control actually points up. (prev/next carousel
   rotation of #rlx-arrow itself is a separate, later concern.) Verified by
   rendering both the unrotated and rotated glyph before picking -90deg. */
body.rolex-section .rlx-icon--back-to-top { transform: rotate(-90deg); }

/* ---- a11y helpers ------------------------------------------------------------- */
body.rolex-section .rlx-visually-hidden {
	position: absolute;
	width: 1px;
	height: 1px;
	margin: -1px;
	padding: 0;
	overflow: hidden;
	clip: rect(0 0 0 0);
	white-space: nowrap;
	border: 0;
}

/* ---- focus-visible (Accessibility, spec p131-133 — design-specs audit
   §1.8/§5, 2026-08-17): the spec's Accessibility section is exclusively a
   focus-state visual reference and contains exactly one hard numeric
   value in the whole document — the dark-background ring below. Prior to
   this, ZERO :focus/:focus-visible rules existed anywhere in this file
   (live-verified: a focused accordion button computed `outline: none
   0px`) — a WCAG 2.4.7 exposure. Every selector here is scoped under
   body.rolex-section, never a bare element selector, per this branch's own
   rule (see the .rlx-band-nav comment above re: the legacy bare-<nav>
   trap in functions.php).

   Dark-background ring: THE one spec-mandated value in this section —
   2px solid #9BF9CE (Ocean green), 3px outline-offset — confirmed both by
   the audit and a direct re-read of the spec's own "Component - dark
   background" accessibility panel. Scoped to controls that render on the
   green band (nav links, the mobile nav disclosure toggle, back-to-top,
   and — batch review fix, MEDIUM — the breadcrumb row's own links: the
   crumb row moved INSIDE the green band in an earlier pass and this group
   was never extended to it, so Tab landed on .rlx-crumbs__back or a desktop
   crumb <a> with computed `outline: none 0px`, same WCAG 2.4.7 exposure
   this whole rule exists to close. Both the mobile back-link anchor AND
   the full trail's own <a>s are covered — the trail's crumb links render
   on this same dark band at every width, not just mobile).

   Light-background ring: NO LONGER AN IMPLEMENTER DEFAULT (2026-09-17).
   The note that stood here was right about the PDF — its "Examples" panel
   draws the light-bg outline but labels no hex or px for it, so
   2px solid var(--rlx-green) at 2px offset was a considered guess.
   The Brand Centre's DESIGN SPECIFICATIONS tab states it outright, in
   Accessibility > Structure and styles:

     component on a LIGHT background -- 2px border, Green   #127749
     component on a DARK  background -- 2px border, Ocean green #9BF9CE
     both with a 3px margin around the item.

   The guessed COLOUR was exactly right: var(--rlx-green) IS #127749. Only
   the offset was short, 2px against a specified 3px, and it is corrected
   below. The dark-bg rule above already used 3px and needed no change. */
body.rolex-section .rlx-band-nav__link:focus-visible,
body.rolex-section .rlx-band-nav-toggle:focus-visible,
body.rolex-section .rlx-band-footer .rlx-backtotop:focus-visible,
body.rolex-section .rlx-crumbs__back:focus-visible,
body.rolex-section .rlx-crumbs ol a:focus-visible {
	outline: 2px solid var(--rlx-green-ocean);
	outline-offset: 3px;
}
/* Lightbox round buttons (close/prev/next, design-specs audit §1.6):
   CORRECTED post-ship (fix round 1, 2026-08-17) -- the reasoning below
   this line described the ring reading against the BUTTON's dark fill,
   but outline-offset:3px paints the ring 3px OUTSIDE the button, on the
   popin's own Light-beige background (p69), not on the button itself.
   Live-measured: #9BF9CE on #F9F7F4 = 1.17:1, nowhere near WCAG's 3:1 for
   non-text UI indicators. var(--rlx-green) on that same beige measures
   ~5.2:1 -- swapped to that instead. #9BF9CE stays the dark-bg ring
   everywhere it actually rings a DARK surface (nav band, back-to-top);
   a ring drawn on the light-beige popin is a light-bg case, full stop --
   the buttons' own dark fill was never the deciding surface. Kept as its
   own rule rather than folded into the .rlx-cta-primary light-bg group
   below only because that group uses outline-offset:2px and the spec's
   3px offset is worth keeping distinct here; same colour choice either
   way. */
body.rolex-section .rlx-lightbox__close:focus-visible,
body.rolex-section .rlx-lightbox__arrow:focus-visible {
	outline: 2px solid var(--rlx-green);
	outline-offset: 3px;
}
body.rolex-section .rlx-cta-primary:focus-visible,
body.rolex-section .rlx-cta-secondary:focus-visible,
body.rolex-section .rlx-inline-link:focus-visible,
body.rolex-section .rlx-cta-tertiary:focus-visible,
body.rolex-section .rlx-card:focus-visible,
body.rolex-section .rlx-hub-tiles__tile:focus-visible,
body.rolex-section .rlx-nw-tiles__tile:focus-visible,
body.rolex-section .rlx-nw-keep__card:focus-visible,
body.rolex-section .rlx-keep__card:focus-visible,
body.rolex-section .rlx-ed-tile:focus-visible,
body.rolex-section .rlx-keep__arrow:focus-visible,
body.rolex-section .rlx-nw-keep__arrow:focus-visible,
body.rolex-section .rlx-nw-keep__dash:focus-visible,
body.rolex-section .rlx-hub__arrow:focus-visible,
body.rolex-section .rlx-ed-carousel__arrow:focus-visible,
body.rolex-section .rlx-accordion__button:focus-visible,
body.rolex-section .rlx-rail__toggle:focus-visible,
body.rolex-section .rlx-rail__close:focus-visible,
body.rolex-section .rlx-rail__reset-round:focus-visible,
body.rolex-section .rlx-rail__option input:focus-visible,
body.rolex-section .rlx-selection__sort select:focus-visible,
body.rolex-section .rlx-contact__form .wpcf7 input[type="text"]:focus-visible,
body.rolex-section .rlx-contact__form .wpcf7 input[type="email"]:focus-visible,
body.rolex-section .rlx-contact__form .wpcf7 select:focus-visible,
body.rolex-section .rlx-contact__form .wpcf7 textarea:focus-visible,
body.rolex-section .rlx-contact__form .wpcf7 input[type="submit"]:focus-visible,
body.rolex-section .rlx-contact__form .wpcf7 button[type="submit"]:focus-visible {
	outline: 2px solid var(--rlx-green);
	outline-offset: 3px;
	/* INSTANT, deliberately. The card hover ring gained a 150ms colour fade
	   (see the hover block far below); this indicator must not inherit it.
	   A keyboard user needs to know where focus went on the frame it moves,
	   not 150ms later. */
	transition: none;
}
/* THE PARENT THEME ANIMATES EVERY PROPERTY OF EVERY LINK (2026-09-29, animation
   audit). roneous/assets/css/theme.less:254 sets `a, a:focus { transition: all
   200ms cubic-bezier(0.785, 0.135, 0.15, 0.86) }` site-wide. Measured by tabbing
   on ddev: the section nav, breadcrumbs, plaque and promo/push media all faded
   their focus ring in over 200ms, and every hover started slowly (that curve is
   easeInOutCirc). The parent is never edited, so this scopes it here: only the
   colour properties Rolex hovers change (no Rolex link hover changes opacity,
   transform or size; the nav underline keeps its 2px width and only changes
   colour), at 150ms `ease`, the same as the card ring below. Focus on any link is
   instant, like the group above. The same parent sheet gives the sort select and
   the form's submit input `transition: all 0.3s ease-in-out`; same treatment. */
body.rolex-section a {
	transition: color 150ms ease, background-color 150ms ease, border-color 150ms ease, text-decoration-color 150ms ease;
}
body.rolex-section a:focus-visible { transition: none; }
body.rolex-section select,
body.rolex-section input[type="submit"] {
	transition: color 150ms ease, background-color 150ms ease, border-color 150ms ease;
}
/* FORM FIELD FOCUS IS DRAWN INSIDE THE FIELD, ON BOTH FORM PAGES
   (2026-09-24, Ernie on staging: "the focused field border ... is getting
   cut off on the right side, and it gets cut off on both sides if the input
   is 100% wide").

   Three wrappers around form 34401 hide overflow -- div.wpcf7, the form,
   and cf7mls's .fieldset-cf7mls-wrapper, which slides the steps -- and their
   edges sit exactly on the fields' (measured 357.5-1157.5 at 1515). A ring
   3px OUTSIDE the field therefore lost whichever side touched that edge:
   the right of Last name, both sides of Email. Offset -2px puts the same
   2px green ring inside the field's own box, where nothing can clip it,
   without touching the plugin's overflow.

   Keyed on .rlx-cm__form, which BOTH pages carry, not .rlx-contact__form,
   which only the model pages do: /rolex/contact/send-a-message/ showed no
   focus indicator at all (every field computed outline:none). Placed after
   the shared rule above, same specificity, so it wins on source order. */
body.rolex-section .rlx-cm__form .wpcf7 input[type="text"]:focus-visible,
body.rolex-section .rlx-cm__form .wpcf7 input[type="email"]:focus-visible,
body.rolex-section .rlx-cm__form .wpcf7 input[type="tel"]:focus-visible,
body.rolex-section .rlx-cm__form .wpcf7 select:focus-visible,
body.rolex-section .rlx-cm__form .wpcf7 textarea:focus-visible {
	outline: 2px solid var(--rlx-green);
	outline-offset: -2px;
	transition: none;
}

/* --- model page: hero (B) --- */
/* Hero sits in the page container. It was full-bleed, which put the copy at
   0.023 (template: 0.078) and let the media run to the right edge at 1.000. */
/* THE MODEL H1 IS MULTI-LINE (2026-09-22). Rolex's SEO table prescribes the
   model name, its specs and its RMC as ONE heading; templates/rolex/model/
   hero.php now nests them. These three rules are the whole cost, and they
   exist to make the nesting invisible:

     - the h1's 14px margin-bottom moves onto the NAME line, where it was
       already doing its work (it used to separate the h1 from the first <p>);
     - the sub-lines are <span> because an <h1> takes phrasing content only,
       so they need display:block to keep their own line;
     - .rlx-body20 already declares font-weight 400 and color var(--rlx-ink),
       so nothing has to fight the h1's 700/brown.

   Measured at 1440 and 390 before and after: every line keeps its top,
   height, size and leading to the pixel. */
body.rolex-section .rlx-hero__title-name,
body.rolex-section .rlx-hero__title-line { display: block; }

body.rolex-section .rlx-hero { display: flex; gap: var(--rlx-gap-half); align-items: stretch; max-width: var(--rlx-container-max); margin-inline: auto; padding-inline: 24px; }
/* Desktop hero: the watch area is centred on the PAGE, not in the space left
   over beside the copy. A plain flex row cannot do that (media would centre on
   ~0.67), so above the stacking breakpoint the hero becomes a 3-column grid
   whose middle column is the watch. The third column is intentionally empty —
   it is what keeps the middle one centred.

   The middle column is 45.4% of the 1620 container = 735.5px, which places it
   at x 592-1328 at 1920. Re-measured 2026-09-10 off the real render
   (rolex-watches-model-page-mockup-send-a-message-desktop.jpg), whose hero
   image box is x 594-1330 (736px): a 2px agreement.

   It was 34.6% (561px), taken from the WIREFRAME's grey placeholder box
   (587x821). That box is a portrait rectangle standing in for the media area;
   the delivered asset is a square 780x780 upright packshot and the mockup
   renders it square at 736. Sizing off the placeholder made the watch itself
   render 218px wide where the mockup's is 282px — a 29% undersize. The
   packshot's own background is the page background, so the image's edges are
   invisible and only the watch's rendered size is legible: hence deriving the
   box from the watch (0.3885 of file width, 0.841 of file height). */
@media (min-width: 768px) {
	body.rolex-section .rlx-hero {
		display: grid;
		grid-template-columns: 1fr 45.4% 1fr;
		align-items: center;
	}
	/* 34.8% = 564/1620 -- see the accessory packshot rule below. */
	body.rolex-section .rlx-hero--accessory { grid-template-columns: 1fr 34.8% 1fr; }
	body.rolex-section .rlx-hero__copy { flex: none; }
	body.rolex-section .rlx-hero__media { flex: none; }
}
body.rolex-section .rlx-hero__copy { flex: 1 1 40%; align-self: center; }
body.rolex-section .rlx-hero__media { flex: 1 1 60%; display: flex; align-items: center; justify-content: center; }
/* Hero packshot size is MEASURED off the mockup, not off the wireframe.
   The wireframe draws a 587x821 portrait placeholder box; the real render
   uses the square 780x780 upright asset at 736x736, page-centred. Derived
   two independent ways from
   rolex-watches-model-page-mockup-send-a-message-desktop.jpg: the watch
   inside the delivered file occupies 0.3885 of its width and 0.841 of its
   height, and the mockup's watch measures 282px wide / 619px tall — giving
   726 and 736. `min(60%, 480px)` rendered it 326px, under half size. */
body.rolex-section .rlx-hero__media img { width: min(100%, 736px); aspect-ratio: 1 / 1; height: auto; display: block; }
/* ACCESSORY packshots are SMALLER than watch ones, and the comps are
   unambiguous about it. All three accessory mockups -- cufflinks, desk clock
   and the generic template -- put the specs panel's top edge at y972 against a
   header ending y140, so the hero band is exactly 832 tall on every one,
   whatever the copy or the object in the packshot does. At the delivered
   800x1180 ratio that is 564 wide, and an independent derivation agrees: the
   desk-clock comp draws its object at 0.705 of the asset's own object, i.e.
   the 800px asset rendered at 564.

   We were reusing the watch page's 736, which is the right number there (a
   square 780x780 asset) and 30% too big here -- it made the accessory hero
   1085 tall against the comp's 832.

   The COLUMN narrows with it, not just the image. At 45.4% the two 1fr side
   columns were 397px and the H1 needed 399 to stay on one line, so "'Crown'
   cufflinks" wrapped where all three comps keep it whole (their H1 ink runs
   371 on a single line). 564/1620 = 34.8% leaves 528 a side. */
body.rolex-section .rlx-hero--accessory .rlx-hero__media img { width: min(100%, 564px); aspect-ratio: 800 / 1180; }
/* BOLD. The comp's hero kicker "Rolex" is visibly bold brown above the H1
   (model-page mockup, ink y383-399); we shipped weight 400. The SIZE is
   right and stays -- Body24 per the design-specs audit noted below. */
body.rolex-section .rlx-hero__kicker { margin-bottom: 0; font-weight: 700; }
/* The H1's bottom margin is the PARENT THEME's generic
   `h1,h2,h3,h4,h5,h6,ul,ol,... { margin-bottom: 24px }` -- an inherited
   value, never a comp-derived one, and 11px too much here.
   Both model-page mockups put the first spec line's ink 66px below the
   H1's ink top (send-a-message and book-an-appointment agree exactly;
   the wireframe's 64 is a shorter H1 with no descender, and mockups
   govern per the client's 15 Sep ruling). We measured 77.
   Stated on the margin rather than the line box: the surplus is entirely
   in this margin, so the kicker-to-H1 pitch -- comp 34, live 36 -- is
   untouched, which a line-height change would not have been.
   14px since 2026-09-16, not 13: the headline leading token moved from 1.2
   to the comps' 1.16, which shortened the H1's line box by 2px per line and
   left this gap at 65. Re-measured rather than assumed after that change. */
/* MOVED ONTO THE NAME LINE 2026-09-22, same 14px, same job. The model name,
   its specs and its RMC are now one multi-line <h1> (Rolex's SEO table), so
   this gap sits between the first line and the rest INSIDE the heading; on
   the heading itself it would push everything after the block down by 14.
   Measured after the move: every line holds its previous top to the pixel.
   The accessory hero shares this rule and this markup. */
body.rolex-section .rlx-hero__copy .rlx-hero__title { margin-bottom: 0; }
body.rolex-section .rlx-hero__copy .rlx-hero__title-name { margin-bottom: 14px; }
/* The three spec lines under the H1 run on a 28px pitch in the comp
   (ink tops y483 / y511 / y539). Ours measured 42 and 38: Body20's 1.6
   line-height plus the reboot's 10px paragraph margin. 28px and no margin
   reproduces the comp's rhythm without touching the Body20 token, which
   every other block on the page is set from. */
body.rolex-section .rlx-hero__copy .rlx-body20 { line-height: 28px; margin: 0; }
/* Design-specs audit §1.6 (2026-08-17): the "3 CTA"/"4 CTA" hero variants
   both specify "Body24+Headline50 Brown, Body20 Black" — kicker (Body24)
   and the h1 (Headline50) go Brown; the Body20 body_lines/price stay on
   the default --rlx-ink (Black), unchanged, per that same spec line. */
body.rolex-section .rlx-hero__copy .rlx-headline50,
body.rolex-section .rlx-hero__kicker { color: var(--rlx-brown); }
body.rolex-section .rlx-hero__price { display: flex; align-items: center; gap: 0.4em; }

/* PRICE DISCLAIMER TOOLTIP. See templates/rolex/model/hero.php for why this
   is a <button> rather than the old focusable span with a `title`.

   The icon is 15x15px on Rolex's own instruction -- Design specifications,
   Watch cover p62, "Black / 15x15px icon" beside the Body20 price line. It
   used to be 1.1em, which is 22px at Large: about half again too big.

   Motion: 150ms, opacity plus a 4px rise, `ease-out`. Tooltips sit in the
   125-200ms tier, entrances take ease-out, and a transition (not keyframes)
   is what survives being triggered twice in a second. Nothing scales from
   zero. */
body.rolex-section .rlx-hero__info { position: relative; display: inline-flex; }
body.rolex-section .rlx-hero__info-btn {
	appearance: none;
	background: none;
	border: 0;
	padding: 0;
	margin: 0;
	display: inline-flex;
	align-items: center;
	color: inherit;
	cursor: help;
	line-height: 0;
}
body.rolex-section .rlx-hero__info .rlx-icon { width: 15px; height: 15px; }
body.rolex-section .rlx-hero__tip {
	position: absolute;
	bottom: calc(100% + 8px);
	left: 50%;
	z-index: 5;
	width: max-content;
	max-width: min(280px, 70vw);
	padding: 10px 12px;
	background: var(--rlx-brown);
	color: #fff;
	font-size: var(--rlx-fixed14);
	line-height: 1.4;
	text-align: left;
	border-radius: 4px;
	opacity: 0;
	visibility: hidden;
	transform: translate(-50%, 4px);
	transition: opacity 150ms cubic-bezier(0.23, 1, 0.32, 1),
	            transform 150ms cubic-bezier(0.23, 1, 0.32, 1),
	            visibility 0s linear 150ms;
}
/* Shown on focus for the keyboard, and on .is-open for a TAP. The old note
   here said "touch, where a tap moves focus": true in Chrome, false in iOS
   Safari, which does not focus a <button> on tap -- so on an iPhone nothing
   matched and the tooltip never opened (Ernie, 2026-09-24; reproduced in
   WebKit: activeElement stays <body>). rolex-bespoke.js toggles .is-open on
   click. Hover is gated separately because a tap fires a phantom hover. */
body.rolex-section .rlx-hero__info-btn:focus-visible ~ .rlx-hero__tip,
body.rolex-section .rlx-hero__info:focus-within .rlx-hero__tip,
body.rolex-section .rlx-hero__info.is-open .rlx-hero__tip {
	opacity: 1;
	visibility: visible;
	transform: translate(-50%, 0);
	transition-delay: 0s;
}
@media (hover: hover) and (pointer: fine) {
	body.rolex-section .rlx-hero__info:hover .rlx-hero__tip {
		opacity: 1;
		visibility: visible;
		transform: translate(-50%, 0);
		transition-delay: 0s;
	}
}
/* The tip is dismissed by Escape (rolex-bespoke.js). While dismissed the
   pointer is still over the control, so hover must not immediately re-show
   it -- this class wins because it is later in the file and equally
   specific at the element it targets. */
body.rolex-section .rlx-hero__info.is-dismissed .rlx-hero__tip {
	opacity: 0;
	visibility: hidden;
}
@media (prefers-reduced-motion: reduce) {
	body.rolex-section .rlx-hero__tip {
		transform: translate(-50%, 0);
		transition: opacity 150ms linear, visibility 0s linear 150ms;
	}
	body.rolex-section .rlx-hero__info-btn:focus-visible ~ .rlx-hero__tip,
	body.rolex-section .rlx-hero__info:focus-within .rlx-hero__tip,
	body.rolex-section .rlx-hero__info.is-open .rlx-hero__tip,
	body.rolex-section .rlx-hero__info:hover .rlx-hero__tip {
		transform: translate(-50%, 0);
	}
}
/* THE PRICE TOOLTIP RAN OFF THE LEFT EDGE ON EVERY MODEL PAGE AT MOBILE
   (found 2026-09-23 in the pre-review sweep, not reported by anyone).

   The tip is centred on its info button -- `left: 50%` + translateX(-50%) --
   and at mobile the button sits at x89.5-x109.5 while the tip is 273-280 wide.
   Centring a 273px box on x107 starts it at -29.5. Measured across ALL 110
   model pages, both breakpoints:

     390 viewport   110/110 clipped at the left, worst 39.5px
     430 viewport   110/110 clipped at the left, worst 40.2px
     768 and up     0/110 clipped -- the well is wide enough, leave it alone

   This is Rolex's own price disclaimer ("Suggested retail price before
   applicable taxes..."), i.e. COMPLIANCE COPY, losing its first ~30px on
   every line. See [[rolex-price-disclaimer-string]] -- the wording is
   byte-pinned by a guard, and it turns out the wording was never the risk.

   Anchoring the tip to the button's LEFT edge instead of its centre fits
   every page with room to spare, measured rather than assumed: worst-case
   right edge 382.5 at a 390 viewport and 392.3 at 430. The existing
   `max-width: min(280px, 70vw)` is unchanged and still caps the width. If a
   longer price string ever pushes the button right (the widest today starts
   at x109.5), re-run that measurement -- 7.5px of headroom at 390 is the
   number to watch.

   Desktop keeps the centred tip: it is not clipped there and centring on the
   control is the better placement when there is room for it. */
@media (max-width: 767px) {
	body.rolex-section .rlx-hero__tip {
		left: 0;
		transform: translate(0, 4px);
	}
	body.rolex-section .rlx-hero__info-btn:focus-visible ~ .rlx-hero__tip,
	body.rolex-section .rlx-hero__info:focus-within .rlx-hero__tip,
	body.rolex-section .rlx-hero__info.is-open .rlx-hero__tip,
	body.rolex-section .rlx-hero__info:hover .rlx-hero__tip {
		transform: translate(0, 0);
	}
}
/* Reduced motion still gets no travel, at mobile too. This block sits after
   the one above AND after the section-wide reduced-motion block so it wins on
   source order -- media queries add no specificity. */
@media (max-width: 767px) and (prefers-reduced-motion: reduce) {
	body.rolex-section .rlx-hero__tip,
	body.rolex-section .rlx-hero__info-btn:focus-visible ~ .rlx-hero__tip,
	body.rolex-section .rlx-hero__info:focus-within .rlx-hero__tip,
	body.rolex-section .rlx-hero__info.is-open .rlx-hero__tip,
	body.rolex-section .rlx-hero__info:hover .rlx-hero__tip {
		transform: translate(0, 0);
	}
}

/* CONTENT-SIZED columns and a 9px row gap, both measured off the comps'
   white badge circles, which are 36px across on every model mockup.
   Columns: the second badge's left edge sits at x325 on the accessories
   comps and x315 on the watch ones against a first badge at x148 -- i.e. the
   first column is as wide as its own longest label plus the 24px gutter, not
   half the copy column. At `1fr 1fr` ours started at x404, some 80px adrift,
   and the gap grew with the copy column instead of staying put.
   Rows: badge centres are 45px apart on the accessories comps and 46 on the
   watch ones, so a 36px badge leaves 9. We shipped 12 -- and the <li> was
   45 tall rather than 36, because an inline-flex anchor sits on the text
   baseline and the strut's descent padded the row; `display: flex` on the
   item takes that out, so the 9 is the whole gap and not 9 plus whatever a
   font happens to leave under the baseline. */
body.rolex-section .rlx-hero__ctas { list-style: none; margin: var(--rlx-gap-half) 0 0; padding: 0; display: grid; grid-template-columns: repeat(2, max-content); gap: 9px 24px; }
body.rolex-section .rlx-hero__ctas li { display: flex; }
body.rolex-section .rlx-hero__ctas .rlx-cta-tertiary { display: inline-flex; align-items: center; gap: 0.5em; }
@media (max-width: 767px) {
	body.rolex-section .rlx-hero { flex-direction: column-reverse; }
	/* AN AXIS FLIP TURNS `align-self: center` INTO A HORIZONTAL RULE.
	   `.rlx-hero__copy` carries `align-self: center` for the DESKTOP row,
	   where the cross axis is vertical and it centres the copy against the
	   packshot. The line above flips this container to a COLUMN at mobile,
	   which makes the cross axis HORIZONTAL: the same declaration then
	   centred the copy block and shrink-wrapped it to its content, so it
	   rendered 232px wide starting at x79 inside a 335px well that begins
	   at x27.

	   Two consequences, one cosmetic and one not. Rolex's mobile model page
	   template (rolex-watches-model-page-template-mobile.jpg, 780 wide)
	   left-aligns the copy on the SAME gutter as the packshot, 54/780 =
	   6.92%, which is our 27px at 390 -- so the inset was wrong on its own
	   terms. And because a centred shrink-wrapped box grows from its middle,
	   any line wider than the well overflows BOTH edges at once, clipping
	   the heading on the left and the CTA on the right. Reported from an
	   iPhone on 2026-09-23 with exactly that symptom.

	   `align-self: stretch` restores the normal-flow behaviour for the
	   column: full well width, left-aligned, and nothing can overflow
	   symmetrically because the box no longer sizes to its content. */
	body.rolex-section .rlx-hero__copy { align-self: stretch; }
	/* MOBILE TURNS THE CTA CLUSTER INSIDE OUT: the 2x2 grid of bare badges
	   becomes ONE horizontally scrolling row of white pills, with the glyph
	   inside the pill instead of wearing it. All four mobile model mockups
	   draw it -- both accessories and both watch -- and in each the second
	   pill runs off the right edge of the 390 viewport, which is what says
	   the row scrolls rather than wraps.

	   Measured on the cufflinks mobile comp (a 2x render, figures halved):
	   pill 1 x28-227.5 and 38.5 tall, pill 2 starting x248 -- so a 40px
	   fully-rounded pill, 20 between them, the first flush with the 27px
	   mobile gutter. Inside it: the phone glyph's ink x55-65 and 14 tall
	   against a 24px padding, 10 to the label, and the label's own ink 13
	   tall, i.e. fixed16 rather than the desktop fixed14 (which also makes
	   the 200px pill width come out right: 24 + 15 + 10 + 127 + 24).

	   Full-bleed by the container trick, not by a wider parent: the row has
	   to reach the viewport edge for the clipped second pill to read as
	   scrollable, while its first pill stays on the copy column's gutter. */
	body.rolex-section .rlx-hero__ctas {
		display: flex;
		flex-wrap: nowrap;
		gap: 20px;
		width: 100vw;
		margin-inline: calc(50% - 50vw);
		padding-inline: 27px;
		overflow-x: auto;
		scrollbar-width: none;
	}
	body.rolex-section .rlx-hero__ctas::-webkit-scrollbar { display: none; }
	body.rolex-section .rlx-hero__ctas li { flex: 0 0 auto; }
	body.rolex-section .rlx-hero__ctas .rlx-cta-tertiary {
		min-height: 40px;
		padding-inline: 24px;
		border-radius: 20px;
		background: var(--rlx-surface);
		gap: 10px;
		font-size: var(--rlx-fixed16);
		white-space: nowrap;
	}
	/* The badge is the PILL now, so the glyph loses its own circle. */
	body.rolex-section .rlx-hero__ctas .rlx-cta-tertiary .rlx-icon {
		width: 15px;
		height: 15px;
		padding: 0;
		border-radius: 0;
		background: none;
	}
	/* The hero has NO media of its own at mobile: Rolex's mobile comps make
	   the upright packshot slide 1 of the gallery carousel, ordered above the
	   hero copy (see .rlx-main--gallery and .rlx-gallery__packshot below).
	   The 381px/0.977-of-viewport size that used to live here has moved to
	   the packshot slide, which is where the packshot now renders.

	   Gated on --gallery: the ten accessory models have no gallery slides, so
	   gallery.php renders nothing for them and there would be no carousel to
	   hold the packshot. They keep the hero media instead. */
	body.rolex-section .rlx-main--gallery .rlx-hero__media { display: none; }
	body.rolex-section .rlx-main--model:not(.rlx-main--gallery) .rlx-hero__media {
		width: 100vw;
		margin-inline: calc(50% - 50vw);
	}
	body.rolex-section .rlx-main--model:not(.rlx-main--gallery) .rlx-hero__media img { width: 97.7%; }
}
/* --- model page: gallery (B) --- */
/* Gallery sits in its own well, narrower than --rlx-container-max: the
   desktop template puts the three tiles at 0.174-0.822 (width 0.648) and the
   Tappers Bespoke reference renders 0.186-0.814. It was full-bleed 0.000-1.000
   with a 2px gap. 64.8% centred reproduces the template; the gap goes to 10px,
   the spacing the reference shows between tiles at 1920. */
/* Well 1216, gutter 8, tiles 400 square -- three "3 columns asset" cells of
   the 12-column grid (3 x 128.17 + 2 x 8 = 400.5; 9 cols + 8 gutters =
   1217.5). Measured off the rendered mockup: tiles at x344-743, 752-1151,
   1159-1559, gaps 8 and 7. The previous 64.8%/10px came from the WIREFRAME
   placeholders, which draw 410-wide non-square boxes and contradict their own
   grid (their S-image block implies a 397 asset, not 410) -- the rendered
   mockup outranks a wireframe placeholder. */
body.rolex-section .rlx-gallery__row { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; width: min(1216px, 100% - var(--rlx-container-inset)); margin-inline: auto; }
/* Mobile-only slide 1, and the dash track that goes with it: at desktop this
   section is a plain 3-up strip, exactly as before. display:none also takes
   the packshot out of grid flow, so the 3 columns still hold 3 tiles. */
body.rolex-section .rlx-gallery__packshot { display: none; }
body.rolex-section .rlx-gallery__dashes { display: none; }
@media (max-width: 767px) {
	body.rolex-section .rlx-gallery__row { width: 86%; }
}
body.rolex-section .rlx-gallery__tile img { width: 100%; aspect-ratio: 1 / 1; height: auto; object-fit: cover; display: block; }
/* --- mobile: packshot + gallery as ONE carousel above the hero copy -------
   Rolex's mobile comps (lightbox-gallery/...-gallery-mobile-*.jpg, which are
   the hero carousel despite the folder name, and the hero of
   ...-send-a-message-mobile.jpg) show one swipeable row whose first slide is
   the upright packshot, a green-active dash track under it, and only then the
   hero copy. Ours rendered the packshot inside .rlx-hero and a separate
   1-column stack of gallery images further down, with the copy in between.

   The reordering is done with `order` on .rlx-main--model rather than by
   moving markup, because .rlx-gallery and .rlx-hero are already siblings
   there. Scoped to --model: taxonomy-rolex_family.php uses .rlx-main too. */
@media (max-width: 767px) {
	body.rolex-section .rlx-main--gallery { display: flex; flex-direction: column; }
	body.rolex-section .rlx-main--gallery .rlx-gallery { order: -1; }
	body.rolex-section .rlx-gallery__row {
		display: flex;
		width: 100vw;
		margin-inline: calc(50% - 50vw);
		gap: 0;
		overflow-x: auto;
		scroll-snap-type: x mandatory;
		scrollbar-width: none;
	}
	body.rolex-section .rlx-gallery__row::-webkit-scrollbar { display: none; }
	body.rolex-section .rlx-gallery__packshot,
	body.rolex-section .rlx-gallery__tile {
		flex: 0 0 100vw;
		scroll-snap-align: start;
	}
	body.rolex-section .rlx-gallery__packshot { display: flex; align-items: center; justify-content: center; }
	/* 0.977 of the viewport, measured off the mobile comp's watch (296x640
	   device px against the file's own 0.3885/0.841 watch-to-file ratios,
	   both resolving to 381px on a 390px viewport). */
	body.rolex-section .rlx-gallery__packshot img { width: 97.7%; height: auto; display: block; }
	/* Dash track: green active, per the comps. Same numbers as the lightbox
	   track, and for the same reason — see that component's note. */
	body.rolex-section .rlx-gallery__dashes {
		display: flex;
		align-items: center;
		justify-content: center;
		gap: 24px;
		margin-top: 12px; /* + the dash button's own 24px box ~= the comp's spacing */
	}
	/* Same tap-target technique as .rlx-nw-keep__dash: the visible bar is
	   3px, but the BUTTON is 24px tall, because the shared handler makes
	   these real buttons and a 3px touch target on a phone is not one.
	   The comp's inactive bar is #D4D4D4, which is ~1.4:1 on #F9F7F4 — fine
	   for the lightbox's aria-hidden decorative track, NOT for an
	   interactive control (WCAG 1.4.11 wants 3:1). So the geometry is the
	   comp's (24/55px, 3px, 24px gap, green active) and only the inactive
	   colour is corrected, to ink at 50% = ~#909090 = 3.2:1 — the same
	   substitution already made for the New watches track. */
	body.rolex-section .rlx-gallery__dash {
		appearance: none;
		-webkit-appearance: none;
		border: 0;
		background: none;
		padding: 0;
		width: 24px;
		height: 24px;
		display: grid;
		place-items: center;
		cursor: pointer;
	}
	body.rolex-section .rlx-gallery__dash::before {
		content: "";
		display: block;
		width: 24px;
		height: 3px;
		border-radius: var(--rlx-dash-radius);
		background: rgba(33, 33, 33, 0.5);
	}
	body.rolex-section .rlx-gallery__dash[aria-current="true"] { width: 55px; }
	body.rolex-section .rlx-gallery__dash[aria-current="true"]::before {
		width: 55px;
		background: var(--rlx-green);
	}
}
/* Tiles are now real <button>s (design-specs audit §1.6, "Watch lightbox —
   NOT BUILT"); reset default button chrome so the grid tile still looks
   exactly like a plain <picture>. */
body.rolex-section .rlx-gallery__tile {
	display: block;
	width: 100%;
	padding: 0;
	border: 0;
	background: none;
	font: inherit;
	cursor: pointer;
	text-align: inherit;
}

/* --- model page: watch lightbox (B) ------------------------------------
   Spec PDF, "Model page components" (p60-86) > "Watch lightbox": CSS grid
   diagrams p67-68, numeric "Specifications" diagram p69.

   Own grid, not the site's: the diagram's flanking margin columns run
   edge-to-edge with the popin itself, unlike every OTHER component's CSS-
   grid diagram in this same document, which shows its pink columns inset
   by "Auto" margins matching the sitewide 1620px container
   (--rlx-container-max). A fullscreen popin has no page column to sit
   inside, so its "6 columns (large) / 8 columns (medium)" asset width
   below is a fraction of the popin's OWN full-viewport width, not of
   --rlx-container-max (deliberately not reusing the
   .rlx-editorial__media--single-* percentage mechanism the audit itself
   already flags as a DELTA against the spec's column steps).

   Background: p69's Medium-breakpoint diagram is explicitly labelled
   "Fullscreen popin / Light beige background". The Large-breakpoint
   diagram on the SAME page carries no such label — but its box starts
   flush against the very top of the page render, exactly where this PDF's
   sticky green header band is documented (design-specs audit, confidence
   notes) to clip label rows at page-break seams; the Medium diagram sits
   lower on the page, where its label had room to survive. One popin
   design with one label, clipped on one of its two diagrams — not two
   different backgrounds. Built as Light beige (var(--rlx-bg)) at every
   breakpoint. NOTE: this deliberately contradicts the "dark scrim"
   description in this task's own brief, which was a paraphrase, not a
   re-read of this page — built per the primary source instead, per the
   task's own instruction to capture exact values with page numbers.

   Round buttons: "Round button - Dark" on both diagrams — a dark fill for
   contrast against the light-beige popin, a deliberately different look
   from the light/white round arrows used elsewhere in this file
   (.rlx-keep__arrow etc., which sit on their own light card/row
   backgrounds, not a fullscreen dark-on-light popin). 30px inset from the
   popin's left/right edge at both breakpoints; close button 30px from
   top AND 30px from right (fix round 1, 2026-08-17: a re-crop of the
   Medium-bp diagram at 400dpi reads "30" on BOTH the top and right
   callouts, not top:30/right:20 as originally transcribed at lower
   zoom — corrected to match p69 exactly). Sized 40px — this file's one
   existing round-button size (.rlx-keep__arrow/.rlx-hub__arrow/
   .rlx-ed-carousel__arrow), reused rather than inventing a second; the
   spec gives no distinct px value for this button anywhere on p67-69.

   Vertical space: "auto - min 60px" above/below the asset on both
   breakpoints — read as "vertically centered, with a 60px floor", not a
   literal margin: auto value. Implemented as flex-centering (which IS
   that "auto" behaviour) plus a 60px padding-block floor.

   Scroll lock: applied via a direct `element.style.overflow` toggle in
   rolex-bespoke.js, NOT a CSS class + rule here. This file's own
   sticky-band comment above already established (live-verified) that
   <html>, not <body>, is the real scrolling element on this site despite
   roneous/style.css's body{overflow-x:hidden} — so the lock has to target
   <html>, an ANCESTOR of body.rolex-section, and there is no CSS selector
   that can reach an ancestor from a descendant's state while still
   starting with the literal string "body.rolex-section" — which
   tests/wp-check-shell.php's leak-guard enforces character-for-character
   on every comma-separated selector in this file (confirmed the hard way:
   `html.rlx-lightbox-open { overflow: hidden; }` was tried first and
   failed that exact check). Inline-style-via-JS has no selector to leak
   in the first place, so it satisfies the guard by construction rather
   than needing an exception to it.

   Small breakpoint: absent from the spec's own Specifications diagram for
   this exact component — it stops at Medium, the same shape as the
   already-documented spec gap in the design-specs audit's §1.5 Watch-grid
   "Medium breakpoint" row. The 90%-width value at <=767px below is an
   implementer default for that gap, not a spec-read number, flagged the
   same way the light-background focus-ring default above is flagged.

   Dashes: spec PDF p8-11, "Simple dashes" component, "Dark" tone variant
   (read directly, not inherited from the audit's paraphrase) — confirmed
   as the correct variant for our light-beige popin because that page's
   own "Light" row shows WHITE dashes over a DARK background swatch, i.e.
   variant names describe the dash's own colour, not the surface it sits
   on; "Dark" (a dark-toned Brown dash) is the one meant for a light
   surface like ours. CORRECTED (fix round 1, 2026-08-17): a 400dpi
   re-crop of p10-11 shows the inactive dash is FULL-OPACITY Brown too —
   current vs. other are differentiated by WIDTH ONLY (50×4px vs 24×4px),
   not by any opacity/tint step. The original rgba(69,44,30,0.3) fade was
   an implementer default guessed because the inactive dash's colour
   wasn't legible at the zoom level available at the time; it isn't a
   guess anymore, it's solid var(--rlx-brown) at both widths. Decorative
   only (aria-hidden — the accessible position readout is the aria-live
   status text next to it), so the spec's separate 24px *tap*-zone value
   doesn't apply here. */
body.rolex-section .rlx-lightbox {
	position: fixed;
	/* THE HEADER STAYS VISIBLE. All three desktop comps keep the green band
	   and the breadcrumb on screen and start the lightbox beneath them, at
	   y140 on a page-ground field -- they are not a full-viewport scrim.
	   Our header is taller than the comp's and can be hidden by the
	   scroll behaviour, so the offset is measured at open time and written
	   to --rlx-lightbox-top by rolex-bespoke.js rather than hardcoded. */
	inset: var(--rlx-lightbox-top, 0px) 0 0 0;
	z-index: 1000000; /* clears the sticky band (998), the fixed main nav (999), the legacy bare-<nav> mobile trap this file documents above (functions.php forces z-index:99999!important on ANY <nav> at <=990px) -- AND (fix round 1, 2026-08-17) the WebToffee cookie-consent plugin's own .cli-modal.cli-blowup settings overlay, which was ALSO at 999999 -- an exact tie the original value didn't clear. Bumped one more order of magnitude past that fourth overlay rather than just +1, so the next thing that shows up at 999999 doesn't retie us again. */
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	/* asset-to-Dashes gap. p69 says 40px "both breakpoints"; all three
	   desktop comps measure 91px (image bottom y 1083, dash top y 1174) and
	   agree with each other, so this follows the comps for the same reason
	   the dash styling below does. The popin's only two in-flow children are
	   the arrow/stage row and the dash track, so this gap IS that distance.
	   Mobile keeps a smaller value (see the max-width: 767px block): there is
	   no mobile comp for this popin. */
	gap: 91px;
	padding: 60px 30px;
	background: var(--rlx-bg);
}
body.rolex-section .rlx-lightbox[hidden] { display: none; } /* wins over the flex rule above on specificity-tie + source order otherwise (classic [hidden] gotcha) */
/* The arrow/stage/arrow row. Arrows are 31px outside the image in all three
   desktop lightbox comps (image x 557-1363, arrow centres x 504 / 1415), so
   they flank the stage rather than sitting at the popin's edges. */
body.rolex-section .rlx-lightbox__row {
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 31px;
	width: 100%;
}
body.rolex-section .rlx-lightbox__stage {
	/* 6 of 12 columns, p69 — but of the 1620 CONTAINER, not of the popin.
	   A bare 50% resolves against the popin's 1860px content box = 930px,
	   ~15% wider than the 807px the comps measure. 1620/2 = 810. */
	width: min(50%, calc(var(--rlx-container-max) / 2));
	display: flex;
	align-items: center;
	justify-content: center;
}
body.rolex-section .rlx-lightbox__image {
	display: block;
	width: 100%;
	height: auto;
	/* The 220px allowance is the dash row + floor; --rlx-lightbox-top is the
	   header the overlay now starts below, and has to come off the same
	   budget or the stage overflows upward and clips the image -- which is
	   exactly what it did at 1080 the moment the offset was introduced. */
	max-height: calc(100vh - var(--rlx-lightbox-top, 0px) - 220px);
	object-fit: contain;
}
body.rolex-section .rlx-lightbox__close,
body.rolex-section .rlx-lightbox__arrow {
	/* 44px, measured: all three comps put the close and both arrows in
	   44x44 circles (close x 1846-1889, arrows x 483-526 / 1394-1437). */
	width: 44px;
	height: 44px;
	border-radius: 50%;
	border: 0;
	display: flex;
	align-items: center;
	justify-content: center;
	cursor: pointer;
	flex: 0 0 auto;
}
/* CORRECTED 2026-09-15: the close is the SAME light disc as the arrows, not
   an inverted dark one. This carried "comp fill #212121 with a light glyph",
   which is backwards -- sampling the disc on all three desktop comps gives
   fill rgb(237,236,234) with a glyph of rgb(32,32,32), identical to the
   arrows beside it. Live had the close dark-on-light while its own siblings
   were light-on-dark, so the set disagreed with itself as well as the comp.
   It stays position:absolute in the corner; only the colours change. */
body.rolex-section .rlx-lightbox__close {
	position: absolute;
	background: #edecea;
	color: var(--rlx-ink);
}
body.rolex-section .rlx-lightbox__arrow {
	position: static;
	background: #edeceA;
	color: var(--rlx-ink);
}
/* currentColor, not a fixed light ink: the two control kinds now have
   opposite tones. Contrast: #212121 on #EDECEA is ~13:1, #F9F7F4 on
   #212121 ~15:1 — both far past the 3:1 floor for a UI glyph. */
body.rolex-section .rlx-lightbox__close .rlx-icon,
body.rolex-section .rlx-lightbox__arrow .rlx-icon { width: 16px; height: 16px; color: currentColor; }
body.rolex-section .rlx-lightbox__close { top: 30px; right: 30px; }
/* Same right-pointing #rlx-arrow glyph as everywhere else in this file,
   flipped for "prev" -- the technique this file already uses for
   .rlx-icon--back-to-top (rotates the identical glyph -90deg) above. */
body.rolex-section .rlx-lightbox__arrow--prev .rlx-icon { transform: scaleX(-1); }
body.rolex-section .rlx-lightbox__arrow[disabled] { opacity: 0.35; cursor: default; }
/* DASHES — measured off this component's own comps, which SUPERSEDE the
   spec-PDF reading recorded above.
   rolex-watches-model-page-mockup-gallery-desktop-{1,2,4}.jpg agree with each
   other (and the active dash tracks the frame number, so it is unambiguously
   this component): active #127749 GREEN at 55px, inactive #D4D4D4 at 24px,
   3px tall, 24px gap. The same green active dash appears in the mobile hero
   carousel comps, so green-active is what Rolex renders in this build.
   The p8-11 "Simple dashes / Dark" reading above is kept as the superseded
   generic-component-sheet reading, not deleted — it was a careful read, it is
   simply not this instance.
   NOTE the other dash tracks on this site (.rlx-banner__dash,
   .rlx-nw-keep__dash) still follow that sheet; they have their own comps and
   are deliberately NOT changed here, so this divergence is intentional and
   should not be "harmonised" back without checking those comps.
   #D4D4D4 on #F9F7F4 is only ~1.4:1, which is acceptable ONLY because the
   whole track is aria-hidden and position is announced by the aria-live
   status text beside it — the same argument the note above already makes. */
body.rolex-section .rlx-lightbox__dashes { display: flex; align-items: center; gap: 24px; }
/* The one track whose BAR IS THE ELEMENT -- there is no ::before here, so
   the radius goes on the dash itself. Worth stating: a sweep that only
   touched `__dash::before` would silently miss this family. */
body.rolex-section .rlx-lightbox__dash {
	display: inline-block;
	width: 24px;
	height: 3px;
	border-radius: var(--rlx-dash-radius);
	background: var(--rlx-track);
}
body.rolex-section .rlx-lightbox__dash.is-current { width: 55px; background: var(--rlx-green); }
@media (max-width: 1024px) {
	/* Medium breakpoint: 8 of 12 columns, p69 — of the container, for the
	   same reason as the large breakpoint above. 1620 * 8/12 = 1080. */
	body.rolex-section .rlx-lightbox__stage { width: min(66.6667%, calc(var(--rlx-container-max) / 12 * 8)); }
}
@media (max-width: 767px) {
	body.rolex-section .rlx-lightbox { padding: 30px 20px; gap: 20px; }
	/* Small breakpoint: absent from the spec's own diagram for this
	   component, and there is no mobile lightbox COMP either (the mobile
	   frames in lightbox-gallery/ are the hero carousel, not this popin) --
	   so this is an implementer default, see the file comment above.
	   The stage now shares a flex row with two 44px arrows, so it has to be
	   allowed to shrink instead of claiming a fixed 90%: 44 + 8 + stage +
	   8 + 44 has to fit 350px at a 390px viewport. */
	body.rolex-section .rlx-lightbox__row { gap: 8px; }
	body.rolex-section .rlx-lightbox__stage { width: auto; flex: 1 1 auto; min-width: 0; }
	/* Small-bp offsets: the spec has no Small-breakpoint diagram for this
	   component at all (see above), so there's no diagram to re-crop for
	   an exact number the way the Medium-bp close offset was corrected
	   above. Kept proportional instead: the round-button inset scales
	   30px (large/medium) -> 16px here for the arrows already, so the
	   close button's now-symmetric 30/30 (fix round 1) scales to a
	   symmetric 16/16 rather than staying asymmetric — matching the ratio,
	   not a spec-read number. */
	body.rolex-section .rlx-lightbox__close { top: 16px; right: 16px; }
}
/* --- model page: overview (B, accessories only) --- */
/* CORRECTED 2026-09-12. This was a 45/55 flex ROW with the media first, so
   the image sat left of the copy and -- because the section carried
   `padding-inline: var(--rlx-gap-half)` instead of the container -- started at
   x45, outside the 1620 well (x150-1770) altogether. Mobile inherited the same
   45px inset, giving a 310px image at x40 where the well is 336 at x27.

   The mockup is ONE span6 column: heading ink x556, paragraph x557-1335, image
   box x556-1363 (w808) -- copy above image, which the template now emits in
   that order. aspect-ratio is dropped with it; the delivered accessory art is
   square already, and forcing 1/1 would crop anything that is not. */
body.rolex-section .rlx-overview {
	display: block;
	width: min(calc(var(--rlx-container-max) / 2), 100% - var(--rlx-container-inset));
	max-width: none;
	margin-inline: auto;
	padding-inline: 0;
}
/* A FULL --rlx-gap under the copy, not the half. Both accessory comps put the
   overview image 91px below the body's line box: cufflinks body ink y1470-1488
   over an image at y1583, desk clock's second body line ink y1751-1769 over an
   image at y1864 -- 90 once the 32px line box is accounted for. The gap ABOVE
   the heading is already 90 (panel bottom to h2 box: 88 and 87 on the two
   comps), so the block is evenly bracketed; gap-half made it look bottom-tight.
   .rlx-overview renders on accessory model pages only. */
body.rolex-section .rlx-overview__media { margin-top: var(--rlx-gap); }
body.rolex-section .rlx-overview__media img { width: 100%; height: auto; aspect-ratio: auto; display: block; }
/* --- model page: specs (B) --- */
/* padding-block is the FULL --rlx-gap, not the half. Measured on four comps:
   the accessories panels put 90px above the first label's line box and 90px
   below the last value's (cufflinks panel y972-1292, first label cap-top
   y1071, last value ink-bottom y1199), and both mobile comps put 60px --
   which is exactly what clamp(45px, 10vh, 90px) resolves to at each
   breakpoint. The watch model comps read 102/102 rather than 90/90 (panel
   y2091-2762, first cap-top y2202, pill bottom y2660); that is the known
   uncapped-10vh deviation already recorded for this deck -- a comp rendered
   at a 1020px-tall viewport -- not a second value. We shipped gap-half, so
   the panel was 45px short top and bottom. */
body.rolex-section .rlx-specs__panel { background: var(--rlx-panel); padding-block: var(--rlx-gap); padding-inline: var(--rlx-gap-half); margin-inline: var(--rlx-gap-half); }
/* Row gap 21, not gap-half. The comp stacks these fields far tighter than a
   section-level gap: on the desktop watch comp column 1 runs label cap-top
   y2202 -> value y2231 -> next label y2283, i.e. 81px from one single-line
   field to the next, and the mobile comp reads the same 80px in CSS pixels
   (y3366/3425/3526 on a 2x render). With a 28px label line box over a 32px
   value line box that leaves 21. We shipped 45 desktop / 40 mobile, which
   made the panel about half again as tall as the comp's. */
body.rolex-section .rlx-specs__grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 21px 32px; margin: 0; }
/* BROWN, not ink. Sampled off the model mockup's spec panel: every label
   reads rgb(70,44,29) -- the brown token -- against its VALUES at
   rgb(33,33,33), which is the ink we already use and which stays. The
   panel read flat because both were ink; the contrast the comp draws is
   colour AND weight, not weight alone. */
/* line-height 1.4, and no margin under it: the comp sets the value's cap-top
   28-29px below the label's on both breakpoints, where a 1.6 body20 line box
   plus the theme's 10px `dt` margin was putting ours 42px below. The VALUE
   keeps 1.6 -- the comp's own second and third value lines are 32px apart. */
body.rolex-section .rlx-specs__label { font-weight: 700; color: var(--rlx-brown); line-height: 1.4; }
body.rolex-section .rlx-specs__row dt { margin: 0; }
/* The mockup rules a hairline between the spec grid and the brochure button
   and sets a download glyph inside the pill. Both were missing.

   The rule is its own element, not a border on the grid, because the two have
   DIFFERENT widths at >=1024px: the grid spans nine columns (75%) and the rule
   spans ten (measured x283-1636 of a 1620 container at x150, i.e. 1350 = 10/12
   starting one column in). A border on the grid would have stopped at x1500.

   Colour is the BROWN token at 20%, not a grey: sampled rgb(209,200,193) over
   the rgb(244,239,235) panel solves to alpha 0.20 on all three channels for
   #452C1E (ink at any alpha runs too cool in blue). Same value on both comps.

   Vertical rhythm, measured on the desktop comp: last spec ink y2528, rule
   y2585, pill top y2616 -- 57px then 31px. 19px of the first gap is already
   the last value's line box, so the grid's own bottom margin carries 38. */
/* width is RESTATED: the theme gives bare <hr> a width of its own, which cut
   the mobile rule to 217px inside a 334px panel. The mobile comp runs it the
   full content width (x54-722 of a 780px 2x render = 27-361 CSS). */
/* The gap ABOVE the rule lives on the rule, not on the grid's bottom margin:
   an accessory panel has no brochure button and so renders no rule at all,
   and a bottom margin on the grid left 128px under the last value there
   where the comp draws 90. */
body.rolex-section .rlx-specs__rule { width: 100%; border: 0; border-top: 1px solid rgba(69, 44, 30, 0.2); margin: 40px 0 31px; }
body.rolex-section .rlx-specs__grid + .rlx-cta-primary { position: relative; }
body.rolex-section .rlx-specs__panel .rlx-cta-primary--download { display: inline-flex; align-items: center; gap: 10px; }
body.rolex-section .rlx-cta-primary--download .rlx-icon { width: 15px; height: 15px; flex: 0 0 auto; }
/* KICKER is brown in the comp (rgb(70,44,29)); it rendered ink. The H4
   below it was already brown and is unchanged. */
body.rolex-section .rlx-contact__kicker { color: var(--rlx-brown); }
body.rolex-section .rlx-specs__row dd { margin: 0; }
@media (max-width: 1024px) { body.rolex-section .rlx-specs__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

/* --- model page: features (B) --- */
/* Text-image column = 42% of the viewport, centred: 0.290-0.710, the value
   the desktop template states and the Tappers Bespoke reference renders at
   1920/1600/1440/1280 alike (ratio-based, NOT a fixed px — verified
   2026-08-25). It was max-width:720px minus 2x45px padding = 630px content,
   i.e. 0.336-0.664: ~88px too narrow on each side at 1920. */
body.rolex-section .rlx-feature { width: 42%; margin-inline: auto; padding-inline: 0; }
@media (max-width: 767px) {
	/* Mobile template: content column 0.070-0.930. */
	body.rolex-section .rlx-feature { width: 86%; }
}
body.rolex-section .rlx-feature__copy { margin-bottom: var(--rlx-gap-half); }
/* Design-specs audit §1.6 (2026-08-17): "Watch key selling points" is
   "Brown/Black text" — the h2 title goes Brown; the body copy
   (.rlx-body20, unclassed here) stays on the default --rlx-ink (Black). */
body.rolex-section .rlx-feature__copy .rlx-headline50 { color: var(--rlx-brown); }
body.rolex-section .rlx-feature__media img { width: 100%; aspect-ratio: 1 / 1; height: auto; object-fit: cover; display: block; }
/* --- model page: Rolex Guarantee (2026-08-25) ------------------------------
   Image left, three-row accordion right, between the gallery and the specs
   panel. Geometry read from the desktop template and confirmed against a live
   Bespoke reference build: block 0.080-0.920 (the standard container), image
   0.084-0.502, accordion 0.572-0.920. Inside a container that spans 0.844 of
   the viewport, an image column of 49.5% resolves to 0.418vw starting at 0.084,
   and the accordion column starts at 0.572 — so the two columns are 49.5% and
   41.2% with the remainder as the gutter between them.
   The accordion itself is the shared .rlx-accordion contract; only the heading
   colour differs (Brown, as the reference renders it and as every other
   Body24 heading in the section does). */
body.rolex-section .rlx-guarantee {
	display: grid;
	grid-template-columns: 49.5% 1fr;
	column-gap: 8.3%;
	align-items: start;
}
body.rolex-section .rlx-guarantee__media img {
	width: 100%;
	aspect-ratio: 3 / 2;
	height: auto;
	object-fit: cover;
	display: block;
}
body.rolex-section .rlx-guarantee .rlx-accordion__button { color: var(--rlx-brown); font-weight: 700; }
body.rolex-section .rlx-guarantee .rlx-accordion__panel { padding-bottom: 16px; }
body.rolex-section .rlx-guarantee .rlx-accordion__item:first-child { border-top: 0; }
@media (max-width: 767px) {
	/* Mobile template stacks the two: image first, then the accordion. */
	body.rolex-section .rlx-guarantee { grid-template-columns: 1fr; row-gap: var(--rlx-gap-half); }
}

/* --- model page: block widths on the 1620 container -----------------------
   Every block in the model-page mockup sits at EXACTLY the container width:
   measured x 148-1771 (1624px) at 1920 for the specs panel, the availability
   panel, the contact cover and the push image alike, and the guarantee image
   is 809px = 6/12 of 1620 starting at that same x=147.

   .rlx-container adds `padding-inline: 24px` INSIDE its 1620 max-width, so
   everything built on it rendered 1572 wide, and blocks that were never on it
   rendered full-bleed (contact 1920) or on their own margin (specs panel
   1830). Same padded-box defect already fixed for the collection editorial
   media: state the width so the 1620 is the CONTENT box, and keep a 24px
   gutter below 1668px viewports via the min().

   Measured 2026-09-10 against
   rolex-watches-model-page-mockup-send-a-message-desktop.jpg. */
body.rolex-section .rlx-hero,
body.rolex-section .rlx-guarantee.rlx-container,
body.rolex-section .rlx-push.rlx-container,
body.rolex-section .rlx-contact,
body.rolex-section .rlx-availability,
body.rolex-section .rlx-specs__panel {
	width: min(var(--rlx-container-max), 100% - var(--rlx-container-inset));
	max-width: none;
	margin-inline: auto;
	padding-inline: 0;
}

/* On an ACCESSORY model page the spec panel butts directly against the bottom
   of the hero packshot -- no gap at all, unlike every other section boundary in
   the section.

   rolex-accessories-model-page-template-desktop.jpg is unambiguous: sampled at
   x=960 the grey image box runs to y972 and the beige panel begins at y972, and
   at x=200 the ground runs to y972 and the same panel begins there. The
   template's own "10vh / 90px" arrows appear only BELOW the panel, never above
   it. The cufflinks mockup agrees -- its panel top is y972 too.

   Scoped to .rlx-hero--accessory deliberately. The WATCH model page is a
   different composition (dark hero band, image box ending y970 with the dark
   band continuing beneath) and is not governed by this. */
/* DESKTOP ONLY (scoped 2026-09-23). Everything measured above is a DESKTOP
   composition: there the accessory hero ends with the PACKSHOT, and the panel
   butting against it is what the template draws.

   Mobile is a different stack. `.rlx-hero` is flex-direction: column-reverse
   there, so the last thing in the hero is not the packshot, it is the CTA
   roller -- and this unscoped rule put the beige panel hard against the
   contact pills, with no gap at all. Reported from a phone 2026-09-23.

   rolex-accessories-model-page-template-mobile.jpg settles it: the CTA roller
   band ends at y1468, the cream ground continues, and the beige panel begins
   at y1588. That is 120 of 780 template px = 60px at a 390 viewport, which is
   the base --rlx-gap the mobile comps use on BOTH model page types -- the same
   thing the padding-block rule below already says in its own comment. So at
   mobile the accessory page wants the ordinary gap, not the desktop's zero. */
@media (min-width: 768px) {
	body.rolex-section .rlx-hero--accessory + .rlx-specs { margin-top: 0; }
}
/* The availability panel keeps its own vertical breathing room and its copy
   sits in a centred column (mockup: text x 577-1343, i.e. 766px wide, inset
   equally 429/428 from the beige edges). */
/* width, not max-width: the container rule above zeroes this panel's own
   padding-inline, so a bare max-width let the copy run flush to the beige
   edge once the viewport was narrower than 800px. Mobile comp measures the
   copy inset 22.5px inside a 336px panel, which is what 100% - 48px gives. */
body.rolex-section .rlx-availability__copy { width: min(800px, 100% - 48px); margin-inline: auto; }

/* These two live AFTER the container-width rule on purpose: they carry the
   same specificity as it (0,2,1), so on a tie source order decides and an
   earlier copy of them lost its padding-inline and width to it.

The mobile comp keeps TWO spec columns (measured on
   rolex-watches-model-page-mockup-send-a-message-mobile.jpg, y 3228-4548),
   so the old 1-column collapse is gone — the >=1024px rule above already
   provides 2 columns all the way down.

   The mobile panel is also FULL-BLEED beige (x 0-779 of a 780px/2x comp =
   100vw) with its text inset 27.5/31px, where desktop has it at the 1620
   container. And between 768 and 1023 nothing insets the text at all once
   the container rule zeroes padding-inline and the 8.3333% grid inset stops
   applying — so state a gutter there too. (That middle band is an
   implementer default: the comps are 1920 and 390 only.) */
@media (min-width: 768px) and (max-width: 1024px) {
	body.rolex-section .rlx-specs__panel { padding-inline: var(--rlx-gap-half); }
}
@media (max-width: 767px) {
	body.rolex-section .rlx-specs__panel {
		width: 100vw;
		margin-inline: calc(50% - 50vw);
		padding-inline: 28px;
	}
}


/* The specs grid lands on the 12-column grid, not on the panel's padding:
   the three column starts measure x 284 / 691 / 1099, a pitch of 407.5px,
   and 1620/12 = 135. So the grid begins one column in (135px = 8.3333%),
   spans nine (1215px = 75%), and its three columns are three grid columns
   each (405px) — which is why the column gap has to be 0 rather than 32px.
   Held to >=1024px, where the panel is wide enough for three columns at all;
   below that the existing 2-column and 1-column rules take over. */
/* 1025, NOT 1024 (corrected 2026-09-19). Rolex's Layout spec defines
   Medium as 768-1024 INCLUSIVE and Large as 1025 and up, so 1024px is a
   Medium viewport. Every boundary in this file used to put it on the Large
   side -- which is exactly the width an iPad in landscape reports, so the
   most common tablet was getting desktop type sizes, a 3-column spec grid
   and a desktop lightbox stage. Four sibling rules moved with this one. */
@media (min-width: 1025px) {
	/* 102 on WATCH model pages, on the client's ruling of 2026-09-16: match
	   the watch mockups rather than the token they disagree with.

	   The four comps do not agree and that is the whole story. Both
	   accessories mockups put 90 above the first label's line box and 90
	   below the last value's (cufflinks panel y972-1292, first cap-top y1071,
	   last ink-bottom y1199), and both mobile mockups put 60 -- which is
	   exactly what clamp(45px, 10vh, 90px) resolves to at each breakpoint,
	   i.e. the token rendered at a 900px-tall frame. The two WATCH mockups
	   put 102 (panel y2091-2762, first cap-top y2202, pill bottom y2660,
	   identical on send-a-message and book-an-appointment) -- the same 10vh
	   rendered at a taller one, the uncapped-10vh deviation this deck is
	   already known for.

	   Keyed POSITIVELY on the accessory hero rather than negatively on its
	   absence: `:not(.rlx-hero--accessory)` would carry that class's own
	   specificity and outrank things it has no business outranking. The
	   adjacency is the same one that already zeroes the accessory panel's top
	   margin, so a page type that stops emitting the modifier loses both
	   rules together rather than silently keeping one.

	   >=1024 only. Below it the base --rlx-gap stands, which is what both
	   mobile comps measure on BOTH page types. */
	body.rolex-section .rlx-specs__panel { padding-block: 102px; }
	body.rolex-section .rlx-hero--accessory + .rlx-specs .rlx-specs__panel { padding-block: var(--rlx-gap); }

	/* COLUMN-MAJOR, with the columns flowing INDEPENDENTLY -- multi-column,
	   not grid. The mockup reads DOWN each column in field order (col 1
	   Reference, Model case, Bezel, Water-resistance; col 2 Movement,
	   Calibre, Power reserve, Bracelet; col 3 Dial, Certification) and each
	   column sets its own vertical rhythm: col 1's "Model case" takes two
	   lines and pushes only col 1 down, while col 2's next field stays
	   where it is. A grid cannot do that -- every cell in a row takes the
	   row's tallest height, which is what we shipped and why the columns
	   stepped together.
	   `grid-auto-flow: column` would not have fixed it either: it changes
	   the fill order but keeps the shared row tracks.
	   The 405px columns and their x284/x691/x1099 starts are unchanged --
	   only the flow is. */
	body.rolex-section .rlx-specs__grid {
		width: 75%;
		margin-inline-start: 8.3333%;
		display: block;
		column-count: 3;
		column-gap: 0;
	}
	body.rolex-section .rlx-specs__row {
		break-inside: avoid;
		/* multi-column, so the grid's row-gap does not apply -- same 21 as the
		   grid declares for the 2-column layouts below this breakpoint. */
		margin-bottom: 21px;
	}
	/* The brochure CTA is a SIBLING of the grid, so the grid's own inset did
	   not carry to it and it sat flush against the panel edge, 135px left of
	   the spec labels above it. The mockup puts the two flush: the button's
	   left edge measures x=283 and the first spec label's ink x=284 against
	   a panel edge of 148 — the same 1/12 (135px) inset. Only >=1024px,
	   where the grid is inset at all; below that the panel's own
	   padding-inline positions both. */
	body.rolex-section .rlx-specs__panel > .rlx-cta-primary { margin-inline-start: 8.3333%; }
	/* Ten columns wide, one column in -- see the rule's own comment above.
	   38 above it rather than the 40 mobile uses: both model mockups put 88px
	   between the last spec value's ink and the brochure button's top edge
	   (last ink y2528, rule y2585, pill y2616-2660, identical on
	   send-a-message and book-an-appointment), and 19 of the first 57 is
	   already the last value's line box. */
	body.rolex-section .rlx-specs__rule { width: 83.3333%; margin-inline-start: 8.3333%; margin-top: 38px; }
}

/* --- model page: contact (B) --- */
/* No horizontal inset: the mockup puts "Contact us" and its rule flush with
   the container edge (ink starts x=149 against a 148 container edge). */
body.rolex-section .rlx-contact__label { padding-inline: 0; border-bottom: 1px solid rgba(33, 33, 33, 0.2); padding-bottom: 12px; }
/* Design-specs audit §1.7 (2026-08-17): Contact module — Message, Screen 1
   is "Brown Body24/Headline50." The CF7 shortcode's OWN internal Screen 1
   ("Please enter your message") already renders Brown per the audit's
   live test — untouched here, it's the multi-step plugin's own markup,
   outside this stylesheet. This rule instead covers the static heading
   this template renders BEFORE the CF7 embed ("Send us a message",
   h4.rlx-headline50) — same visual role, same spec line, so held to the
   same colour for consistency. */
body.rolex-section .rlx-contact__form .rlx-headline50 { color: var(--rlx-brown); }
body.rolex-section .rlx-contact .rlx-accordion__button { display: flex; justify-content: space-between; align-items: center; width: 100%; background: none; border: 0; padding: 16px 0; cursor: pointer; }
/* Uncropped, like every other Rolex editorial image (see
   memory/rolex-layout-12col-and-block-order.md). The delivered cover is
   2400x560 (4.286) and the mockup renders it 1624x382 (4.251, within
   measurement error) — the previous `aspect-ratio: 1080/400` + `object-fit:
   cover` cropped a 4.286 photo into a 2.7 box. */
body.rolex-section .rlx-contact__image { width: 100%; height: auto; display: block; }
body.rolex-section .rlx-contact__cover { display: block; }
/* overflow: the cf7mls plugin slides inactive step fieldsets horizontally
   beside the active one; without clipping they widen the page at every
   viewport (staging verification 2026-08-13: scrollWidth 1935/1920, 405/390). */
/* The white panel runs the FULL container width in the mockup (measured
   x 148-1770 = 1623px at 1920, i.e. the 1620 container), with only its
   CONTENTS centred in a ~800px column — the textarea measures 796px wide,
   centred on the page axis. It used to be a 720px-wide white card. */
/* padding-block 60/80, measured off the white panel in
   rolex-watches-model-page-mockup-send-a-message-desktop.jpg: panel y7545-
   8179, the headline's 58px line box starts y7626 (cap-top y7641 less the
   4px half-leading and the 10.6px ascender-to-cap of a 50px face), and the
   Next pill's box ends y8099. 60 + the kicker's own 23px line box lands the
   headline at y7628 against the comp's y7626. We shipped gap-half (45) on
   all four sides. The bottom is genuinely the larger of the two -- 80 from
   the pill to the panel edge against 60 above the kicker. */
body.rolex-section .rlx-contact__form { background: var(--rlx-surface); margin: 0 auto; padding-block: 60px 80px; padding-inline: var(--rlx-gap-half); text-align: center; overflow: hidden; }
body.rolex-section .rlx-contact__form > * { max-width: 800px; margin-inline: auto; }
/* Keep the cf7mls clip at the CONTENT column, not at the now-full-width
   panel: the plugin slides inactive step fieldsets horizontally beside the
   active one, and clipping at 1620 instead of 800 would let them show. */
body.rolex-section .rlx-contact__form .wpcf7 { overflow: hidden; }
/* `margin: 0 auto 4px`, NOT `margin: 0 0 4px`. The shorthand form resets
   margin-inline to 0, which overrode the `margin-inline: auto` this element
   inherits from `.rlx-contact__form > *` above — so the kicker's 800px box
   sat hard against the panel's left padding (measured: box left 195 where
   the H4's was 560) while its centred text drew at x595 instead of x960,
   under a heading and intro that were both correctly centred. Invisible at
   mobile, where the box is narrower than the 800px cap and the two margin
   values are equivalent. Reported by the client on a model page. */
/* No gap under the kicker: the comp butts the two line boxes (kicker ink
   ends y7628, the headline's cap begins y7641 -- 13px of ink separation,
   which is what two adjacent line boxes already give). */
body.rolex-section .rlx-contact__kicker { margin: 0 auto; }
/* 29 under the headline and 43 under the intro, both measured between LINE
   BOXES on the comp (headline box ends y7684, intro box y7713-7777, textarea
   y7820). 10px of the 43 is already the CF7 control wrapper's own margin-top,
   so this carries 33. Shipped values were 15 and 10. */
body.rolex-section .rlx-contact__form .rlx-headline50 { margin-block: 0 29px; }
/* 600, sized by the BREAK rather than by the comp's own line length. The
   comp sets this paragraph in two lines, splitting after "...Please enter
   your" (522px) with "message below and we will be delighted to assist you."
   (451px) beneath. Our body face renders ~7% wider than the comp's at the
   same nominal size, so at 560 the break fell one word early -- after
   "enter" -- and left a second line LONGER than the first, which is the
   bottom-heavy shape the client flagged. Anything from 560 to 648 reproduces
   the comp's break (the next word, "message", needs 649); 600 sits in the
   middle of that window rather than on its edge. */
body.rolex-section .rlx-contact__intro { max-width: 600px; margin-inline: auto; margin-block: 0 33px; }
body.rolex-section .rlx-contact__form .wpcf7 input[type="text"],
body.rolex-section .rlx-contact__form .wpcf7 input[type="email"],
body.rolex-section .rlx-contact__form .wpcf7 select,
body.rolex-section .rlx-contact__form .wpcf7 textarea {
	/* `font-size`, NOT `font`. `font: var(--rlx-fixed16)` expands to
	   `font: 16px`, which is an INVALID font shorthand (it needs a family
	   too), so the whole declaration was dropped and every field in this
	   block rendered at the theme's inherited 12px. Measured against the
	   mockup's own type — Body20 draws 19px of ink and Headline50 draws 47,
	   a consistent 0.94em — the textarea's placeholder draws 15px of ink,
	   i.e. a 16px font. So the intent was right and only the syntax was
	   wrong. */
	font-size: var(--rlx-fixed16);
	line-height: 1.5;
	width: 100%;
	padding: 12px;
	border: 1px solid rgba(33, 33, 33, 0.3);
	background: var(--rlx-bg);
}
/* The message box is 200px tall, measured off
   rolex-watches-model-page-mockup-send-a-message-desktop.jpg (the box runs
   y7820-8019 at x564-1359). It was rendering 50px: the OLD Bespoke-Lite
   stylesheet still sets `height: 50px` on
   `.wtp-rlx-message-wrapper label span.wpcf7-form-control-wrap textarea`,
   and this block simply never declared a height to beat it — which it does
   comfortably, (0,3,2) against (0,2,3). The form's `rows="10"` had no effect
   for the same reason. Reported by the client on a model page. */
body.rolex-section .rlx-contact__form .wpcf7 textarea { height: 200px; }
body.rolex-section .rlx-contact__form .wpcf7 input[type="submit"],
body.rolex-section .rlx-contact__form .wpcf7 button[type="submit"] { font-size: var(--rlx-fixed16); line-height: 1.5; background: var(--rlx-green); color: #fff; border: 0; border-radius: 24px; padding: 12px 28px; cursor: pointer; }

/* --- grid card (C, Task 4; wireframe fix 2026-08-17) -----------------------
   Shared card partial for every grid/carousel: collection archives, the
   watches hub carousel, the browse grid, the accessories grid, the Discover
   carousel. Watch variants (collection/model) get a 1/1 media box; the
   accessory variant (a packshot, both image keys the same URL) gets Rolex's
   800/1180 packshot ratio via the --accessory modifier, same override
   pattern as .rlx-hero--accessory.
   Wireframe fix: the panel background (--rlx-panel, #F4EFEA) now lives on
   the card ROOT, not just .rlx-card__media -- the mockup's tile color
   persists through the text rows below the image, with the page background
   resuming only past the tile's own edge (controller-verified probe: tile
   bg #f4efeb exactly, page bg #f8f7f3 resumes below it). .rlx-card__media
   itself is transparent now, on purpose: the delivered _collection packshots
   (see the image-source fix in card.php) already bake #f4efeb into all four
   corners, so an OPAQUE media background would just be a second, redundant
   coat of the identical color -- transparent lets the packshot's own baked
   background merge seamlessly with the tile behind it, no visible seam. */
body.rolex-section .rlx-card { display: block; color: inherit; text-decoration: none; background: var(--rlx-panel); }
/* NO PACKSHOT INSET, AT ANY WIDTH (2026-09-17, on instruction: "please also
   remove the padding on the rlx-card__media", asked of /rolex/watches/ and
   the collection archives such as /rolex/datejust/).

   NOT A COMP DEVIATION AFTER ALL -- this note said it was, for a few hours
   on 2026-09-17, and that was wrong. CORRECTED the same day against Rolex's
   own Design specifications (Brand Centre > Bespoke section > Design
   specifications > Our Rolex selection components), whose Featured selection
   diagram annotates the card "Watch asset 70% of the card height".

   Measured against that: the 54/42/0 inset rendered the asset at ~56.8% of
   card height. Removing it renders 68.2% on the collection grid and 64.6% on
   the carousel and watches hub. So the inset was the thing OUT of spec, and
   this change moves toward 70%, not away from it. What is left of the gap is
   our text block, which runs 31.8-35.4% against a specified 25% -- see the
   Brand Centre sweep doc; the likely cause is the attribute wrapping to two
   lines, which is a copy question, not this rule's.

   The spec draws the asset PORTRAIT and inset from the card's side edges,
   which is also what we now render even at padding 0: the delivered
   packshots are 800x1180 (0.678) and `object-fit: contain` in the square box
   below letterboxes them to 272x402 at a 402 tile, i.e. centred with ~65px
   of tile each side. The side inset comes from the asset, not from padding.

   The superseded 54/42/0 was decomposed from the mockups 2026-09-15 and did
   match them -- three comp cards (datejust rows 1 and 2, submariner row 1)
   put the "Rolex" kicker's ink 376px below the card top on a 402x518 tile,
   and 54 + a 318px box reproduced the comp's 95px watch-ink offset and 239px
   watch height, landing the kicker at 377. That derivation is kept because
   it is what was overridden, and because it is a worked example of a
   rendered comp and the published spec disagreeing: the comp is a rendering,
   the 70% is the rule.
   (The one figure that never matched was the watch's WIDTH, 109 against 97,
   which is not framing: the comp card is a Datejust 31 and ours a Datejust
   41, and packshots are height-normalised, so a smaller model is narrower.)

   It is also the SECOND time this has been asked. Mobile already ran this
   exact change -- "Ashton item 27, watch image sizes can be increased" --
   and the block that did it (a max-width:767px override to padding 0) is
   removed just below, because this rule now does its job at every width.
   Its finding stands and is worth keeping: measured off
   rolex-collection-datejust-mockup-mobile.jpg, the comp's watch ink is
   68x130 CSS on a 165x287 card; at a 13px inset ours was 54x104 (80% of
   the comp), and at zero it is 64x122 (94%). The last 6% is unreachable --
   it would need a 174px-tall media box on a 165px tile, and the delivered
   packshot's own internal whitespace is not ours to crop.

   Zero is what the assets expect either way: the delivered _collection
   packshots bake the tile colour into their four corners (see the
   --rlx-panel note), which is only worth doing if they meet the tile edge.

   Accessory tiles are unaffected -- they letterbox via their own
   .rlx-card--accessory rule below (max-width 240px desktop / 148px mobile),
   which already declared padding: 0 and still does. */
body.rolex-section .rlx-card__media {
	padding: 0;
}
body.rolex-section .rlx-card__media img { width: 100%; aspect-ratio: 1 / 1; height: auto; object-fit: contain; display: block; }

/* EQUAL CARD HEIGHTS (2026-09-14, Rolex staging review: "The cards end at
   different lengths, it should be a consistent size. Apply to accessories
   too.")

   .rlx-grid is a grid and its CELLS already stretch to the tallest in their
   row -- but .rlx-card sits INSIDE the cell as a plain block, so it only ever
   grew to its own content. Measured on submariner at 390: 340, 340, 302, 323,
   323, 323, i.e. up to 38px of ragged tile bottom. The card now fills its
   cell, so every tile in a row ends level and the tint runs to the same line.

   grid-auto-rows: 1fr takes it the rest of the way: without it the cells only
   matched their OWN row, so rows still stepped against each other (340 then
   323 on submariner, 360 then 381 on accessories) wherever a model name wrapped
   to two lines. Every tile in the grid is now the same height.

   Applies to both grids -- the watch collections and the accessories archive
   use the same .rlx-grid/.rlx-grid__cell/.rlx-card structure.

   EXTENDED 2026-09-15 to .rlx-hub__cell, the "Our Rolex selection" carousel
   on /rolex/watches/ (rolex-watches-hub.php), reported by the client. It
   holds the same .rlx-card but in a DIFFERENT cell class, so the rule below
   never matched it and the fix above had left it ragged: measured 564, 542,
   542, 564 -- the two cards whose attribute line wraps to two lines stood
   22px taller than the two that do not.
   Its cells were never the problem and are not touched: .rlx-hub__row is a
   grid, so all four cells already measured 564. Only the card inside needed
   to fill its cell, which is exactly the same defect and the same remedy.

   .rlx-ed-carousel__cell (the /rolex/ hub's 8-card carousel) is covered at
   the same time. It measures level TODAY, but only because those eight
   cards happen to carry same-length copy -- structurally it was as exposed
   as the two above. The guard in wp-check-restyle now derives the list of
   cell classes from the TEMPLATES rather than restating it, which is what
   surfaced this one and what will surface the next. */
body.rolex-section .rlx-grid { grid-auto-rows: 1fr; }
body.rolex-section .rlx-grid__cell,
body.rolex-section .rlx-hub__cell,
body.rolex-section .rlx-ed-carousel__cell { display: flex; }
body.rolex-section .rlx-grid__cell > .rlx-card,
body.rolex-section .rlx-hub__cell > .rlx-card,
body.rolex-section .rlx-ed-carousel__cell > .rlx-card { flex: 1 1 auto; display: flex; flex-direction: column; }

/* (The max-width:767px override that used to set .rlx-card__media padding
   to 0 lived here. Removed 2026-09-17 -- the base rule above is now 0 at
   every width, so it had become a no-op. Its measurement is carried in that
   rule's comment.) */
/* Accessory packshots are LETTERBOXED inside their tile at both breakpoints,
   not sized to the tile width. The comp's desktop tile is 400 wide and its
   rendered media 240x354 -- 80px of tile ground each side; mobile is a 165
   tile holding 148x218.5. Both are 800/1180 (0.678), so the delivered ratio
   is right at both breakpoints and only the SIZE was wrong: at full content
   width our media came out 338 wide and ~499 tall against the comp's 354.
   Established by template-fitting each delivered packshot against each tile
   (MAD 5.5-6.1 at 240 wide, rising to 10.1-15.6 when the search was biased
   toward a larger box), and cross-checked by ink-bbox ratio.

   The comp is hand-composed: 9 of 10 tiles are identical at these numbers
   and the desk-clock tile alone is drawn ~7% larger at desktop and ~12% at
   mobile. One rule cannot reproduce a hand-placed outlier, so this takes the
   value 9 of 10 tiles share rather than splitting the difference. */
body.rolex-section .rlx-card--accessory .rlx-card__media {
	/* No 32px inset on these. The comp puts the packshot 0-10px from the tile
	   top at desktop, and at mobile the inset left a 101px content box that
	   the 148px letterbox below could never reach -- the padding, not the
	   cap, was deciding the size. The letterboxing is the max-width. */
	padding: 0;
}
body.rolex-section .rlx-card--accessory .rlx-card__media img {
	aspect-ratio: 800 / 1180;
	max-width: 240px;
	margin-inline: auto;
}
@media (max-width: 767px) {
	body.rolex-section .rlx-card--accessory .rlx-card__media img { max-width: 148px; }
}
/* Text stack: wireframe measures Legend16 kicker, Body24/700 name, Legend16
   attribute + price (supersedes Task 5's Fixed14 kicker / Body20 x3 --
   card.php's own primitive classes carry the size/line-height/weight now,
   same "primitive class in markup" convention every other card-like
   partial in this project already uses, e.g. hub-tiles.php). Each row gets
   its own inline padding (block-level <p>s, each needs its own left/right
   inset to line up with the media's own 32px-padded content); only the
   stack's actual last row (kicker/name always render, attribute and price
   are each conditional, so which row is "last" varies per card) gets the
   tile's own 24px bottom padding, via :last-child rather than a fixed
   nth-of-type, so it's correct regardless of which optional rows are
   present. */
/* CARD INTERNAL PADDING, measured off the comps rather than assumed.
   It is RESPONSIVE and it is two authored values, not one number scaled:

     desktop  text inset 51px of a 402px tile (12.7%), price ink to tile
              bottom 74px
     mobile   text inset 12.5px of a 165px tile (7.6%), price ink to tile
              bottom 22px

   Verified on 9 desktop cards (3 rows x 3 columns of
   our-rolex-selection-mockup-desktop.jpg, all reading 51) and on the mobile
   mockup's own card stack, and independently re-measured on the watches-hub
   carousel and the accessories grid, which are the same component.

   The bottom figures are padding, not ink: the last line box sits ~5px
   (desktop) / ~3px (mobile) below its ink, so 69 and 19 land on the comp's
   74 and 22.

   NOT set on .rlx-card itself -- .rlx-card__media is a sibling with its own
   32px padding and would double-inset, shrinking the 330px packshot. */
body.rolex-section .rlx-card__kicker,
body.rolex-section .rlx-card__name,
body.rolex-section .rlx-card__attribute,
body.rolex-section .rlx-card__price {
	padding-inline: 50px;
}
/* BOTTOM INSET FOLLOWS THE SPEC, NOT THE COMP (Ernie's ruling, 2026-09-19).
   Rolex states 50 / 50 / 30 at Large / Medium / Small and sizes the card's
   text block at 25% of card height. We shipped 69 / 50 / 19, comp-derived:
   69 landed the desktop mockup's measured 74px of ink-to-tile-bottom.

   This is the FIRST recorded exception to `rolex-comp-source-precedence`.
   The rule says the rendered mockup outranks the spec sheet; Ernie overrode
   it for this value specifically. Recorded as an exception so the rule
   itself is not quietly assumed to have changed.

   WHAT 25% CANNOT DO, measured rather than assumed. Our text ink is 97-105px
   at EVERY breakpoint, because Rolex's card draws three text rows
   (Legend16 / Body24 / Legend16) and ours renders four — kicker, name,
   attribute, price. At Medium the ink alone is 105px against a 25% budget of
   82px, so the target is arithmetically out of reach there and at Small
   without dropping a row of real content. Large reaches 27%. The rest is
   content, not spacing, and is logged for a ruling rather than fudged. */
body.rolex-section .rlx-card > :last-child {
	padding-bottom: 50px;
}
/* MEDIUM STEP (2026-09-19). Rolex's Design specifications give this component
   -- "Featured selection", PDF p44-47, i.e. THIS carousel -- a per-breakpoint
   card inset: 50/50 Large, 30/50 Medium, 20/30 Small. We shipped only two of
   the three; the 50px inline ran unbroken from 768px up.

   The spec is the sole source here. Every mockup Rolex supplied is
   `-desktop` or `-mobile` (44 and 42 of them, no tablet variant anywhere in
   tmp/08.2026), so there is no comp to outrank it at Medium and
   `rolex-comp-source-precedence` leaves the spec governing.

   The 30 is taken as written. The bottom is NOT: Large stays at the
   comp-derived 69 (which lands the comp's measured 74px ink), so this steps
   69 -> 50 -> 19 rather than the spec's 50 -> 50 -> 30. That discontinuity is
   the deliberate consequence of following the comp at Large and the spec at
   Medium; it is logged as comp-vs-spec in the sweep doc, not an oversight. */
@media (min-width: 768px) and (max-width: 1024px) {
	body.rolex-section .rlx-card__kicker,
	body.rolex-section .rlx-card__name,
	body.rolex-section .rlx-card__attribute,
	body.rolex-section .rlx-card__price {
		padding-inline: 30px;
	}
	body.rolex-section .rlx-card > :last-child {
		padding-bottom: 50px;
	}
}
@media (max-width: 767px) {
	body.rolex-section .rlx-card__kicker,
	body.rolex-section .rlx-card__name,
	body.rolex-section .rlx-card__attribute,
	body.rolex-section .rlx-card__price {
		padding-inline: 12px;
	}
	body.rolex-section .rlx-card > :last-child {
		padding-bottom: 30px;
	}
}
/* No top margin: the 54/0 media inset above already carries the whole
   space between the packshot and the kicker, and the comp leaves none of
   its own (54 + 318 + 0 = 372, kicker ink at 376). A 16px margin here put
   it at 393. */
body.rolex-section .rlx-card__kicker { margin: 0; opacity: 0.7; color: var(--rlx-brown); }
body.rolex-section .rlx-card__name { margin: 4px 0 0; font-weight: 700; color: var(--rlx-brown); }
body.rolex-section .rlx-card__attribute,
body.rolex-section .rlx-card__price { margin: 2px 0 0; }

/* --- collection/accessories grid pages (C, Task 5) ------------------------
   Shared by taxonomy-rolex_family.php's two routes (17 watch-family archives
   + the accessories page). Rhythm follows the shell's existing
   --rlx-gap/--rlx-gap-half (clamp(45-90px)/clamp(24-45px)) tokens, matching
   the "10vh/90px rhythm" the datejust mockup shows between sections.
   NOTE: Cover aspect-ratio now uses --rlx-cover-ar token (Task 1 restyle);
   legacy 16/7 rule removed and replaced with token-based system. */
body.rolex-section .rlx-coll-hero { margin: 0; }
body.rolex-section .rlx-coll-hero picture,
body.rolex-section .rlx-coll-hero img { display: block; width: 100%; height: auto; }

/* P2 parity fix (2026-08-17): mockup's own annotated template
   (rolex-watches-template-desktop.jpg) measures this band's two columns at
   ~40/60, not the even 50/50 this shipped with — the Headline50 title
   column is visibly narrower than the Body20 intro column beside it. */
body.rolex-section .rlx-coll-intro {
	display: grid;
	/*
	 * TWO HALVES, not 2fr/3fr with a 64px gap.
	 *
	 * The right column starts at column 7 of 12 — x960 — in every comp that
	 * has one: accessories 965, datejust 967, contact 969, and the article
	 * pages 966 (which is why .rlx-article__intro already carried this split
	 * and no longer needs its own rule). 2fr/3fr + 64px started it at x841.
	 *
	 * The body column is 5 of 12, not the remaining 6: the widest body line
	 * reaches ~1608-1617 across these comps, 18-27px short of a 675px
	 * column's right edge and 150+ short of an 810px one. The twelfth column
	 * is deliberately empty.
	 */
	grid-template-columns: 50% 41.6667%;
	gap: var(--rlx-gap-half) 0;
	align-items: start;
}
/* DISCOVER ROLEX ONLY: the body column is pushed to the container's right edge
   (2026-09-14, Rolex staging review): "Have the introduction copy on the right
   hand side be right aligned with the edge of the assets on the page. Creating
   more space in the middle between the copy on the left hand side."

   This OVERRIDES a comp-derived decision, deliberately and on request. The
   note above records why the twelfth column is empty: across the accessories,
   datejust, contact and article comps the widest body line reaches ~1608-1617,
   short of the container edge, and the discover comp agrees. Rolex have asked
   for the body to line up with the image edge below it instead, which widens
   the middle gutter from 0 to 135px.

   Scoped to the page he raised it on rather than applied to every intro: the
   other pages' comps still show the short column, and changing those on the
   strength of a note about this page would be guessing at his intent. If he
   wants it everywhere, drop the page-template qualifier.

   Both body classes are required: wp-check-shell asserts every selector in
   this file stays inside body.rolex-section, so the page-template class
   QUALIFIES that scope rather than replacing it. */
/* EVERY PAGE SINCE 2026-09-28 (Rolex Staging Link #2 review: "This was
   corrected on the Discover Rolex page and should be applied to all pages
   within the Rolex section ... Have the introduction copy be more on the
   right-hand side"). The page-template qualifier is dropped exactly as the
   note above anticipated, and .rlx-nw-intro -- the New Watches intro, the
   same split under its own class -- takes it too. */
body.rolex-section .rlx-coll-intro,
body.rolex-section .rlx-nw-intro { justify-content: space-between; }
/* THE TAGLINE IS THE HEADLINE'S SECOND LINE, not a 24px subtitle.
   Measured on the datejust comp: the left column is two lines of 46px ink
   ("Rolex Datejust" / "Make a date of a day") in the SAME size and the same
   brown, against 16-19px ink for the body beside it. Rendered as a 24px
   regular-weight paragraph at 0.85 opacity, it read as a caption under the
   title instead of part of it. */
/* The intro heading is BROWN, not --rlx-ink. Measured in the left column
   (x148-900) of the datejust, submariner, explorer and sky-dweller
   collection comps, the watchmaking article, the single-POS contact page
   and the watches-selection page: every one is 100% brown pixels at
   (67,44,28) against our #452C1E, while the body column beside it is 0%
   brown at (32,32,30). A full-width scan hides this -- it mins to the ink
   column, whose sum 94 beats brown's 139 -- which is why an earlier pass
   read these headings as neutral. Scoped to this block, not to
   .rlx-headline50, for the same reason .rlx-availability does it here:
   a token-level recolour would over-apply brown to unrelated headings.
   12:1 on --rlx-bg, so well clear of the contrast floor. */
/* The h1 carries .rlx-headline50, which sets `color: var(--rlx-ink)` on the
   element itself, so a colour on this wrapper alone never reaches it --
   inheritance loses to a direct match every time. Hence the second
   selector, which outranks it 0,3,1 to 0,2,1. The tagline takes `inherit`
   and so follows the wrapper. */
/* The new-watches MODEL intro is the same shape as the collection one: a
   16px brown kicker over TWO 50px brown lines, not a 50px title with a grey
   24px subtitle. Measured in the left column (x149-725) of all five model
   comps -- cap height 36 => 50.2px on both lines, pitch 58 baseline to
   baseline, and 100% brown pixels at (67,44,28) on the kicker and both
   lines. The mobile comp settles it structurally: the run wraps mid-phrase
   ("Rolex Oyster Perpetual / 41 The echo of origins"), which can only happen
   if the two are one text flow. The deck agrees -- it delivers them as a
   single paragraph. */
body.rolex-section .rlx-nw-intro__kicker,
body.rolex-section .rlx-nw-intro__heading,
body.rolex-section .rlx-nw-intro__heading .rlx-headline50 { color: var(--rlx-brown); }
body.rolex-section .rlx-nw-intro__heading .rlx-headline50 { margin-bottom: 0; line-height: 1.15; }
body.rolex-section .rlx-nw-intro__tagline {
	margin-top: 0;
	font-size: var(--rlx-headline50);
	line-height: 1.15;
	font-weight: 700;
	color: inherit;
	opacity: 1;
}

body.rolex-section .rlx-coll-intro__heading,
body.rolex-section .rlx-coll-intro__heading .rlx-headline50 { color: var(--rlx-brown); }
/* One 57px pitch across both lines. The h1's 24px margin-bottom made it 79,
   which reads as two stacked headlines rather than one two-line headline.
   The comps measure ink-top to ink-top at 57/58/58/58 (datejust, submariner,
   explorer, sky-dweller) on a 50px face = 1.15, where the section token
   --rlx-lh-headline is 1.10 (55px). Scoped to this block rather than moving
   the token, which every other headline in the section is set from. */
body.rolex-section .rlx-coll-intro__heading .rlx-headline50 {
	margin-bottom: 0;
	line-height: 1.15;
}
body.rolex-section .rlx-coll-intro__tagline {
	margin-top: 0;
	font-size: var(--rlx-headline50);
	line-height: 1.15;
	font-weight: 700;
	color: inherit;
	opacity: 1;
}
/* 1.5 HERE, against the section's 1.6 token. The --rlx-lh-body comment
   above records the measurement and the reason it could not be acted on:
   the two-column intro blocks measure a 30px pitch on a 20px face while
   nearly all other body copy measures 32, and one token cannot be both.
   A scoped rule can. This matters more now that the bold lede breaks into
   its own paragraph: the gap below is `1lh`, so the comp's 60px
   across-the-break pitch only comes out right when the line box is 30.
   Client ruling, 15 Sep 2026: the JPG mockups govern over the spec PDF. */
body.rolex-section .rlx-coll-intro__body { margin: 0; line-height: 1.5; }
@media (max-width: 767px) {
	body.rolex-section .rlx-coll-intro { grid-template-columns: 1fr; }
}

/* Grid: repeat(3, minmax(0,1fr)) desktop, 1-col mobile, per the brief. */
/* THE CARD WELL IS 1222px, CENTRED — not the 1620 container.
   Measured identically on three comps: datejust and submariner put their
   three cards at x349-750, x759-1160, x1169-1570 (402 each, 8px gutters,
   well 1222 centred on 959) and accessories at x352/x760/x1168 (400 each,
   well 1216). Rendered across the full container the same three cards came
   out 494 wide with 45px gutters.
   The selection page reuses this grid beside its filter rail and sets its
   own width below — there the well is the column it is given, not a centred
   1222. */
body.rolex-section .rlx-grid {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: var(--rlx-card-gap);
	width: min(1222px, 100%);
	margin-inline: auto;
}
body.rolex-section .rlx-selection-layout .rlx-grid { width: 100%; }
/* This page is the one place a .rlx-container sits INSIDE another: the whole
   layout is a container, and grids/grid.php wraps its grid in a second one.
   Both applied the page gutter, so the cards were inset 27 twice and came
   out 138 wide at x54 instead of 165 at x27 -- invisible at desktop, where
   1620 is capped by --rlx-container-max long before the gutter bites, and
   only exposed once the mobile gutter became a real number. Neutralised
   here rather than globally, because the article and contact templates
   deliberately nest a narrower .rlx-container inside a full-bleed section. */
body.rolex-section .rlx-selection-layout .rlx-container { width: 100%; margin-inline: 0; }
body.rolex-section .rlx-grid__cell.rlx-card--hidden { display: none; }
/* Two DIFFERENT hidden states, both display:none, deliberately not merged.
   --hidden means "matches the filter, but sits past the load-more batch";
   --filtered means "does not match the current filter at all". Load more
   reveals the first and must never reveal the second, so the filter script
   can toggle each without disturbing the other. display:none (not
   visibility) keeps the grid's auto-rows sizing to the visible cards only. */
body.rolex-section .rlx-grid__cell.rlx-card--filtered { display: none; }
body.rolex-section .rlx-grid__loadmore { text-align: center; margin-top: var(--rlx-gap-half); }
body.rolex-section .rlx-grid__loadmore--hidden { display: none; }
@media (max-width: 767px) {
	/* TWO columns at mobile, not one. Measured across all 16 collection
	   comps plus selection and accessories: tile 330 device / 165 CSS,
	   gutter 12 / 6, well 672 / 336. Settled by scanning datejust's whole
	   grid band every 4px -- 438 of 438 non-blank lines show two runs, none
	   shows a single 672 -- and confirmed by air-king, whose ONE product
	   card sits at x54-383 and does not stretch to the well, which only a
	   fixed two-column track does. One column made the accessories grid
	   6282 CSS px tall against the comp's ~1400. */
	body.rolex-section .rlx-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 6px; }
}

/* Quote: serif, Quote50-scale, left; attribution Body20.
   Design-specs audit §0.4/§1.3 (2026-08-17): spec has a dedicated Quote50
   token (Georgia, 40/50/50/50 across the 4 breakpoint columns — see the
   responsive-ramp block near the type primitives above); this previously
   borrowed --rlx-headline36 (a sans-serif token, overridden to Georgia
   here) as a stand-in, capping quote text at 36px and never reaching
   spec's 40-50px range at any breakpoint. Now uses --rlx-quote50 directly.
   Line-height CORRECTED 2026-09-12 to the spec's 1.3. It had been left at
   --rlx-lh-headline deliberately ("out of scope for this pass"), which also
   meant it silently tracked that token -- so when the headline token moved to
   1.2 this would have drifted again. Now stated in its own token: spec
   pp.5-6, "Quote50 Georgia regular - Line-height 1.3" at both the L (40px)
   and XL (50px) columns. */
/* The parent theme styles every `blockquote` as a pull-quote panel:
   italic, #f6f6f6 ground, a 2px #bbb left rule and 20px of padding. This
   element IS a <blockquote>, so all four leaked in -- pushing the ink to
   x577 against the comp's x556 and boxing the quote in a grey card the
   mockup does not have (datejust desktop comp: roman Georgia on the plain
   section ground, no rule, no panel). Reset all four here rather than
   changing the markup: the element is semantically correct as a
   blockquote, and the theme rule is not ours to edit. */
body.rolex-section .rlx-quote__text {
	margin: 0;
	padding: 0;
	border: 0;
	background: none;
	font-style: normal;
	font-family: var(--rlx-font-serif);
	font-size: var(--rlx-quote50);
	line-height: var(--rlx-lh-quote);
	color: var(--rlx-ink);
}
body.rolex-section .rlx-quote__text p { margin: 0; }
body.rolex-section .rlx-quote__attribution { margin-top: 16px; opacity: 0.7; }
/* THE LINE UNDER THE QUOTE IS A HEADLINE, NOT A 24px NOTE.
   On the datejust comp it is four lines of BROWN bold running x557-1319 at
   y3627-3846 -- 46px of ink per line (cap+descender on a 50px face) and a
   58px pitch. We shipped 24px green over two lines. The placement work done
   here earlier was right; the size and the colour were carried assumptions,
   and sampling that exact band gives rgb(69,44,29), while the same sampler
   returns rgb(18,119,73) on the page's genuinely green element higher up --
   so the method distinguishes them. */
body.rolex-section .rlx-quote__subheading {
	margin-top: var(--rlx-gap-half);
	/* A bare <p>, so it inherits the THEME's face (Hind) -- `body` is Hind
	   and the section sets its own face per element, not on body. Every
	   other text class in the section carries one; this one did not, and it
	   was the only element in the section still rendering Hind. */
	font-family: var(--rlx-font-sans);
	font-size: var(--rlx-headline50);
	/* 58px pitch on a 50px face; the section headline token is 1.10 (55px). */
	line-height: 1.16;
}
/* Quote: ONE centred six-column column, stacked — quote, attribution, then
   the green subheading beneath it.

   This was a two-column grid, serif quote left and green subheading right,
   on the stated grounds that it was "the datejust mockup's layout". It is
   not, and re-measuring the mockup is what showed it: datejust's quote ink
   runs x556-1328, its attribution x557-721 and its green subheading
   x556-1319 — all three starting at x556, i.e. column 4 of 12, and stacked
   vertically (quote y3249-3471, attribution y3472-3517, subheading
   y3627-3846). Submariner, day-date and explorer measure the same column to
   within 2px. `max-width: none` also defeated .rlx-container, which is why
   the two columns spanned the full 1920 with the quote flush at x24.
   Reported by the client on /rolex/datejust/. */
body.rolex-section .rlx-quote__inner {
	width: min(calc(var(--rlx-container-max) / 2), 100% - var(--rlx-container-inset));
	max-width: none;
	margin-inline: auto;
	padding-inline: 0;
	text-align: left;
}
body.rolex-section .rlx-quote__subheading {
	color: var(--rlx-brown);
	font-weight: 700;
	/* The comp's gap from the attribution to the green paragraph measures
	   110px (datejust: attribution ends y3517, subheading ink starts y3627),
	   which is the full block gap plus this paragraph's own leading — not
	   the half gap this used to take. */
	margin-top: var(--rlx-gap);
}

/* Editorial blocks: centered single-column text, full/large image(s) below —
   alternating rhythm per the datejust mockup (full-bleed video/photo panels
   between centered text blocks). A 2-SEPARATE-STEM slot (cosmograph-daytona's
   "Calibre 4131"/"Oysterflex bracelet") renders as a 2-up row; a single pair
   is one full-width image; a text-only block (datejust's "The Cyclops lens")
   renders no media at all. */
/* NOTE (2026-08-23 layout parity): NO `margin-inline: 0` here. The template
   renders `<div class="rlx-container rlx-editorial__copy">` -- one element,
   both classes, equal specificity (0,2,1) -- so whatever this rule declares
   beats .rlx-container above, which is ~1070 lines earlier. Zeroing
   margin-inline here therefore cancelled the container's own centring and
   hard-left-aligned the column (measured 0.000-0.396 of viewport at 1920
   against a 0.290-0.710 mockup census). Left ALIGNMENT is text-align;
   left POSITION would need a modifier class, never a cancellation here.

   THE MEASURE IS 854px, NOT 760px, AND THE 48px IS THE POINT (Task 4).
   Because both classes land on ONE element, this column carries
   .rlx-container's `padding-inline: 24px` itself -- so max-width sizes the
   BORDER box while the mockup census reads INK. Rolex's editorial column is
   x=557-1364 of 1920, i.e. 806px of text; 806 + 24 + 24 = 854. At 760px the
   text measured 604-1316 = 0.315-0.685 against a censused 0.290-0.710 --
   0.025 out, just past the 0.02 tolerance, and invisible while the sweep
   compared border boxes (760px centred reads 0.302-0.698, an apparent 0.012
   'pass' that the padding on both sides was cancelling out).
   At 854px the text lands on 557-1363 = 0.290-0.710. Below 854px the
   max-width does not bind at all, so mobile is untouched: the column is
   full-bleed and its text sits at the 24px padding either side (0.062-0.938
   against a censused 0.071-0.931, inside tolerance). Anything that changes
   .rlx-container's padding-inline must change this number with it. */
/* .rlx-editorial--media-first WAS a DOM-order class with no declarations of
   its own. It now needs one, and this is the "future order-dependent rule"
   its old comment anticipated.

   .rlx-editorial__media below carries `margin-top: var(--rlx-gap-half)` —
   the 5vh/45px the model-page wireframe puts between a heading+body and its
   OWN image, correct while the copy always came first. Flipping collection
   pages to media-first moved that margin ABOVE the image, where it merely
   padded the 90px section gap out to 135px, and left NOTHING between the
   image and the copy underneath it: the heading butted straight against the
   photograph (reported on /rolex/explorer-ii/, reproduced at 0px on all six
   of its editorial blocks). The copy's own trailing paragraph margin had
   been supplying that gap by accident in the old order.

   90px, not 45px, and measured rather than assumed: on the day-date and
   submariner comps the distance from an image band's bottom edge to the next
   text's INK is 98-111px in both directions (99/100/103/104/105 image→text,
   98/98/100 text→image). Ink sits ~10px below a Headline's line box, so the
   box-to-box gap Rolex draws here is the same --rlx-gap (10vh/90px, 60px on
   mobile) as between blocks — there is no 45px step on this page type. */
body.rolex-section .rlx-editorial--media-first .rlx-editorial__media {
	margin-top: 0;
	margin-bottom: var(--rlx-gap);
}
/* ...BUT --media-first is a DOM-ORDER class that does not always describe the
   DOM. RLX_Panel_Map::COPY_SPLIT_AROUND_NEXT reorders a block's children into
   copy, media, copy so part of the copy sits BENEATH the image (the comp puts
   the caliber paragraph there). The block keeps its --media-first class, so
   the `margin-top: 0` above still applied, and the leading copy butted
   straight against the photograph at 0px.

   Reported on /rolex/deepsea/ 2026-09-23 and measured there: the copy box
   ended at y3210 and the picture began at y3210. It is the same defect the
   comment above records on /rolex/explorer-ii/, arriving from the opposite
   direction — there the image lost its gap BELOW, here the image loses its
   gap ABOVE.

   Restores the component's own `margin-top: var(--rlx-gap)` (see the base
   rule's own measurements) for the one arrangement the override should never
   have covered, keyed on a copy ACTUALLY preceding the media rather than on
   the class claiming it does not. (0,4,1) beats the (0,3,1) above, so the tie
   is explicit and not a source-order accident. A true media-first block has
   no copy sibling before its media and cannot match.

   Swept before changing it: of the section's collection, hub and accessories
   pages, exactly one element matched at 0px (deepsea). /rolex/accessories/
   already measured a correct 90px, because its block is not --media-first and
   so never lost the base margin. */
body.rolex-section .rlx-editorial--media-first .rlx-editorial__copy + .rlx-editorial__media {
	margin-top: var(--rlx-gap);
}
/* THE 24px MUST BE RESTATED HERE NOW. The measure above is still right --
   806px of censused ink inside an 854px border box -- but its premise is
   not: it relied on this element inheriting `.rlx-container`'s
   `padding-inline: 24px`, and the container was later rewritten to
   `width: min(1620px, 100% - 48px); padding-inline: 0` so that full-width
   ink could reach x148-1771. From that point the padding was 0, the 854
   sized the CONTENT box, and the column rendered at x533-1387 with its ink
   24px left of the comp's x557 on every editorial page in the section.
   Measured independently on the collection archives (comp ink x557) and the
   New Watches pages (x556-557) against our x533.
   Nothing in the CSS text changed, which is exactly why the guard on this
   line kept passing: it asserted the declaration, not the rendered result.
   `.rlx-ed-retailer__block` below already restates its own 24px and
   measures correctly -- this is the same pattern, for the same reason. */
body.rolex-section .rlx-editorial__copy { max-width: 854px; padding-inline: 24px; text-align: left; }
/* --copy: media at the copy column's own measure. Same 854 border box and
   24px inset as .rlx-editorial__copy above, so the image and the paragraph
   under it share one edge. */
/* (0,3,1) so it beats the same-specificity --single-landscape width rule
   that ships later in this file; the class alone was applied and ignored. */
body.rolex-section .rlx-editorial .rlx-editorial__media--copy {
	max-width: 854px;
	padding-inline: 24px;
	margin-inline: auto;
	width: 100%;
}
body.rolex-section .rlx-editorial .rlx-editorial__media--copy img { width: 100%; height: auto; }

/* MOBILE: the 24px inset above is part of the DESKTOP 854 measure
   (806 ink + 24 + 24) and must not survive the breakpoint.
   At mobile `.rlx-editorial__copy` is already a `.rlx-container`, so the
   well supplies the whole gutter (390 - 54 = 336 at x27); its own 24px
   then insets the TEXT a second time, to x51/288 wide. Every one of the
   16 collection mobile comps puts its dominant ink edge at x27 (780px
   comps, ink L=54; measured as a left-edge histogram over all of them,
   with no cluster at 51 on any page), for images and body copy alike.
   The `--copy` media is NOT a container -- it is a plain full-width child,
   so at mobile its own max-width/padding drew 342 at x24, 6px proud of
   the well on the wrong side. Same shape as the `.rlx-article__video`
   fix below: take the inset from the token, not from `width: 100%`. */
@media (max-width: 767px) {
	body.rolex-section .rlx-editorial__copy { padding-inline: 0; }
	body.rolex-section .rlx-editorial .rlx-editorial__media--copy {
		max-width: none;
		padding-inline: 0;
		width: calc(100% - var(--rlx-container-inset));
	}
}
/* The copy's last paragraph carries a 10px bottom margin that ESCAPES the
   section (the section is a plain block, so its box ends at that
   paragraph's border edge). Mid-page that escaped margin collapses with the
   90px section margins either side and loses — every content-to-content gap
   measures exactly 90. But .rlx-main is `display: flow-root`, so at the END
   of the main band the escaped margin is CONTAINED and adds to main's own
   90px padding-bottom: the last editorial sat 100px above Keep exploring on
   every collection page where the model page's last block (.rlx-push, which
   ends in an inline CTA) sat at 90. Zeroing it costs nothing mid-page and
   squares the one boundary that was off-rhythm. */
body.rolex-section .rlx-editorial__copy > :last-child { margin-bottom: 0; }
/* 26px, not 12. Measured ink-bottom to ink-top on the datejust comp's
   editorial column at five separate blocks -- 31, 30, 30, 30, 30 -- against
   our 16. The heading's line box sits ~4px below its ink, so 26 lands on 30.
   Corroborated independently on the collection archives and the New Watches
   pages, which share this rule. */
body.rolex-section .rlx-editorial__copy h2 { margin: 0 0 26px; }
/* The subheading CONTINUES the heading rather than sitting under it. Rolex's
   collection comps set the pair as one headline: on the Explorer mockup
   "Superlative Chronometer" and "certification" are the same size, the same
   Brown and 57px apart -- headline50 at line-height 1.2, i.e. consecutive
   lines of one block, no gap between them. It used to render body24 at 0.85
   opacity, which is what Ashton flagged on 2026-09-13 (items 21/22 with the
   Explorer screenshot, and item 26: "should be bolded").

   The h2's 12px is the heading-to-BODY gap, so it is cancelled only when a
   subheading actually follows. rlx-editorial__subheading stays LAST in the
   class attribute -- wp-check-grids greps `rlx-editorial__subheading">`. */
body.rolex-section .rlx-editorial__copy h2:has( + .rlx-editorial__subheading ) { margin-bottom: 0; }
body.rolex-section .rlx-editorial__subheading { margin: 0 0 12px; }
body.rolex-section .rlx-editorial__media {
	/*
	 * A FULL gap above the image, not the half gap.
	 *
	 * The half gap is the model-page idiom — 45px binds a heading to its own
	 * image, 90px separates blocks, and the model wireframe annotates that
	 * outright. It was applied to .rlx-editorial as well, where no comp uses
	 * it. Measured copy-ink-bottom to image-top: new-watches op41 95 / 94 /
	 * 95, watchmaking 124 / 111 / 106, oyster-story 95, servicing 106 — the
	 * same ~90px block gap as everything else on those page types, never 45.
	 * The media-first path above already used the full gap, so the two
	 * directions were asymmetric: 88px above a heading, 45px below it.
	 *
	 * Scoped originally to .rlx-article; the new-watches measurement showed
	 * it is the component's own behaviour, so it moves here and that
	 * override is gone.
	 */
	margin-top: var(--rlx-gap);
	display: grid;
	grid-template-columns: 1fr;
	gap: 2px;
}
body.rolex-section .rlx-editorial__media--twoup { grid-template-columns: repeat(2, minmax(0, 1fr)); }
body.rolex-section .rlx-editorial__image img { display: block; width: 100%; height: auto; aspect-ratio: 16 / 10; object-fit: cover; }
/* MOBILE BOX FOLLOWS THE MOBILE ASSET (2026-09-09). Desktop keeps 16/10,
   which is right: above 768px this <picture> serves the LANDSCAPE stem.
   Below it, it serves the `-portrait` companion, and the box did not change —
   the same defect the Discover hero slide had, one component along.
   Measured on the rendered pages at 390px: every editorial image on
   /rolex/deepsea/, /rolex/submariner/ and /rolex/datejust/ — 14 of 14, none
   landscape — served a portrait file (0.451 to 0.906) into this 1.6 box.
   Rolex's own collection mobile comps put that slot at 672x841 = 0.7990, and
   both comps checked agree to four decimals:
     rolex-collection-deepsea-mockup-mobile.jpg        672x841
     rolex-collection-gmt-master-II-mockup-mobile.jpg  672x841
   4/5 is 0.8000, i.e. the comp within 0.1%, and is already this file's
   two-up value, so the section keeps one portrait ratio rather than two.
   RESIDUAL CROP, STATED: the tallest delivered companions are 780x1730
   (0.451) — a phone-shaped frame that still loses height in a 4/5 box. That
   is what the comp specifies; matching the asset instead would make those
   blocks about twice the height of every neighbouring one. */
body.rolex-section .rlx-editorial__media--twoup .rlx-editorial__image img { aspect-ratio: 4 / 5; }
/* SUPERSEDED 2026-09-11: the mobile box is the PORTRAIT ASSET'S OWN SHAPE.
   The 4/5 above was read off two slots on two comps; measuring all 116
   editorial images across the 17 collection mobile comps gives roughly 20
   distinct ratios, and 0.78-0.80 covers only about 25 of them. The box is
   width 336 (390 when the slot bleeds) with the height falling out of the
   asset -- exactly what the desktop --single rule further down already does
   and says, and what the cover does section-wide.

   The old note's stated "residual crop" was the tell, and it was wrong: it
   said a 780x1730 companion (0.451) "still loses height in a 4/5 box ...
   that is what the comp specifies". The comp specifies no such thing --
   datejust's slot measures 336.5x746.5 = 0.451 on the mobile comp, i.e. the
   asset uncropped. object-fit: fill (not cover) because with height auto
   there is nothing to crop, and fill cannot letterbox. */
@media (max-width: 767px) {
	body.rolex-section .rlx-editorial__image img,
	body.rolex-section .rlx-editorial__media--twoup .rlx-editorial__image img {
		aspect-ratio: auto;
		height: auto;
		object-fit: fill;
	}
}
@media (max-width: 767px) {
	body.rolex-section .rlx-editorial__media--twoup { grid-template-columns: 1fr; }
}

/* P9 parity fix (2026-08-17): a single image sizes by its own orientation
   -- landscape ≈2/3 container width, portrait ≈5/12 -- left-aligned within
   the same container the text column above uses. Only the 2-image
   --twoup pair (the "know-how PAIR", e.g. cosmograph-daytona's "Calibre
   4131"/"Oysterflex bracelet", unchanged above) and text-only blocks stay
   full-bleed. Sizing lands on the wrapper + the picture element, not the
   <img>, so the existing aspect-ratio/object-fit rule above keeps working
   unmodified underneath -- only how much of the section's width that box
   occupies changes. */
/* WIDTH, NOT MAX-WIDTH-PLUS-PADDING (corrected 2026-09-10). This box is what
   the 12-column spans below are percentages OF, so its content box has to be
   the container itself. With `max-width: 1620px` + `padding-inline: 24px` the
   content box was 1572 at any wide viewport, so a 10/12 span measured
   83.3333% of 1572 = 1310px where Rolex's comp has 1350 -- every band 40px
   narrow, which is exactly what the rendered measurement showed.
   `width: min(container, 100% - 48px)` keeps the same 24px breathing room at
   narrow viewports while making the box exactly 1620 once there is room. */
body.rolex-section .rlx-editorial__media--single-landscape,
body.rolex-section .rlx-editorial__media--single-portrait {
	width: min(var(--rlx-container-max), 100% - var(--rlx-container-inset));
	max-width: none;
	margin-inline: auto;
	padding-inline: 0;
}
/* SINGLE-IMAGE WIDTHS AND ALIGNMENT, CORRECTED 2026-09-10 (reported: "lower
   page content is missaligned" on a collection page, and again on a model
   page, with "please ensure all pages have correct alignment").

   What was here: 66.6667% / 41.6667%, `justify-self: start`, measured off one
   mockup in the 2026-08-17 "P9 parity fix". Two problems, both measured.

   1. LEFT-ALIGNED, WHERE ROLEX CENTRES. Every single-image block in both
      comps is symmetric about the page centre. Ours sat at the container's
      left edge (measured 0.091-0.636 at 1920), leaving the whole right third
      empty next to a copy column that starts at 0.290 — which is what reads
      as misaligned.
   2. THE PERCENTAGES MATCHED NEITHER COMP NOR THE SPEC. The design-specs
      audit (docs/superpowers/qa/2026-08-17-design-specs-audit.md §1.3) had
      already flagged this: Rolex's Image component defines DISCRETE width
      steps (~100 / 83 / 50% of content width) and 66.7%/41.7% "lands on
      neither spec's 83% nor 50% step".

   Measured off the comps, which agree on exactly two steps, both centred:
     rolex-collection-deepsea-mockup-desktop.jpg
       x=557-1363 of 1920 -> 0.290-0.710, 807px = 51.3% of the 1572px content
       x=284-1635          -> 0.148-0.852, 1352px = 86.0%
     rolex-new-watches-2026-page-template-oyster-perpetual-36-desktop.jpg
       x=557-1363 (x2)     -> 0.290-0.710, 807px = 51.3%
       x=284-1636 (x2)     -> 0.148-0.853, 1352px = 86.0%
   51.3% is the spec's ~50% step and lands the image exactly on the text
   column (0.290-0.710 is the censused `text` ratio); 86.0% is the ~83% step.
   Each block was attributed by cropping the comp and reading the copy
   directly above it, not by assuming which block was which.

   WHAT IS STILL AN APPROXIMATION, and worth a Link #1 question: in the comps
   BOTH steps are used on landscape-shaped photographs, so orientation is not
   what Rolex selects on — the width is an editorial choice per block, which
   is the "4 width variants, NOT BUILT as a generic component" delta the audit
   records. Until a per-block width lands in the data, this maps our two
   existing orientation variants onto the two measured steps: landscape -> the
   83% step, portrait -> the 50% step. Both now sit on a real measured
   position instead of an invented one. */
/* SUPERSEDED 2026-09-10 by the 12-column spans below, and the note above is
   what pointed at them: "the width is an editorial choice per block ... 4
   width variants, NOT BUILT as a generic component". They are four column
   spans, they ARE derivable, and the signal is the shape of the file Rolex
   delivered plus whether the block leads the page. Measured as fractions of
   the 1620px container on their 1920px comps:

     bleed  100vw   the 2880x1050 XL deliveries, edge to edge
     12/12  1.000   the LEAD art band
     10/12  0.833   everything else  (was approximated as 86%)
     6/12   0.500   portrait deliveries  (was approximated as 51.3%)

   The old orientation-derived pair is gone rather than kept as a fallback:
   every single-image block now carries exactly one span class from
   RLX_Asset_Resolver::span_for(), so a block with an unreadable file lands on
   span10 -- the commonest width -- instead of silently keeping a second,
   contradictory rule alive. */
/* A TWO-UP IS SPANNED AS A PAIR, not per image. The width rule above names
   only the --single-* variants, so a two-up never got a container width at
   all and sat full-bleed: measured on oyster-perpetual, the media was 1920
   at x0 with two 959px halves. No comp does that -- every 2-up across the 17
   collection desktop comps sits in the ten-column well at x283-284, width
   1350-1360, and submariner's LEAD pair at x148 in the twelve.

   So the span sizes the MEDIA here and each image fills its own cell, rather
   than the single-image path's "each image is a percentage of a full-width
   media". Rolex composes these as one wide asset with the gutter baked in;
   we hold two files in a 2px grid. Same outer box, which is the point. */
body.rolex-section .rlx-editorial__media--twoup {
	width: min(var(--rlx-container-max), 100% - var(--rlx-container-inset));
	max-width: none;
	margin-inline: auto;
	padding-inline: 0;
}
body.rolex-section .rlx-editorial__media--twoup.rlx-editorial__media--span10 {
	width: min(calc(var(--rlx-container-max) * 0.833333), 100% - var(--rlx-container-inset));
}
body.rolex-section .rlx-editorial__media--twoup.rlx-editorial__media--span6 {
	width: min(calc(var(--rlx-container-max) / 2), 100% - var(--rlx-container-inset));
}

/* A bleed-ratio image lifted out of a multi-image block (see
   templates/rolex/grids/editorial-block.php). Same 100vw escape
   .rlx-image-block--bleed uses, because .rlx-editorial__media is inside the
   section's centred container and cannot reach the viewport edge otherwise.

   aspect-ratio:auto and height:auto are stated so the file renders at its own
   shape: these are the 2880x1050-class assets the 4/5 two-up cell was cropping
   by ~70%, and the comps run them uncropped at 1920x700. Placed BEFORE the
   three span rules below so it does not fight them -- it carries no span
   class, so there is nothing to tie-break. */
body.rolex-section .rlx-editorial__media--bleed {
	width: 100vw;
	max-width: none;
	margin-inline: calc(50% - 50vw);
	padding-inline: 0;
	grid-template-columns: 1fr;
}
body.rolex-section .rlx-editorial__media--bleed .rlx-editorial__image { width: 100%; justify-self: stretch; }
body.rolex-section .rlx-editorial__media--bleed .rlx-editorial__image img {
	width: 100%;
	height: auto;
	aspect-ratio: auto;
	object-fit: fill;
}

body.rolex-section .rlx-editorial__media--span12 .rlx-editorial__image { width: 100%; justify-self: center; }
body.rolex-section .rlx-editorial__media--span10 .rlx-editorial__image { width: 83.3333%; justify-self: center; }
body.rolex-section .rlx-editorial__media--span6 .rlx-editorial__image { width: 50%; justify-self: center; }
/* AFTER the three span rules above, deliberately. Those are (0,3,1) and so
   is this; at equal specificity the later rule wins, and with this block
   placed first each half of a two-up came out 83.33% of its own cell -- 562
   inside a 674 track, inset from both edges. The media box measured right
   (1350 at x285) while the images did not, which is why the box alone was
   not enough to verify it. */
body.rolex-section .rlx-editorial__media--twoup .rlx-editorial__image {
	width: 100%;
	justify-self: stretch;
}

/* UNCROPPED. The forced `aspect-ratio: 16/10; object-fit: cover` above is
   right for the two-up pairs and wrong for a single delivered file: Rolex
   renders each at its own shape, which is why the delivered ratio and the
   ratio of the comp band it occupies agree file for file (day-date: 1.818 vs
   1.830, 0.833 vs 0.807, 2.743 vs 2.759). With the crop in force, day-date's
   President-bracelet image -- delivered 1200x1440 PORTRAIT -- was being
   letter-boxed into a landscape box and losing the top and bottom of the
   bracelet. `height: auto` + no aspect-ratio lets the file be its own shape.

   Desktop only. The mobile comps have not been measured yet, so the 4/5
   mobile box below stays exactly as it was rather than being changed on a
   guess. */
@media (min-width: 768px) {
	body.rolex-section .rlx-editorial__media--single .rlx-editorial__image img {
		aspect-ratio: auto;
		height: auto;
		object-fit: fill;
	}
}

/* AN EDITORIAL BLOCK CAN BE FULL-BLEED TOO, and this was missing on the first
   pass -- span_for() returns 'bleed' for any 2880x1050-shaped delivery, and
   seven collections put one on an EDITORIAL block (air-king, datejust,
   explorer, explorer-ii, lady-datejust, land-dweller, submariner), not just on
   a copy-less band. Confirmed against Rolex's comps: submariner's second art
   band and datejust's fifth both run x 0-1919 and both belong to a block that
   has a heading. Without this rule those seven rendered their bleed image at
   container width, silently, because the class existed and nothing matched it.

   Only the MEDIA goes edge to edge -- .rlx-editorial__copy keeps its own
   container, which is why this sits on the media wrapper and not the section.
   Declared after the span rules above so it wins on equal specificity. */
body.rolex-section .rlx-editorial__media--bleed {
	width: 100vw;
	max-width: none;
	margin-inline: calc(50% - 50vw);
	padding-inline: 0;
}
body.rolex-section .rlx-editorial__media--bleed .rlx-editorial__image { width: 100%; justify-self: stretch; }
@media (max-width: 767px) {
	body.rolex-section .rlx-editorial__media--span12 .rlx-editorial__image,
	body.rolex-section .rlx-editorial__media--span10 .rlx-editorial__image,
	body.rolex-section .rlx-editorial__media--span6 .rlx-editorial__image {
		width: 100%;
	}
}

/* Image block (reconciliation slice, Task 3): copy-less picture band --
   same P9 orientation-sizing values as the single-image editorial rule just
   above (landscape ≈2/3 container width, portrait ≈5/12, left-aligned).
   The section itself already carries .rlx-container (max-width/margin-inline
   /padding-inline applied there, same rule the editorial media wrapper
   above duplicates onto itself) -- so only the <picture> needs a width
   modifier here; no separate centering rule is needed. */
body.rolex-section .rlx-image-block img { width: 100%; height: auto; display: block; }
/* <picture> has no block-level UA default (unlike the editorial version's
   .rlx-editorial__image, which is blockified for free as a CSS Grid item of
   its display:grid parent) -- this section isn't a grid, so `display: block`
   is set explicitly here or the width percentages below would not apply. */
body.rolex-section .rlx-image-block picture { display: block; }
/* Same two measured steps as the editorial single image above, and centred
   for the same reason. The copy-less band is the block the Deepsea comp shows
   at y5985 and y10052 — no heading above it, x=284-1635 = 0.148-0.852 — which
   is the 86% step. `margin-inline: auto` rather than justify-self here because
   this section is not a grid (see the display:block note above). */
/* THE SAME FOUR SPANS, and this is where FULL BLEED lives -- the reported
   defect ("this needs to be full width"). Rolex's copy-less bands are their
   2880x1050 XL deliveries and run edge to edge on every collection comp
   (day-date has three, all measured at x 0-1919 on a 1920 comp); this partial
   rendered them inset inside .rlx-container. Orientation could not tell them
   apart from an ordinary landscape band -- submariner's third band is also
   landscape, 2000x1131, and sits at 10/12 -- so the file's ratio decides, via
   RLX_Asset_Resolver::span_for().

   The bleed rule cancels .rlx-container's inset from CSS rather than dropping
   the class in the template, so the non-bleed spans stay centred on exactly
   the same column as the rest of the page. `100vw` + the negative half-margin
   is the standard full-bleed-inside-a-container idiom; `max-width: none` is
   required because .rlx-container caps at --rlx-container-max. */
/* Same percentage-base correction as the editorial media wrapper: this
   section carries .rlx-container (max-width 1620 + 24px padding), so a
   10/12 span would otherwise measure 83.3333% of a 1572px content box --
   1310px against the comp's 1350. The bleed variant below sets its own
   width and is unaffected. */
body.rolex-section .rlx-image-block--span12,
body.rolex-section .rlx-image-block--span10,
body.rolex-section .rlx-image-block--span6 {
	width: min(var(--rlx-container-max), 100% - var(--rlx-container-inset));
	max-width: none;
	padding-inline: 0;
}
body.rolex-section .rlx-image-block--span12 picture { width: 100%; margin-inline: auto; }
body.rolex-section .rlx-image-block--span10 picture { width: 83.3333%; margin-inline: auto; }
body.rolex-section .rlx-image-block--span6 picture { width: 50%; margin-inline: auto; }
/* ---- the #F4EFEA tinted panel band --------------------------------------
   WHICH blocks get it is per-block data in RLX_Panel_Map, not a rule -- see
   that class for the measurement and for why a positional rule fails.

   The geometry here is the whole of it. .rlx-editorial spans the full width
   already (its __copy and __media children carry .rlx-container), so the
   tint is a plain background and needs none of the 100vw escape
   .rlx-image-block--bleed below uses.

   The band carries a gap on BOTH sides of its top edge: one --rlx-gap of
   ground above the band, and one more of padding inside it before content
   starts. Measured on the datejust comp this rule was first built from:
   content ends y3846, band runs y3941-5225, band content starts y4031 --
   94 of ground above the edge, then 90 of padding below it. The accessories
   comp agrees: last card box ends y2887, band starts y2978 (91), band
   content starts y3068 (90).

   An earlier version zeroed margin-block entirely, reasoning that keeping
   .rlx-block's 90px margin would "put 180 between the band edge and its
   content". That conflated the two: a margin sits OUTSIDE the band and
   cannot change the band-edge-to-content distance, which is padding alone.
   The result was a 0px gap above every panel -- the tint began flush against
   the bottom of whatever preceded it, reported on /rolex/accessories/ where
   it started at the last product card's edge.

   Only the top margin is restored. The block after a panel brings its own
   90px top margin, so setting margin-bottom here would double it. */
body.rolex-section .rlx-editorial--panel {
	/* The parent theme puts `padding: 72px 0` on every <section>, which the
	   rule further up zeroes via section:not(...):not(...). That negation
	   scores (0,4,2) -- :not() carries its argument's specificity -- against
	   this rule's (0,2,1), so declaring the padding here alone lost silently:
	   the background and the margin applied and the padding read 0. Hence the
	   third :not(), which is how .rlx-availability and .rlx-ed-trio are
	   already excused from the same rule. */
	margin-block: var(--rlx-gap) 0;
	padding-block: var(--rlx-gap);
	background: var(--rlx-panel);
}

body.rolex-section .rlx-image-block--bleed {
	max-width: none;
	padding-inline: 0;
	width: 100vw;
	margin-inline: calc(50% - 50vw);
}
body.rolex-section .rlx-image-block--bleed picture { width: 100%; margin-inline: 0; }
@media (max-width: 767px) {
	body.rolex-section .rlx-image-block--span12 picture,
	body.rolex-section .rlx-image-block--span10 picture,
	body.rolex-section .rlx-image-block--span6 picture {
		width: 100%;
	}
}

/* Video facade: full-bleed panel, centered play affordance. Posterless
   (fetch-failed) videos render the branded imageless panel, never a broken
   image. */
body.rolex-section .rlx-facade-section { margin-block: var(--rlx-gap); }
/* CONTAINER WIDTH, not 100%. Every comp that has a video puts it at
   x148-1771 — the 1620 container — at 16:9, and measured that way in all
   three of its callers: the collection archives (datejust y2238-3150 and
   y5315-6228, submariner y2398-3315, day-date y2248-3160, explorer
   y1604-2517), new watches (oyster-perpetual-41 y1180-2092) and watchmaking.
   `width: 100%` of a full-width section rendered 1920x1080 on every one of
   them. Reported by the client on /rolex/datejust/. Callers that want a
   different width (oyster-story's is 10 columns) override this; none wants
   full bleed. */
body.rolex-section .rlx-facade {
	position: relative;
	display: block;
	width: min(var(--rlx-container-max), 100% - var(--rlx-container-inset));
	margin-inline: auto;
	padding: 0;
	border: 0;
	background: none;
	cursor: pointer;
}
body.rolex-section .rlx-facade__media,
body.rolex-section .rlx-facade__media img { display: block; width: 100%; height: auto; }
body.rolex-section .rlx-facade__media img { aspect-ratio: 16 / 9; object-fit: cover; }
body.rolex-section .rlx-facade__panel {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 100%;
	aspect-ratio: 16 / 9;
	background: linear-gradient(135deg, #0b3e26 0%, var(--rlx-green) 100%);
}
body.rolex-section .rlx-facade__panel-heading {
	position: absolute;
	bottom: var(--rlx-gap-half);
	left: 50%;
	transform: translateX(-50%);
	color: #fff;
	font-size: var(--rlx-body24);
	font-weight: 700;
	text-align: center;
}
/* PLAY CTA TO THE BRAND CENTRE SPEC (2026-09-24, Ernie). The component
   sheet draws it as: structure "Filled circle: 60x60px, Icon: 14x14px";
   default "Filled circle: White, Icon: Brown"; hover "Filled circle: White,
   Icon: Green". We shipped a bare 64px white triangle with no circle and no
   hover state. Brown on white is ~12:1 and the green ~5.6:1.

   The colour change is instant on purpose, like the focus rings: it is
   feedback on a hover the visitor is making, not an entrance. */
body.rolex-section .rlx-facade__play {
	position: absolute;
	top: 50%;
	left: 50%;
	transform: translate(-50%, -50%);
	display: flex;
	align-items: center;
	justify-content: center;
	width: 60px;
	height: 60px;
	border-radius: 50%;
	background: #FFFFFF;
	color: var(--rlx-brown);
	pointer-events: none;
}
body.rolex-section .rlx-facade__play .rlx-icon--play {
	display: block;
	width: 14px;
	height: 14px;
}
@media (hover: hover) and (pointer: fine) {
	body.rolex-section .rlx-facade:hover .rlx-facade__play { color: var(--rlx-green); }
}
/* The facade had no focus state at all. Keyboard focus gets the hover
   colour plus the section's standard ring, on the circle a sighted keyboard
   user is looking at rather than round the whole 16:9 poster. */
body.rolex-section .rlx-facade:focus-visible { outline: none; }
body.rolex-section .rlx-facade:focus-visible .rlx-facade__play {
	color: var(--rlx-green);
	outline: 2px solid var(--rlx-green);
	outline-offset: 3px;
}
/* Final-review Fix 5: a malformed/absent youtube_id renders the poster
   with no play button at all -- a plain, non-interactive <div>, not the
   <button> above, so it must not look clickable. */
body.rolex-section .rlx-facade--static { cursor: default; }
/* NO WIDTH HERE (2026-09-20, client report: videos going full-bleed ON
   PLAY). This rule used to set `width: 100%`, and that quietly beat the
   constrained width on `.rlx-facade` above -- same specificity (0,2,1),
   later in the file, so it won. The activated iframe carries BOTH classes
   (rolex-bespoke.js copies the button's className deliberately, precisely so
   the width rules keep matching), so 100% resolved against the full-width
   `.rlx-facade-section` and the player broke out of the container.

   It looked fine on the article pages only by coincidence: their videos sit
   inside `.rlx-article__video`, whose own higher-specificity rule outranked
   this one. The collection archives have no such wrapper, so datejust,
   submariner, day-date and explorer all went 1440 wide on a 1210 poster --
   which is exactly what the client screenshotted. Measured before the fix:
   poster 1210 at x115, iframe 1440 at x0.

   `.rlx-facade` already states the width AND `margin-inline: auto`, and
   every caller that wants a different one overrides it there (the tinted
   1908 band at 1412, oyster-story's 10 columns). So the iframe needs to
   state no width at all -- it inherits the right one from the class it is
   given. Guarded in tests/wp-check-restyle.php. */
body.rolex-section .rlx-facade__iframe {
	display: block;
	aspect-ratio: 16 / 9;
	border: 0;
}
/* The comp sets this on the SAME copy column as every editorial block --
   air-king's facade body starts at x556 and daytona's at x557, against the
   x580 a bare 760px max-width produced by centring a narrower measure in
   the 1620 container. Same 854 border box (806 ink + 24 + 24) as
   .rlx-editorial__copy, and it carries .rlx-container for the same reason,
   so it needs the same mobile inset reset below. */
/* VIDEO IN A TINTED BAND -- 1908's last section. Measured on its mockup:
   the tint runs y10388-11822, the 7140 macro sits 89px below the tint's
   top edge (our 90px section padding) and is 1412px wide, centred at
   x254-1665, with the heading below it. We rendered it on the page ground
   at the container's own 1620@150.
   1412 is not a 12-column span and is not derived from one; it is what the
   comp draws, symmetric to the pixel (254 left, 255 right). */
body.rolex-section .rlx-facade-section--panel {
	/* Carved out of the section padding reset above by NAME, not by
	   raising specificity here: that reset is keyed on :not() chains,
	   which carry their arguments' specificity (0,5,2) and silently
	   outrank a (0,2,1) override -- the same trap the store card hit.
	   See memory/css-not-carries-specificity.md. */
	background: var(--rlx-panel);
	padding-block: var(--rlx-gap);
}
/* The comp's tint here is ONE unbroken band (y10388-11822), so the
   .rlx-block margin between this section and the tinted editorial under it
   would show 90px of page ground straight through the middle of it. Closed
   rather than papered over: both keep their own 90px padding, which puts
   the heading 180px below the video against the comp's 173. */
body.rolex-section .rlx-facade-section--panel + .rlx-editorial--panel {
	margin-top: 0;
}
body.rolex-section .rlx-facade-section--panel .rlx-facade {
	width: min(1412px, 100% - var(--rlx-container-inset));
	margin-inline: auto;
}
body.rolex-section .rlx-facade__body { max-width: 854px; padding-inline: 24px; text-align: left; margin-top: var(--rlx-gap-half); }
/* Stated HERE, not in the editorial reset above: media queries carry no
   specificity, so a shared `padding-inline: 0` block earlier in the file
   loses to the equal-specificity rule on the line above this one. */
@media (max-width: 767px) {
	body.rolex-section .rlx-facade__body { padding-inline: 0; }
}

/* --- watches hub (C, Task 6) --------------------------------------------
   page-templates/rolex-watches-hub.php. The carousel copies keep-exploring's
   structural pattern with NEW rlx-hub__ element names (never .rlx-keep --
   that class belongs to A's "Keep exploring" component, a separate section
   on this same page). rlx-hub-carousel carries no padding-block: the
   <section> already has rlx-block (margin-block) in
   page-templates/rolex-watches-hub.php:220 — a padding-block here would
   double the section-to-section gap. */
/* TILE GUTTER IS 8px, NOT --rlx-gap-half (45px).
   Measured on three different comps by three independent passes and
   re-verified directly: the retailer hub pair is two 808px panels at x148
   and x964 -- 8px apart, 6 scan rows agreeing -- and the Discover trio and
   the watches-hub carousel read the same 8. It is the SAME 8px the Our
   Selection card grid already uses correctly, so this was one design-system
   value applied in one place and missed in three. 45px cost each tile ~20px
   of width. */
/* FOUR IN VIEW AT >=768, fixed, not minmax (2026-09-21).

   minmax(240px, 1fr) sized the cells correctly while the carousel held
   exactly four cards -- 1fr filled the well and 240 never bound. Raising it
   to the comp's eight (two pages, which is what its second dash pages to)
   made 1fr resolve to well/8, the 240px floor took over, and the row
   rendered ~6.5 narrow cards instead of the comp's four.

   This is the SAME defect .rlx-ed-carousel__row was fixed for on 2026-08-17,
   in the same file, for the same reason -- that row had 8 cards from the
   start and read ~5.5 columns at 1920. Fixed the same way, deliberately:
   one --rlx-hub-gap token feeding both `gap` and the calc(), so the divisor
   and the gutter cannot drift apart. Base is the 2-up mobile case (Ashton
   item 16, "two models at a time"); >=768 overrides to 4-up. */
body.rolex-section .rlx-hub__row {
	--rlx-hub-gap: var(--rlx-card-gap);
	display: grid;
	grid-auto-flow: column;
	grid-auto-columns: calc((100% - var(--rlx-hub-gap)) / 2);
	gap: var(--rlx-hub-gap);
	overflow-x: auto;
	scroll-snap-type: x mandatory;
	scrollbar-width: none;
	margin-top: 24px;
}
body.rolex-section .rlx-hub__row::-webkit-scrollbar { display: none; }
body.rolex-section .rlx-hub__cell { scroll-snap-align: start; }
body.rolex-section .rlx-hub__nav { display: flex; gap: 8px; justify-content: flex-end; margin-top: 16px; }
body.rolex-section .rlx-hub__arrow {
	width: 40px;
	height: 40px;
	border-radius: 50%;
	border: 1px solid rgba(33, 33, 33, 0.2);
	background: var(--rlx-surface);
	cursor: pointer;
}
body.rolex-section .rlx-hub__arrow[disabled] { visibility: hidden; }
body.rolex-section .rlx-hub__arrow .rlx-icon { width: 16px; height: 16px; }
body.rolex-section .rlx-hub__viewall { text-align: center; margin-top: var(--rlx-gap-half); }

/* TWO MODELS AT A TIME ON MOBILE, with the green bars under them -- Ashton
   item 16: "Two models at a time, the green Rolex bars below it, and the user
   can swipe to the next two models".

   THE WATCHES HUB ROW ONLY. Item 16 is filed under "Rolex Watches Page", and
   Discover's .rlx-ed-carousel__row carries its own measured 1-up rule further
   down this file, taken off the Discover mobile comp. Item 11 asks us to
   "review the mockups for the number of watches to be present in the
   preview" on Discover -- it does not assert a number -- so that row keeps
   the count its own comp was measured at and gains only the bars.

   The hub row was grid-auto-columns: minmax(240px, 1fr). At a 336 mobile well
   that is 1.4 cards, so the second was always cut mid-card. Two cards at the
   grid's own mobile gutter (6px) is (336 - 6) / 2 = 165 -- the same 165 the
   collection grid's cards measure at 390, so the preview lines up with the
   grid below it.

   The bars are not new styling: these rows now opt into the SHARED
   [data-rlx-carousel-dots] mechanism keep-exploring already used, and the
   three dash classes share one rule set (see .rlx-keep__dash above). Swipe
   already worked -- both rows are overflow-x:auto with scroll-snap -- so only
   the card width and the indicator were missing. */
@media (max-width: 767px) {
	/* 6px, the same literal gutter .rlx-grid takes at this width -- the
	   comp's carousel pair and its card grids share one rhythm
	   (165 + 6 + 165 = the 336 well). The 8px default is the desktop card
	   gap. Only the TOKEN changes here; the 2-up division is the base rule
	   above, so this cannot fall out of step with it. */
	body.rolex-section .rlx-hub__row { --rlx-hub-gap: 6px; }
}
@media (min-width: 768px) {
	body.rolex-section .rlx-hub__row {
		grid-auto-columns: calc((100% - 3 * var(--rlx-hub-gap)) / 4);
	}
}

/* Promo block: same media-then-copy shape as A's push.php, hub-scoped names. */
body.rolex-section .rlx-hub-promo { text-align: left; }
body.rolex-section .rlx-hub-promo__media { display: block; }
/* CORRECTED 2026-09-12: was `aspect-ratio: 16/7; object-fit: cover`, which
   matched neither source. The delivered push art is 2400x800 (3.0); the
   mockup measures that band 1628x564 (2.887). 16/7 is 2.286, so at a 1620
   container it rendered 709 tall and `cover` threw away ~21% of the width.
   Following the asset gives 540 against the comp's 561 -- a 21px residual,
   versus 507px of a Rolex photograph discarded. */
body.rolex-section .rlx-hub-promo__media img { display: block; width: 100%; height: auto; aspect-ratio: auto; object-fit: fill; }
/* The heading sits ABOVE the image, 25px clear of it (comp ink y1732-1757,
   photo top y1782). It used to sit below, with a 45px top margin. */
body.rolex-section .rlx-hub-promo__heading { margin: 0 0 25px; }
/* THE STRAPLINE IS FLUSH LEFT, NOT CENTRED (2026-09-10, reported: "where the
   world begins is missaligned"). This rule carried `margin: 0 0 16px` and then
   `margin-inline: auto`; the longhand overrode the shorthand's zero side
   margins, so the 640px paragraph centred itself — measured 400px from the
   container edge at 1440 while the heading, the image and the CTA all sat at
   24px. The section is `text-align: left` two rules above, and Rolex's own
   watches comp (rolex-watches-mockup-desktop.jpg) shows the kicker, the
   "Where a new world begins" headline and "Learn more" all on the SAME left
   edge as the image above them. max-width stays: it is a measure limit, and
   it was never what pushed the text right. */
/* Below the image: kicker 24px under the photo, the 36px statement 14px
   under that, the CTA 15px under that -- all measured ink-to-ink on
   rolex-watches-with-grid-mockup-desktop.jpg. max-width stays a measure
   limit on the statement; it was never what pushed the old text right. */
body.rolex-section .rlx-hub-promo__kicker { margin: 24px 0 0; color: var(--rlx-brown); }
body.rolex-section .rlx-hub-promo__statement { margin: 14px 0 0; max-width: 640px; color: var(--rlx-brown); }
body.rolex-section .rlx-hub-promo__cta { display: inline-flex; align-items: center; margin-top: 15px; }

/* Tile groups: repeat(3, minmax(0,1fr)) desktop, 1-col mobile, per the brief. */
body.rolex-section .rlx-hub-tiles__heading { margin: 0 0 var(--rlx-gap-half); }
body.rolex-section .rlx-hub-tiles__grid {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	/* 3 x 536 + 2 x 8 = 1624, the container exactly. */
	gap: var(--rlx-gap) var(--rlx-card-gap);
}
body.rolex-section .rlx-hub-tiles__tile { display: block; color: inherit; text-decoration: none; }
/* NO forced ratio at desktop. The delivered tile art is 1170x780 = 1.500 and
   every comp renders it 536x358 = 1.497; the 4/3 box cropped ~11% of the
   width. The mobile override below is untouched — 3/4 already equals the
   portrait companion's own 780x1040 = 0.750 and measured uncropped. */
body.rolex-section .rlx-hub-tiles__media img { display: block; width: 100%; height: auto; }
/* MOBILE BOX FOLLOWS THE PORTRAIT ASSET (2026-09-09, reported against
   staging /rolex/watches/: "on mobile when the portrait image is shown the
   aspect ratio needs to also change to portrait").
   These tiles serve a GENUINELY portrait file below 768px — measured on the
   rendered page, rolex-watches-*-portrait.jpg is 780x1040 (0.750) for all 17
   collections — into this 4/3 landscape box, which cover-cropped away ~44%
   of the image height. Rolex's own mobile comp agrees the box is portrait:
   in rolex-watches-mockup-mobile.jpg the tiles are a 2-column grid whose
   image boxes measure 330x440 = 0.7500 exactly.
   Deliberately NOT applied to the other 4/3 tile primitives: the Discover
   trio's and the new-watches tiles' "-portrait" files are not portrait at
   all (780x780, 1098x800, 780x520 — Rolex's -portrait suffix means "mobile
   variant", not orientation), so a 3/4 box there would crop a landscape
   photograph instead of fixing one. A page-by-page sweep at 390px found five
   further components with a genuine portrait-file-in-landscape-box mismatch
   (history, team, showroom, contact, and the collection editorials); each
   needs its own comp measured before its box is changed, so they are
   reported rather than guessed at here. */
@media (max-width: 767px) {
	body.rolex-section .rlx-hub-tiles__media img { aspect-ratio: 3 / 4; }
}
body.rolex-section .rlx-hub-tiles__kicker { margin: 16px 0 0; opacity: 0.7; }
/* Rolex staging review 2026-09-14: "Review text color for collection names,
   should be the Rolex brown. This can be found in the Rolex Brand Centre design
   specifications." The spec's p.32 palette gives headings Brown and body Black;
   these tile names are headings for their card, and were inheriting the body
   ink through rlx-body20. */
body.rolex-section .rlx-hub-tiles__name { margin: 4px 0 0; font-weight: 700; color: var(--rlx-brown); }
@media (max-width: 767px) {
	/* TWO columns, tile 165 CSS, gutter 6 -- the same measurement as the card
	   grid. NOTE the NEW-WATCHES hub is genuinely different: its comp stacks
	   ONE full-well 336x336 square per row, so .rlx-nw-tiles__grid keeps its
	   single column below. Two auditors contradicted each other here because
	   each measured a different hub. */
	body.rolex-section .rlx-hub-tiles__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 6px; }
}

/* --- watches selection page (C, Task 7) ---------------------------------
   page-templates/rolex-watches-selection.php + templates/rolex/grids/filter-rail.php.
   Two-region layout: a fixed-width rail (reuses A's .rlx-accordion contract
   with a NEW .rlx-rail__* wrapper, never .rlx-hub-tiles__/.rlx-editorial__
   — a distinct component, same accordion mechanism) beside the grid region
   sharing templates/rolex/grids/grid.php with every other collection page. */
body.rolex-section .rlx-selection-layout__form {
	display: grid;
	/* Rail 265 (columns 1-2 of 12, 2 x 128.17 + 8), column 3 left empty as the
	   gap, cards on 4-12. Measured: the comp's rail rules run x147.5-412.5 and
	   the card grid starts at x569, i.e. a 157px gap -- not 280/64. */
	grid-template-columns: 265px minmax(0, 1fr);
	gap: var(--rlx-gap-half) 157px;
	align-items: start;
}
@media (max-width: 991px) {
	body.rolex-section .rlx-selection-layout__form { grid-template-columns: 1fr; }
}

/* ---- filter rail, measured off the mockups -------------------------------
   Row pitch is 70, built the way the spec sheet annotates it: a 1px divider,
   20px above the label, the Body24 label's own ~29px line box, 20px below.
   We shipped 107 -- mostly a default <h3> margin-bottom leaking around the
   accordion button, plus a 42px line-height. The divider is brown at 20%,
   not ink at 15%, and the labels are brown, not ink. */
body.rolex-section .rlx-rail__head {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 16px;
	margin-bottom: 28px;
}
body.rolex-section .rlx-rail__title {
	margin: 0;
	font-family: var(--rlx-font-sans);
	font-size: var(--rlx-body24);
	line-height: 1.2;
	/* BOLD, like the group labels below (2026-09-24): the desktop comp's
	   "Filters" stems measure 3.2px at 24px, against 0.9px on the Fixed14
	   option text in the same file. Regular Helvetica is ~2px at that size. */
	font-weight: 700;
	color: var(--rlx-brown);
}
body.rolex-section .rlx-rail__reset {
	display: inline-flex;
	align-items: center;
	gap: 9px;
	min-height: 44px;
	padding: 0 35px;
	border-radius: 22px;
	background: #EDECEA;
	color: var(--rlx-brown);
	font-family: var(--rlx-font-sans);
	font-size: var(--rlx-fixed16);
	font-weight: 700;
	text-decoration: none;
	white-space: nowrap;
}
body.rolex-section .rlx-rail__reset:hover { background: #E3E1DE; color: var(--rlx-brown); }
body.rolex-section .rlx-rail__reset .rlx-icon { width: 14px; height: 14px; }
body.rolex-section .rlx-rail__item { padding-block: 0; border-top: 1px solid rgba(69, 44, 30, 0.2); }
body.rolex-section .rlx-rail__item h3 { margin: 0; }
body.rolex-section .rlx-rail .rlx-accordion__button {
	padding-block: 20px;
	line-height: 1.2;
	color: var(--rlx-brown);
	/* BOLD (2026-09-24). The mobile wireframe draws its "Body24" group label
	   in bold, and the desktop mockup's "Collection" stems measure 3.2px at
	   24px -- bold, not regular. We shipped 400 at every width. */
	font-weight: 700;
	/* FLUSH with the divider in both comps. The base accordion button never
	   set padding-inline, so the browser's own ~6px button padding inset
	   every label and its plus. */
	padding-inline: 0;
}
/* Mobile rows pitch 69 in the comp (dividers every 138px at 2x). The label
   drops to 18px here, so the 20px padding that gives 70 at desktop gives
   only 62.6; 23px restores the pitch. */
@media (max-width: 767px) {
	body.rolex-section .rlx-rail .rlx-accordion__button { padding-block: 23px; }
}
body.rolex-section .rlx-rail .rlx-accordion__button .rlx-icon { width: 12px; height: 12px; }
body.rolex-section .rlx-rail__panel { padding-bottom: 40px; }
/* .rlx-rail__links is gone with Ashton item 39: the Collection group was a
   <ul> of 17 archive links and is now 17 .rlx-rail__option checkboxes like
   every other group, so it inherits their styling and needs none of its own.
   wp-check-grids asserts the class no longer appears in the rendered rail. */
/* Option rows are a 36px pitch with a 16x16 box and an 11px gap; the
   Collection group's plain links keep their own 32px pitch, which already
   matched. */
body.rolex-section .rlx-rail__option {
	display: flex;
	align-items: center;
	gap: 11px;
	min-height: 36px;
	padding-block: 0;
	font-size: var(--rlx-fixed14);
	cursor: pointer;
}
body.rolex-section .rlx-rail__option input { width: 16px; height: 16px; flex: 0 0 auto; }
/* Options the filter script found would empty the grid, and groups with
   none left (2026-09-24; rolex-bespoke.js refreshOptions() says when). A
   class rather than [hidden]: .rlx-rail__option is display:flex, and the
   theme's [hidden] handling has had to be restated in this section before. */
body.rolex-section .rlx-rail__option.rlx-rail__option--unavailable,
body.rolex-section .rlx-rail__item.rlx-rail__item--empty { display: none; }
/* RESTATED 2026-09-12. The parent theme uppercases and tracks label text, so
   the filter options rendered "SMALL SIZE" / "WHITE GOLD" / "UNDER $10,000"
   with 1px letter-spacing. The markup is already sentence case and so is every
   comp -- this is the theme leaking in, the same class as the [hidden] and
   width:100% restatements the CF7 block carries. Stated on the label itself
   because that is where the theme's rule lands. */
body.rolex-section .rlx-rail__option,
body.rolex-section label.rlx-rail__option { text-transform: none; letter-spacing: normal; }
body.rolex-section .rlx-rail__actions { display: flex; align-items: center; gap: var(--rlx-gap-half); margin-top: var(--rlx-gap-half); }
/* NO CONFIRM ON THE DESKTOP RAIL ONCE FILTERING IS LIVE (2026-09-24, Ernie:
   "on desktop there is a confirm link that is always shown"). The desktop
   comp has no button; rolex-bespoke.js stamps [data-rlx-filter-live] on the
   form only when it has taken over filtering, at which point the submit
   does nothing. Without the script the attribute never appears and Confirm
   stays, as the only way to submit. Below 768 it stays too: it is the
   mobile panel's own Confirm, which the mockup draws and which closes it. */
@media (min-width: 768px) {
	body.rolex-section .rlx-selection-layout__form[data-rlx-filter-live] .rlx-rail__actions { display: none; }
}

body.rolex-section .rlx-selection__controls {
	display: flex;
	align-items: center;
	justify-content: space-between;
	margin-bottom: var(--rlx-gap-half);
}
/* SORT SITS RIGHT (2026-09-14, Rolex staging review: "Sort by should be on the
   right-hand side of the page"), and the comp agrees -- it draws "Sort by
   featured" against the right edge of the grid column.

   space-between alone did not do it: the only other child of this row is
   .rlx-selection__count, which is visually-hidden and therefore
   position:absolute, so it leaves the flow entirely and the sort was the sole
   flex item -- which space-between parks at the START. margin-left:auto rather
   than justify-content:flex-end so that if the count is ever made visible it
   still takes the left end and the sort stays right. */
body.rolex-section .rlx-selection__sort { margin-left: auto; }
/* "Sort by" was wrapping to two lines -- the label measured 75x58 against a
   28.8px line-height, i.e. "Sort" over "by". The comp runs it on one line. */
body.rolex-section .rlx-selection__sort > span { white-space: nowrap; }
/* The sort control is BORDERLESS TEXT plus a chevron -- the comp band holds
   no non-background pixels outside the glyph boxes: no border, no fill, no
   underline, no pill. 24px, and #212121 rather than the rail's brown (the
   mobile spec annotates it brown; the desktop mockup renders it ink, and the
   mockup is what we match). We shipped a 14px bordered native select. */
body.rolex-section .rlx-selection__sort {
	position: relative;
	display: inline-flex;
	align-items: baseline;
	/* Two DIFFERENT gaps, measured glyph-cluster to glyph-cluster on
	   our-rolex-selection-mockup-desktop.jpg: the label-to-value gap is an
	   ordinary word space (5px: "by" ends 1664, "featured" starts 1670),
	   because the comp reads as one sentence -- while the value-to-chevron
	   gap is 14px ("featured" ends 1760, the chevron starts 1775). A single
	   flex gap cannot be both, so the chevron carries the difference as a
	   margin. Total text run then measures 174px, the comp's exactly. */
	gap: 6px;
	font-family: var(--rlx-font-sans);
	font-size: var(--rlx-body24);
	line-height: 1.2;
	color: var(--rlx-ink);
	cursor: pointer;
	/* The wrapper IS a <label>, and the parent theme styles every label
	   uppercase + 1px tracking -- the same rule .rlx-rail__option has to
	   undo a few lines above. The comp runs this control as plain sentence
	   case ("Sort by featured"), so restate both. Theme form rules are never
	   beaten by omission, only by an explicit counter-declaration. */
	text-transform: none;
	letter-spacing: normal;
}
/* The comp's chevron is a STROKE glyph, not a solid triangle -- zoomed to
   28x28 it is a ~2px V, ~13x7. We shipped a filled clip-path wedge, and the
   #rlx-drop-down sprite symbol is filled too, so neither matches. Drawn with
   two borders on a rotated box: a 9px square rotated 45deg measures 9*sqrt2
   ~= 12.7px across, which is the comp's width. */
body.rolex-section .rlx-selection__sort::after {
	content: "";
	width: 9px;
	height: 9px;
	flex: 0 0 auto;
	border-right: 2px solid currentColor;
	border-bottom: 2px solid currentColor;
	transform: translateY(-4px) rotate(45deg);
	margin-left: 8px; /* 6px flex gap + 8px = the comp's 14px. */
}
body.rolex-section .rlx-selection__sort select {
	font-family: var(--rlx-font-sans);
	font-size: var(--rlx-body24);
	line-height: 1.2;
	color: var(--rlx-ink);
	background: none;
	border: 0;
	border-radius: 0;
	padding: 0;
	appearance: none;
	-webkit-appearance: none;
	cursor: pointer;
	/* The parent theme forces selects to height:50px and width:100%. Both
	   have to be restated, not assumed overridden: the 50px box centred the
	   24px value ~10px ABOVE the label's baseline (the defect Rolex flagged
	   -- "Sort by" and "Featured" reading as two different sizes on two
	   different lines), and the forced width stretched the control to 342px
	   against the comp's 200px. */
	height: auto;
	min-height: 0;
	width: auto;
	/* The comp renders the value lower-case, as the tail of the sentence
	   "Sort by featured". Done as a TRANSFORM, never by editing the option
	   text: the accessibility tree and the submitted value both stay
	   "Featured". (The rlx_copy_selection blob heads this control "Sort by
	   features" -- a garbled extraction, and extracted copy is not approved
	   copy; the rendered mockup wins on presentation.) */
	text-transform: lowercase;
}
/* A native <select> sizes itself to its LONGEST option, not the selected one
   -- "Price: high to low" at 24px is ~200px, which is the real reason the
   chevron sat 140px from the text. rolex-bespoke.js measures the selected
   option and sets an explicit width; this class only marks that it did, so
   that with no script the control still works, just wider. */
body.rolex-section .rlx-selection__sort select[style*="width"] { max-width: none; }
body.rolex-section .rlx-selection__empty { text-align: center; padding: var(--rlx-gap) 24px; }
/* Always in the DOM so the filter script can show it when a filter change
   empties the grid; hidden whenever anything matches. */
body.rolex-section .rlx-selection__empty--hidden { display: none; }
body.rolex-section .rlx-selection__empty .rlx-cta-secondary { margin-top: 16px; }
@media (max-width: 767px) {
	body.rolex-section .rlx-selection__controls { flex-direction: column; align-items: flex-start; gap: 16px; }
}

/* Final-review Fix 4 (fidelity gap): mobile filters toggle. The button is
   hidden entirely at desktop widths — the rail there is always visible,
   unchanged. Below 767px it appears; rolex-bespoke.js is what actually
   collapses `.rlx-rail__body` (by stamping `[data-rlx-rail-init]` onto
   `.rlx-rail` on load, only when it detects a mobile viewport, then toggling
   `.is-open` on click) — so with JS absent/disabled neither attribute nor
   class is ever added and `.rlx-rail__body` keeps its default `display`,
   i.e. stays fully visible at every width, matching the no-JS requirement. */
body.rolex-section .rlx-rail__toggle {
	display: none;
	width: 100%;
	align-items: center;
	justify-content: space-between;
	font-family: var(--rlx-font-sans);
	font-size: var(--rlx-fixed14);
	color: var(--rlx-ink);
	background: var(--rlx-surface);
	border: 1px solid rgba(33, 33, 33, 0.2);
	border-radius: 9999px;
	padding: 12px 20px;
	margin-bottom: var(--rlx-gap-half);
	cursor: pointer;
}
@media (max-width: 767px) {
	/* The head row is the DESKTOP treatment. At the toggle breakpoint the
	   comp shows only the inline "Filters +" bar, and Reset moves into the
	   drawer's sticky bar -- rendering both stacked two "Filters" labels. */
	body.rolex-section .rlx-rail__head { display: none; }
	body.rolex-section .rlx-rail__toggle { display: flex; }
	body.rolex-section .rlx-rail[data-rlx-rail-init] .rlx-rail__body { display: none; }
}

/* THE MOBILE FILTERS ROW IS TWO WORDS OF TEXT, NOT A PILL (2026-09-24,
   measured on our-rolex-selection-mockup-mobile.jpg and the matching
   template, which agree): "Filters +" at the left and "Sort by v" at the
   right, on ONE row, 18px bold brown (#452C1E sampled), 20px above the
   cards. We shipped a full-width white bordered pill with a filled triangle,
   and Sort on its own row further down, below the whole rail.

   The two controls live in different cells -- the toggle in __rail, Sort in
   __grid -- so the row is built by flattening both wrappers (and .rlx-rail
   between them) with display:contents and placing the pieces on the form's
   own grid: toggle | sort on row 1, the rail body across row 2, everything
   else in the grid region across the rows after. The selectors that hide
   and show the body still match: display:contents changes layout, not the
   DOM. Desktop and tablet never see any of this. */
@media (max-width: 767px) {
	body.rolex-section .rlx-selection-layout__form {
		grid-template-columns: auto minmax(0, 1fr);
		column-gap: 16px;
		row-gap: 0;
	}
	body.rolex-section .rlx-selection-layout__rail,
	body.rolex-section .rlx-selection-layout__rail > .rlx-rail,
	body.rolex-section .rlx-selection-layout__grid { display: contents; }
	body.rolex-section .rlx-rail__toggle { grid-column: 1; grid-row: 1; }
	body.rolex-section .rlx-selection-layout__grid > .rlx-selection__controls { grid-column: 2; grid-row: 1; }
	body.rolex-section .rlx-rail__body { grid-column: 1 / -1; grid-row: 2; margin-top: 20px; }
	body.rolex-section .rlx-selection-layout__grid > .rlx-selection__controls ~ * { grid-column: 1 / -1; }

	body.rolex-section .rlx-rail__toggle {
		width: auto;
		justify-content: flex-start;
		/* 11.5px from the "s" to the plus in the comp. */
		gap: 12px;
		margin: 0;
		padding: 0;
		background: none;
		border: 0;
		border-radius: 0;
		-webkit-appearance: none;
		appearance: none;
		font-size: var(--rlx-body24);
		line-height: 1.2;
		font-weight: 700;
		color: var(--rlx-brown);
		text-transform: none;
		letter-spacing: normal;
	}
	body.rolex-section .rlx-rail__toggle .rlx-icon { width: 12px; height: 12px; }

	/* Row 1's right-hand cell. Restates the column stack the base mobile
	   rule gives this row, now that the row holds only Sort. margin-bottom
	   is the comp's 20px to the cards. */
	body.rolex-section .rlx-selection__controls {
		flex-direction: row;
		justify-content: flex-end;
		align-items: center;
		gap: 0;
		margin-bottom: 20px;
	}
	/* "Sort by v" -- the mobile comp and template both draw the label and
	   chevron only, bold brown, with no selected value. The <select> stays
	   the real control: it is laid transparent over the whole label, so a
	   tap opens the native picker (which shows the current choice) and the
	   accessibility tree still reads "Sort by, Featured". !important is for
	   the width only: rolex-bespoke.js writes an inline width sized to the
	   selected option, which is right for the desktop "Sort by featured"
	   run and wrong here. */
	body.rolex-section .rlx-selection__sort {
		/* The parent theme gives every <label> a 5px margin-bottom, which
		   stood the Filters row 25px off the cards instead of 20. */
		margin: 0;
		align-items: center;
		gap: 0;
		font-size: var(--rlx-body24);
		font-weight: 700;
		color: var(--rlx-brown);
	}
	body.rolex-section .rlx-selection__sort select {
		position: absolute;
		inset: 0;
		width: 100% !important;
		height: 100%;
		opacity: 0;
		font-size: 16px; /* under 16px iOS zooms the page on focus */
	}
	/* 9.5px from "by" to the chevron in the comp; the chevron is 14.5 x 9. */
	body.rolex-section .rlx-selection__sort::after {
		width: 8px;
		height: 8px;
		margin-left: 10px;
		transform: translateY(-3px) rotate(45deg);
	}
}
/* The select is transparent at mobile, so its focus ring would be too. Put
   the ring on the visible label instead. */
@media (max-width: 767px) {
	body.rolex-section .rlx-selection__sort:focus-within {
		outline: 2px solid var(--rlx-green);
		outline-offset: 4px;
	}
}

/* The cards sit 20px under the Filters row in the comp. .rlx-grid-section
   is an .rlx-block, so it brought the section's 60px top margin with it and
   the row stood 85px clear. The row's own margin-bottom is the gap. */
@media (max-width: 767px) {
	body.rolex-section .rlx-selection-layout__grid > .rlx-grid-section { margin-top: 0; }
}

/* ---- the mobile filter panel (2026-09-24) --------------------------------
   Measured on our-rolex-selection-filters-closed-mockup-mobile.jpg (780px =
   2x) and its template, which annotates the numbers: #F9F7F4 panel; 20px /
   cross / 20px / Headline36 (24px bold here, cap top at y64) / 40px to the
   first divider; a STICKY 84px #FFF bar at the foot with the primary CTA,
   20px, then a 44px round reset (#F6F6F6, ink icon). Everything below is
   gated on [data-rlx-rail-init], which only the script sets, and only at
   <=767px: without it the body stays inline in the page, as it always has.

   The panel is the SCROLL CONTAINER, and a flex column at least as tall as
   the screen, so margin-top:auto parks the bar at the bottom when the groups
   are short (the comp's all-closed state) and position:sticky holds it there
   when an open group runs past the fold. */
body.rolex-section .rlx-rail__drawer-head { display: none; }
body.rolex-section .rlx-rail__reset-round { display: none; }
@media (max-width: 767px) {
	body.rolex-section .rlx-rail[data-rlx-rail-init].is-open .rlx-rail__body {
		display: flex;
		flex-direction: column;
		position: fixed;
		inset: 0;
		z-index: 100000;
		margin: 0;
		padding: 0 27px;
		background: var(--rlx-bg);
		overflow-y: auto;
		overscroll-behavior: contain;
		-webkit-overflow-scrolling: touch;
	}
	body.rolex-section .rlx-rail[data-rlx-rail-init] .rlx-rail__drawer-head {
		display: block;
		position: relative;
		flex: 0 0 auto;
		/* 56 + the 24px title's half-leading and ascender = the cap top at 64. */
		padding-top: 56px;
	}
	body.rolex-section .rlx-rail__drawer-title {
		margin: 0 0 40px;
		font-family: var(--rlx-font-sans);
		font-size: var(--rlx-headline36);
		line-height: 1.2;
		font-weight: 700;
		color: var(--rlx-brown);
		text-transform: none;
		letter-spacing: normal;
	}
	/* The cross is a 9px glyph centred on (360, 28) in the comp; the button
	   around it is a 44px target, so it overhangs the 27px gutter. */
	body.rolex-section .rlx-rail__close {
		position: absolute;
		top: 6px;
		right: -19px;
		width: 44px;
		height: 44px;
		display: flex;
		align-items: center;
		justify-content: center;
		padding: 0;
		margin: 0;
		border: 0;
		border-radius: 0;
		background: none;
		-webkit-appearance: none;
		appearance: none;
		color: var(--rlx-brown);
		cursor: pointer;
	}
	body.rolex-section .rlx-rail__close .rlx-icon { width: 10px; height: 10px; }
	body.rolex-section .rlx-rail[data-rlx-rail-init] .rlx-accordion { flex: 0 0 auto; }
	/* The closed comp rules off the last group as well as the first. */
	body.rolex-section .rlx-rail[data-rlx-rail-init] .rlx-rail__item:last-child { border-bottom: 1px solid rgba(69, 44, 30, 0.2); }

	/* Confirm and the round reset read as the comp's bar at this width
	   whether or not the script ran; only the sticky full-bleed white bar
	   needs the panel. */
	body.rolex-section .rlx-rail__actions { justify-content: center; gap: 20px; }
	body.rolex-section button.rlx-rail__confirm {
		min-height: 44px;
		padding: 0 30px;
		border-radius: 9999px;
		background: var(--rlx-green);
		color: #fff;
		/* 14px: the comp's "Confirm" cap is 10px, in a 112x44 pill. */
		font-size: var(--rlx-fixed14);
		font-weight: 700;
	}
	body.rolex-section button.rlx-rail__confirm:hover { background: var(--rlx-green-rolex); color: #fff; text-decoration: none; }
	body.rolex-section .rlx-rail__reset-round {
		display: inline-flex;
		align-items: center;
		justify-content: center;
		flex: 0 0 auto;
		width: 44px;
		height: 44px;
		border-radius: 50%;
		background: #F6F6F6;
		color: var(--rlx-ink);
	}
	body.rolex-section .rlx-rail__reset-round .rlx-icon { width: 18px; height: 18px; }
	body.rolex-section .rlx-rail[data-rlx-rail-init] .rlx-rail__actions {
		position: sticky;
		bottom: 0;
		flex: 0 0 auto;
		margin: auto -27px 0;
		min-height: 84px;
		padding: 20px 27px calc(20px + env(safe-area-inset-bottom));
		box-sizing: border-box;
		background: #FFFFFF;
	}
}
/* The page behind the open panel must not scroll. On <body>, inside the
   section scope: <html> stays overflow:visible (the parent theme never sets
   it), so body's overflow is the one propagated to the viewport. */
body.rolex-section.rlx-rail-locked { overflow: hidden; }

/* --- New watches 2026 (sub-project D, Task 3) -----------------------------
   page-templates/rolex-new-watches.php + templates/rolex/grids/{nw-tiles,
   nw-keep}.php. Hero reuses .rlx-coll-hero (eager); everything below the
   hero (tiles/blocks/keep row images) is loading="lazy" in the partials
   themselves. New .rlx-nw-intro is deliberately its own component (not a
   reuse of .rlx-coll-intro) because the child route needs a THIRD stacked
   element -- a Fixed16 kicker above the Headline50 -- that .rlx-coll-intro
   has no slot for; the hub route (title+tagline+intro only) uses the same
   markup with the kicker paragraph simply omitted. */
/* SAME SPLIT AS .rlx-coll-intro, for the same reason its own note gives: the
   right column starts at column 7 of 12 -- x960 -- in every comp that has
   one, and the New Watches comps measure x966 with it. Two equal halves with
   no column gap, not repeat(2,1fr) + 64px, which put the column at x992 and
   ran its text on to x1770 against the comp's x1628. */
body.rolex-section .rlx-nw-intro {
	display: grid;
	grid-template-columns: 50% 41.6667%;
	gap: var(--rlx-gap-half) 0;
	align-items: start;
}
body.rolex-section .rlx-nw-intro__kicker { margin: 0 0 12px; opacity: 0.7; }
/* SUPERSEDED 2026-09-11. This set the tagline 8px below the title at 0.85
   opacity, i.e. as a subtitle. The comps render it as the headline's second
   line -- same 50px, same brown, one 58px pitch -- so the treatment now
   lives with the rest of the intro type above; a later duplicate here would
   just re-open the 8px gap. */
body.rolex-section .rlx-nw-intro__body { margin: 0; }
@media (max-width: 767px) {
	body.rolex-section .rlx-nw-intro { grid-template-columns: 1fr; }
}

/* Hub tiles: repeat(2, minmax(0,1fr)) desktop -- 1-col mobile, same grid shape as
   .rlx-hub-tiles__grid but its own class names (this is a DIFFERENT page
   template's component, never shared markup with rolex-watches-hub.php). */
body.rolex-section .rlx-nw-tiles__grid {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	/* Comp: 2 x 808 with a 9px gutter, filling the 1625 container; the row
	   gap is the section's own 90px block rhythm, not the 32px this had. */
	gap: var(--rlx-gap) var(--rlx-card-gap);
}
body.rolex-section .rlx-nw-tiles__tile { display: block; color: inherit; text-decoration: none; }
/* NO forced ratio. The new-watches hub tile serves 1200x800 = 1.500 at
   desktop and 1170x1170 = 1.000 at mobile, and the comp renders them
   808x539 = 1.499 and 672x672 = 1.000 — its own asset, both times. The 4/3
   box cropped 11% of the width at desktop and 33% at mobile, where a square
   delivery was being forced landscape. */
body.rolex-section .rlx-nw-tiles__media img { width: 100%; height: auto; display: block; }
/* Tile names are Headline36 BROWN, not Body20 ink. Cap height 25-26 on every
   hub tile => 34.9-36.3px, and 100% brown pixels on the name and the kicker
   alike -- the kicker was already the right size, only its colour was wrong
   (and the 0.7 opacity was ours, not the comp's). The hub follows the spec's
   Push component ramp (Fixed16 brown over Headline36 brown), not the Grid
   component's Body24: a Body24 name would read cap ~17, and none does. */
body.rolex-section .rlx-nw-tiles__kicker { margin: 16px 0 0; color: var(--rlx-brown); }
body.rolex-section .rlx-nw-tiles__name {
	margin: 4px 0 0;
	font-size: var(--rlx-headline36);
	line-height: var(--rlx-lh-headline);
	font-weight: 700;
	color: var(--rlx-brown);
}
@media (max-width: 767px) {
	body.rolex-section .rlx-nw-tiles__grid { grid-template-columns: 1fr; }
}

/* Child keep row: a scroll-snap CAROUSEL at every breakpoint, four cards
   wide on desktop, same mechanism as .rlx-keep__row/.rlx-hub__row but its
   own class names.

   WAS A FIXED repeat(4, minmax(0, 1fr)) GRID until 2026-09-10, when the row
   went from four sibling cards to all five models (Rolex's own mockups show
   five, the current page's included and marked — see
   RLX_Copy_Importer::NW_KEEP_ORDER). A fifth card in a four-column grid
   wraps onto a second row, so the desktop grid had to go; the comps show a
   next chevron and a progress track, i.e. a carousel, which is what this is
   now. The column formula is .rlx-keep__row's, not a new number: four
   columns and three gaps out of 100%. */
body.rolex-section .rlx-nw-keep__row {
	--rlx-nw-keep-gap: var(--rlx-card-gap);
	display: grid;
	grid-auto-flow: column;
	/* Two tiles at mobile, as the keep row above -- see its note. */
	grid-auto-columns: calc((100% - var(--rlx-nw-keep-gap)) / 2);
	gap: var(--rlx-nw-keep-gap);
	overflow-x: auto;
	scroll-snap-type: x mandatory;
	scrollbar-width: none;
	margin-top: 24px;
}
@media (min-width: 768px) {
	body.rolex-section .rlx-nw-keep__row {
		grid-auto-columns: calc((100% - 3 * var(--rlx-nw-keep-gap)) / 4);
	}
}
body.rolex-section .rlx-nw-keep__row::-webkit-scrollbar { display: none; }
body.rolex-section .rlx-nw-keep__heading { margin: 0; }
body.rolex-section .rlx-nw-keep__card {
	display: block;
	scroll-snap-align: start;
	color: inherit;
	text-decoration: none;
}
/* NO forced ratio — same 3:2 delivery and the same comp reading as the
   shared keep-exploring row above (comp 400x266 = 1.504 desktop,
   332x225 = 1.476 mobile, assets 600x400 and 780x520). */
body.rolex-section .rlx-nw-keep__card img { display: block; width: 100%; height: auto; }
body.rolex-section .rlx-nw-keep__name { margin: 16px 0 0; font-weight: 700; }

/* THE CURRENT PAGE'S CARD. Rolex's mockups render the current model's
   caption in the brand green while every other caption stays ink — that is
   the whole of the treatment, no border and no tint. --rlx-green (#127749)
   measures 5.58:1 on white, so it clears the 4.5:1 body-text floor without
   adjustment. The state is never carried by colour alone: nw-keep.php also
   emits aria-current="page" and renders this card as a <div> rather than a
   dead link to the page you are already on. */
body.rolex-section .rlx-nw-keep__card--current .rlx-nw-keep__name { color: var(--rlx-green); }

/* Controls: progress track dead-centre, arrows right. Right-aligned arrows
   are this build's convention for every carousel and were confirmed by the
   user on 2026-09-09 ("the chevrons next prev need to be positioned to the
   right like they were"); the empty first column is what lets the track sit
   on the row's true centre rather than merely left of the arrows. */
body.rolex-section .rlx-nw-keep__controls {
	display: grid;
	grid-template-columns: 1fr auto 1fr;
	align-items: center;
	margin-top: 24px;
}
body.rolex-section .rlx-nw-keep__dots {
	grid-column: 2;
	display: flex;
	align-items: center;
	gap: 8px;
}
/* NO grid-column / justify-self here any more (2026-09-21). This nav used to
   be the third child of the .rlx-nw-keep__controls grid; it now lives in the
   __viewport so it can flank the row. `justify-self: end` is NOT inert on an
   absolutely positioned box -- CSS Box Alignment applies it to the
   inset-modified containing block -- so it shrink-to-fit the bar to 88px and
   pinned it right, which put the Previous arrow next to Next instead of on
   the far side of the row. The left/right insets could not win against it.
   The controls grid keeps its 1fr auto 1fr, which still centres the dots. */
body.rolex-section .rlx-nw-keep__nav {
	display: flex;
	gap: 8px;
}
body.rolex-section .rlx-nw-keep__arrow {
	width: 40px;
	height: 40px;
	border-radius: 50%;
	border: 1px solid rgba(33, 33, 33, 0.2);
	background: var(--rlx-surface);
	cursor: pointer;
}
body.rolex-section .rlx-nw-keep__arrow[disabled] { visibility: hidden; }

/* Progress segments. Same 24x4 -> 50x4 geometry as the hero slider's
   .rlx-banner__dash, and the same reason for drawing on a ::before: the
   BUTTON keeps a 24px minimum tap target while the visible dash stays 4px.
   The colours differ because the surface does — the hero's dashes sit on
   photography and are white, these sit on white and cannot be. Current is
   --rlx-green, matching the current-card caption above and the comp;
   inactive is ink at 50%, which blends to ~#909090 for 3.2:1 against white
   and so clears the 3:1 non-text contrast floor (WCAG 1.4.11). The count is
   built by assets/js/rolex-bespoke.js from how far the row actually
   scrolls, never hard-coded here. */
body.rolex-section .rlx-nw-keep__dash {
	appearance: none;
	-webkit-appearance: none;
	border: 0;
	background: none;
	padding: 0;
	width: 24px;
	height: 24px;
	display: grid;
	place-items: center;
	cursor: pointer;
	transition: width 200ms ease;
}
body.rolex-section .rlx-nw-keep__dash::before {
	content: "";
	display: block;
	width: 24px;
	height: 4px;
	border-radius: var(--rlx-dash-radius);
	background: rgba(33, 33, 33, 0.5);
	transition: width 200ms ease, background-color 200ms ease;
}
body.rolex-section .rlx-nw-keep__dash[aria-current="true"] { width: 50px; }
body.rolex-section .rlx-nw-keep__dash[aria-current="true"]::before {
	width: 50px;
	background: var(--rlx-green);
}
@media (prefers-reduced-motion: reduce) {
	body.rolex-section .rlx-nw-keep__dash,
	body.rolex-section .rlx-nw-keep__dash::before { transition: none; }
}
@media (max-width: 767px) {
	body.rolex-section .rlx-keep__row,
	body.rolex-section .rlx-nw-keep__row { --rlx-keep-gap: 4px; --rlx-nw-keep-gap: 4px; }
}

/* --- Editorial slice (Task 4): Discover / Contact / Retailer ------------
   page-templates/rolex-{discover,contact,retailer}.php +
   templates/rolex/grids/{ed-tiles,ed-store-card}.php. A dedicated
   `rlx-ed-*` class family throughout -- never reusing `.rlx-hub-*`/
   `.rlx-editorial*` names, same "new component, new prefix" convention
   nw-tiles/nw-keep already established, even where a rule's actual
   declarations are identical to an existing one (e.g. the carousel row's
   scroll-snap mechanics mirror `.rlx-hub__row` exactly, by design -- same
   JS hooks, same behaviour, deliberately separate CSS namespace). */

/* Discover's 8-card carousel: same scroll-snap shape as .rlx-hub__row.
   No padding-block here: the <section> already has rlx-block (margin-block)
   in page-templates/rolex-discover.php:144 — padding-block would double
   the section-to-section gap.
   P3 parity fix (2026-08-17): minmax(240px,1fr) with 8 items rendered ~5.5
   columns at 1920 (measured), one more than the mockup's fixed 4-up. A
   dedicated --rlx-ed-carousel-gap token feeds BOTH the row's own `gap` and
   the desktop calc() below — same "one token, two consumers" pattern
   .rlx-keep__row/--rlx-keep-gap already established — so the two can never
   drift out of sync; its value is this row's actual current gap
   (--rlx-gap-half), unchanged, not a new number. */
body.rolex-section .rlx-ed-carousel__row {
	--rlx-ed-carousel-gap: var(--rlx-card-gap);
	display: grid;
	grid-auto-flow: column;
	/* CORRECTED 2026-09-15: TWO cards per view at mobile, like the card
	   grids -- 165px cells on a 6px gutter in the 336 well.

	   This was 100% (one full-well card) on the reading that "the Discover
	   mobile comp has exactly one side-by-side band on the whole page
	   (keep-exploring)". That reading came from the PLAIN mobile mockup,
	   which is the variant WITHOUT this carousel -- and it located the
	   carousel's band by matching the live section sequence onto the comp's
	   height, i.e. positionally, which is the method that has manufactured
	   false findings on this project before.

	   discover-rolex-with-grid-mockup-moblie.jpg is the variant that matches
	   what we render, and it draws the carousel 2-up at device y1100-1400:
	   two 165px panels at x27 and x198, with the carousel's OWN dash track
	   and "View all" pill directly beneath them. Confirmed visually, not by
	   offset. The plain mockup has no such band anywhere, which is exactly
	   why it looked like 1-up. */
	grid-auto-columns: calc((100% - var(--rlx-ed-carousel-gap)) / 2);
	gap: var(--rlx-ed-carousel-gap);
	overflow-x: auto;
	scroll-snap-type: x mandatory;
	scrollbar-width: none;
	margin-top: 24px;
}
@media (max-width: 767px) {
	/* 6px, the same literal gutter .rlx-grid takes at this width -- the
	   comp's carousel pair and its card grids share one rhythm (165 + 6 +
	   165 = the 336 well). The 8px default is the desktop card gap. */
	body.rolex-section .rlx-ed-carousel__row { --rlx-ed-carousel-gap: 6px; }
}
@media (min-width: 768px) {
	body.rolex-section .rlx-ed-carousel__row {
		grid-auto-columns: calc((100% - 3 * var(--rlx-ed-carousel-gap)) / 4);
	}
}
body.rolex-section .rlx-ed-carousel__row::-webkit-scrollbar { display: none; }
body.rolex-section .rlx-ed-carousel__cell { scroll-snap-align: start; }
/* EQUAL-HEIGHT CARDS (2026-09-09, reported with a screenshot: "the our rolex
   selection cards need to be the same height responsivly"). The CELLS were
   already equal — .rlx-ed-carousel__row is a grid and its items stretch — but
   .rlx-card is display:block with a content-driven height, so a card whose
   description wrapped to one fewer line left its panel short of the cell.
   Measured at 390px before the fix: cells all 382.2px, cards 382.2 / 365.4 /
   365.4 / 382.2 — the two single-line descriptions ("platinum", "Everose
   gold") sat 16.8px short. At 1920px all four happened to wrap the same way,
   which is why this only showed at narrow widths, i.e. "responsivly".
   Scoped to the carousel cell: .rlx-card is a shared primitive used outside
   this component, where a stretched height is not wanted. */
body.rolex-section .rlx-ed-carousel__cell .rlx-card { height: 100%; }
/* (A .rlx-ed-carousel__row-scoped `padding: 0` sat here earlier on
   2026-09-17, when only this carousel was meant to lose the inset. The base
   rule now does it everywhere, so the override is gone rather than left to
   look meaningful.) */
/* Our Rolex selection carousel nav — FLANKING THE ROW (2026-09-17, on
   instruction: "we also need the nav for this element to be on either side").

   NOTE the comment that used to sit here claimed this nav was "CENTRED
   (2026-09-09)". It never was: the rule below it read `justify-content:
   flex-end`, and wp-check-restyle.php pinned flex-end too. The prose was
   stale, so it is replaced rather than carried forward.

   This is what Rolex's own comp draws. Measured on
   discover-rolex-with-grid-mockup-desktop.jpg: the four 402px cards run
   x148-1779 on a 1632 well, and the chevron is a 42px disc centred at
   x1821 / y1522 — i.e. OUTSIDE the row, 22px clear of the last card, and
   vertically centred on the tile (which spans y1237-1774, centre 1505).
   Scaled to our 1392 well at 1440 that is a ~36px disc, 19px clear; we keep
   the established 40px arrow and take 18px of clearance.

   The outward pull is `min()`ed against the gutter we actually have, because
   the comp is drawn at 1920 with 144px each side and we only get 24px at
   1440. (100vw - 100%)/2 is the live gutter; the -8px keeps a scrollbar's
   width from turning the pull into horizontal overflow. So the arrows sit
   fully outside the cards on a wide screen exactly as the comp has them,
   and tuck over the outer tiles as the window narrows, without ever
   pushing the page sideways.

   HIDDEN BELOW 768 (2026-09-21, client instruction). The note that used to
   sit here said Rolex's mobile comp (discover-rolex-with-grid-mockup-moblie.jpg)
   draws NO arrows there — just the 2-up cards, the dash track and View all —
   and that "removing a control is not what was asked". It has now been asked,
   for every carousel in the section, so the flag is discharged: see the
   shared @media (max-width: 767px) rule below. Keyboard access is unchanged,
   because every one of these rows carries tabindex="0" and scrolls with the
   arrow keys. */
body.rolex-section .rlx-ed-carousel__viewport { position: relative; }
body.rolex-section .rlx-ed-carousel__nav { display: flex; gap: 8px; justify-content: flex-end; margin-top: 16px; }
@media (min-width: 768px) {
	body.rolex-section .rlx-ed-carousel__nav {
		/* 40px arrow + the comp's own 22px clearance. Our 1920 render puts the
		   row at x150-1770 against the comp's x148-1779, i.e. effectively 1:1
		   at that width, so the comp's measured gap transfers directly. */
		--rlx-ed-nav-out: 62px;
		position: absolute;
		top: 50%;
		left: calc(-1 * min(var(--rlx-ed-nav-out), max(0px, (100vw - 100%) / 2 - 8px)));
		right: calc(-1 * min(var(--rlx-ed-nav-out), max(0px, (100vw - 100%) / 2 - 8px)));
		margin-top: 0;
		transform: translateY(-50%);
		justify-content: space-between;
		/* the bar spans the row, so it must not swallow clicks or swipes
		   meant for the cards underneath it */
		pointer-events: none;
	}
	body.rolex-section .rlx-ed-carousel__arrow { pointer-events: auto; }
}
body.rolex-section .rlx-ed-carousel__arrow {
	width: 40px;
	height: 40px;
	border-radius: 50%;
	border: 1px solid rgba(33, 33, 33, 0.2);
	background: var(--rlx-surface);
	cursor: pointer;
}
body.rolex-section .rlx-ed-carousel__arrow[disabled] { visibility: hidden; }
body.rolex-section .rlx-ed-carousel__arrow .rlx-icon { width: 16px; height: 16px; }

/* A TRAILING MARGIN ON THE LAST BLOCK IS PAID TWICE (2026-09-23).
   `main.rlx-ed-retailer` closes itself with `padding-bottom: var(--rlx-gap)`.
   Whatever ends it -- on /rolex/history/ the legacy image, on /rolex/team/ and
   /rolex/showroom/ their own closing blocks -- also carries its own
   `margin-bottom: var(--rlx-gap)`, for separating it from a SIBLING that, as
   the last child, does not exist. So the distance from the last image to the
   Keep exploring boundary was two gaps, not one.

   Measured against Rolex's own rendered mockup
   (rolex-at-retailer-name-our-history-page-mockup-desktop.jpg, 1920 wide):
   last image bottom y4765, section boundary y4863 -- 98px, which is the
   familiar uncapped-10vh rendering of the same 90px token this section uses
   (see the comps-render-108/80 note). Ours measured 180px.

   The gap belongs to the container that is always there, not to whichever
   block happens to fall last. */
body.rolex-section .rlx-ed-retailer > :last-child { margin-bottom: 0; }

/* ===========================================================================
   CAROUSEL NAV, SHARED ACROSS THE SECTION (2026-09-21, client instruction:
   "the nav needs to be on either end of the carousel ... and that needs to be
   true on the keep exploring and all carousel elements within the Rolex
   section", plus "on mobile the carousel nav needs to be hidden").

   Rolex's own desktop comp shows the behaviour exactly
   (discover-rolex-with-grid-mockup-desktop.jpg, the "Our Rolex selection"
   band): ONE arrow, on the RIGHT, vertically centred on the CARDS -- and no
   left arrow at all, because on the first page there is nothing behind you.
   So a disabled arrow is HIDDEN, not dimmed to 0.35 as all four were.

   visibility: hidden, NOT display: none, and the [disabled] attribute stays.
   display:none would drop a keyboard user's focus to <body> the moment they
   paged to the end while focused on Next; visibility keeps the box, keeps it
   unclickable, and leaves the flex layout of the bar unchanged so the
   remaining arrow does not jump sides.

   The Discover carousel was already positioned this way; these three now
   match it, via the __viewport wrapper each template gained. The 62px outset
   is Discover's measured value (40px arrow + the comp's 22px clearance) and
   the min()/max() clamp keeps the arrows inside the window on a narrow
   desktop rather than causing a horizontal scrollbar.

   NOT the model-page lightbox (.rlx-lightbox__arrow): that is a modal's
   control, not a page carousel, and it keeps its dimmed disabled state.
   NOT .rlx-gallery__row either -- it has no tabindex and no nav.
   ======================================================================== */
body.rolex-section .rlx-keep__viewport,
body.rolex-section .rlx-nw-keep__viewport,
body.rolex-section .rlx-hub__viewport { position: relative; }
@media (min-width: 768px) {
	body.rolex-section .rlx-keep__nav,
	body.rolex-section .rlx-nw-keep__nav,
	body.rolex-section .rlx-hub__nav {
		--rlx-ed-nav-out: 62px;
		position: absolute;
		top: 50%;
		left: calc(-1 * min(var(--rlx-ed-nav-out), max(0px, (100vw - 100%) / 2 - 8px)));
		right: calc(-1 * min(var(--rlx-ed-nav-out), max(0px, (100vw - 100%) / 2 - 8px)));
		margin-top: 0;
		transform: translateY(-50%);
		justify-content: space-between;
		/* the bar spans the row, so it must not swallow clicks or swipes
		   meant for the cards underneath it */
		pointer-events: none;
	}
	body.rolex-section .rlx-keep__arrow,
	body.rolex-section .rlx-nw-keep__arrow,
	body.rolex-section .rlx-hub__arrow { pointer-events: auto; }
}
/* MOBILE: no arrows at all, on any of the four. The dash track stays -- it is
   the affordance the comp draws -- and the rows are swipe-driven. */
@media (max-width: 767px) {
	body.rolex-section .rlx-keep__nav,
	body.rolex-section .rlx-nw-keep__nav,
	body.rolex-section .rlx-hub__nav,
	body.rolex-section .rlx-ed-carousel__nav { display: none; }
}

/* PREVIOUS POINTS LEFT (2026-09-09, reported on the Our Rolex selection
   carousel: "the prev chevron needs to update"). The icon sprite ships ONE
   chevron — `arrow`, pointing right (inc/rolex/rlx-icons.php's $known list
   has no left variant) — and all three carousels rendered it unrotated for
   Previous, so "Previous" pointed the same way as "Next". Rotating the glyph
   inside any [data-rlx-prev] button fixes this component AND the two others
   built on the same primitive (templates/rolex/keep-exploring.php,
   page-templates/rolex-watches-hub.php). The rotation is on the .rlx-icon,
   not the button, so the focus ring, border and hit area are unaffected. */
body.rolex-section [data-rlx-prev] .rlx-icon { transform: rotate(180deg); }

/* GLYPH CENTRING (2026-09-09, reported with a screenshot of the Our Rolex
   selection nav: "it is the svg that needs centering vert in the button").
   rlx_icon() emits an INLINE <svg class="rlx-icon">, so inside these 40px
   round buttons it sat on the text baseline and reserved descender space
   below it — the glyph rendered a few px high of centre in all three
   carousels. Making the button a flex centring box removes the line box
   entirely. The `Previous`/`Next` label rlx_icon() appends is
   .rlx-visually-hidden (position:absolute), so it is out of flow and does
   NOT become a second flex item that would push the glyph off-centre.
   Applies to all three primitives that share this button: the Discover
   carousel, Keep exploring, and the watches hub row. */
body.rolex-section .rlx-ed-carousel__arrow,
body.rolex-section .rlx-nw-keep__arrow,
body.rolex-section .rlx-keep__arrow,
body.rolex-section .rlx-hub__arrow {
	display: inline-flex;
	align-items: center;
	justify-content: center;
}
/* Wireframe fix (2026-08-17): discover-rolex-with-grid-template-desktop.jpg
   marks exactly 40px between the card row and its "Primary CTA" (View all)
   button here -- a distinct, smaller measurement from the shell's
   --rlx-gap-half token (clamp(24px, 5vh, 45px), ≈45px at typical desktop
   viewport heights), so stated as a literal value rather than reusing that
   token. Scoped to the Discover carousel's own View-all only, per the
   wireframe measured; the hub's structurally-similar .rlx-hub__viewall is
   untouched (not what this wireframe measures). */
body.rolex-section .rlx-ed-carousel__viewall { text-align: center; margin-top: 40px; }

/* Discover's 3 full-width promo rows (watches/accessories/contact) --
   each row is its own <section>+<h2>, wrapping ONE rlx-ed-tile--promo. */
/* BOTH the heading's margin-bottom AND the grid's margin-top, because the
   two COLLAPSE: setting only .rlx-ed-trio__grid { margin-top } left the
   heading's own 24px winning as max(24, 16) and nothing moved. Stating both
   makes the collapsed result the token. */
body.rolex-section .rlx-ed-promo h2,
body.rolex-section .rlx-ed-trio > h2 { margin: 0 0 var(--rlx-heading-gap); }

/* Discover's "Discover Rolex" trio: 3-up grid, 1-col mobile. */
/* DISCOVER ROLEX SITS ON THE PANEL ("tab") BACKGROUND (2026-09-09,
   reported: "the discover rolex section needs to have the tab bg and the
   other sections are a white bg", pointing at
   tmp/08.2026/Discover Rolex_Bespoke section/discover-rolex-page-templates).
   Measured off the gutter column of Rolex's own two desktop comps rather
   than guessed — both agree on three distinct bands:
     discover-rolex-with-grid-mockup-desktop.jpg  beige #F6F6F3 -> panel
       #F3EDEA (74.5%-86.1%) -> white #FFFFFF (86.1%-96.0%)
     discover-rolex-mockup-desktop.jpg            same order, same colours
   #F3EDEA is --rlx-panel (#F4EFEA) after JPEG shift, and cropping the panel
   band confirms it is exactly the "Discover Rolex" trio. The white band
   below it is Keep exploring, which already carries --rlx-surface (#FFFFFF)
   and needed no change; sampling four other page comps (watches, watches
   with grid, new-watches hub, watchmaking) found that band white on every
   one, so that is a template-wide constant, not a Discover special case.
   The page colour ABOVE the trio stays --rlx-bg: the comps keep the intro,
   the selection carousel and the three promos on #F6F6F3, not white.

   FULL-BLEED: this element is also .rlx-container (max-width 1620px), so a
   plain background would stop at the container edge while the comps run the
   colour to both viewport edges. box-shadow paints the overflow and
   clip-path stops it bleeding vertically into the neighbouring bands.

   The padding is the band's OWN, which is what the earlier "needs bottom
   padding under learn more" was actually describing — measured ~71px above
   the heading and ~123px below the last "Learn more" in the comp, either
   side of --rlx-gap's 90px. Because the band must abut the white Keep
   exploring band with no beige strip between them (the comps have the two
   touching at y=5096), .rlx-main drops its own bottom padding on this one
   page — that rule still protects every other page, where the last section
   would otherwise sit flush with the green footer band.

   The page class is written AFTER .rolex-section on the body
   (body.rolex-section.page-template-rolex-discover) rather than before it:
   same elements matched, same specificity, but tests/wp-check-shell.php
   enforces that every selector in this file leads with body.rolex-section so
   nothing can leak outside the section, and it flagged the other order. */
body.rolex-section .rlx-ed-trio {
	background: var(--rlx-panel);
	padding-block: var(--rlx-gap);
	box-shadow: 0 0 0 100vmax var(--rlx-panel);
	clip-path: inset(0 -100vmax);
}
body.rolex-section.page-template-rolex-discover .rlx-main { padding-bottom: 0; }

/* ===================================================================
   TINTED BANDS ABUT FULL-BLEED PHOTO BANDS (client report, 15 Sep 2026:
   "there is a lighter bg at the bottom that should not be there" and
   "the bleed image should have no margin between the section above").

   Profiled down every collection mockup's left edge, a tint band always
   runs straight into the region after it -- there is never a strip of
   page ground between a tint and a photograph:

     1908       TINT y3666-4996  -> PHOT y4996    TINT y10388-11822 -> PHOT y11822
     submariner TINT y3728-5438  -> PHOT y5438    TINT y9026-10592  -> PHOT y10592
     land-dweller PHOT -> TINT on all three bands, TINT y14982-16540 -> PHOT
     yacht-master-II PHOT y11398 -> TINT -> PHOT y12828

   We put 90px of page ground at each of those junctions: the bleed band
   carries `margin-top: var(--rlx-gap)` from .rlx-block, and where a tint
   ENDS the page it was .rlx-main's own 90px padding-bottom showing above
   the white Keep exploring band.

   Both sides are zeroed, because adjacent margins collapse to the LARGER
   of the two -- zeroing only the following band's margin-top would leave
   the preceding band's margin-bottom standing.

   The Discover rule above did this page-specifically ("comps have them
   touching"); this is the same finding, generalised to every route whose
   last band is tinted. It stays because Discover's last band is the trio,
   not a panel. */
body.rolex-section .rlx-editorial--panel + .rlx-image-block--bleed,
body.rolex-section .rlx-facade-section--panel + .rlx-image-block--bleed,
body.rolex-section .rlx-ed-retailer__band + .rlx-image-block--bleed,
body.rolex-section .rlx-image-block--bleed + .rlx-editorial--panel,
body.rolex-section .rlx-image-block--bleed + .rlx-facade-section--panel,
body.rolex-section .rlx-image-block--bleed + .rlx-ed-retailer__band {
	margin-top: 0;
}
body.rolex-section .rlx-editorial--panel:has( + .rlx-image-block--bleed ),
body.rolex-section .rlx-facade-section--panel:has( + .rlx-image-block--bleed ),
body.rolex-section .rlx-ed-retailer__band:has( + .rlx-image-block--bleed ),
body.rolex-section .rlx-image-block--bleed:has( + .rlx-editorial--panel ),
body.rolex-section .rlx-image-block--bleed:has( + .rlx-facade-section--panel ),
body.rolex-section .rlx-image-block--bleed:has( + .rlx-ed-retailer__band ) {
	margin-bottom: 0;
}
/* A tinted band that ENDS the page runs straight into Keep exploring --
   .rlx-keep is a sibling of .rlx-main, not of the band, so this is the
   main's own padding rather than an adjacency. */
body.rolex-section .rlx-main:has( > :last-child.rlx-editorial--panel ),
body.rolex-section .rlx-main:has( > :last-child.rlx-facade-section--panel ),
body.rolex-section .rlx-main:has( > :last-child.rlx-ed-retailer__band ) {
	padding-bottom: 0;
}

/* Same junction, second shape: the photograph is not always its own
   .rlx-image-block. On submariner the band after the first tint is an
   EDITORIAL whose leading media runs full-bleed (1920@0), and its comp
   abuts the tint exactly (TINT y3728-5438 -> PHOT y5438). Keyed on the
   media being the section's FIRST child, so an editorial whose bleed sits
   below its copy is untouched -- there the page ground legitimately
   separates the two. Mirrored for a trailing bleed meeting a tint. */
body.rolex-section .rlx-editorial--panel + .rlx-editorial:has( > .rlx-editorial__media--bleed:first-child ),
body.rolex-section .rlx-facade-section--panel + .rlx-editorial:has( > .rlx-editorial__media--bleed:first-child ),
body.rolex-section .rlx-ed-retailer__band + .rlx-editorial:has( > .rlx-editorial__media--bleed:first-child ),
body.rolex-section .rlx-editorial:has( > .rlx-editorial__media--bleed:last-child ) + .rlx-editorial--panel,
body.rolex-section .rlx-editorial:has( > .rlx-editorial__media--bleed:last-child ) + .rlx-facade-section--panel,
body.rolex-section .rlx-editorial:has( > .rlx-editorial__media--bleed:last-child ) + .rlx-ed-retailer__band {
	margin-top: 0;
}
/* The MEDIA's own margin escapes the section. An editorial has no bottom
   padding or border, so a trailing .rlx-editorial__media--bleed carrying
   `margin-bottom: var(--rlx-gap)` pushes the next band down THROUGH the
   section's box: on daytona the section ends at y9487 and the tint below
   starts at 9577, with both SECTIONS' margins already at 0. Zeroing the
   section margins alone therefore fixes nothing at this junction -- which
   is exactly what it did until this rule was added, and why daytona read
   clean on a sweep that only looked at section boxes. Mirrored for a
   leading bleed after a tint. */
body.rolex-section .rlx-editorial:has( + .rlx-editorial--panel ) > .rlx-editorial__media--bleed:last-child,
body.rolex-section .rlx-editorial:has( + .rlx-facade-section--panel ) > .rlx-editorial__media--bleed:last-child,
body.rolex-section .rlx-editorial:has( + .rlx-ed-retailer__band ) > .rlx-editorial__media--bleed:last-child {
	margin-bottom: 0;
}
body.rolex-section .rlx-editorial--panel + .rlx-editorial > .rlx-editorial__media--bleed:first-child,
body.rolex-section .rlx-facade-section--panel + .rlx-editorial > .rlx-editorial__media--bleed:first-child,
body.rolex-section .rlx-ed-retailer__band + .rlx-editorial > .rlx-editorial__media--bleed:first-child {
	margin-top: 0;
}
body.rolex-section .rlx-editorial--panel:has( + .rlx-editorial:has( > .rlx-editorial__media--bleed:first-child ) ),
body.rolex-section .rlx-facade-section--panel:has( + .rlx-editorial:has( > .rlx-editorial__media--bleed:first-child ) ),
body.rolex-section .rlx-ed-retailer__band:has( + .rlx-editorial:has( > .rlx-editorial__media--bleed:first-child ) ),
body.rolex-section .rlx-editorial:has( > .rlx-editorial__media--bleed:last-child ):has( + .rlx-editorial--panel ),
body.rolex-section .rlx-editorial:has( > .rlx-editorial__media--bleed:last-child ):has( + .rlx-facade-section--panel ),
body.rolex-section .rlx-editorial:has( > .rlx-editorial__media--bleed:last-child ):has( + .rlx-ed-retailer__band ) {
	margin-bottom: 0;
}

body.rolex-section .rlx-ed-trio__grid {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: 32px 8px; /* column gutter is the 8px tile value -- see the note on .rlx-hub__row */
	margin-top: var(--rlx-heading-gap);
}
@media (max-width: 767px) {
	body.rolex-section .rlx-ed-trio__grid { grid-template-columns: 1fr; }
}

/* templates/rolex/grids/ed-tiles.php: ONE tile, 3 size variants. */
body.rolex-section .rlx-ed-tile { display: block; color: inherit; text-decoration: none; }
body.rolex-section .rlx-ed-tile__media img { display: block; width: 100%; height: auto; object-fit: cover; }
/* Same correction as .rlx-hub-promo__media above, same evidence: 2400x800
   art, comp band 2.887, 16/7 cropping ~21% off the sides. The --trio and
   --hub variants below are NOT changed -- their boxes have no measured comp
   yet (see .rlx-hub-tiles__media's own note), and the retailer hub tiles have
   an unresolved asset-pairing defect at mobile where two tiles serve a
   landscape file with no portrait sibling, so following the asset there would
   render a 2440x800 into a 336-wide column at 110px tall. Those wait for the
   assets, not for a ratio. */
body.rolex-section .rlx-ed-tile--promo .rlx-ed-tile__media img { aspect-ratio: auto; object-fit: fill; }
/* THE CONTACT PUSH BAND IS CROPPED, and that is the comp's own doing.
   Its delivered landscape is 1200x800 = 1.5, while the comp draws the band
   1620x540 = 3.0 -- so unlike the trio and hub tiles, where the comp was
   rendering each asset's native ratio and we were imposing a crop, here the
   COMP crops. Same situation as the full-bleed boutique band further up this
   page, whose own note records the comp cropping a 2880x1700 to 1.899 and
   says it was checked rather than assumed. Scoped to .rlx-ed-push so the
   Discover promo tile, whose 2400x800 asset already matches its band, keeps
   following its own art. */
body.rolex-section .rlx-ed-push .rlx-ed-tile--promo .rlx-ed-tile__media img {
	aspect-ratio: 1620 / 540;
	object-fit: cover;
}
/* Comp: h2 ink bottom y3746 -> image top y3775; image bottom y4314 ->
   "Message" ink top y4343. Both 29, and both measured INK to IMAGE EDGE.
   The 16px media-to-title margin the shared tile rule uses is right for
   Discover's tiles and is left alone.

   21 and 20, NOT 29: the earlier values put the comp's ink figure straight
   onto a margin, but a 36px headline's ink sits 5.6px above its line box's
   bottom edge and 10.7px below its top, so a 29px margin rendered 37 and 38
   ink-to-image. Re-measured on the live block by ink rather than by box --
   heading ink ends y34, image y71-610, title ink y648 -- and set so both
   read 29 the way the comp does. The CTA gap under the title was already
   right at 14 against the comp's 15 and is untouched. */
body.rolex-section .rlx-ed-push__title { margin: 0 0 21px; color: var(--rlx-brown); }
body.rolex-section .rlx-ed-push .rlx-ed-tile__media + .rlx-ed-tile__title { margin-top: 20px; }
/* THE COMPS HAVE NOW BEEN MEASURED, so the hold above is lifted for DESKTOP.
   The note said the trio and hub boxes had "no measured comp yet"; they do:
     Discover trio       comp 1.49  -- assets 1200x800 and 810x540, both 3:2
     retailer hub pair   comp 1.499 -- exactly the asset's native 1200x800
     retailer hub lead   comp 2.90  -- asset 2440x800 = 3.05
   So the comps are drawing each asset's own ratio, and 4/3 was cropping art
   that already fitted. Same principle the heroes and the promo tile follow.
   The lead is within 5% of its asset and is not separately cropped here.

   MOBILE IS DELIBERATELY NOT `auto`. That was the note's second reason and it
   still stands: two hub tiles serve a landscape file with no portrait
   sibling, so following the asset at 336 wide would render a 2440x800 as a
   110px band. 1:1 there is also what BOTH sources want -- the retailer hub
   mobile comp draws all three tiles square, and the client asked for square
   mobile images on 2026-09-14. */
body.rolex-section .rlx-ed-tile--trio .rlx-ed-tile__media img,
body.rolex-section .rlx-ed-tile--hub .rlx-ed-tile__media img { aspect-ratio: auto; }
/* Tile kicker + title are ONE brown, bold, tightly-set pair -- Ashton items
   14 ("copy should be bolded here too") and 15 ("spacing between the copy
   could be tighter"), raised on the Discover Rolex trio at mobile.

   Measured off discover-rolex-send-a-message-mockup-mobile.jpg, ink to ink,
   halved to CSS px. Both the TRIO and the PROMO tiles set the kicker and the
   title in the same Brown (sampled #442C1D ~ --rlx-brown), both bold, with
   the kicker only ~5-6px above the title -- they read as one label, not a
   caption over a heading:

                        comp    was     why it drifted
     image -> kicker    18.0    20.5    kicker margin-top 16
     kicker -> title     5.0    14.5    title margin-top 4 + body20's 1.6 lh
     title -> CTA       15.5    18.0

   The kicker was also 0.7 opacity over #212121, which is what made it read as
   grey caption text; the comp has it at full strength. Applied to every
   ed-tile rather than scoped to mobile or to the trio: the DESKTOP mockup and
   the promo tiles measure the same (promo: brown, brown, 6.0px gap), so the
   trio at mobile is where Ashton noticed it, not where it is wrong. */
body.rolex-section .rlx-ed-tile__kicker { margin: 13px 0 0; font-weight: 700; color: var(--rlx-brown); }
body.rolex-section .rlx-ed-tile__title { margin: 0; font-weight: 700; color: var(--rlx-brown); line-height: var(--rlx-lh-headline); }
/* The 16px under the image belongs to the FIRST caption line, whichever
   element that turns out to be. ed-tiles.php omits the kicker entirely when
   a tile has none, and the hub's "Contact us" promo is such a tile — so
   __title's 4px landed directly under the photograph there, 4px where its
   two sibling promos have 16px. Only tiles without a kicker are affected. */
body.rolex-section .rlx-ed-tile__media + .rlx-ed-tile__title { margin-top: 16px; }
body.rolex-section .rlx-ed-tile__cta { margin-top: 8px; }

/* Retailer hub's 3 page tiles: 1 full-width + 2 side-by-side, matching
   the real hub mockup (rolex-at-retailer-name-hub-mockup-desktop.jpg). */
/* Lead image pair on a retailer page (history): two archive photographs side by
   side under the intro, per Rolex's page-1 layout brief. Deliberately mirrors the
   hub's team/history tile pair below — same 2-column grid, same --rlx-gap-half
   gutter, same mobile stack — so the section reads as one layout language rather
   than two similar-but-different ones. */
body.rolex-section .rlx-ed-retailer__pair {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: var(--rlx-gap-half);
	margin-block: var(--rlx-gap);
}
body.rolex-section .rlx-ed-retailer__pair-item img {
	width: 100%;
	height: auto;
	display: block;
	/* NO CROP, because the pair is now a MATCHED pair (2026-09-09). The 4/3
	   cover crop this replaces existed for a specific reason, recorded here at
	   the time: the delivered pair was 2.13:1 beside 0.86:1 (a 2000x940
	   composite next to a 1200x1400 portrait), which rendered 764x359 beside
	   764x891 — a ragged band where the mockup shows an even one, so a shared
	   ratio was forced onto both.
	   That reason is gone. The client has cut the composite into its two halves
	   at 990x938 EACH, so the two cells are identical by construction and the
	   band is even with no crop at all. Rendering them at their own ratio also
	   respects that these are the client's own crops, made for this row.
	   Recorded for the review: the pair box in the client's column-4 mockup
	   measures 488x393 (1.24), between this 1.055 and the old 4/3 (1.333). A
	   1.24 box would crop ~15% off images the client cut deliberately, so the
	   assets win; this is one value to change if Rolex or the client asks.

	   SCOPED TO DESKTOP 2026-09-12. 990/938 is a no-op at >=768px because the
	   delivered halves ARE 990x938 -- but mobile serves the -portrait variant
	   at 940x989 (0.950), and this ratio with no object-fit resolves to
	   `fill`, which STRETCHED those two photographs of people 11.2% wider at
	   390. "No crop" was the intent and stretching is worse than cropping.
	   Below 768 the pair is a single column anyway, so the even-band argument
	   for forcing a shared ratio does not apply there. */
	aspect-ratio: 990 / 938;
}
@media (max-width: 767px) {
	body.rolex-section .rlx-ed-retailer__pair { grid-template-columns: 1fr; }
	/* SQUARE at mobile. Client ruling, 15 Sep 2026: "We have liberty on the
	   retailer pages that have been approved - yes crop mobile square".
	   Every other retailer image already rendered 336x336 here; these pair
	   items were 336x354 (0.95) and the legacy image 336x339 (0.99), close
	   enough to read as a mistake rather than a choice. Now stated. */
	body.rolex-section .rlx-ed-retailer__pair-item img,
	body.rolex-section .rlx-ed-retailer-legacy__image img {
		aspect-ratio: 1 / 1;
		object-fit: cover;
	}
}

/* The lead tile follows its own 2440x800 asset too (comp 2.90 vs asset 3.05);
   16/7 = 2.286 was cropping ~25% off its sides. */
body.rolex-section .rlx-ed-retailer-hub-tiles > .rlx-ed-tile--hub .rlx-ed-tile__media img { aspect-ratio: auto; }
/* The retailer hub's captions sit LOWER than the shared tile rule puts them,
   and its own comp says so on all three of its tiles. Measured ink-to-ink on
   rolex-at-retailer-name-hub-mockup-desktop.jpg: the lead tile's image ends
   y1499 with "Our Rolex showrooms" ink at y1530 and "Learn more" ink at
   y1587; the pair repeats it exactly (image y2230, title ink y2261, CTA ink
   y2318). That is 31 from the image and 30 between the two lines of text,
   where the shared 16/8 margins were giving us 24 and 20.

   Scoped to this hub, not raised globally: the 16px media-to-title margin is
   already recorded as correct for Discover's trio, and the push tiles carry
   their own 29 for the same reason. */
body.rolex-section .rlx-ed-retailer-hub-tiles .rlx-ed-tile__media + .rlx-ed-tile__title { margin-top: 23px; }
body.rolex-section .rlx-ed-retailer-hub-tiles .rlx-ed-tile__cta { margin-top: 18px; }
@media (max-width: 767px) {
	/* Square at mobile -- comp and client instruction agree, and it is what
	   keeps the unpaired landscape assets from collapsing to a 110px band. */
	/* Must match the desktop rule's own shape (> .rlx-ed-tile--hub), or it
	   loses on specificity and the lead tile renders 336x110 -- verified,
	   not assumed: that is exactly what it did with a shorter selector. */
	body.rolex-section .rlx-ed-retailer-hub-tiles > .rlx-ed-tile--hub .rlx-ed-tile__media img,
	body.rolex-section .rlx-ed-retailer-hub-tiles .rlx-ed-tile--hub .rlx-ed-tile__media img {
		aspect-ratio: 1 / 1;
		object-fit: cover;
	}
	/* AND the caption tightens at mobile: 21 and 21, against desktop's 31 and
	   30. Measured on rolex-at-retailer-name-hub-mockup-mobile.jpg, where the
	   three square tiles end at CSS y1080 / 1550 / 2020 and each one's title
	   ink follows 21 later with its "Learn more" ink 21 under that -- the same
	   pair of gaps on all three, where desktop's comp gives two different
	   ones. The 8px CTA margin is the shared rule's own value restored: it was
	   already right here, and only desktop needed the 18. */
	body.rolex-section .rlx-ed-retailer-hub-tiles .rlx-ed-tile__media + .rlx-ed-tile__title { margin-top: 13px; }
	body.rolex-section .rlx-ed-retailer-hub-tiles .rlx-ed-tile__cta { margin-top: 8px; }
}
body.rolex-section .rlx-ed-retailer-hub-tiles__pair {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: 8px; /* comp: two 808px panels 8px apart -- see the note on .rlx-hub__row */
	margin-top: var(--rlx-gap-half);
}
/* A COLUMN GUTTER IS NOT A ROW GAP (2026-09-22, client: "the spacing between
   the our rolex team and history below it on mobile is missing the required
   spacing").

   The pair is a 2-up grid whose 8px `gap` is a COLUMN gutter -- the comp's
   two 808px panels 8px apart. At <=767 the grid collapses to one column and
   that 8px silently became the ROW gap between two stacked tiles, i.e. 8px
   between one tile's CTA and the next tile's photograph.

   Measured at 430/390/767 before the fix, the three tiles stacked with gaps
   of 40px then 8px -- the SAME relationship rendered two ways on one page,
   which is what reads as missing spacing.

   40px is not a new number: it is `--rlx-gap-half`, the pair's own margin-top,
   i.e. exactly what already separates the first tile from this pair. Taking
   it for the row gap makes all three stacked tiles evenly spaced. Stated
   rather than measured off the comp: the retailer-hub mobile comp does not
   isolate this gap cleanly (its tiles are 630 CSS px apart with the title and
   CTA block between them), and internal consistency on the same page is the
   stronger evidence here. Desktop is untouched -- the 8px gutter is still
   correct the moment there are two columns. */
@media (max-width: 767px) {
	body.rolex-section .rlx-ed-retailer-hub-tiles__pair {
		grid-template-columns: 1fr;
		gap: var(--rlx-gap-half);
	}
}

/* THE PARENT THEME DELETES EVERY LINE BREAK ON PHONES.
   roneous/style.min.css carries a blanket `br { display: none }` inside
   @media (max-width: 767px). Found 2026-09-22 while checking the contact
   page on mobile: the store address is authored as two lines
   ("4518 Plainfield Ave NE<br>Grand Rapids, MI 49525") and renders as two
   lines at desktop, but at 390 the break vanished and the text reflowed to
   "4518 Plainfield Ave NE Grand Rapids, MI / 49525" -- the postcode
   orphaned on its own line. The <br> was in the DOM the whole time; its
   computed display was `none`.

   Restated for OUR content only, not `body.rolex-section br`: that would
   reach the site header and footer, which are the parent theme's markup and
   may be relying on the rule. .rlx-main is the section's own content area.
   Counted first -- exactly one <br> exists across the whole section today
   (this address), so the blast radius is that one element, but the rule is
   written for the class of bug rather than the instance.

   A child-theme override, never an edit to the parent's stylesheet. */
@media (max-width: 767px) {
	body.rolex-section .rlx-main br { display: inline; }
}

/* THE INTRO'S OPTIONAL SECONDARY CTA (2026-09-22). Only the contact page
   passes one today: Rolex's single-POS comp draws "Send a message" as a
   green Fixed14 link with the chevron, inside the intro's RIGHT column,
   directly under the paragraph. It was a primary pill in the LEFT column
   with no top margin at all, so it also sat flush against the text above
   it -- the spacing report and the treatment turned out to be the same
   defect.

   15px / 24px, measured rather than chosen. The comps give 27px desktop and
   33px mobile of INK between the paragraph's last line and the link; the
   Body20 paragraph's own descender space eats 12 of that at desktop and 9
   at mobile, so the margins differ even though the target gaps are only 6px
   apart. Both re-measured live after setting them (27 and 33.5).

   Deliberately NOT --rlx-gap-half: that token is the SECTION rhythm, and
   this is a gap inside one block -- the same distinction --rlx-heading-gap
   exists for, and the same mistake .rlx-ed-promo h2 was making. */
body.rolex-section .rlx-coll-intro__cta { margin: 15px 0 0; }
@media (max-width: 767px) {
	body.rolex-section .rlx-coll-intro__cta { margin-top: 24px; }
}

/* templates/rolex/grids/ed-store-card.php (Contact page). */
/* .rlx-ed-store__location's rule was removed 2026-09-19: the location is now
   the card's H2 (.rlx-ed-store__label) and no separate line renders. The
   class is gone from the markup too, so this is a deletion rather than a
   dead rule left to rot. */
body.rolex-section .rlx-ed-store__lines {
	list-style: none;
	margin: var(--rlx-gap-half) 0 0;
	padding: 0;
	display: flex;
	flex-wrap: wrap;
	gap: 12px 24px;
}
/* Opening hours: its own row between the address and the CTA list, not a
   member of the list (see ed-store-card.php for why, and for what is
   deliberately NOT built). The 20px above and below are Rolex's own rhythm
   for this card at Large -- spec p99 runs address -> 20 -> hours -> 20 ->
   CTAs -- and Fixed16 is the token the spec names for both halves of the
   line. The stored value is free text and may be several lines, so
   white-space stays normal and the <br>s from nl2br carry the breaks. */
body.rolex-section .rlx-ed-store__hours {
	white-space: normal;
	margin: 20px 0;
	color: var(--rlx-ink);
}
/* STRUCTURED HOURS. Rolex's line is `Fixed 16` + `Fixed 16` in Black /
   Green (spec p99): a bold "Open today" against that day's hours in green.
   The whole week sits behind the disclosure.

   The summary ships with the neutral server text and the script swaps in the
   day -- see ed-store-card.php for why it cannot be rendered server-side. So
   the green is applied to the VALUE span, which is empty until then and
   therefore invisible rather than a stray coloured gap. */
body.rolex-section details.rlx-ed-store__hours > summary {
	display: flex;
	align-items: baseline;
	gap: 0.5em;
	cursor: pointer;
	list-style: none;
	color: var(--rlx-ink);
}
body.rolex-section details.rlx-ed-store__hours > summary::-webkit-details-marker { display: none; }
body.rolex-section .rlx-ed-store__hours-label { font-weight: 700; }
body.rolex-section .rlx-ed-store__hours-value { color: var(--rlx-green); }
/* The caret. Drawn rather than relying on the UA marker, which cannot be
   positioned consistently and is hidden above. Rotates on open; the
   transform is the only thing that moves, and it is dropped under reduced
   motion. */
/* THE CARET FOLLOWS THE TIME, it does not sit at the row's right edge
   (2026-09-22, client: "fix the Open today chevron drift on mobile").

   It carried `margin-left: auto`, which pushes a flex item to the end of
   its line. That read as "next to the time" only because the summary box
   happens to be shrink-to-fit at desktop; at 390 the summary spans the full
   335px column and the caret flew 108px clear of the time (26px at 1440 --
   the same rule, two different answers, which is the tell).

   Rolex's mobile comp draws it immediately after the time. Dropping the
   auto margin lets the summary's own `gap: 0.5em` set the distance, which
   is 8px at Fixed16 -- and 8px is what the comp measures. */
body.rolex-section details.rlx-ed-store__hours > summary::after {
	content: "";
	/* A FILLED GREEN TRIANGLE (2026-09-22, client), not the ink-coloured
	   chevron outline this was. Measured off Rolex's mobile comp, which is
	   2x: the caret is 24x12 device = 12x6 CSS, pointing down, filled
	   rgb(17,119,72) -- which is --rlx-green (#127749 = rgb(18,119,73)) to
	   within JPEG noise, so the token is used rather than the sampled value.

	   The classic border trick: a zero-size box whose left and right borders
	   are transparent and whose top border is the fill. 6px a side gives the
	   12x6 the comp measures. */
	width: 0;
	height: 0;
	border-left: 6px solid transparent;
	border-right: 6px solid transparent;
	border-top: 6px solid var(--rlx-green);
	/* The summary is align-items: baseline and this pseudo carries no text,
	   so it has no baseline to align on -- the nudge is measured, not
	   guessed. The comp centres the triangle on the time text (triangle
	   centre y2359.5 against the text band's 2359). -3px left it 2px high;
	   -1px lands the two centres on each other, live-measured at 390. */
	transform: translateY(-1px);
	transition: transform 150ms cubic-bezier(0.23, 1, 0.32, 1);
}
body.rolex-section details.rlx-ed-store__hours[open] > summary::after {
	/* Points UP when open. Rotating about the box's own centre flips it in
	   place, so the same nudge holds. */
	transform: translateY(-1px) rotate(180deg);
}
body.rolex-section .rlx-ed-store__week {
	list-style: none;
	margin: 12px 0 0;
	padding: 0;
}
body.rolex-section .rlx-ed-store__week li {
	display: flex;
	justify-content: space-between;
	gap: 1em;
	padding: 2px 0;
	color: var(--rlx-ink);
}
body.rolex-section .rlx-ed-store__week li[data-closed] { opacity: 0.7; }
@media (prefers-reduced-motion: reduce) {
	body.rolex-section details.rlx-ed-store__hours > summary::after { transition: none; }
}
/* THE GAP BELONGS TO THE OPTIONAL ELEMENT (`gap-belongs-to-the-optional-
   element`). `.rlx-ed-store__lines` owns a --rlx-gap-half top margin, which
   is right when it follows the address directly. When the hours row is
   present it sits between them, and the two margins collapse to the larger
   one -- 45px, where the spec's rhythm is 20 and the comp measures ~31. So
   the hours row owns the gap below itself and zeroes the list's, and a card
   with no hours set is untouched. */
body.rolex-section .rlx-ed-store__hours + .rlx-ed-store__lines { margin-top: 0; }

/* Placed AFTER the base .rlx-ed-store__lines rule above, deliberately. Both
   selectors score (0,2,1), and a media query adds no specificity, so the
   mobile override only wins on SOURCE ORDER. Written first beside
   .rlx-hero__ctas, where it read better, it lost silently and the list went
   on wrapping -- caught by measuring flex-wrap in the rendered page rather
   than by trusting the edit. Keep this block below the base rule. */
@media (max-width: 767px) {
/* THE STORE CARD'S CONTACT CLUSTER IS THE SAME SCROLLER (2026-09-23).
   /rolex/contact/ rendered its three actions -- call, send a message, get
   directions -- as a WRAPPING flex list, so "Get directions" dropped to a
   second row and each action wore its glyph in a separate white circle.
   Rolex's single-POS mobile mockup draws the model page's idiom instead:
   ONE horizontally scrolling row of pills with the glyph inside the pill,
   the second pill clipped at the right edge, which is the tell that it
   scrolls. Reported from the browser at 430.

   Deliberately the SAME declarations as .rlx-hero__ctas directly above,
   not an approximation of them: same 100vw bleed so the clipped pill can
   reach the viewport edge while the first stays on the 27px gutter, same
   pill geometry, same hidden scrollbar, same de-circled glyph. If that
   block's values change, change these with it -- they are one component
   wearing two class names, which is a smell worth recording rather than
   hiding.

   .rlx-ed-store__lines holds EXACTLY these three actions and nothing else
   (verified in the rendered DOM: the address and opening hours are not in
   this list), so switching it to nowrap cannot strand other content. */
body.rolex-section .rlx-ed-store__lines {
	display: flex;
	flex-wrap: nowrap;
	/* 14px, not the 20 this shipped with earlier today. Measured on the
	   mobile comp at the pills' own CENTRE line (y2495-2499), where the
	   20px radius no longer insets the edge: pill 1 ends x437, pill 2
	   starts x465, i.e. 27px at 2x. Reading the gap near the pill's TOP
	   edge instead reports ~25px, because each rounded corner eats 8css
	   off the run -- that is how the 20 got there. */
	gap: 14px;
	width: 100vw;
	margin-inline: calc(50% - 50vw);
	padding-inline: 27px;
	overflow-x: auto;
	scrollbar-width: none;
}
body.rolex-section .rlx-ed-store__lines::-webkit-scrollbar { display: none; }
body.rolex-section .rlx-ed-store__lines > li { flex: 0 0 auto; }
body.rolex-section .rlx-ed-store__lines .rlx-cta-tertiary {
	min-height: 40px;
	padding-inline: 24px;
	border-radius: 20px;
	/* #F2F2F2 literally, for the SAME reason the status tags above it are:
	   --rlx-surface is #FFFFFF on this build, so these three actions were
	   painting white on the page's own #F9F7F4 while the mobile comp draws
	   them (242,242,242) -- sampled over 1783 px in one flat run, the same
	   value the Brand Centre Tags sheet gives. Height 40 and padding-inline
	   24 were already right (comp: 80px tall at 2x, padR 24.0css). */
	background: #F2F2F2;
	gap: 10px;
	font-size: var(--rlx-fixed16);
	white-space: nowrap;
}
body.rolex-section .rlx-ed-store__lines .rlx-cta-tertiary .rlx-icon {
	width: 15px;
	height: 15px;
	padding: 0;
	border-radius: 0;
	background: none;
}
}

/* ROUND CTA, LIGHT GREY, ON THE CONTACT CARD (2026-09-24, Ernie, with the
   Brand Centre Round CTA sheet). The sheet's Light grey variant: filled
   circle 44x44 at desktop, #D4D4D4 at 30% opacity, black icon 14x14;
   hover #F3F3F3 at 50%, icon still black. The mobile row is the column
   the sheet gives as 40x40, but the single-POS mobile mockup draws these
   three as pills with the glyph inside (the block above), so from 768 up
   only.

   What was wrong: the shared .rlx-cta-tertiary circle is filled with
   --rlx-surface, which is #FFFFFF on this build, and this card is #FFFFFF,
   so all three circles were invisible and the icons read as bare glyphs.
   "Black" is --rlx-ink: the comps sample Rolex's black at (32,32,32).
   Scoped to this card: .rlx-cta-tertiary on the model hero sits on the
   page ground and its own comp draws a white circle there.

   The single-POS desktop mockup itself draws these at 40px in a beige
   #F8F7F3 with a brown glyph; the component sheet is the one Ernie asked
   for, so it wins, and the disagreement is recorded rather than averaged. */
@media (min-width: 768px) {
	body.rolex-section .rlx-ed-store__lines .rlx-cta-tertiary .rlx-icon {
		width: 44px;
		height: 44px;
		padding: 15px;
		border-radius: 50%;
		background: rgba(212, 212, 212, 0.3);
		color: var(--rlx-ink);
	}
	/* One line, always. Beside the map at 768-900 the card's text column is
	   only 135-159px, and the labels wrapped -- the phone number broke
	   after "363-". Measured: already true at 768 before the circle grew,
	   and the 8px it gained tipped 820 and 900 over too. The run may reach
	   into the card's own ~40px padding at 768; it stays inside the card. */
	body.rolex-section .rlx-ed-store__lines .rlx-cta-tertiary { white-space: nowrap; }
	/* ONE ACTION PER ROW (2026-09-28, Rolex Staging Link #2 review: "Get
	   Directions can be underneath 'send a message' on desktop"). The list
	   wrapped, so phone sat alone and message + directions shared row 2.
	   A column keeps the markup order: phone, message, directions. */
	body.rolex-section .rlx-ed-store__lines {
		flex-direction: column;
		align-items: flex-start;
	}
}
@media (min-width: 768px) and (hover: hover) and (pointer: fine) {
	body.rolex-section .rlx-ed-store__lines .rlx-cta-tertiary:hover .rlx-icon { background: rgba(243, 243, 243, 0.5); }
}


/* Contact page's 2 kept services blocks -- deliberately its own
   `rlx-ed-service` component, not a reuse of `.rlx-editorial*`. */
/* ONE block: an 808 image left, a 672 accordion right, heading above both.
   This used to be one alternating full-bleed band PER service. The comp
   (rolex-contact-page-single-pos-mockup-desktop.jpg, y1976-2508) puts the
   image at x148-955 and the accordion's rules at x1096-1768, i.e. 49.9% /
   8.5% gap / 41.6% of the 1620 container -- which is .rlx-guarantee's
   49.5%/8.3% to within 6px, the same component shape. The image keeps its
   own ratio rather than a forced 4/3: the delivered file is the one the comp
   prints. */
/* The contact page's full-bleed boutique band. 1920x1011 = 1.899 in the comp
   against a 2880x1700 = 1.694 delivery, i.e. the comp crops this one --
   verified by rendering the band beside the file: same photograph, top and
   bottom trimmed. So this band forces its ratio, unlike the editorial and
   cover slots where the comps do not crop. */
body.rolex-section .rlx-ed-bleed {
	width: 100vw;
	max-width: none;
	margin-inline: calc(50% - 50vw);
}
body.rolex-section .rlx-ed-bleed img {
	display: block;
	width: 100%;
	aspect-ratio: 1920 / 1011;
	height: auto;
	object-fit: cover;
}
@media (max-width: 767px) {
	body.rolex-section .rlx-ed-bleed img { aspect-ratio: auto; object-fit: fill; }
}

body.rolex-section .rlx-ed-service {
	display: grid;
	grid-template-columns: 49.9% 1fr;
	column-gap: 8.5%;
	align-items: start;
}
body.rolex-section .rlx-ed-service__title { grid-column: 1 / -1; margin: 0 0 var(--rlx-gap-half); }
body.rolex-section .rlx-ed-service__media img { display: block; width: 100%; height: auto; }
body.rolex-section .rlx-ed-service__accordion .rlx-accordion__button { color: var(--rlx-brown); }
@media (max-width: 767px) {
	body.rolex-section .rlx-ed-service { grid-template-columns: 1fr; column-gap: 0; row-gap: var(--rlx-gap-half); }
	/* EACH SERVICE IMAGE KEEPS ITS OWN SHAPE ON MOBILE (2026-09-09). The 4/3
	   box above is correct on desktop, where both slots serve a landscape
	   stem. On mobile the two slots serve DIFFERENT shapes — measured at
	   390px, appointment is 740x840 (0.881) and message is 1170x1170 (1.000)
	   — so no single ratio fits both, and 4/3 cover-cropped the portrait one.
	   Rolex's contact mobile comp says the same thing: its two slots measure
	   684x780 (0.877) and 672x672 (1.000), which are those two files' own
	   ratios. Dropping the forced ratio therefore reproduces the comp for
	   both slots exactly, and is why this is `auto` rather than a third
	   literal value that would be wrong for one of them. */
	body.rolex-section .rlx-ed-service__media img { aspect-ratio: auto; }
}

/* Retailer child pages: cover(reused .rlx-coll-hero) -> H1+intro
   (reused .rlx-coll-intro, tagline-less) -> L image -> block -> portrait
   image -> block -> XL image (hero reused, lazy). */
body.rolex-section .rlx-ed-retailer__image { margin-block: var(--rlx-gap); }
/* The "Paul and Sons... The Legacy Continues Today" image (history only) is
   a plain .rlx-container div, NOT a .rlx-block and not a
   .rlx-ed-retailer__image, so it inherited neither source of the 90px
   rhythm and had no rule of its own at all. It sat 10px under its own
   paragraph — that 10px being the <p>'s trailing margin — where every other
   image on the page sits at 90. Same declarations as its siblings above. */
body.rolex-section .rlx-ed-retailer-legacy__image { margin-block: var(--rlx-gap); }
/* max-width, NOT width: this one's delivered asset is only 1200x1212, so a
   `width: 100%` like its siblings use upscaled it 1.31x at 1920 (its
   siblings are 4800px wide and never hit that). Centred rather than
   left-aligned, which is how Rolex places every single image in this build.
   There is no Rolex comp for this section at all — it is client-supplied
   content via RETAILER_MEDIA['history']['extra_section'] — so not upscaling
   and not overflowing is the defensible default. */
body.rolex-section .rlx-ed-retailer-legacy__image picture,
body.rolex-section .rlx-ed-retailer-legacy__image img { display: block; max-width: 100%; height: auto; margin-inline: auto; }
body.rolex-section .rlx-ed-retailer__image picture,
/* THE RETAILER TINTED BAND. Every retailer mockup carries exactly one
   #F4EFEB band (history y1906-3612, team y3088-4780, showrooms
   y1884-3216) wrapping a heading, its body and the image below them.
   Full-bleed like the collection panels, with the section's own 90px
   padding; the copy and image inside keep their own container insets. */
body.rolex-section .rlx-ed-retailer__band {
	background: var(--rlx-panel);
	padding-block: var(--rlx-gap);
	/* THE GAP ABOVE THE TINT (2026-09-22, client: "add separation between
	   the An age-old craft... copy block and the section below it").

	   Measured on /rolex/history/ before this: every block boundary on the
	   page is 90px at desktop and 60px at mobile -- except this one, which
	   was 10px at both. The 10 is a stray paragraph margin, not a designed
	   gap.

	   The cause is the parent theme: roneous sets
	   `section, footer { margin-bottom: 0 !important }`, which beats
	   .rlx-block's own `margin-block` on every <section> in this build. The
	   layout only looks right elsewhere because the NEXT element supplies
	   the gap with its margin-top -- and this band is not .rlx-block, so it
	   had none to give. Its padding-block is inside the tint, so it
	   separates the band's copy from the band's edge, not the band from
	   what precedes it.

	   A margin rather than making the band .rlx-block: the adjacency rules
	   above deliberately zero this margin where a tinted band meets a
	   full-bleed image, and they are keyed on `+` so they outrank this and
	   keep those seams closed. */
	margin-top: var(--rlx-gap);
}
body.rolex-section .rlx-ed-retailer__band > :first-child { margin-top: 0; }
body.rolex-section .rlx-ed-retailer__band > :last-child { margin-bottom: 0; }
body.rolex-section .rlx-ed-retailer__image img { display: block; width: 100%; height: auto; }
/* CORRECTED 2026-09-12 -- these three were HOUSE CROPS and the section's own
   rule is that the box follows the asset (see .rlx-cover's note: no house
   crop). They were `aspect-ratio: 16/10 | 4/5 | 16/7` with `object-fit:
   cover`, which discarded whatever did not fit. Measured deviation of box
   ratio from the delivered file's own ratio, before this change:

     history  mobile  --xl        390x171  from 1000x2000   357%
     showroom mobile  --xl        390x171  from  780x840    146%
     team     desktop --xl       1920x840  from 1971x1478    71%
     team     desktop --portrait  640x800  from 2560x933     71%
     showroom desktop --l        1620x1013 from 2440x800     48%

   The history mobile case rendered a PORTRAIT asset as a 171px letterbox
   strip -- subject gone entirely. These are the client's own approved 2022
   store photographs, so cropping them to fit a grid we invented is the wrong
   trade: the heights now vary per asset, which is the standing rule and what
   every other image in the section already does.

   The portrait variant's 640px cap was also off-grid (the 12-col well gives
   span5 670 / span6 810, never 640) and carried no rationale. It is now
   span6, which is the width the comps use for a single portrait image. */
body.rolex-section .rlx-ed-retailer__image--l img,
body.rolex-section .rlx-ed-retailer__image--xl img { aspect-ratio: auto; object-fit: fill; }
body.rolex-section .rlx-ed-retailer__image--portrait img {
	aspect-ratio: auto;
	object-fit: fill;
	max-width: min(810px, 100%);
	margin-inline: auto;
}

/* MOBILE: ALL RETAILER IMAGES ARE SQUARE, IN THE WELL (2026-09-14, Rolex
   staging review): "Mobile: ensure the images are all the same size/style for
   consistency. A square image should be applied to match the other entries on
   the page."

   This DELIBERATELY re-introduces a crop, and only at mobile. The desktop rule
   above -- box follows the asset, no house crop -- is unchanged and still the
   default everywhere else; Rolex have asked for consistency over fidelity on
   this one breakpoint, on their own pages, and that is their call to make.

   What it replaces, measured at 390 before this: 336x392, 336x216, 390x780,
   336x224, 336x362, 336x522, 390x293, 336x336, 336x458, 390x420 -- ten
   different shapes down one page, which is what "all the same size/style" is
   reacting to. Two of them (showroom's 780x780 pair) were already square,
   which is the "other entries" being matched.

   --xl comes into the well too rather than staying full-bleed: he asks for one
   size, and the well is what the other entries use. object-fit:cover centres
   the crop, so history's 1000x2000 portrait keeps its middle rather than its
   top. */
@media (max-width: 767px) {
	/* EXTENDED SECTION-WIDE 2026-09-15, on the client's ruling that the
	   14 Sep instruction ("make mobile images square") applies throughout,
	   not just to the retailer pages it was first raised on. Same treatment
	   as those: 1:1 with object-fit:cover, so a crop is centred rather than
	   top-anchored.

	   Measured at 390 before this, the in-flow imagery ran 0.39, 0.45, 0.5,
	   0.78, 0.8, 0.93, 1.26, 1.34 and 1.78 on the collection, accessories,
	   New Watches and article pages -- the same "many shapes down one page"
	   the instruction is reacting to.

	   THREE THINGS ARE DELIBERATELY EXCLUDED, because squaring them would
	   contradict a separate ruling or misrepresent the content:
	     - the page HERO (.rlx-coll-hero / .rlx-hero), which renders each
	       asset's own intrinsic ratio by a standing rule of its own;
	     - the VIDEO poster (.rlx-facade-section), which is 16:9 because the
	       video is;
	     - the full-bleed decorative bands (.rlx-ed-bleed, .rlx-ed-push),
	       the latter built to a ratio the contact comp specifies.
	   Raise those separately if they are wanted square too. */
	/* NARROWED 2026-09-23, on the client's ruling: "keep square on retailer
	   pages, use the asset ratio on Rolex bands."

	   The 14 Sep instruction ("make mobile images square") was raised on the
	   RETAILER pages and, on 15 Sep, extended section-wide. Squaring the
	   Rolex-supplied editorial bands turned out to cost more than framing.
	   Measured on /rolex/oyster-story/ at 430: the 1927 Mercedes Gleitze
	   newspaper advertisement is 780x1043 and lost 25% of its HEIGHT -- the
	   bottom of the ad, its printed price list and its red banner. Four other
	   bands lost 13%. On /rolex/accessories/ the landscape introduction shots
	   (1.78) lost 44% of their WIDTH.

	   Cropping a photograph costs framing. Cropping a period ADVERTISEMENT
	   costs the content it exists to carry, and Rolex supplied that scan for
	   what it says.

	   So these three render each asset's own ratio, the same standing rule
	   the hero already follows, using the aspect-ratio:auto / contain idiom
	   the --stacked and --bleed rule below already established.

	   THE RETAILER PAGES ARE UNAFFECTED and stay square: verified that
	   /rolex/history/, /team/, /showroom/ and /paul-medawar-fine-jewelry/
	   carry ZERO images under these three selectors -- every one of theirs is
	   inside .rlx-ed-retailer*, which keeps its own 1:1 rules above. */
	body.rolex-section .rlx-editorial__media img,
	body.rolex-section .rlx-image-block img,
	body.rolex-section .rlx-guarantee__media img {
		aspect-ratio: auto;
		object-fit: contain;
		height: auto;
		max-width: 100%;
	}
	/* TWO EXEMPTIONS, both found by measuring against the comps after the
	   rule above went in:

	   --stacked: a single delivered file holding two photographs one above
	   the other (~0.45). Squaring it centre-crops across the seam between
	   them; its own ratio is what the comp draws.

	   --bleed image blocks: the comp renders these at the asset's intrinsic
	   ratio at mobile (390x443 on day-date and deepsea, against our 390x390),
	   and the editorial full-bleed sibling already does -- so squaring only
	   the standalone ones made the two disagree with each other as well as
	   with the comp. Full-bleed bands were already excluded in principle;
	   this makes the standalone ones follow the same line. */
	body.rolex-section .rlx-editorial__media--stacked img,
	body.rolex-section .rlx-image-block--bleed img {
		aspect-ratio: auto;
		object-fit: contain;
	}
	body.rolex-section .rlx-ed-retailer__image--l img,
	body.rolex-section .rlx-ed-retailer__image--xl img,
	body.rolex-section .rlx-ed-retailer__image--portrait img {
		aspect-ratio: 1 / 1;
		object-fit: cover;
		max-width: 100%;
	}
	body.rolex-section .rlx-ed-retailer__image--xl {
		width: min(var(--rlx-container-max), 100% - var(--rlx-container-inset));
		max-width: none;
		margin-inline: auto;
		padding-inline: 0;
	}
}
/* NOTE (2026-08-23 layout parity, Task 4): the SAME defect Task 3 fixed on
   .rlx-editorial__copy, on this sibling. page-templates/rolex-retailer.php:312
   and :328 render `<section class="rlx-ed-retailer__block rlx-block
   rlx-container">` -- one element, all three classes -- and 2744a34 ("restyle:
   left-aligned editorial blocks per mockups") rewrote this rule from
   `max-width: 760px; margin-inline: auto; text-align: center` to
   `max-width: none; margin-inline: 0; text-align: left`. Only text-align was
   meant to change; max-width: none cancelled .rlx-container's own
   --rlx-container-max and ran the copy edge to edge. Measured on
   /rolex/history/, /rolex/showroom/ and /rolex/team/ at 1920x1200 it read
   0.013-0.988 of viewport against a 0.292-0.708 mockup census (delta 0.279,
   tolerance 0.02); at 390 it was already inside tolerance because the
   max-width never binds there.
   854px is the same content-box measure .rlx-editorial__copy uses and is
   derived the same way: 806px of censused ink plus .rlx-container's 24px
   padding either side. margin-inline is NOT restated -- .rlx-container's
   `auto` is what centres this, and re-declaring 0 here is what broke it. */
body.rolex-section .rlx-ed-retailer__block { max-width: 854px; text-align: left; padding-inline: 24px; }
/* MOBILE: the 24px above is part of the DESKTOP 854 measure and must not
   survive the breakpoint -- the block is a .rlx-container, so the well
   already supplies the whole gutter and its own inset put the copy at
   x51/288. Both retailer mobile mockups put their dominant ink edge at
   x27 (780px comps, ink L=54), like every other route in the section.
   Stated HERE rather than in the shared reset earlier in the file: media
   queries carry no specificity, and this rule ships later. */
@media (max-width: 767px) {
	body.rolex-section .rlx-ed-retailer__block { padding-inline: 0; }
}
body.rolex-section .rlx-ed-retailer__block h2 { margin: 0 0 12px; }

/* ---- Discover hero banner (templates/rolex/banner.php, Task 4) --------- */
/* P4 parity fix (2026-08-17): the mockup's banner crop is the Oyster
   Perpetual cover with essentially no visible scrim — this shipped with a
   left-to-right gradient at 0.35 alpha fading out only by 55%, far heavier
   than the mockup. Reduced to a subtle bottom-left legibility helper — the
   copy block (.rlx-banner__copy, unchanged) sits left-aligned against the
   container edge — at 0.18 alpha, fading out by 40% of the diagonal, just
   enough to keep the white kicker/tagline readable over a bright section
   of the photo, never a visible wash. */
body.rolex-section .rlx-banner__slide {
	position: relative;
	/* Own aspect ratio, RE-MEASURED 2026-09-10: 2880/1050 = 2.743.
	   This was 40/9 (4.444) on a note that the mockup banner "measures
	   ≈1920×430". It does not. Measured the same way the mobile ratio below
	   was — nav's bottom edge to the beige body — all THREE desktop Discover
	   mockups agree exactly:
	     discover-rolex-mockup-desktop.jpg                1920 x 700  2.743
	     discover-rolex-send-a-message-mockup-desktop.jpg 1920 x 700  2.743
	     discover-rolex-book-an-appointment-mockup-...jpg 1920 x 700  2.743
	   with a crisp boundary (photo pixels above, #F8F7F3 below). The
	   wireframe's placeholder box gives 670 (2.867); the rendered mockups
	   win, per the source precedence this build already follows for the
	   model-page hero. 2.743 is also exactly Rolex's XL band ratio
	   (2880x1050) used by the collection pages, which is why it is written
	   as that fraction rather than a decimal.
	   At 40/9 this hero rendered 432px tall against Rolex's 700 — 62% of
	   its height, and it cover-cropped a 3.429 asset that hard.
	   Still scoped to this class only; every other .rlx-cover consumer
	   (hub/selection/new-watches/retailer/contact covers, the 16/5
	   collection-archive override) is untouched. */
	--rlx-cover-ar: 2880 / 1050;

	/* MOBILE IS PORTRAIT HERE, AND ONLY HERE (2026-09-09). The shared
	   --rlx-cover-ar-mobile is 3/2, measured off a page-cover mobile comp
	   (782x510). The Discover hero SLIDER is a different shape: measured on
	   Rolex's own two Discover mobile comps, the hero band runs from the
	   nav's bottom edge to the beige body at
	     discover-rolex-template-mobile.jpg  784 x 1054  ratio 0.744
	     discover-rolex-mockup-mobile.jpg    780 x 1050  ratio 0.743
	   i.e. 3/4 (0.750) within 0.8% — TALLER than wide, where the shared
	   token is half again WIDER than tall. Inheriting 3/2 here squeezed a
	   portrait hero into a landscape box, which is what the reported
	   "slider should use the portrait version on mobile" is describing: the
	   <picture> element already serves img_mobile below 768px
	   (templates/rolex/banner.php), so the asset switch was working and the
	   BOX was wrong. Scoped to this class so every page cover keeps 3/2. */
	--rlx-cover-ar-mobile: 3 / 4;
}
/* COPY TONE (2026-09-10, user: "the text on this slider needs to be the dark
   color"). Rolex's slider spec says kicker and tagline are WHITE. That is
   correct on their Deepsea banner and illegible on their accessories one --
   a cufflink on white cloud, where white type measures 1.07:1 against a
   4.5:1 floor. So the ink follows the artwork, per slide, from a measurement
   rather than an opinion; RLX_Discover_Slider::SLIDES carries the numbers.
   --rlx-banner-ink is the one token both type rules read, so a tone can
   never colour the kicker and miss the tagline. */
body.rolex-section .rlx-banner__slide { --rlx-banner-ink: #fff; }
body.rolex-section .rlx-banner__slide[data-rlx-tone="dark"] { --rlx-banner-ink: var(--rlx-ink); }

/* THE LIGHT-TONE SCRIM IS LOAD-BEARING, not decoration, and it is what makes
   white type legal on THREE of Rolex's four banners. All three are mixed-tone
   photography on which BOTH inks fail somewhere unaided -- see
   RLX_Discover_Slider::SLIDES for the per-slide numbers -- so the scrim, not
   the ink, is doing the work.

   Percentage of the copy region where WHITE text falls under 4.5:1, by scrim
   alpha (measured, 60x60 samples per slide):

              a=0.35  a=0.45  a=0.55
     Deepsea     8.4%    0.4%    0.0%
     Oyster     30.9%    5.8%    0.0%
     Watchmk    64.0%    7.8%    0.0%

   Hence 0.55, and hence FLAT to 45% before it fades: the copy column spans
   x 4-44%, so a gradient that starts decaying at the left edge is already
   thin where the tagline ends. It previously ran `to top right` from the
   bottom-left corner -- away from the copy entirely -- which is why the
   defect survived to the client.

   Dark-tone slides get NO scrim: ink already clears the floor across the
   whole region there, and a dark wash under dark type would only erode it.

   SUPERSEDED 2026-09-28: no slide uses a scrim any more (Rolex review, twice:
   "There is a dark overlay on top of the banners"). Every slide clears 3:1 on
   its own artwork; see RLX_Discover_Slider::SLIDES. The fallback below is 0,
   and the rule stays only so a future slide can opt in with copy_scrim. */
body.rolex-section .rlx-banner__slide::before {
	content: "";
	position: absolute;
	inset: 0;
	background: linear-gradient(to right, rgba(0, 0, 0, var(--rlx-banner-scrim, 0)) 0%, rgba(0, 0, 0, var(--rlx-banner-scrim, 0)) 45%, transparent 70%);
	pointer-events: none;
}
body.rolex-section .rlx-banner__slide[data-rlx-tone="dark"]::before { background: none; }
body.rolex-section .rlx-banner__copy {
	position: absolute;
	top: 50%;
	left: calc((100% - min(var(--rlx-container-max), 100% - var(--rlx-container-inset))) / 2);
	transform: translateY(-50%);
	display: flex;
	flex-direction: column;
	/* Slider spec, Copy block: kicker Headline26 + tagline Headline70, both
	   WHITE. align-items keeps the CTA at its own intrinsic width instead of
	   stretching across the flex column. */
	align-items: flex-start;
	color: var(--rlx-banner-ink);
	max-width: calc(min(var(--rlx-container-max), 100% - var(--rlx-container-inset)));
}
/* RIGHT-HAND PLACEMENT, PER SLIDE (2026-09-20, client ruling; first shipped
   section-wide the same day and corrected to per-slide within the hour).

   Only the slide that asks for it moves. `data-rlx-copy-side` comes from
   RLX_Discover_Slider::SLIDES, defaults to "left" when absent, and today
   exactly one slide -- Rolex accessories -- carries "right", because it is
   the one of the four whose artwork puts its subject on the left. Placement
   follows the artwork, which is the same rule that class already applies to
   copy_tone.

   The geometry below is measured, not guessed.

   Rolex's own Discover mockup puts it on the right, and the placement is a
   clean grid position rather than a guess: measured with a pixel ruler on
   discover-rolex-mockup-desktop.jpg, the kicker, the Headline70 tagline and
   the Discover CTA all share a left edge at x1100. The 1620 container starts
   at x154, and column 8 of 12 starts at 154 + 7 x (127.08 + 8) = 1099.6.
   So the block begins at COLUMN 8 and runs to the container's right edge --
   the last five columns.

   Written from the same tokens the container uses, so it tracks the 8%/7%
   margins at every width instead of hardcoding 1100. Desktop only: the
   mobile comps run the copy across the narrow well and the existing
   bottom-anchored rule below owns that case. */
/* THE COPY BLOCK IS FIVE OF TWELVE COLUMNS ON EITHER SIDE (2026-09-22). The
   5-column cap was written for the right-hand placement alone; the left-hand
   one -- three of the four slides -- was capped at the WHOLE well, i.e. it
   was not really capped at all. The spec sheet's Large CSS grid (p19) draws
   the left-positioned block over columns 1-5 exactly as the right-positioned
   one covers 8-12, and its Medium grid does the same 5-of-12, so this is one
   value for both sides at both breakpoints and only the `left` differs.

   It changes nothing at Large today (the longest tagline renders 552px
   against a 670px cap) and it wraps "The Oyster story" and "Rolex Deepsea"
   at Medium, where they were running past the column the spec gives them. */
@media (min-width: 768px) {
	body.rolex-section .rlx-banner__copy {
		--rlx-banner-well: min(var(--rlx-container-max), 100% - var(--rlx-container-inset));
		--rlx-banner-col: calc((var(--rlx-banner-well) - (11 * var(--rlx-card-gap))) / 12);
		max-width: calc(5 * var(--rlx-banner-col) + 4 * var(--rlx-card-gap));
	}
	body.rolex-section .rlx-banner__slide[data-rlx-copy-side="right"] .rlx-banner__copy {
		left: calc((100% - var(--rlx-banner-well)) / 2 + 7 * (var(--rlx-banner-col) + var(--rlx-card-gap)));
	}
}
/* MOBILE PUTS THE COPY LOW ON THE ARTWORK (2026-09-09, reported: "the
   mobile slider needs to have the text over the image moved down").
   Desktop stays vertically centred (top:50% above). Measured on
   discover-rolex-with-grid-mockup-moblie.jpg, whose hero band is 780x1050
   (0.7429, the 3/4 box this component already sets):
     kicker "Rolex"      y 658- 687 within the slide -> 62.7%
     tagline             y 719- 770                  -> 68.5%-73.3%
     "Discover" CTA      y 827- 908                  -> 78.8%-86.5%
     dash progress track y 984- 989                  -> 93.7%
   So the copy block ends 13.5% of the slide height above its bottom edge,
   where centring put its TOP at 36.3%. Anchoring to the bottom rather than
   setting top:62.7% keeps the block's own height (kicker + tagline + CTA,
   which reflow at the smaller type ramp) from pushing the CTA off the
   artwork, and leaves the dash track its own room below. */
@media (max-width: 767px) {
	body.rolex-section .rlx-banner__copy {
		top: auto;
		/* 74px, NOT the 13.5% this shipped with (2026-09-22). The spec sheet's
		   Small diagram (p22) states the stack from the bottom edge up:
		   20px to the dash ink, the 4px ink, then 50px to the bottom of the
		   CTA -- so the copy block's own bottom edge is a FIXED 20+4+50=74px.
		   13.5% resolved to 70.2px on a 390 viewport (a 520px-tall 3/4 box),
		   which is why the percentage read correct when it was measured off
		   the mobile comp and drifted everywhere else: it is 57.6px on a 320
		   device and 80px on a 430 one. The comp and the spec agree here to
		   within 4px, so this is a precision fix, not a placement change. */
		bottom: 74px;
		transform: none;
	}
}
body.rolex-section .rlx-banner__kicker { color: var(--rlx-banner-ink); margin: 0 0 8px; }
/* Slider spec: 20px between the tagline and the CTA (was 24px on the
   pre-slider static banner). Expressed as the tagline's own margin-bottom
   rather than a `gap` on .rlx-banner__copy so the kicker->tagline step
   (8px, above) stays independent of it. */
body.rolex-section .rlx-banner__tagline { color: var(--rlx-banner-ink); margin: 0 0 20px; }

/* Inherited section padding reset (fix round 1, 2026-08-21) — REQUIRED for
   the controls below to land on the artwork.

   The parent theme ships a global `section, footer { padding: 72px 0 }`
   (roneous-theme-styles.css). This file already resets that at the top --
   `body.rolex-section .rlx-main section:not(.rlx-availability)` (see the long
   comment there) -- but the banner renders OUTSIDE `.rlx-main` (the nearest
   preceding structure in the rendered Discover page is `.rlx-crumbs`;
   `.rlx-main` is not an ancestor at all), so that reset never matched it and
   the 72px survived.

   Consequence, measured before this rule at 1280px wide: the section box was
   432px tall against a 288px 40/9 crop, and `.rlx-banner__controls` --
   absolutely positioned, and therefore resolved against the PADDING box --
   sat 4px BELOW the bottom edge of the photograph, on the page background.
   At 390px (40px padding, `bottom: 16px`) they straddled the edge.

   Fixed here rather than by re-anchoring the controls into the slide grid
   cell: with the inherited padding gone, the artwork's own box defines the
   section box, so Task 2's `bottom: 24px` / `bottom: 16px` means exactly what
   it says at every width, and the controls' positioning model is left alone.
   Same specificity idiom as the .rlx-main reset above (2 types + 2 classes),
   so it beats the parent theme's single-type selector regardless of load
   order, and it is scoped to this ONE section -- no other band's rhythm
   changes. The banner is a full-bleed hero: flush under the crumbs band is
   the mockup's own look, not a side effect. */
body.rolex-section section.rlx-banner { padding-block: 0; }

/* ---- Slider: stacking + the current-slide transition -------------------
   Only one slide is ever visible. Every slide is placed in the SAME single
   grid cell (grid-template-areas: "rlx-slide" + grid-area on the slides),
   so the section's height is driven by the slides themselves rather than by
   absolute positioning, and the current one is revealed by the
   [data-rlx-slider-current] attribute Task 3's JS moves. banner.php stamps
   that attribute on the first slide server-side, so the pre-hydration and
   no-JS states already show slide 1 rather than an empty band.

   `visibility` (not just opacity) so the off-screen slides' CTA links leave
   the tab order and stop taking pointer events; it is delayed out and
   instant in so the fade is actually visible in both directions.

   The whole stacking group is gated on [data-rlx-slider], which banner.php
   emits ONLY when more than one slide renders. In the one-slide state there
   is therefore no stacking, no transition and no controls at all — that
   state is a plain static banner, exactly what it was before this task. */
body.rolex-section .rlx-banner[data-rlx-slider] {
	position: relative;
	display: grid;
	grid-template-areas: "rlx-slide";
	isolation: isolate;
}
body.rolex-section .rlx-banner[data-rlx-slider] > .rlx-banner__slide {
	grid-area: rlx-slide;
	opacity: 0;
	visibility: hidden;
	transition: opacity 600ms ease-in-out, visibility 0s linear 600ms;
}
body.rolex-section .rlx-banner[data-rlx-slider] > .rlx-banner__slide[data-rlx-slider-current] {
	opacity: 1;
	visibility: visible;
	transition: opacity 600ms ease-in-out, visibility 0s linear 0s;
}

/* ---- Slider: dash progress track + round nav --------------------------
   Bottom-left of the same container well .rlx-banner__copy is aligned to,
   so the dashes line up under the copy rather than under the raw viewport
   edge. position:absolute keeps the controls out of the slide grid cell (an
   in-flow child with no grid-area would open a second implicit row and make
   the section taller than the artwork). */
body.rolex-section .rlx-banner__controls {
	position: absolute;
	z-index: 2;
	/* This bar now holds ONLY the dash track, and that track centres itself
	   absolutely, so the flex properties below do nothing to it. They stay
	   because the bar is still the element that positions and sizes the
	   track's row -- the arrows moved out to .rlx-banner on 2026-09-22 (see
	   .rlx-banner__arrow), which is why the `justify-content: flex-end` that
	   briefly lived here is gone again. */
	/* DASH OFFSET IS THE SPEC SHEET'S, 40/30/20px (2026-09-22, client: "see
	   Design Specs for the Slider Component and ensure we are following the
	   Specs"). Rolex annotates the gap from the dash INK to the component's
	   bottom edge on all three Specifications diagrams --
	   `Bespoke section-Design-Specs.pdf` p20 (Large, 40px), p21 (Medium,
	   30px), p22 (Small, 20px). This shipped at 24/16 from the original
	   Task 2 build, i.e. ~18px high at every width.

	   WHY 42 AND NOT 40. This bar has no in-flow child: .rlx-banner__dashes
	   below is position: absolute, so the flex box is ZERO-TALL and the
	   track's translate(-50%, -50%) centres the 4px ink on this very line.
	   `bottom` therefore addresses the ink's CENTRE, and +2 puts its bottom
	   EDGE on the spec's number. Measured in the rendered page, not assumed.

	   DISCLOSED COMP-VS-SPEC DELTA. Rolex's own rendered comps put it lower
	   than their spec sheet does: discover-rolex-mockup-desktop.jpg draws the
	   ink at y757-759 of a 1920x700 hero whose last row is 809, i.e. 50px up,
	   and the mobile comp lands 30.5 CSS px up against the spec's 20. This
	   build follows the SPEC here on today's explicit instruction, which is
	   the reverse of rolex-comp-source-precedence's default. Logged in
	   docs/superpowers/qa/2026-09-17-brand-centre-discrepancy-sweep.md. */
	bottom: 42px;
	left: calc((100% - min(var(--rlx-container-max), 100% - var(--rlx-container-inset))) / 2);
	right: calc((100% - min(var(--rlx-container-max), 100% - var(--rlx-container-inset))) / 2);
	display: flex;
	align-items: center;
	gap: 8px;
}
/* Medium breakpoint (768-1024), the spec's own 30px. This file already uses
   this exact query twice, so the slider joins the existing Medium step
   rather than introducing a fourth breakpoint. */
@media (min-width: 768px) and (max-width: 1024px) {
	body.rolex-section .rlx-banner__controls { bottom: 32px; }
}
/* DASH GUTTER IS 26px, not the 8px card gap (measured 2026-09-21).
   Rolex's Discover comps draw it the same at both breakpoints, and the
   desktop one is 1:1 at 1920 so it reads directly:

     desktop  dashes 53 / 22 / 22 px, gaps 26 and 26
     mobile   dashes 54 / 23 / 23 CSS, gaps ~25 (measured at 2x, 51 device)

   Our dash WIDTHS were already right (50 current / 24 default against the
   spec's 50x4 and 24x4); only the gutter was wrong, and it was wrong at
   BOTH breakpoints because this is one shared rule. It had inherited the
   8px card gap, which is a grid gutter and has nothing to do with this
   track. One value, measured twice, so it is stated once here rather than
   overridden per breakpoint. */
body.rolex-section .rlx-banner__dashes {
	display: flex;
	align-items: center;
	gap: 26px;
	/* CENTRED ON THE PAGE, at every width (2026-09-22, client, for desktop;
	   mobile was already centred on 2026-09-21). Rolex's desktop comp puts
	   the track's midpoint at x960 of a 1920 frame -- dead centre -- and the
	   mobile comp at x390.5 of 780, likewise.

	   ABSOLUTE, not an auto margin. The controls bar is a flex row holding
	   the track AND the two round arrows, so `margin-inline: auto` centres
	   the track in the space the arrows leave over, i.e. off-centre by half
	   the nav's width. Only taking it out of flow centres it on the bar
	   itself. .rlx-banner__controls is already position: absolute, so it is
	   the containing block; translate(-50%, -50%) does the centring so no
	   width has to be known.

	   This replaces the old `margin-right: auto` (track left, nav right) and
	   the mobile-only `margin-inline: auto` that followed it -- one rule now
	   covers both breakpoints, and the arrows keep their own flex placement
	   at the bar's right edge. */
	position: absolute;
	top: 50%;
	left: 50%;
	transform: translate(-50%, -50%);
}
/* Spec: dash 24x4px, 50x4px when current, White — drawn on a ::before so
   the BUTTON can carry the 24px minimum tap target (WCAG 2.5.8 / the
   spec's own touch-target note) without the visible dash growing to it.
   DISCLOSED INTERPRETATION (whole-branch review 2026-08-21, minor 3): the
   spec says only "White" for both states. It ships as #fff at opacity 0.5
   for the non-current dash and opacity 1 for the current one — an
   interpretation, not a spec value, recorded here the same way this
   branch's other interpretations (the ramp steps, Quote50 col3) are. Two
   solid white dashes would give the current one no distinction beyond its
   width; 50% white is the conventional inactive treatment and matches the
   mockup. Both opacities are asserted by tests/wp-check-restyle.php so a
   future tidy-up cannot flip them silently. If Rolex rules otherwise, the
   change is these two declarations and those two assertions. */
body.rolex-section .rlx-banner__dash {
	appearance: none;
	-webkit-appearance: none;
	border: 0;
	background: none;
	padding: 0;
	margin: 0;
	cursor: pointer;
	min-width: 24px;
	min-height: 24px;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	flex: none;
}
/* ANIMATED DASHES, per the spec sheet's own diagram (2026-09-22, client:
   "follow the Design Spec for Animated dashes > Light").

   That diagram settles what this rule had carried since 2026-08-21 as a
   disclosed interpretation. The spec's PROSE says only "White" for both
   states, so the non-current dash shipped at opacity 0.5 to distinguish it.
   The DIAGRAM resolves it: measured off the Animated > Light "Default"
   swatch, the three dashes are 48, 22 and 23px wide and all three sample
   solid white (250,255,255 / 243,249,255 / 244,250,255). The state is
   carried by WIDTH ALONE -- 50 against 24 -- and that is exactly what
   separates the "Animated" variant from "Simple", where every dash is 50px
   and only the colour changes.

   So the opacity goes, and the transition with it is width only. The gap
   between dashes measures 26px in the same diagram, corroborating the 26
   already taken from the page comp. */
body.rolex-section .rlx-banner__dash::before {
	content: "";
	display: block;
	width: 24px;
	height: 4px;
	border-radius: var(--rlx-dash-radius);
	background: #fff;
	transition: width 300ms ease;
}
body.rolex-section .rlx-banner__dash[aria-current="true"]::before {
	width: 50px;
	height: 4px;
}
/* Spec: round nav 44x44px desktop, 40x40px mobile, 14x14px icon. The FILL
   is specified too, on the spec sheet's Round CTA page -- see the block
   below; the "translucent white fill with a white hairline" this comment
   used to describe was an invention and is gone as of 2026-09-22. The
   shipped #rlx-arrow glyph points RIGHT (see the back-to-top comment above)
   and paints with `fill="currentColor"`, so `color` carries the spec's icon
   colour and prev is that same glyph rotated 180deg, not a new symbol. */
/* THE ARROWS FLANK THE BANNER (2026-09-22, client: "both need to behave and
   be positioned like on .rlx-ed-carousel__nav ... centered vert on the
   banner and placed to the right and left over the banner, and shown only
   if there is a next or prev banner").

   They used to sit in the bottom control bar beside the dash track. They are
   now positioned against .rlx-banner, which is already position: relative,
   so top: 50% centres them on the ARTWORK rather than on that bar.

   Inline position was the container well's own edge until 2026-09-22 and is
   now the MIDPOINT OF THE MARGIN BAND outside it -- see the --prev/--next
   rules below, which carry the measurement. The Discover carousel's 62px
   outset does not transfer either: that row has page gutter to sit in, and a
   full-bleed banner has none, which is why the band is measured rather than
   a fixed outset.

   `visibility` for the end states, not `display`, for the same reason as the
   carousel arrows: a keyboard visitor paging to the last slide with focus on
   Next must not have focus dropped to <body>. rolex-bespoke.js sets the
   `disabled` attribute and never touches inline styles. */
/* THE CHIP IS THE SPEC'S ROUND CTA, NOT AN INVENTION (2026-09-22). This
   shipped as a translucent white fill behind a white hairline, which was an
   implementer's guess at "white, over artwork". The spec sheet states it on
   p9, `Call to action > Round CTA`, and it is a FILLED CIRCLE WITH NO
   BORDER in two variants, both drawn from the p2 palette:

     Grey        #767676 ("Dark grey")  @ 30%, icon White   hover #545454 @ 30%
     Light grey  #D4D4D4 ("Grey")       @ 30%, icon Black   hover #F3F3F3 @ 50%
     44x44px desktop / 40x40px mobile, icon 14x14px in both

   The two variants exist so the implementer can pick by BACKGROUND, which is
   exactly the split `data-rlx-tone` already carries: a light-tone slide is
   one with dark artwork (white copy ink) and takes Grey; a dark-tone slide is
   pale artwork (dark copy ink) and takes Light grey. Measured over each
   slide's own artwork at the arrow positions, that mapping clears the 3:1
   non-text floor (WCAG 1.4.11) on seven of the eight zones by 9.1:1 or
   better. THE EIGHTH IS RECORDED, NOT SILENTLY PATCHED -- see the contrast
   note under the dark-tone rule below. */
body.rolex-section .rlx-banner__arrow {
	position: absolute;
	top: 50%;
	transform: translateY(-50%);
	z-index: 2;
	width: 44px;
	height: 44px;
	border-radius: 50%;
	border: 0;
	background: rgba(118, 118, 118, 0.3);
	color: #fff;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	padding: 0;
	cursor: pointer;
	flex: none;
	transition: background-color 150ms ease;
}
/* CENTRED IN THE OUTER MARGIN BAND, not flush to the container line
   (2026-09-22). The spec sheet's p20/p21 Specifications diagrams annotate
   the button "Round button / Centered" with a measure arrow on EACH side of
   it, running from the grid's outer column line to the frame edge -- so the
   button is centred in the 8% margin, OUTSIDE the content well, and it stays
   there in both the left- and right-copy variants.

   Rolex's rendered comp agrees to the pixel, which is rare enough to record:
   on discover-rolex-mockup-desktop.jpg the circle measures x1822-1865 by
   y438-481 -- 44x44 exactly, centre (1843.5, 459.5) against a hero centre of
   459.5 and a predicted 1920 - 150/2 = 1845.

   This previously used the well's own edge, which puts the button's outer
   edge ON that line and its body INSIDE the text column: 95px too far in at
   1920. `- 22px` is half the button's own 44px width, so `right` addresses
   the CENTRE; the width is fixed at every breakpoint that shows these, so
   the arithmetic is exact rather than a transform trick that would have to
   fight the translateY above. */
body.rolex-section .rlx-banner__arrow--prev {
	left: calc((100% - min(var(--rlx-container-max), 100% - var(--rlx-container-inset))) / 4 - 22px);
}
body.rolex-section .rlx-banner__arrow--next {
	right: calc((100% - min(var(--rlx-container-max), 100% - var(--rlx-container-inset))) / 4 - 22px);
}
body.rolex-section .rlx-banner__arrow[disabled] {
	visibility: hidden;
	cursor: default;
}
body.rolex-section .rlx-banner__arrow .rlx-icon { width: 14px; height: 14px; }

/* The dashes and arrows sit OUTSIDE the slides, in .rlx-banner__controls, so
   they cannot inherit --rlx-banner-ink -- and white controls on the white
   accessories banner are invisible, which makes the slider look like it has
   no controls at all. banner.php seeds [data-rlx-tone] on the section
   for slide 1 and rolex-bespoke.js moves it with the current slide, so these
   swap as the visitor advances. rgba(33,33,33,.5) blends to ~#909090 for
   3.2:1 against a white plate, clearing the 3:1 non-text floor (WCAG 1.4.11);
   the CURRENT dash is solid ink, which is what actually carries the state. */
body.rolex-section .rlx-banner[data-rlx-tone="dark"] .rlx-banner__arrow {
	background: rgba(212, 212, 212, 0.3);
	color: var(--rlx-ink);
}
/* MEASURED, and one zone does not clear the floor. Sampled over each
   desktop asset cover-cropped into the rendered 1920x700 box, in the two
   44px circles this file now places at x75 and x1845, with each light-tone
   slide's own scrim applied -- icon against the composited chip:

     Deepsea      (light -> Grey)        prev 14.9:1   next 13.3:1
     Oyster story (light -> Grey)        prev 13.8:1   next  2.29:1  <-- FAILS
     Accessories  (dark  -> Light grey)  prev 11.9:1   next 10.4:1
     Watchmaking  (dark  -> Light grey)  prev 12.5:1   next  9.1:1

   The Oyster Story artwork is split: its left third is a dark blue where
   white reads at 12:1, and its right edge is a pale sky (179,197,211) where
   the Grey chip composites to (161,173,183) and a white icon reaches only
   2.29:1 against a 3:1 floor. NO SPEC VARIANT CLEARS BOTH EDGES of that one
   image -- flipping it to Light grey fixes the right (9.6:1) and breaks the
   left (1.78:1, because that edge carries the slide's own 0.75 scrim). Rolex is not clear of this either: the chip drawn on their
   own discover-rolex-mockup-desktop.jpg samples (172,172,172) behind a pure
   white glyph, which is 2.27:1.

   NOT PATCHED HERE ON PURPOSE. The fix is a per-slide value and the two
   candidates (a heavier fill for that slide, or a different Oyster crop)
   are a client decision, not an implementer's; inventing a per-side nav
   field would also put a datum in RLX_Discover_Slider that Rolex's own model
   has no room for. Raised 2026-09-22. The PREVIOUS treatment was worse on
   the same zone (rgba(255,255,255,.15) measured ~1.5:1), so this is an
   improvement everywhere and a regression nowhere. */

/* Hover, per the same p9 table. Gated on a real pointer so a tap does not
   leave a phone stuck in the hover fill, and it transitions background-color
   only -- nothing about these buttons transforms, which is what the spec's
   own Accessibility examples (p131) require of every hover in the section. */
@media (hover: hover) and (pointer: fine) {
	body.rolex-section .rlx-banner__arrow:hover {
		background: rgba(84, 84, 84, 0.3);
	}
	body.rolex-section .rlx-banner[data-rlx-tone="dark"] .rlx-banner__arrow:hover {
		background: rgba(243, 243, 243, 0.5);
	}
}
/* Dark tone: the same diagram's Dark row gives "Dashes: Brown", again one
   solid colour for every dash with only the width changing. */
body.rolex-section .rlx-banner[data-rlx-dash-tone="dark"] .rlx-banner__dash::before {
	background: var(--rlx-brown);
}
/* ...keyed on data-rlx-dash-tone, not data-rlx-tone, since 2026-09-28: it
   defaults to the copy tone, and Oyster Story overrides it because its
   dashes sit on the dark sea while its copy and arrows sit on the pale sky. */
/* MOBILE TONE (2026-09-28). At mobile the copy block is bottom-anchored, so
   on artwork that is pale above and dark below it lands on a different half
   of the picture than it does at desktop. banner.php stamps a resolved
   data-rlx-tone-mobile on every slide and on the section (the JS mirrors it),
   defaulting to the desktop tone, so these rules are a no-op for every slide
   that does not ask for a different mobile ink. Same specificity as the
   desktop tone rules above, and later, so they win below 768px only. */
@media (max-width: 767px) {
	body.rolex-section .rlx-banner__slide[data-rlx-tone-mobile="light"] { --rlx-banner-ink: #fff; }
	body.rolex-section .rlx-banner__slide[data-rlx-tone-mobile="dark"] { --rlx-banner-ink: var(--rlx-ink); }
	body.rolex-section .rlx-banner[data-rlx-tone-mobile="light"] .rlx-banner__dash::before { background: #fff; }
	body.rolex-section .rlx-banner[data-rlx-tone-mobile="dark"] .rlx-banner__dash::before { background: var(--rlx-brown); }
}
body.rolex-section .rlx-banner__arrow--prev .rlx-icon { transform: rotate(180deg); }
/* Dark-bg focus ring (#9BF9CE, the same one the green nav band and
   back-to-top use) — these controls sit on photography, never on this
   file's light/beige surfaces, so the light-bg var(--rlx-green) ring in the
   group above would be the wrong surface for them. */
body.rolex-section .rlx-banner__dash:focus-visible,
body.rolex-section .rlx-banner__arrow:focus-visible {
	outline: 2px solid var(--rlx-green-ocean);
	outline-offset: 3px;
}
@media (max-width: 767px) {
	body.rolex-section .rlx-banner__controls { bottom: 22px; }
	/* NO ARROWS ON THE HERO AT MOBILE (2026-09-21), the same instruction as
	   the four carousel navs above and the same evidence: Rolex's mobile comp
	   (discover-rolex-with-grid-mockup-moblie.jpg, hero at device y1140) draws
	   the dash track alone, bottom-left over the artwork, and no round
	   buttons anywhere on it.

	   SCOPED TO .rlx-banner__arrow, NOT to .rlx-banner__controls, although the
	   instruction named the latter: that element wraps the dashes TOO, and the
	   comp keeps the dashes. Hiding the wrapper would take away the only
	   indication on a phone that the hero has four slides at all. The
	   `bottom: 16px` above still applies, so the dash track keeps its mobile
	   offset. Raised with the client. */
	/* No arrows on the hero at mobile; the comp draws the dash track alone.
	   The track's own centring lives in the base rule and needs nothing here. */
	body.rolex-section .rlx-banner__arrow { display: none; }
}

/* Reduced motion: every slider transition — the slide cross-fade AND the
   dash width/opacity morph — collapses to instantaneous. The visibility
   delay goes too, otherwise a "no motion" user still waits 600ms for the
   outgoing slide to stop taking pointer events. */
@media (prefers-reduced-motion: reduce) {
	body.rolex-section .rlx-banner[data-rlx-slider] > .rlx-banner__slide,
	body.rolex-section .rlx-banner[data-rlx-slider] > .rlx-banner__slide[data-rlx-slider-current],
	body.rolex-section .rlx-banner__dash::before {
		transition: none;
	}
}

/* ===================================================================
   ARTICLE PAGES — /rolex/watchmaking/ and /rolex/oyster-story/
   (page-templates/rolex-article.php, data in inc/rolex/class-rlx-article.php)

   Measured off each page's own comp at full resolution, not eyeballed:
   rolex-watchmaking-mockup-desktop.jpg (1920x11603) and
   oyster-story-article-desktop.jpg (1920x12089), band-scanned by row
   flatness then x-extent'd per band. The measured table lives in
   docs/superpowers/plans/2026-09-10-five-legacy-pages.md.

   SOURCE ORDER IS LOAD-BEARING. This block sits at the END of the file on
   purpose. Several rules here have the same specificity as the generic
   .rlx-container / .rlx-editorial__copy / .rlx-block rules they must beat
   (e.g. (0,2,1) vs (0,2,1)), and earlier in this same drop a new media
   query lost exactly that way — same specificity, declared before the rule
   it needed to override. Do not relocate these upward.
   =================================================================== */

/* Page ground. The two articles do NOT share a background: watchmaking's
   comp annotates #F9F7F4 (--rlx-bg), oyster-story's #FFFFFF
   (--rlx-surface). Measured per page rather than assumed alike. */
body.rolex-section .rlx-article--ground-bg { background: var(--rlx-bg); }
/* NO TINTED STRIP UNDER A CLOSING FULL-BLEED IMAGE (2026-09-20, client
   report on /rolex/watchmaking/: "the colour bg is extending after the last
   image").

   `.rlx-main` carries 90px of bottom padding for the section's vertical
   rhythm. On a page whose LAST block is a full-bleed image that padding has
   nothing to sit under, so it paints a 90px band of --rlx-bg between the
   image and the white Keep exploring block. Measured on watchmaking: image
   ends 6612, main ends 6702, Keep exploring starts 6702.

   Every comp ends the same way and none of them shows that band -- white
   begins at the image's bottom edge. Sampled down the left gutter of four
   mockups, the last ~600px before the green footer is pure #FFFFFF in all
   four (watchmaking y10800, datejust y10557, rolex-watches y5370, discover
   y4275), which is the Keep exploring band.

   The rhythm is NOT lost: `.rlx-keep` already carries its own 90px
   padding-block, so the heading still lands 90px below the image -- the 90px
   is simply white now, as drawn, instead of tinted.

   Keyed on the CONDITION (a bleed image closing the page) rather than on a
   page, so a page that gains or loses one is handled without a new rule.
   `--ground-surface` needs no equivalent: its ground is already white, so
   the same padding is invisible there. */
body.rolex-section .rlx-article--ground-bg:has( > :last-child .rlx-image-block--bleed:last-child ) {
	padding-bottom: 0;
}
/* SAME RULE, THE RETAILER PAGES' OWN SHAPE (2026-09-21, client, on
   /rolex/team/: "ensure that there is no background color extending under
   the last image on the page").

   team/showroom/history close on .rlx-ed-retailer__image--xl, a full-bleed
   band, and it is the LAST CHILD of .rlx-main -- not of .rlx-article, so the
   rule above never matched it. Measured on /rolex/team/ at 1440: the image
   ended at y712 and .rlx-main at y892, i.e. 180px of #F9F7F4 below a
   full-bleed photograph, from the image's own 90px margin-bottom plus
   .rlx-main's 90px padding-bottom. Both have to go, which is why this is two
   declarations and not one -- zeroing the padding alone leaves 90.

   :has() keyed on :last-child, so a page whose XL band is followed by more
   content keeps both gaps. The next section (Keep exploring) is white and
   brings its own 90px of padding-top, so the image still has air under it --
   it is just white air rather than a tinted strip. */
/* FROM 768 UP ONLY. Below it the XL band is NOT full-bleed: the
   @media (max-width: 767px) block above gives it the container width and
   squares it to 1/1, so it is an ordinary contained image with margins
   either side. Zeroing the gap under a CONTAINED image does not remove a
   tinted strip -- it jams the photograph against the white Keep exploring
   band, which is what this rule did on /rolex/team/ at 390 before the
   breakpoint was added. The strip this fixes only exists where the image
   actually runs edge to edge. */
@media (min-width: 768px) {
	body.rolex-section .rlx-main:has( > .rlx-ed-retailer__image--xl:last-child ) {
		padding-bottom: 0;
	}
	body.rolex-section .rlx-main > .rlx-ed-retailer__image--xl:last-child {
		margin-bottom: 0;
	}
}
body.rolex-section .rlx-article--ground-surface { background: var(--rlx-surface); }

/* The 12-column container, 1620px of CONTENT rather than 1620px of box.
   .rlx-container puts its 24px padding INSIDE max-width, which leaves 1572
   — but both comps measure the container's own ink at x150 and x1769, i.e.
   the full 1620 (and the video at x152-1775 = 1624, the same 1624 every
   model-page block measures). Same width:min() pattern the model-page
   blocks already use, for the same reason. */
body.rolex-section .rlx-article .rlx-container:not(.rlx-image-block) {
	width: min(var(--rlx-container-max), 100% - var(--rlx-container-inset));
	max-width: none;
	margin-inline: auto;
	padding-inline: 0;
}
/* .rlx-image-block is EXCLUDED above because it is itself a .rlx-container
   and already sets its own width per span — including --bleed's
   `width: 100vw; margin-inline: calc(50% - 50vw)` escape. Measured: without
   the :not(), servicing's closing bleed rendered 1620px wide at x150
   instead of 1920 at x0, because this rule is both more specific (0,3,1 vs
   0,2,1) and declared later. */

/* Intro: H1 left, lead + body right. Both comps put the H1's ink at the
   container's left edge (x150) and the body's at x966 — column 7 of 12
   starts at 150 + 6x135 = 960, so the heading column is 6/12.

   The BODY column is 5/12 (675px, x960-1635), not the remaining 6/12. That
   is measured, not assumed: the widest body line reaches x1617 on
   watchmaking and x1598 on oyster-story, i.e. 18px and 37px short of a
   675px column's right edge — the ordinary ragged-right of 5-6 justified-
   left lines. Against an 810px column they would be 153px and 171px short,
   which no 6-line paragraph does. The 12th column is deliberately empty.

   Hence this overrides .rlx-coll-intro's own 2fr/3fr + 64px gap rather than
   reusing it: 2fr/3fr with a 64px gap would start the body at x836. */

body.rolex-section .rlx-article__intro-body { margin: 0; }
body.rolex-section .rlx-article__intro-body > p { margin: 0; }
/* Deck-bold lead paragraph — bold in BOTH decks' first intro run and bold in
   both rendered mockups. A lead paragraph, so it carries its own class
   rather than a <strong> inside the body text. */
body.rolex-section .rlx-article__lead { font-weight: 700; }
/* The comp puts ONE BLANK LINE between paragraphs, not 45px. Measured
   ink-top to ink-top within a paragraph against baseline-to-baseline across
   the break, in 14 blocks spanning the article, collection, model,
   accessories and servicing comps at both breakpoints: the ratio is exactly
   2.00 in every one. The lead is the one place we set a paragraph margin and
   it was set to --rlx-gap-half (45px desktop), giving 75px baseline-to-
   baseline where the comp measures 60. */
body.rolex-section .rlx-article__lead + p { margin-top: 1lh; }

/* Video width genuinely differs between the two pages and both were
   measured: watchmaking's player spans the container (x152-1775 = 1624),
   oyster-story's spans 10 columns (x283-1636 = 1354 ~ 1350 at offset 135).
   The facade itself is .rlx-facade-section.rlx-block, so these wrappers only
   constrain width — the block rhythm stays where it already lives. */
/* A GAP UNDER THE VIDEO. The wrapper had none and the block below it starts
   at margin-top 0 (article sections manage their own spacing), so the player
   sat flush against the next block -- 90px above it, 0 below. The margin
   goes on this DIV, not on the <section> inside: the parent theme ships
   `section, footer { margin-bottom: 0 !important }`, which no amount of
   specificity on a <section> can beat. */
/* AMENDED 2026-09-23. The premise above is half right. The next block does
   start at margin-top 0, but `.rlx-article__section` pays `padding-block:
   var(--rlx-gap)`, so a gap of exactly one --rlx-gap ALREADY existed between
   the player and the next section's ink. Charging it here as well made every
   such junction 180px against the template's 90.

   rolex-servicing-procedure-page-template-desktop.jpg annotates it directly:
   the video band ends, "10vh / 90px", then Headline50. One gap, not two.
   Measured on /rolex/servicing-procedure/ before this: video bottom to first
   ink 180px.

   Why it looked right when it was written: on /rolex/oyster-story/ and
   /rolex/watchmaking/ the next section carries --panel, so it is TINTED. There
   the 90px is real and visible -- it holds the player off the tint's edge --
   and the section's own padding then sits inside the tint where it belongs.
   Only on /rolex/servicing-procedure/, where the next section is untinted,
   does the extra 90 land in open ground and simply double the gap.

   So the gap belongs to the tinted panel, which is the optional element, not
   to the video, which is always there. Keyed positively on --panel rather
   than negatively: `:not()` would carry that class's specificity (see the
   --copy pair rule further down, which was bitten by exactly that). */
body.rolex-section .rlx-article__video { margin-bottom: 0; }
body.rolex-section .rlx-article__video + .rlx-article__section--panel { margin-top: var(--rlx-gap); }

body.rolex-section .rlx-article__video--container .rlx-facade {
	width: min(var(--rlx-container-max), 100% - var(--rlx-container-inset));
	margin-inline: auto;
}
body.rolex-section .rlx-article__video--span10 .rlx-facade {
	width: min(calc(var(--rlx-container-max) * 0.833333), 100% - var(--rlx-container-inset));
	margin-inline: auto;
}

/* Copy column: 6 of 12 columns, CENTRED (col 4, x556-1365). Measured at
   805/807/802/805/797/808 on watchmaking and 807/801/800/800/804 on
   oyster-story — 810px to within text bearing, on every section of both
   pages. The shared .rlx-editorial__copy rule is max-width:854px aligned to
   the container's LEFT edge, which is correct for the collection and model
   pages and wrong here, so this narrows and centres it for articles only. */
/* `.rlx-editorial__copy` also carries `.rlx-container`, so this must
   out-specify the article container rule above. It gained a `:not()` when
   the bleed image-block had to be excluded, taking it to (0,4,1) — and this
   rule, at (0,3,1), silently lost: the copy column snapped back to the full
   1620 and every section's text reflowed. Written with `.rlx-container` in
   the selector so the two are tied by construction and source order decides,
   which is the same footing the rest of this block already relies on. */
body.rolex-section .rlx-article .rlx-editorial__copy.rlx-container {
	width: min(calc(var(--rlx-container-max) / 2), 100% - var(--rlx-container-inset));
	max-width: none;
	margin-inline: auto;
	padding-inline: 0;
}



/* Band backgrounds and the vertical rhythm.

   Each section owns its own padding-block: var(--rlx-gap), and the inner
   .rlx-editorial's .rlx-block margins are zeroed so the two cannot add up
   to 180. That reproduces the comps' two DIFFERENT measured gaps from one
   number:

     image -> next heading, SAME band   90 + leading   (measured 116)
     image -> band colour change        90 | 90        (measured 101 + 111)

   which is why consecutive sections on the SAME background drop one of the
   two paddings. Without that, watchmaking's Innovation-in-motion section
   (its 5th, sharing one #F9F7F4 band with the 4th) would sit 180px down
   instead of 90 — the two are one continuous band in the comp, with no
   colour boundary between them. */
body.rolex-section .rlx-article__section {
	padding-block: var(--rlx-gap);
}
body.rolex-section .rlx-article__section--panel {
	background: var(--rlx-panel);
}
body.rolex-section .rlx-article__section > .rlx-editorial.rlx-block {
	margin-block: 0;
}
/* Keyed on --copy, NOT on .rlx-article__section, so the zero-padding lead
   and closing image bands are not swept in. They were: `:not()` carries its
   argument's specificity, so the old pair of selectors scored (0,6,1) and
   silently beat the (0,3,1) rule that puts a gap between two consecutive
   closing bands — servicing's two closers rendered flush against each other.
   Matching on a positive class instead of two negations is both clearer and
   two points less specific. */
body.rolex-section .rlx-article__section--copy:not(.rlx-article__section--panel) + .rlx-article__section--copy:not(.rlx-article__section--panel),
body.rolex-section .rlx-article__section--copy.rlx-article__section--panel + .rlx-article__section--copy.rlx-article__section--panel {
	padding-top: 0;
}

/* The ASC plaque above a section's heading, and the pill CTA below its copy
   — both live only on /rolex/servicing/ today but are generic per-section
   fields, not slug-scoped.

   The plaque renders 200x100 from a 300x150 file, at the copy column's left
   edge (measured x556-755 in the comp, i.e. flush with the heading below
   it). The CTA is the same green pill the rest of the section uses. Both
   take the article copy column, so they carry .rlx-container — and the
   selectors name BOTH .rlx-article and .rlx-container so they out-specify
   the article container rule, which gained a :not() and sits at (0,4,1).
   Without that these rendered at the full 1620 and the plaque drew at x150
   instead of x555. Third time this trap has bitten in this file; see the
   note on .rlx-editorial__copy.rlx-container. */
body.rolex-section .rlx-article .rlx-article__plaque.rlx-container {
	width: min(calc(var(--rlx-container-max) / 2), 100% - var(--rlx-container-inset));
	max-width: none;
	/* 37 under it, at BOTH breakpoints -- the comps agree on that one and
	   disagree on everything else about this element. Desktop: tint band ends
	   y3524, plaque y3656-3755, "Your Authorized Service Centre" line box
	   opens y3792. Mobile (a 2x render, halved): band ends y2868, plaque
	   y2931-3000, heading box y3037. 24 put the heading 13 too close on both. */
	margin: 0 auto 37px;
	padding-inline: 0;
}
/* ABOVE it, the two comps want different things: 132 at desktop against the
   section's own 90, but 63 at mobile, which the 60 gap already gives. So the
   extra 42 is desktop-only rather than a change to the shared margin -- at
   mobile it would put the plaque 42px past its own comp. */
@media (min-width: 768px) {
	body.rolex-section .rlx-article .rlx-article__plaque.rlx-container { margin-top: 42px; }
}
body.rolex-section .rlx-article .rlx-article__plaque img { display: block; width: 200px; height: auto; }
/* Mobile draws the plaque at 140x70 (the 280x140 delivery at 2x on the
   780-wide comp), against 200x100 on desktop. Added 2026-09-12 with the
   <picture> that finally serves the 280x140 file. */
@media (max-width: 767px) {
	body.rolex-section .rlx-article .rlx-article__plaque img { width: 140px; }
}
/* The CTA now lives INSIDE the editorial copy column (2026-09-12), between
   the copy and the image, so it needs no container width of its own -- it
   inherits the copy's. Only the gap above it is stated: the servicing comp
   runs copy ink to y5186 and starts the pill at y5223.

   The button's own SIZE rules were removed with that move. They restated the
   pill at min-height 40 / padding 0 28px / radius 20px, with no recorded
   reason, and being more specific they silently beat the base
   .rlx-cta-primary -- which carries the measured spec value and a comment
   citing it: "35px | Label | 35px, height 44, radius 22", corroborated by
   both comps that draw one ("View all" 118x44, "+ More results" 171x44).
   So the article pill rendered 167x40 where every source says 44 tall with
   35px sides. Colour, weight and font-size were duplicates of the base rule
   too. */
body.rolex-section .rlx-article .rlx-article__cta {
	margin: 28px 0 0;
}

/* Copy-less image bands — the LEAD one (servicing opens with a span12 image
   directly under its intro) and the CLOSING ones (watchmaking has one,
   servicing two, oyster-story none).

   Both drop the section's own padding, because these bands sit INSIDE a
   neighbouring band rather than forming one: on watchmaking the panel ends
   y10018 and the closing image starts y10019, with no ground-coloured strip
   between them, so the preceding section's padding-bottom is the whole gap.
   The same-background collapse rule above then zeroes the FOLLOWING
   section's padding-top, which is what puts servicing's first heading 90px
   under its lead image instead of 180. */
body.rolex-section .rlx-article__section--lead,
body.rolex-section .rlx-article__section--closing { padding-block: 0; }
/* Only the CLOSING bands zero their inner margins. The LEAD band must keep
   its image-block's own `margin-block` top: measured, the intro's bottom
   margin does not survive to separate them (it is zeroed further up as the
   last block before .rlx-main's padding), so the image's own 90px top margin
   is the only thing holding servicing's lead image off the intro. Zeroing it
   put them flush at y955. Its bottom margin is already 0 by the same rule,
   and the following --copy section's padding-top supplies that side. */
body.rolex-section .rlx-article__section--closing > .rlx-image-block.rlx-block { margin-block: 0; }
/* ...except between two CONSECUTIVE closing bands, which have no section
   padding on either side left to supply a gap. servicing's comp measures
   99px between its span10 and bleed closers. */
body.rolex-section .rlx-article__section--closing + .rlx-article__section--closing {
	padding-top: var(--rlx-gap);
}

@media (max-width: 767px) {
	/* Both comps stack the intro to one column. The mobile watchmaking
	   mockup measures content at x54-725 of 780 (a 390 viewport at 2x),
	   i.e. a 27px gutter; we ship 24px section-wide and keep it here so
	   these two pages line up with every other Rolex page rather than with
	   the comp alone. Recorded as a deviation in the plan doc. */
	body.rolex-section .rlx-article__intro { grid-template-columns: 1fr; }
	/* Both players collapse to the container inset (the comp measures the
	   mobile video at x54-726 of 780 = 336 at a 390 viewport). `width: 100%`
	   was wrong and measured wrong: .rlx-article__video is a plain
	   full-width div, so 100% of it is the whole 390 viewport. */
body.rolex-section .rlx-article__video--container .rlx-facade,
	body.rolex-section .rlx-article__video--span10 .rlx-facade {
		width: calc(100% - var(--rlx-container-inset));
		margin-inline: auto;
	}
	body.rolex-section .rlx-article .rlx-editorial__copy.rlx-container {
		width: min(100%, 100% - var(--rlx-container-inset));
	}
}

/* ===================================================================
   SEND A MESSAGE — /rolex/contact/send-a-message/ (#28356) and its
   thank-you page (#29084).
   page-templates/rolex-contact-message.php, data in
   inc/rolex/class-rlx-contact-message.php.

   Measured off rolex-contact-module-message-step{1,2,3}-mockup-desktop.jpg
   at full resolution. Container 150-1770; the module's column is x552-1362,
   i.e. six of twelve, centred — the same column the article pages use.

   As with the article block, this sits at the END of the file on purpose:
   several rules here tie on specificity with the generic ones they must
   beat, and with the legacy bespoke-light.css rules the old build left
   behind. Do not relocate upward.
   =================================================================== */

body.rolex-section .rlx-cm { background: var(--rlx-bg); }

/* The whole module is one centred six-column column with centred text.
   Measured: kicker x855-1065, H1 x656-1265, body x700-1221 — every one
   centred on x960 — and the controls at x552-1362. */
body.rolex-section .rlx-cm__panel.rlx-container {
	width: min(calc(var(--rlx-container-max) / 2), 100% - var(--rlx-container-inset));
	max-width: none;
	margin-inline: auto;
	padding-inline: 0;
	text-align: center;
}

/* BODY24, bold, in the brown ink — not Fixed16, which is what it looks like
   next to a Headline50 and is what the first cut used. Measured: the comp's
   kicker draws 23px of ink and 210px wide, against 47px for the Headline50
   below it and 18px for the Body20 under that. At the 0.94em ink ratio those
   calibrate to 50 and 20 exactly, which puts the kicker at 24. Fixed16 drew
   it 148px wide. */
body.rolex-section .rlx-cm__kicker { margin: 0 0 10px; font-weight: 700; color: var(--rlx-brown); }
body.rolex-section .rlx-cm__title { margin: 0; color: var(--rlx-brown); }
/* Body copy is capped well inside the column: the comp's longest body line
   is 521px on step 1 and 515px on step 3, wrapping to two lines where 810
   would have fitted them on one. Same 560px measure the model page's
   contact intro already uses. */
body.rolex-section .rlx-cm__body,
body.rolex-section .rlx-cm__confirm {
	max-width: 560px;
	margin: 28px auto 0;
}
body.rolex-section .rlx-cm__confirm { font-weight: 700; }
body.rolex-section .rlx-cm__confirm + .rlx-cm__body { margin-top: 20px; }

/* "‹ Back" on step 2 — at the CONTAINER's left edge (x151-209), above the
   kicker, not inside the column. cf7mls renders its own back button at the
   bottom of the fieldset; this is a proxy that clicks it (see the
   template's note on why proxying beats moving the plugin's node), and it
   stays `hidden` until the JS has actually found the real one. */
body.rolex-section .rlx-cm__back {
	/* BLOCK-level flex, not inline-flex. As an inline box inside the panel's
	   `text-align: center` it was centred FIRST and shifted afterwards, and
	   because centring counts the negative margin as part of the box's
	   inline size the two compounded: the button landed at x730 instead of
	   x150. Block-level takes it out of the centring entirely, so the
	   negative margin alone positions it. */
	display: flex;
	width: fit-content;
	align-items: center;
	gap: 8px;
	/* The comp puts this at the CONTAINER's left edge (x151), while its
	   parent is the half-width column starting at x555. The offset is half
	   the difference between the two, computed rather than hardcoded so it
	   stays right at every width: 1920 -> (810-1620)/2 = -405px, landing on
	   x150; ~900 -> (810-852)/2 = -21px; 390 -> (342-342)/2 = 0. That last
	   case is why there is no mobile override. */
	margin: 0 0 var(--rlx-gap-half);
	margin-left: calc((min(calc(var(--rlx-container-max) / 2), 100vw - 48px) - min(var(--rlx-container-max), 100vw - 48px)) / 2);
	padding: 0;
	border: 0;
	background: none;
	font: inherit;
	font-size: var(--rlx-fixed16);
	color: var(--rlx-ink);
	cursor: pointer;
}
/* An author `display` beats the UA's `[hidden] { display: none }`, so the
   explicit `display: flex` above un-hid the button and it appeared on step
   1, where the comp has no Back at all. Both the proxy and the step-2
   heading are toggled via the `hidden` attribute, so this has to be
   restated for anything given an explicit display. */
body.rolex-section .rlx-cm__back[hidden],
body.rolex-section .rlx-cm__head[hidden] { display: none; }
body.rolex-section .rlx-cm__back .rlx-icon { width: 14px; height: 14px; transform: rotate(180deg); }
body.rolex-section .rlx-cm__back:hover { color: var(--rlx-green); }
/* Hidden only once the proxy is live — see rolex-bespoke.js. Without the
   [data-rlx-cm-proxied] gate a cf7mls change that renamed its button would
   leave the page with NO back control at all. */
body.rolex-section .rlx-cm[data-rlx-cm-proxied] .rlx-cm__form .cf7mls_back { display: none; }

/* ---- the form ---------------------------------------------------------- */
body.rolex-section .rlx-cm__form { margin-top: var(--rlx-gap-half); text-align: left; }
body.rolex-section .rlx-cm__form .wpcf7 { overflow: hidden; }

/* Step 1's message box: a WHITE panel, no border, 298px tall, the full
   column wide — sampled from the comp, where the fill reads #FFFFFF against
   the page's #F9F7F4 and there is no rule at its edge. The legacy
   bespoke-light.css still forces height:50px on
   `.wtp-rlx-message-wrapper label span.wpcf7-form-control-wrap textarea`,
   which is why the height is declared rather than left to rows="10". */
body.rolex-section .rlx-cm__form .wpcf7 textarea {
	width: 100%;
	height: 298px;
	/* 40, measured: both comps set the first character's cap-top 46px below
	   the box's top edge, and at 16px/1.5 the half-leading plus the
	   ascender-to-cap gap already account for ~7 of that. The left inset
	   reads 33-39 across the two comps (the box edges themselves carry +-4
	   of JPEG slop), so one value serves both axes. Was 16 on all four. */
	padding: 40px;
	border: 0;
	background: var(--rlx-surface);
	font-size: var(--rlx-fixed16);
	line-height: 1.5;
	/* The field's own text is INK at regular weight in both comps (darkest
	   sampled pixel rgb(32,32,32) on each). It rendered brown at 700 --
	   inherited, never declared here -- which read as a heading rather than
	   as something the visitor is meant to edit. */
	color: var(--rlx-ink);
	font-weight: 400;
	resize: vertical;
}

/* "Enter your message" is the label text in CF7 form 34401, and NEITHER comp
   draws it outside the box: the send-a-message comp shows it as the field's
   own placeholder (grey, inside, top-left) and the model comp replaces it
   entirely with the prefilled "I'm interested in..." sentence. Collapsed
   rather than display:none deliberately -- the <label> is the textarea's
   accessible name, and font-size:0 keeps it in the accessibility tree while
   taking it out of the layout. The textarea restores its own size above.
   rlx-contact-form.php supplies the placeholder the comp shows. */
/* `:has(textarea)` is LOad-BEARING, not decoration. `.wtp-rlx-message-wrapper`
   is on every row of form 34401, step 2's included, so the same rule without
   it collapsed all thirteen labels -- "Title", "First name", "Email address"
   and the rest -- and nothing caught it because step 2 is hidden until the
   visitor clicks Next. Only the label that WRAPS the message field is the one
   the comps replace.

   It also wins the cascade: :has() takes its argument's specificity, so this
   is (0,4,3) against the generic `.rlx-cm__form .wpcf7 label` rule's (0,4,1)
   further down the sheet, which would otherwise take the tie on source order.

   margin:0 is for MOBILE. The theme's class is called `no-margin-desktop`
   and means it: below 768 the label keeps a 25px top margin, which sat on top
   of the 10px the control wrapper already adds. */
body.rolex-section .rlx-cm__form .wpcf7 .wtp-rlx-message-wrapper label:has(textarea) { font-size: 0; line-height: 0; margin: 0; }
/* opacity:1 because the comp draws the placeholder at FULL ink -- sampled
   rgb(32,32,32), the same value as the model page's prefilled sentence --
   not at the browser's default ~54%. */
body.rolex-section .rlx-cm__form .wpcf7 textarea::placeholder { color: var(--rlx-ink); opacity: 1; }

/* THE FIELD IS THE OPPOSITE TONE TO WHATEVER IS BEHIND IT, and which one is
   white flips between the two places this form appears:

     send-a-message page -- the form sits directly on the page ground
       (#F9F7F4), and the comp draws the box WHITE. That is the rule above.
     model page -- .rlx-contact__form paints a WHITE panel around the form,
       and the comp draws the box #F8F7F3, i.e. our --rlx-bg.

   Borderless in both, so the fill is the only thing marking the box: white
   on white left an empty field indistinguishable from the panel on the model
   page. Scoped to .rlx-contact__form rather than changed globally, because
   doing it globally makes the send-a-message field invisible instead -- the
   mistake this comment exists to stop someone repeating. */
body.rolex-section .rlx-contact__form.rlx-cm__form .wpcf7 textarea {
	background: var(--rlx-bg);
	/* ...and it is SHORTER here: the model comp draws the box y7820-8019, a
	   flat 200, where the standalone send-a-message comp draws 298. */
	height: 200px;
}

/* The cover image ABUTS the white form panel -- no gap at all. The model comp
   ends the photograph at y7544 and starts the white panel at y7545, both on
   the same 1620 container. .rlx-cm__form's own margin-top (gap-half) is for
   the standalone page, where the form follows a heading rather than a
   full-width image, so it is zeroed here rather than removed. */
body.rolex-section .rlx-contact__panel > .rlx-contact__form.rlx-cm__form { margin-top: 0; }

/* AND ITS HEADER STAYS CENTRED. The model page's form element carries BOTH
   .rlx-contact__form (centred, line ~1985) and .rlx-cm__form (left, added
   later for the standalone send-a-message page). Equal specificity, so the
   later one won and the model page's kicker and heading went left while the
   body under them stayed centred -- two alignments in one block. Both comps
   that show this form centre the header. (0,3,1) so it beats either alone. */
body.rolex-section .rlx-contact__form.rlx-cm__form { text-align: center; }

/* Step 2's fields are UNDERLINED, not boxed: the comp draws a single
   1px rule at #B0A69D under each, full column width for the full-width
   fields and part-width for the ones sharing a row. */
body.rolex-section .rlx-cm__form .wpcf7 input[type="text"],
body.rolex-section .rlx-cm__form .wpcf7 input[type="email"],
body.rolex-section .rlx-cm__form .wpcf7 input[type="tel"],
body.rolex-section .rlx-cm__form .wpcf7 select {
	width: 100%;
	height: auto;
	padding: 4px 0 10px;
	border: 0;
	border-bottom: 1px solid #b0a69d;
	border-radius: 0;
	background: transparent;
	font-size: var(--rlx-fixed16);
	line-height: 1.5;
	color: var(--rlx-ink);
}
/* Field labels: small, regular weight, warm grey. The VALUE beneath each
   label is the normal #212121 ink at 16px. Both are stated rather than
   inherited: the theme renders labels bold in the brown heading colour,
   which made every label compete with its own value.

   AMENDED 2026-09-12 -- CONTRAST. This was #9D9088, recorded as "sampled
   from the comp". That sample caught an ANTI-ALIASED EDGE, not the ink: a
   darkest-decile sample of the same comp label returns (99,99,99) = 5.62:1.
   #9D9088 measures 2.90:1 on the page ground and 3.10:1 on the white field,
   both under the 4.5:1 floor for body text -- on the labels of a form people
   have to fill in.

   #6B615C keeps the warm hue at a passing value (4.67:1 on the #F9F7F4
   ground, 5.00:1 on white), so the label still sits back from its value
   without failing. Accessibility is a floor: where a comp and the floor
   disagree, match everything else and fix the contrast.

   Do NOT re-sample a comp by eye-dropping one pixel. Light text on a light
   ground reads far lighter at its anti-aliased edge than its actual ink;
   sample the darkest decile inside the glyph band. */
body.rolex-section .rlx-cm__form .wpcf7 label {
	display: block;
	font-size: var(--rlx-fixed14, 14px);
	font-weight: 400;
	line-height: 1.4;
	color: #6b615c;
	margin-bottom: 0;
}
body.rolex-section .rlx-cm__form .wpcf7 .and-or {
	display: block;
	/* 16px, not the half gap: the comp runs the email field into the phone
	   row at ~70px total, where a 45px margin on top of the input's own
	   spacing pushed it past 100. */
	margin-block: 16px 4px;
	font-size: var(--rlx-fixed14, 14px);
	color: #6b615c;
}
/* VALIDATION IS VISIBLE (2026-09-14, Rolex staging review): "When submitting a
   form, if there is a required field missing, it is not specified on the page.
   In this case the Title is missing, a red box or some indication should
   appear to let the user know which field is missing."

   CF7 already emits the markup -- it adds .wpcf7-not-valid to the offending
   control and a .wpcf7-not-valid-tip beside it -- but this stylesheet carried
   NO rules for either, so in this section the field looked untouched and the
   tip inherited whatever the parent theme did with it. Nothing needed to be
   invented; it needed to be shown.

   #B3261E rather than a pure red: 6.11:1 on the page ground and 6.54:1 on the
   white field, both clear of the 4.5:1 floor. A pure #F00 would not be.

   The red border is paired with the tip text, never used alone -- colour is
   not the only channel carrying the message. */
body.rolex-section .rlx-cm__form .wpcf7 .wpcf7-not-valid {
	border-color: #b3261e;
	/* AN INSET OUTLINE, NOT A SHADOW (2026-09-24, Ernie: "the errors
	   outlines also being cut off"). This was an OUTER 1px box-shadow, and
	   the same three overflow:hidden wrappers that clipped the focus ring
	   clipped it: their edges sit on the fields', so Email lost both sides
	   and Last name its right.

	   Not an inset shadow either: WebKit drops author box-shadow on a
	   control that keeps its native appearance, and both selects here (Title,
	   phone Code) are appearance:auto -- in Safari they showed no red ring at
	   all, only the red underline. An outline draws on native controls, and
	   at -1px it sits inside the field where nothing can clip it. */
	box-shadow: none;
	outline: 1px solid #b3261e;
	outline-offset: -1px;
}
/* Focus still wins on an invalid field: the green ring above is earlier in
   the file at the same specificity, so this rule would otherwise replace it
   with the 1px red one the moment the visitor tabs back in to fix it. */
body.rolex-section .rlx-cm__form .wpcf7 .wpcf7-not-valid:focus-visible {
	outline: 2px solid var(--rlx-green);
	outline-offset: -2px;
}
body.rolex-section .rlx-cm__form .wpcf7 span.wpcf7-not-valid-tip {
	/* !important because the PARENT THEME hides these outright --
	   roneous-theme-styles.css carries `span.wpcf7-not-valid-tip { display:
	   none !important }`, so no amount of specificity wins without matching it.
	   Two other stylesheets in this build already restate it the same way
	   (hybird.css for .hybrid-contact-form, bespoke-light.css for
	   .wtp-rlx-message-form-wrapper), so this is the established way to beat
	   that rule rather than a new hammer. Same family as the theme's
	   `br { display:none }` at mobile and its [hidden] override. */
	display: block !important;
	margin-top: 6px;
	font-family: var(--rlx-font-sans);
	font-size: var(--rlx-fixed14, 14px);
	line-height: 1.4;
	color: #b3261e;
}
/* The form-level summary CF7 prints under the submit row. Styled for both
   outcomes so a failure is not mistaken for a success. */
body.rolex-section .rlx-cm__form .wpcf7 .wpcf7-response-output {
	margin: 16px 0 0;
	padding: 12px 16px;
	border: 1px solid currentColor;
	font-size: var(--rlx-fixed14, 14px);
	line-height: 1.4;
}
body.rolex-section .rlx-cm__form .wpcf7 form.invalid .wpcf7-response-output,
body.rolex-section .rlx-cm__form .wpcf7 form.unaccepted .wpcf7-response-output,
body.rolex-section .rlx-cm__form .wpcf7 form.payment-required .wpcf7-response-output { color: #b3261e; }
body.rolex-section .rlx-cm__form .wpcf7 form.sent .wpcf7-response-output { color: var(--rlx-green); }
/* LABELS AND ERROR NOTICES SIT FLUSH LEFT ON THEIR FIELD (2026-09-24,
   Ernie: "left aligned field labels", and "ensure the error notices are
   also correct"). The step 2 mockup starts every label on the field's own
   left edge (Title x553, underline x553) in plain untracked sentence case.
   Ours inherited the module's centred heading alignment and the parent
   theme's 1px label tracking, so "Title" began 33px inside its field and
   "Email address" 343px inside it. Every field's error tip is inside its
   label and inherited the same, and the consent tip started 57px LEFT of
   the checkbox it is about.

   The heading, intro and the step buttons stay centred, as the comp draws
   them: only the form's field furniture is realigned. The comps have no
   error state, so the tips and the form-level summary follow the labels. */
body.rolex-section .rlx-cm__form .wpcf7 label,
body.rolex-section .rlx-cm__form .wpcf7 .and-or,
body.rolex-section .rlx-cm__form .wpcf7 span.wpcf7-not-valid-tip,
body.rolex-section .rlx-cm__form .wpcf7 .wpcf7-response-output {
	text-align: left;
	letter-spacing: normal;
	text-transform: none;
}

body.rolex-section .rlx-cm__form .wpcf7 .wtp-acceptance-wrapper { margin-top: 16px; font-size: var(--rlx-fixed14, 14px); }
/* THE CONSENT ROWS SIT FLUSH LEFT WITH THE FIELDS (2026-09-24, Ernie:
   "left-align the terms and conditions and agree to receive marketing
   information checkboxes ... make sure that all the forms have these fields
   left-aligned"). The step 2 mockup starts both rows on the fields' left
   edge. Ours centred them: CF7 wraps each in a <p> that inherited the
   module's centred alignment. Keyed on .rlx-cm__form, so the model pages'
   form and /rolex/contact/send-a-message/ both take it.

   Two more things the centring hid. CF7's own .wpcf7-list-item carries a
   1em left margin, which would leave the box 14px off the field edge once
   left-aligned. And the theme's 25px label margin-top sat INSIDE the list
   item, so the invalid-state ring drew as a 45px box with the row at its
   foot; the gap moves onto the row's wrapper instead. */
body.rolex-section .rlx-cm__form .wpcf7 .wtp-acceptance-wrapper,
body.rolex-section .rlx-cm__form .wpcf7 .wtp-acceptance-wrapper p { text-align: left; }
body.rolex-section .rlx-cm__form .wpcf7 .wtp-acceptance-wrapper .wpcf7-list-item { margin: 0; }
body.rolex-section .rlx-cm__form .wpcf7 .wtp-acceptance-wrapper .wpcf7-list-item label { margin-top: 0; }
body.rolex-section .rlx-cm__form .wpcf7 [type="checkbox"] { accent-color: var(--rlx-green); }

/* Every button in the module is the same green pill, 40px tall, centred —
   step 1 "Next" (114x40), step 2 "Send a message" (191x40), step 3 "Back to
   homepage" (201x40); all three sample #127849 in the comps. */
body.rolex-section .rlx-cm__form .cf7mls-btns,
body.rolex-section .rlx-cm__form .wpcf7 p:has(> .wpcf7-submit) { text-align: center; }
/* 41 above the step-1 button, and BOTH comps agree: the model page draws the
   textarea to y8019 with the pill at y8060, and the standalone send-a-message
   comp draws y1319 / y1360. Was 25. */
/* .action-button is on the selector to WIN, not to describe: bespoke-light
   carries `html body.rolex-section .cf7mls-btns .cf7mls_next.action-button
   { margin: 25px auto 0 auto }` at (0,4,2), so the same rule without it lost
   silently. This is (0,5,1). */
body.rolex-section .rlx-cm__form .cf7mls-btns .cf7mls_next.action-button { margin-top: 41px; }
body.rolex-section .rlx-cm__form .wpcf7 input[type="submit"],
body.rolex-section .rlx-cm__form .wpcf7 button[type="submit"],
body.rolex-section .rlx-cm__form .cf7mls_next,
body.rolex-section .rlx-cm__cta .rlx-cta-primary {
	display: flex;
	align-items: center;
	justify-content: center;
	/* width/height are RESTATED, not inherited: the parent theme sets
	   `input[type="submit"] { width: 100%; height: 56px }`, which rendered
	   step 2's "Send a message" as an 810x56 bar instead of the comp's
	   191x40 pill. */
	width: fit-content;
	height: auto;
	min-height: 40px;
	/* `float: none` is what actually centres step 2's submit. cf7mls.css
	   sets `float: right` on it, and a float resolves `auto` margins to 0 —
	   so margin-inline: auto silently did nothing and the button sat flush
	   against the column's right edge at x1184 instead of centred at x960.
	   Both declarations are needed: the float has to go, and then the auto
	   margins do the centring (the ancestor's text-align cannot, since
	   these are block-level flex boxes). */
	float: none;
	margin-inline: auto;
	padding: 0 28px;
	border: 0;
	border-radius: 20px;
	background: var(--rlx-green);
	color: #fff;
	font-size: var(--rlx-fixed16);
	line-height: 1;
	text-decoration: none;
	cursor: pointer;
}
body.rolex-section .rlx-cm__cta { margin: var(--rlx-gap-half) 0 0; }
/* All three buttons are bold in the comps, and step 1's carries a chevron —
   the deck writes that button "Next>" and the mockup draws it as "Next ›".
   Added as a pseudo-element rather than by editing the label, because the
   label lives in the cf7mls step shortcode inside the form post, i.e. in
   the database. */
body.rolex-section .rlx-cm__form .wpcf7 input[type="submit"],
body.rolex-section .rlx-cm__form .wpcf7 button[type="submit"],
body.rolex-section .rlx-cm__form .cf7mls_next,
body.rolex-section .rlx-cm__cta .rlx-cta-primary {
	font-weight: 700;
	/* The theme uppercases submit buttons; all three comps render these in
	   sentence case ("Next", "Send a message", "Back to homepage"). */
	text-transform: none;
	letter-spacing: normal;
}
body.rolex-section .rlx-cm__form .cf7mls_next::after { content: "\203A"; margin-left: 10px; font-weight: 400; }

/* Step 3's image: EIGHT columns at offset two, centred — measured
   x423-1497 (1080 at offset 270 is x420-1500). Not one of
   RLX_Asset_Resolver::span_for()'s three steps, so it carries its own rule
   rather than borrowing .rlx-image-block's span table. */
body.rolex-section .rlx-cm__figure {
	width: min(calc(var(--rlx-container-max) / 12 * 8), 100% - var(--rlx-container-inset));
	max-width: none;
	margin-block: var(--rlx-gap) 0;
	margin-inline: auto;
	padding-inline: 0;
}
body.rolex-section .rlx-cm__figure img { display: block; width: 100%; height: auto; }

@media (max-width: 767px) {
	body.rolex-section .rlx-cm__panel.rlx-container { width: calc(100% - var(--rlx-container-inset)); }
	body.rolex-section .rlx-cm__figure { width: calc(100% - var(--rlx-container-inset)); }
	/* HALF the desktop inset: the mobile model comp draws the field
	   x111-672 of a 2x render with its first character at x153 and its
	   cap-top 53 device-pixels down, i.e. ~20 CSS on both axes. */
	body.rolex-section .rlx-cm__form .wpcf7 textarea { height: 267px; padding: 20px; }

	/* The model page's send-a-message panel runs TIGHTER at mobile than at
	   desktop, and by different amounts at each joint. Measured on
	   rolex-watches-model-page-mockup-send-a-message-mobile.jpg (a 2x render,
	   so every figure below is the comp's halved): panel y12190-13453 = 631.5
	   tall and x55-726 = 335.5 wide, kicker cap-top 47.5 from the top, the
	   field x111-672 (so 28 of inset, not 40), the pill's 40px box at 532 and
	   60 of panel beneath it.
	   This block sits at the END of the sheet on purpose -- a media query adds
	   no specificity, so it can only beat the desktop declarations on source
	   order. */
	body.rolex-section .rlx-contact__form { padding-block: 43px 60px; padding-inline: 28px; }
	body.rolex-section .rlx-contact__form .rlx-headline50 { margin-block: 0 15px; }
	body.rolex-section .rlx-contact__intro { margin-block: 0 20px; }
	body.rolex-section .rlx-cm__form .cf7mls-btns .cf7mls_next.action-button { margin-top: 30px; }
}

/* ------------------------------------------------------------------------
   CONTACT: store card + consent-gated map, one unit (Ashton items 52/53)
   ------------------------------------------------------------------------
   Measured off rolex-contact-page-single-pos-mockup-desktop.jpg: the unit
   spans the 1620 container (x156-1768 in the comp), the map is 1073 wide and
   the card 541, both 740 tall -- span8 + span4 on the 12-col grid, so the
   grid columns below are the comp's own proportions, not a chosen ratio.

   DOM order is card-then-map because that is the MOBILE comp's order (card
   with address/hours/CTAs first, map full-width below it). Desktop moves the
   map into column 1 with grid-column rather than reordering the markup, so
   the linear reading order stays correct at the breakpoint that uses it. */
body.rolex-section .rlx-store-unit { display: grid; gap: 0; }
/* BOTH CHILDREN CARRY .rlx-container AND SO DOES THE UNIT. Nested, the
   gutter applies twice: at desktop every column came out 48px narrow (map
   1032 against the comp's 1073, card 492 against 541), and at mobile the card
   sat 282 wide inside a 336 well. The UNIT owns the gutter at both
   breakpoints; its children must never re-apply it. The mobile map overrides
   this again below to escape the well entirely. */
body.rolex-section .rlx-store-unit > .rlx-map,
body.rolex-section .rlx-store-unit > .rlx-ed-store {
	max-width: none;
	width: auto;
	margin-inline: 0;
	padding-inline: 0;
	/* min-width:0 IS LOAD-BEARING ON iOS. Reported by Ernie 2026-09-23 on a
	   real iPhone: /rolex/contact/ could be swiped sideways by 27px, and
	   only that page. Measured on an iPhone 14 / iOS 16.4 through
	   BrowserStack, because nothing here reproduces it -- Chromium and
	   desktop WebKit, ddev and staging, both report scrollWidth ===
	   clientWidth.

	   The device readout, which is what settled it:

	     scrollW=417  clientW=390                      27px of real overflow
	     .rlx-ed-store__lines  L=27 R=417  ml=0px      margin did not apply
	     SECTION.rlx-ed-store  w=390                   card 54.6px too wide
	     .rlx-store-unit  width=335.390625px           the well is CORRECT

	   It is CIRCULAR SIZING, not a Safari calc bug -- a distinction that
	   matters, because the first three fixes I reached for were all wrong.
	   .rlx-ed-store__lines and .rlx-map are width:100vw pulled back by
	   margin-inline: calc(50% - 50vw). A grid item defaults to
	   min-width:auto, so the 390px child STRETCHES its item from 335.4 to
	   390; the margin's 50% then resolves against that stretched 390, giving
	   195 - 195 = 0; with no pull-back the child stays 390 and the whole
	   thing sits at a stable, wrong fixed point. Chrome resolves the
	   percentage against the item's definite size and never enters the loop.
	   The card's children (tags, label, address, hours) all measured 390 for
	   the same reason -- they were inside a stretched card, not broken
	   themselves.

	   min-width:0 makes the item shrinkable, so the containing block is
	   definite again. Verified ON THE DEVICE, in place, before shipping:
	     scrollW 417 -> 390,  cardW -> 335.4,  ml -> -27.296875px.
	   All three land on the Chrome values at once.

	   WHAT WAS TRIED AND REJECTED: overflow-x:clip on main. It clamped the
	   pan but left the map and the pill row 27px short of the left edge on
	   iOS -- symptom gone, layout still wrong. Also considered and not
	   needed: rewriting all ten calc(50% - 50vw) escapes to -7vw/-8vw. The
	   calc is fine; only its containing block was.

	   THE GENERAL HAZARD: any width:100vw bleed child inside a grid or flex
	   item needs this. Today .rlx-store-unit is the only such parent in the
	   section -- which is exactly why the contact page was the only page
	   that panned. */
	min-width: 0;
}
/* The card's .rlx-block margin would push it 90px below the map's top edge
   inside the grid row (grid margins do not collapse). The comp has both
   boxes starting on the same line. The map already zeroes its own margin in
   the desktop block below; the card needs the same at every width. */
body.rolex-section .rlx-store-unit > .rlx-ed-store { margin-block: 0; }

@media (min-width: 768px) {
	body.rolex-section .rlx-store-unit {
		grid-template-columns: repeat(12, 1fr);
		align-items: stretch;
	}
	body.rolex-section .rlx-store-unit > .rlx-map { grid-column: 1 / span 8; grid-row: 1; margin: 0; padding: 0; }
	body.rolex-section .rlx-store-unit > .rlx-ed-store {
		grid-column: 9 / span 4;
		grid-row: 1;
		background: #fff;
		/* The comp insets the card's content ~100px horizontally and ~90px
		   from the top (tags at y1116 in a card starting y1025, text left
		   edge at card-relative x100 of 540). Held as a percentage so the
		   inset stays proportional at 1440 and 768 instead of swallowing a
		   narrower card. */
		padding: var(--rlx-gap, 90px) 18.5%;
		box-sizing: border-box;
	}
	/* THE RATIO GOES ON THE FACADE, NOT THE UNIT.
	   `aspect-ratio` on the grid container never bound: a grid row is at
	   least as tall as its content, and .rlx-map__facade had no height of
	   its own, so the <img>'s `height:100%` resolved against an auto-height
	   parent and fell back to the asset's intrinsic 1032px. The unit
	   declared 1620/740 and rendered 1064 -- the declaration was inert, not
	   merely overridden.
	   Sizing the facade instead gives the row a real height to be: 8 of 12
	   columns of 1620 = 1080 wide, 740 tall per the comp. min-height:0 lets
	   the grid item shrink to it rather than to its content. */
	body.rolex-section .rlx-store-unit > .rlx-map { min-height: 0; }
	body.rolex-section .rlx-store-unit .rlx-map__facade { aspect-ratio: 1080 / 740; height: auto; }
}

/* The facade IS the sized element (same contract as .rlx-facade): the iframe
   JS creates carries the button's own classes, so these rules keep matching
   after activation. */
body.rolex-section .rlx-map { position: relative; }
body.rolex-section .rlx-map__facade,
body.rolex-section .rlx-map__iframe {
	display: block;
	width: 100%;
	height: 100%;
	min-height: 320px;
	padding: 0;
	border: 0;
	background: var(--rlx-panel);
	cursor: pointer;
	position: relative;
	overflow: hidden;
}
body.rolex-section .rlx-map__iframe { cursor: auto; }
body.rolex-section .rlx-map__image { width: 100%; height: 100%; object-fit: cover; display: block; }
body.rolex-section .rlx-map__panel { display: block; width: 100%; height: 100%; background: var(--rlx-panel); }
/* The cue sits over the photograph, so it carries its own ground rather than
   relying on the image behind it -- that image is a real store photo and its
   luminance is not ours to control. */
body.rolex-section .rlx-map__cue {
	position: absolute;
	left: 50%;
	top: 50%;
	transform: translate(-50%, -50%);
	display: inline-flex;
	align-items: center;
	gap: 10px;
	padding: 12px 22px;
	border-radius: 24px;
	background: #fff;
	color: var(--rlx-brown);
	font-weight: 700;
}
body.rolex-section .rlx-map__cue .rlx-icon { width: 18px; height: 18px; }
body.rolex-section .rlx-map__note { margin: 12px 0 0; color: var(--rlx-ink); }
body.rolex-section .rlx-map__address { margin: 4px 0 0; color: var(--rlx-brown); }

/* RETAILER STATUS TAGS -- now built to Rolex's OWN "Tags" component sheet
   (Brand Centre > Design specifications, supplied by Ernie 2026-09-23), not
   inferred from a page comp. The sheet annotates, in its own words: "Label:
   Helvetica now bold 11px / Border-radius: 4px", "Bg: #F2F2F2", inks "Green /
   Black / Gold", 8px of inline padding and 4px between tags.

   Every one of those was checked against the page comps rather than taken on
   the sheet's word, and the comps agree:

     rolex-contact-page-single-pos-mockup-mobile.jpg (2x, pills y1968-2007)
       pill height        40px  -> 20 css
       padding-inline     16px  -> 8 css, measured on ALL THREE pills, exact
       gap                 8px  -> 4 css
       cap height         16px  -> 8 css, i.e. 11px type (Helvetica cap 0.714)
       background   (242,242,242) -> #F2F2F2, one colour across 320 sampled px
     rolex-contact-page-single-pos-mockup-desktop.jpg (1x, pills y1116-1134)
       pill height        19px,  cap height 8px -- the SAME 20px/11px tag.

   So this is one component at both breakpoints, and it needs no breakpoint
   split. padding-block is 4px because that is what puts an 11px/12px line box
   in a 20px pill; the sheet annotates the horizontal structure only.

   THE SUPERSEDED REASONING IS KEPT ON PURPOSE. This rule previously ran at
   rlx-fixed14 with a comment arguing that "the mockup is the authority on
   PLACEMENT, the spec on the TYPE SYSTEM, and 14px is the smallest size in
   that ramp", so a one-off 12px for two chips was refused. That was sound on
   the evidence then available -- what was missing is that Rolex's type system
   DOES carry an 11px size, scoped to this component, and the Tags sheet is
   where it is written down. The sheet replaces the inference; it does not
   convict it.

   ROLEX'S TWO SOURCES DISAGREE ON THE GROUND, recorded rather than silently
   resolved (same handling as the "* Mandatory information" space). The mobile
   comp draws the pill #F2F2F2 on a WHITE section and the Tags sheet says
   #F2F2F2; the desktop comp draws it (248,247,243) = #F8F7F3 on white. Two
   sources to one, and the component sheet is the authority on the component,
   so #F2F2F2 it is -- written literally, NOT as var(--rlx-surface), which is
   #FFFFFF on this build and was painting the chips the same colour as the
   card they sit in.

   Contrast recomputed on #F2F2F2 (the old figures were against #F8F7F3):
   green #006039 6.87:1 and black #212121 14.38:1 pass; Rolex's gold #A27E2C
   measures 3.38:1, under the 4.5 floor -- 11px bold is not large text. Held
   at #866925, darkened along the same hue, which is 4.62:1. Deliberate, per
   the project's accessibility rule, and unchanged in direction from before. */
body.rolex-section .rlx-ed-store__tags {
	list-style: none;
	margin: 0 0 20px;
	padding: 0;
	display: flex;
	flex-wrap: wrap;
	gap: 4px;
}
body.rolex-section .rlx-ed-store__tag {
	background: #F2F2F2;
	/* The type class this <li> used to carry (rlx-fixed14) was also what
	   supplied the section's font. Dropping it for the 11px size dropped the
	   family too, and the chips silently rendered in the theme's Hind --
	   caught by reading the computed style, not by looking. State the family
	   here rather than depend on a size class to carry it. */
	font-family: var(--rlx-font-sans);
	font-size: 11px;
	line-height: 12px;
	padding: 4px 8px;   /* 4 + 12 + 4 = the comps' 20px pill */
	border-radius: 4px;
	font-weight: 700;
	white-space: nowrap;
}
body.rolex-section .rlx-ed-store__tag--green { color: var(--rlx-green-rolex); }
body.rolex-section .rlx-ed-store__tag--ink   { color: var(--rlx-ink, #212121); }
body.rolex-section .rlx-ed-store__tag--gold  { color: #866925; } /* Rolex's #A27E2C is 3.38:1 on #F2F2F2 -- see the note above */
body.rolex-section .rlx-ed-store__address { margin: 4px 0 16px; }

@media (max-width: 767px) {
	/* THE TAG ROW SITS TIGHT TO THE HEADING ON MOBILE, and only on mobile.
	   Measured ink-to-ink, because the heading's own half-leading is part of
	   what the eye reads as the gap (see [[measure-ink-not-boxes]]):

	     pill box bottom -> heading CAP top
	       mobile comp   13px   (y2007 -> y2033 at 2x; y2033 is the cap, the
	                             x-height starts at y2044 -- reading the
	                             x-height top as the cap is how this lands
	                             ~5px wrong, so it is written down here)
	       desktop comp  30px
	       ours, before  26px mobile / 27px desktop, from one 20px margin

	   Both comps run the same 32px/24px headline pair we already render, so
	   the two ink gaps are not a type mismatch -- Rolex genuinely tightens
	   this on mobile. The base 20px stays for desktop (27 against the comp's
	   30 is a 3px deviation, left alone and recorded rather than tuned by
	   eye), and only the narrow case is overridden. This rule sits AFTER the
	   base one on purpose: a media query adds no specificity, so an override
	   written earlier in the file would lose on source order. */
	body.rolex-section .rlx-ed-store__tags { margin-bottom: 7px; }


	/* The mobile comp runs the map EDGE TO EDGE under the card, not inset in
	   the 336 well. Exactly the escape .rlx-editorial__media--bleed already
	   uses -- margin-inline: calc(50% - 50vw), never width:100vw plus a
	   transform, which overflows by the scrollbar width. */
	body.rolex-section .rlx-store-unit > .rlx-map {
		width: 100vw;
		max-width: none;
		margin-inline: calc(50% - 50vw);
		padding-inline: 0;
	}
	body.rolex-section .rlx-map__facade,
	body.rolex-section .rlx-map__iframe { min-height: 360px; }
	/* THE MOBILE MAP IS SQUARE (2026-09-19). Comp and spec agree for once:
	   `rolex-contact-page-single-pos-mockup-mobile.jpg` runs the map from
	   y2665 to y3445 across its full 784px width -- 784 x 780, i.e. 1.005:1 --
	   and Rolex's own p100 annotates the Small breakpoint "1:1 map ratio".
	   We were rendering 400 x 434 (0.92:1), the residue of a 360px min-height
	   with no ratio to bind it.

	   min-height is zeroed HERE so the ratio wins at narrow widths too;
	   below 360px a min-height would otherwise letterbox the square back
	   into a rectangle. The desktop 1080/740 above is untouched -- that is
	   the desktop comp's own box, and it still governs from 768 up. */
	body.rolex-section .rlx-store-unit .rlx-map__facade,
	body.rolex-section .rlx-store-unit .rlx-map__iframe {
		aspect-ratio: 1 / 1;
		height: auto;
		min-height: 0;
	}
	/* HALF the token: every other consumer subtracts it from 100% as a
	   both-sides total, but this is a padding on one element, so it needs one
	   side. It read the whole token before, which put the note's text at x54
	   on a 390 viewport where the gutter is 27 — a pre-existing 27px error,
	   found 2026-09-17 while making the token a percentage. */
	body.rolex-section .rlx-map__note { padding-inline: calc(var(--rlx-container-inset) / 2); }
}

/* ---- LINKED IMAGES: HOVER, PER ROLEX'S OWN SPEC (2026-09-17) -------------
   REPLACES the 1.04 scale shipped earlier today in dc99f81. The client asked
   for a scale with frankadams.com given as the example, and that was built;
   this supersedes it on instruction, because Rolex turns out to specify the
   treatment and it is not a transform.

   SOURCE, and why we had it wrong first. The Bespoke section page on the
   Brand Centre has three tabs; we had only ever read Guidelines, which says
   nothing beyond "interactions should follow UX best practices". The DESIGN
   SPECIFICATIONS tab carries an Accessibility > Examples table with Base and
   Hover columns for nine components -- Primary/Secondary/Tertiary CTA,
   Navigation link, Play button, Drop-down, Form field, Check box, and PUSH,
   which is a linked image card exactly like ours. Every Hover cell draws a
   thin rule around the whole component. NOT ONE of them scales, moves or
   transforms anything.

   Its "Structure and styles" block gives the values outright:
     component on a LIGHT background -- 2px border, Green   #127749
     component on a DARK  background -- 2px border, Ocean green #9BF9CE
     both with a 3px margin around the item.

   That is the same pair, and the same 3px, this file already uses for
   :focus-visible. So hover and focus share one indicator, which is what the
   table shows and is the reason the focus group above needed no new colour.

   ALL EIGHT COMPONENTS TAKE THE LIGHT-BACKGROUND RING, including the model
   push, whose own artwork is dark: outline-offset paints the ring OUTSIDE
   the element, on the page's light-beige, so the deciding surface is the
   page and not the art. That is the same correction already recorded against
   .rlx-lightbox__close above -- #9BF9CE on #F9F7F4 measures 1.17:1, nowhere
   near the 3:1 WCAG wants for a non-text indicator, where --rlx-green
   measures ~5.2:1.

   `outline` rather than `border`, because a real border would add 2px to the
   box and shift every comp-pinned card on hover; outline is painted outside
   the box and changes no geometry. No transition: nothing in the spec's
   table implies motion, and an instant indicator is also what the focus
   rings do. Nothing here needs a prefers-reduced-motion guard as a result.

   PUSH ENCLOSES ART PLUS COPY (fixed 2026-09-19). The spec's Push drawing
   rings the whole card -- image, kicker, title and secondary CTA. This
   comment used to say matching it "needs a template change (the CTA is
   itself an <a> and cannot nest)" and leave it. That reasoning was sound
   about NESTING and wrong about the fix: `:has()` puts the ring on the
   section without touching the markup at all. `.rlx-push` is exactly the
   card the spec draws, so it now carries the outline when its media anchor
   is hovered.

   `.rlx-hub-promo` needed one extra step, because it opens with an
   `__heading` that sits OUTSIDE the card in the spec's drawing -- ringing
   that section would enclose a title Rolex does not enclose. promo.php now
   wraps the card parts in `.rlx-hub-promo__card`, a plain block with no
   styles of its own, and the ring follows that. Geometry was measured before
   and after to prove nothing moved. */
/* SCROLL ROWS WERE CLIPPING THE RING, TOP AND BOTTOM (2026-09-20, client
   report with a screenshot: the green ring showed on a card's left and right
   edges and stopped dead at its top and bottom).

   Cause is the CSS overflow interaction this file already documents further
   up: `overflow-x: auto` with `overflow-y: visible` computes overflow-y to
   `auto`, so the row clips vertically even though nothing scrolls that way.
   Measured, every affected row had ZERO headroom -- the cards sit flush
   against the padding box, so a ring drawn 3px outside them had nowhere to
   go. Horizontally it survived because the scrollable overflow region
   extends that way.

   Four rows carry ring-bearing cards: Keep exploring (on EVERY page), the
   new-watches keep row, the watches hub row and the Discover carousel.

   The fix reserves the ring's own 5px inside the row and gives it straight
   back to the layout: `padding-block` opens the room and an equal NEGATIVE
   margin pays for it, so every card sits exactly where it did.

   The margin is -5px on both sides rather than `calc(24px - 5px)`, and that
   distinction was measured, not guessed. All four rows follow an
   `.rlx-headline36` whose own margin-bottom is 24px, in a block parent, so
   the two margins COLLAPSE. Restating 24px gave a collapsed 24 plus 5px of
   padding -- a 29px gap, five too many, on every page in the section. A
   negative margin collapses as max(positives) + min(negatives): 24 + (-5) =
   19, plus the 5px padding = 24, unchanged. It also hardcodes nothing, so a
   future change to that 24px heading gap still comes out right.

   EXTENDED TO ALL FOUR SIDES 2026-09-20, same client, second report: the
   first card's ring was still cut on its LEFT and the last card's on its
   RIGHT. The 2026-09-19 fix only opened the block axis. Measured: every row
   had `padding-inline: 0` and zero left headroom, so the card flush against
   the row's inline padding edge lost its ring exactly the way the top and
   bottom ones had.

   Inline margins do NOT collapse, unlike block ones, and that is what makes
   this work rather than shift anything: the negative inline margin widens
   the element by 5px a side, so its CONTENT box still starts and ends on the
   container and the first card stays at the container's left edge. A card
   scrolled half out of view still clips, which is correct -- this only buys
   room at the two ends. */
/* THE INLINE RING ROOM CAN NEVER EXCEED THE ROW'S OWN GUTTER (2026-09-22,
   client report with a DevTools screenshot at 430: "Keep exploring is showing
   a sliver of the next card image").

   It was a 1px sliver, and it is arithmetic, not a rounding artefact. The
   5px of ring room above is PADDING on a scroll container, so it is part of
   the scrollport: whatever lands in it is visible. The next card begins one
   GUTTER after the last visible one. So the leak is exactly

       ring room - gutter

   and the rows divide on that sum alone. Measured at 430/390/767, every page:

       .rlx-keep__row       gutter 4px  ->  1.02px of card 3 showing   LEAK
       .rlx-nw-keep__row    gutter 4px  ->  same rule, same 1px        LEAK
       .rlx-hub__row        gutter 6px  ->  0                          clean
       .rlx-ed-carousel__row gutter 6px ->  0                          clean

   and at >=768 every gutter is 8px, so nothing leaked there -- which is why
   this only ever showed on a phone. The 4px mobile gutter is NOT the thing to
   change: it is measured off six comps (332/8 device) and its own rule states
   the invariant this violated, "Mobile shows exactly TWO tiles and no peek of
   a third".

   So the room is capped at the gutter, per row, derived rather than typed:
   a sixth pixel of "ring room" in a 4px gutter is definitionally another
   card's pixel, at any breakpoint, for any future row.

   THE COST, stated rather than buried: on the two 4px rows at mobile the
   first card's left ring and the last card's right ring now have 4px of room
   against the 5px the ring occupies (2px outline at a 3px offset), so their
   outermost 1px clips. Block-axis room is untouched at the full 5px, every
   row keeps 5px at >=768, and a 1px clip on a focus ring that a touch device
   will rarely draw beats 1px of the wrong photograph on every phone. */
body.rolex-section .rlx-keep__row { --rlx-ring-room-inline: min(var(--rlx-ring-room), var(--rlx-keep-gap)); }
body.rolex-section .rlx-nw-keep__row { --rlx-ring-room-inline: min(var(--rlx-ring-room), var(--rlx-nw-keep-gap)); }
body.rolex-section .rlx-hub__row { --rlx-ring-room-inline: min(var(--rlx-ring-room), var(--rlx-hub-gap)); }
body.rolex-section .rlx-ed-carousel__row { --rlx-ring-room-inline: min(var(--rlx-ring-room), var(--rlx-ed-carousel-gap)); }
body.rolex-section .rlx-keep__row,
body.rolex-section .rlx-nw-keep__row,
body.rolex-section .rlx-hub__row,
body.rolex-section .rlx-ed-carousel__row {
	padding: var(--rlx-ring-room) var(--rlx-ring-room-inline);
	margin: calc(-1 * var(--rlx-ring-room)) calc(-1 * var(--rlx-ring-room-inline));
	/* AND the snap has to respect it. These rows are `scroll-snap-type: x
	   mandatory`, and `scroll-snap-align: start` aligns a card to the
	   SCROLLPORT's start -- which is the padding-box edge, not the content
	   edge. So the browser immediately scrolled 5px to put the first card
	   back against the border, undoing the room and re-clipping the ring
	   (measured: scrollLeft settled at exactly 5). scroll-padding moves the
	   snap line inward by the same amount, which is what it exists for. */
	scroll-padding: var(--rlx-ring-room) var(--rlx-ring-room-inline);
}
/* THE RING FADES IN (2026-09-21, client: "make the image border outline
   transition smoother"). It used to appear and vanish on the frame.

   An outline cannot animate from `none`, so the resting state declares the
   SAME ring in `transparent` and only its COLOUR changes on hover. That
   costs nothing: outline is outside the box model, so a transparent one
   reserves no space and shifts nothing -- and the 5px of ring room these
   rows already carry (see --rlx-ring-room above) was sized for the visible
   ring, so the geometry is unchanged either way.

   150ms `ease`: a card hover is a high-frequency, low-stakes interaction, so
   the motion has to be quick enough to feel like feedback rather than an
   effect. `ease`, not a custom curve, because this is a colour change and
   not an entrance.

   outline-color is named explicitly rather than `transition: all` -- `all`
   would also animate the focus ring, the offset and anything a later rule
   adds to these elements.

   Focus is NOT animated: the :focus-visible group far above carries
   `transition: none` so a keyboard ring still appears on the frame it is
   earned. A fade is fine for a pointer hover; it is not fine for the
   indicator telling someone where their keyboard is. */
@media (hover: hover) and (pointer: fine) {
	body.rolex-section a.rlx-card,
	body.rolex-section a.rlx-hub-tiles__tile,
	body.rolex-section a.rlx-nw-tiles__tile,
	body.rolex-section a.rlx-ed-tile,
	body.rolex-section a.rlx-keep__card,
	body.rolex-section a.rlx-nw-keep__card,
	body.rolex-section .rlx-push,
	body.rolex-section .rlx-hub-promo__card {
		outline: 2px solid transparent;
		outline-offset: 3px;
		transition: outline-color 150ms ease;
	}
	body.rolex-section a.rlx-card:hover,
	body.rolex-section a.rlx-hub-tiles__tile:hover,
	body.rolex-section a.rlx-nw-tiles__tile:hover,
	body.rolex-section a.rlx-ed-tile:hover,
	body.rolex-section a.rlx-keep__card:hover,
	body.rolex-section a.rlx-nw-keep__card:hover {
		outline-color: var(--rlx-green);
	}
	/* The ring belongs to the CARD, not the art. Keyed on the media anchor
	   only, so hovering the secondary CTA still gets its own smaller box --
	   the spec lists Secondary CTA as its own row with its own hover.
	   `.rlx-hub-promo__card` is the wrapper promo.php adds for exactly this
	   reason: its section opens with a heading the spec does NOT enclose. */
	body.rolex-section .rlx-push:has(a.rlx-push__media:hover),
	body.rolex-section .rlx-hub-promo__card:has(a.rlx-hub-promo__media:hover) {
		outline-color: var(--rlx-green);
	}
	/* Reduced motion keeps the ring and drops the fade -- the indicator is
	   information, the 150ms is decoration. */
	@media (prefers-reduced-motion: reduce) {
		body.rolex-section a.rlx-card,
		body.rolex-section a.rlx-hub-tiles__tile,
		body.rolex-section a.rlx-nw-tiles__tile,
		body.rolex-section a.rlx-ed-tile,
		body.rolex-section a.rlx-keep__card,
		body.rolex-section a.rlx-nw-keep__card,
		body.rolex-section .rlx-push,
		body.rolex-section .rlx-hub-promo__card { transition: none; }
	}
}
