/*
 * RoboPharma 2026, components.
 * Depends on tokens.css and base.css. Load order is enforced in functions.php.
 */

/* ══ Header and navigation ═══════════════════════════════════════════════════
   Sticky, navy, and the same height as --rp-header-h so scroll-padding-top
   lines up with it.

   The mobile menu is a <details> element. That is deliberate: it opens and
   closes without JavaScript, it is keyboard operable and screen-reader
   announced for free, and it degrades to an always-open list if CSS fails.
   A div-plus-JS toggle has to reimplement all of that and usually gets the
   aria wrong. */

.rp-header {
  position: sticky;
  top: 0;
  z-index: 100;
  background: var(--rp-navy);
  color: var(--rp-white);
  min-height: var(--rp-header-h);
  display: flex;
  align-items: center;
}

.rp-header__inner {
  /* Positioning context for the mega panels: they align to the CONTENT column,
     so a panel's left edge sits under the logo and under every section heading
     down the page. Anchoring to the nav instead lines them up with nothing. */
  position: relative;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
  /* NO width:100% here. It beat .rp-container's min(1320px, 100%) and let the
     header run the full viewport, putting the nav and CTA ~50px right of the
     design. The container class alone governs the width. */
}

.rp-header__brand { display: inline-flex; align-items: center; flex: 0 0 auto; }
.rp-header__brand img { height: 30px; width: auto; }
.rp-header__brand .custom-logo { height: 30px; width: auto; }

@media (min-width: 60rem) {
  .rp-header__brand img,
  .rp-header__brand .custom-logo { height: 36px; }
}

/* ── Desktop nav and mega menus ──────────────────────────────────────────────
   Type measured off direction-3.html: Archivo at width 112, 15.5px, weight 400,
   in --rp-blue-paler on the translucent navy header.
   ─────────────────────────────────────────────────────────────────────────── */
.rp-nav { display: none; }

.rp-nav__list {
  list-style: none;
  display: flex;
  align-items: center;
  gap: 26px;
  margin: 0;
  padding: 0;
  white-space: nowrap;
}

/* static, so the panel resolves against .rp-header__inner. */
.rp-nav__item { margin: 0; position: static; display: flex; align-items: center; gap: 2px; }

.rp-nav__link {
  color: var(--rp-blue-paler);
  text-decoration: none;
  font-family: var(--rp-font-display);
  font-stretch: 112%;
  font-size: 15.5px;
  font-weight: 400;
  padding: 0.5rem 0;
  display: inline-flex;
  align-items: center;
  position: relative;
}

/* The underline is a pseudo-element that scales, so the link text never
   shifts on hover. A border-bottom toggle moves the baseline by a pixel and
   the whole nav jitters. */
.rp-nav__link::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 2px;
  background: var(--rp-accent-gradient);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.18s ease;
}

.rp-nav__item:hover > .rp-nav__link::after,
.rp-nav__link:focus-visible::after,
.rp-nav__item.is-open > .rp-nav__link::after,
.rp-nav .current-menu-item > a::after,
.rp-nav .current_page_item > a::after { transform: scaleX(1); }

.rp-nav .current-menu-item > a,
.rp-nav .current_page_item > a { font-weight: 700; }

/* The disclosure button. Small target next to the label rather than part of it,
   because the label's job is to navigate. */
.rp-nav__disclosure {
  background: none;
  border: 0;
  padding: 8px 2px 8px 4px;
  cursor: pointer;
  color: var(--rp-blue-paler);
  display: inline-flex;
  align-items: center;
  line-height: 0;
  position: relative;
}

/* WCAG 2.2 target size (2.5.8). The visible button is 13x23, under the 24x24
   minimum — Lighthouse desktop flagged it 2026-08-16. The mobile copy already
   passed on its bigger padding (see .rp-menu-panel .rp-nav__disclosure).

   The hit area is grown with a pseudo-element rather than with padding, so the
   nav does not re-space: four buttons gaining 11px each would widen the bar by
   44px and shift every item.

   It is anchored LEFT and grows RIGHT deliberately. Centring it would spread
   5.5px each way, and the thing immediately to the left is the nav link — so a
   centred target would swallow clicks on the last letter of "Industries" and
   open the panel instead of following the link. To the right is the gap before
   the next item, which is dead space and safe to claim. */
.rp-nav__disclosure::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 0;
  transform: translateY(-50%);
  width: 24px;
  height: 24px;
}

.rp-mega__chev {
  width: 7px; height: 7px;
  border-right: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  transform: translateY(-2px) rotate(45deg);
  transition: transform .18s ease;
  opacity: .75;
}

.rp-nav__item.is-open .rp-mega__chev,
html:not(.rp-nav-js) .rp-nav__item--has-panel:hover .rp-mega__chev {
  transform: translateY(1px) rotate(-135deg);
}

/* ── The panel ───────────────────────────────────────────────────────────────
   Absolutely positioned, so opening one never reflows the page, and pinned to
   the content column's left edge.
   ─────────────────────────────────────────────────────────────────────────── */
.rp-mega__panel {
  position: absolute;
  top: calc(100% + 12px);
  left: var(--rp-gutter);
  right: var(--rp-gutter);
  z-index: 61;
  max-width: 920px;
  background: var(--rp-sand);
  border: 1px solid rgb(18 33 46 / 0.1);
  border-top: 3px solid var(--rp-amber);
  border-radius: var(--rp-radius);
  box-shadow: 0 18px 48px rgb(6 14 26 / 0.28);

  opacity: 0;
  visibility: hidden;
  transform: translateY(-6px);
  transition: opacity .16s ease, transform .16s ease, visibility 0s linear .16s;
}

/* Two owners, never at once: without JS the stylesheet opens panels on hover
   and focus; nav.js adds .rp-nav--js and takes over. See assets/js/nav.js. */
html:not(.rp-nav-js) .rp-nav__item--has-panel:hover > .rp-mega__panel,
html:not(.rp-nav-js) .rp-nav__item--has-panel:focus-within > .rp-mega__panel,
.rp-nav__item.is-open > .rp-mega__panel {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
  transition-delay: 0s;
}

@media (prefers-reduced-motion: reduce) {
  .rp-mega__panel { transition: none; transform: none; }
}

/* A pointer travelling from the label to the panel crosses the 12px gap above;
   without something under it, :hover drops mid-journey. */
.rp-mega__panel::before {
  content: "";
  position: absolute;
  left: 0; right: 0; top: -15px;
  height: 15px;
}

.rp-mega__inner { padding: 30px 34px 32px; }

.rp-mega__lead {
  margin: 0 0 24px;
  font-family: var(--rp-font-body);
  font-size: 14.5px;
  line-height: 1.5;
  color: var(--rp-slate);
  white-space: normal;
  max-width: 62ch;
}

.rp-mega__links {
  list-style: none;
  /* The divider belongs to the row of links, not to the lead paragraph above
     it: the lead is width-limited for readability, so a border on it stopped
     two thirds of the way across the panel. */
  border-top: 1px solid rgb(18 33 46 / 0.09);
  padding: 24px 0 0;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 44px;

  margin: 0;
}

/* No negative inset: the hover box is exactly its grid column, so its left edge
   sits on the panel's content rail with the lead and the featured card, and the
   last column's right edge lands on the card's right edge.
   Flex, so the link stretches to the full height of the tallest item in the row
   — otherwise each box sizes to its own description and the three targets end
   up visibly different heights. */
.rp-mega__links li {
  display: flex;
  margin-inline: 0;
}

.rp-mega__links a {
  display: block;
  flex: 1;
  /* Padding matches the featured card's 22px horizontally, so the two boxed
     things in this panel inset their text identically. No negative margin: the
     box stays exactly its grid column, so its outer edges still line up with
     the card's. Getting here took two passes — first the box bled 14px past the
     card, then it had no padding at all and the text sat on the box edge. */
  padding: 16px 22px;
  border-radius: var(--rp-radius-sm);
  text-decoration: none;
  white-space: normal;
  transition: background .16s ease;
}

.rp-mega__links a:hover,
.rp-mega__links a:focus-visible { background: rgb(18 33 46 / 0.05); }

.rp-mega__label {
  display: block;
  font-family: var(--rp-font-display);
  font-stretch: 112%;
  font-size: 17px;
  line-height: 1.25;
  color: var(--rp-navy);
  margin-bottom: 7px;
}

.rp-mega__links a:hover .rp-mega__label { color: var(--rp-burnt); }

.rp-mega__desc {
  display: block;
  font-family: var(--rp-font-body);
  font-size: 13.5px;
  line-height: 1.5;
  color: var(--rp-slate);
}

.rp-mega__featured {
  display: block;
  margin-top: 24px;
  padding: 20px 22px;
  border-radius: var(--rp-radius-sm);
  background: var(--rp-sand-deep);
  border: 1px solid rgb(18 33 46 / 0.08);
  text-decoration: none;
  white-space: normal;
  transition: border-color .16s ease;
}

.rp-mega__featured:hover { border-color: rgb(161 66 12 / 0.35); }

.rp-mega__flabel {
  display: block;
  font-family: var(--rp-font-display);
  font-stretch: 112%;
  font-size: 16px;
  color: var(--rp-navy);
}

.rp-mega__fdesc {
  display: block;
  margin-top: 5px;
  font-size: 13.5px;
  line-height: 1.5;
  color: var(--rp-slate);
}

.rp-mega__fcta {
  display: inline-block;
  margin-top: 12px;
  font-family: var(--rp-font-mono);
  font-size: 11.5px;
  font-weight: 500;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--rp-burnt);
}

/* ── The same tree inside the mobile panel ───────────────────────────────────
   Same markup, stacked. The panel becomes flow content rather than an overlay,
   so a tapped menu pushes the ones below it down instead of covering them, and
   the label still navigates while the chevron still toggles.
   ─────────────────────────────────────────────────────────────────────────── */
.rp-menu-panel .rp-nav__list { display: block; white-space: normal; }

.rp-menu-panel .rp-nav__item {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
}

.rp-menu-panel .rp-nav__item + .rp-nav__item { border-top: 1px solid var(--rp-line-dark); }

.rp-menu-panel .rp-nav__link {
  flex: 1;
  color: var(--rp-white);
  font-size: 18px;
  padding: 14px 0;
}

.rp-menu-panel .rp-nav__link::after { display: none; }

/* Big enough to hit with a thumb without swallowing the link beside it. */
.rp-menu-panel .rp-nav__disclosure { padding: 14px 4px 14px 20px; color: var(--rp-white); }

.rp-menu-panel .rp-mega__panel {
  position: static;
  opacity: 1;
  visibility: visible;
  transform: none;
  transition: none;
  max-width: none;
  width: 100%;
  background: rgb(255 255 255 / 0.05);
  border: 0;
  border-left: 2px solid var(--rp-amber);
  border-radius: 0;
  box-shadow: none;
  margin-bottom: 10px;
  display: none;
}

.rp-menu-panel .rp-nav__item.is-open > .rp-mega__panel { display: block; }

/* No hover on touch, so without JS the chevron cannot do anything. Rather than
   hide the panels behind a dead button, stand them open — the mobile menu
   becomes a plain nested list, which is exactly the right no-JS fallback. */
html:not(.rp-nav-js) .rp-menu-panel .rp-mega__panel { display: block; }
html:not(.rp-nav-js) .rp-menu-panel .rp-nav__disclosure { display: none; }

.rp-menu-panel .rp-mega__panel::before { display: none; }
.rp-menu-panel .rp-mega__inner { padding: 16px 18px; }
.rp-menu-panel .rp-mega__lead { display: none; }
.rp-menu-panel .rp-mega__links { grid-template-columns: 1fr; gap: 4px; }
.rp-menu-panel .rp-mega__links a { margin: 0; padding: 11px 0; }
.rp-menu-panel .rp-mega__links a:hover { background: none; }
.rp-menu-panel .rp-mega__label { color: var(--rp-white); font-size: 15.5px; margin-bottom: 4px; }
.rp-menu-panel .rp-mega__desc { color: var(--rp-blue-pale); font-size: 13px; }
.rp-menu-panel .rp-mega__featured { display: none; }

/* The header CTA duplicates the one inside the mobile panel, so it is hidden
   below the desktop breakpoint rather than shown twice. */
.rp-header__cta { display: none; }

@media (min-width: 60rem) {
  .rp-nav { display: block; }
  .rp-menu-toggle { display: none; }
  .rp-header__cta { display: inline-flex; padding: 0.65rem 1.25rem; }
}

/* ── Mobile menu ─────────────────────────────────────────────────────────── */

/* margin-left:auto is what pushes the toggle to the right edge. It used to ride
   on .rp-header__cta, but that button is display:none below the desktop
   breakpoint, so a hidden element was carrying the only thing holding the
   toggle right — leaving it parked mid-header, one flex gap from the wordmark. */
.rp-menu-toggle { flex: 0 0 auto; margin-left: auto; }

.rp-menu-toggle > summary {
  list-style: none;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.6rem 0.85rem;
  border: 1px solid var(--rp-line-dark);
  border-radius: var(--rp-radius-sm);
  color: var(--rp-white);
  font-size: 0.875rem;
  font-weight: 600;
  /* 44px minimum touch target, the WCAG 2.2 target-size floor. */
  min-height: 44px;
}

.rp-menu-toggle > summary::-webkit-details-marker { display: none; }
.rp-menu-toggle > summary::marker { content: ""; }

.rp-menu-toggle__bars {
  display: block;
  width: 18px; height: 2px;
  background: currentColor;
  position: relative;
}

.rp-menu-toggle__bars::before,
.rp-menu-toggle__bars::after {
  content: "";
  position: absolute;
  left: 0;
  width: 18px; height: 2px;
  background: currentColor;
}

.rp-menu-toggle__bars::before { top: -6px; }
.rp-menu-toggle__bars::after  { top: 6px; }

.rp-menu-toggle[open] .rp-menu-toggle__bars { background: transparent; }
.rp-menu-toggle[open] .rp-menu-toggle__bars::before { top: 0; transform: rotate(45deg); }
.rp-menu-toggle[open] .rp-menu-toggle__bars::after  { top: 0; transform: rotate(-45deg); }

.rp-menu-panel {
  position: absolute;
  left: 0; right: 0;
  top: 100%;
  background: var(--rp-navy-deep);
  border-top: 1px solid var(--rp-line-dark);
  padding: 0.5rem var(--rp-gutter) 1.5rem;
  max-height: calc(100dvh - var(--rp-header-h));
  overflow-y: auto;
}

.rp-menu-panel ul { list-style: none; margin: 0; padding: 0; }

/* The separator belongs to the ROW, not to the link inside it. Putting it on
   the anchor meant the one top-level item without a panel (a plain <a>) got a
   rule and heavier weight while its <summary> siblings got neither, and every
   link inside an open panel got a rule it should not have. */
.rp-menu-panel .rp-nav__item + .rp-nav__item { border-top: 1px solid var(--rp-line-dark); }

.rp-menu-panel a { color: var(--rp-white); text-decoration: none; }

.rp-menu-panel .rp-btn { margin-top: 1.25rem; width: 100%; text-align: center; }

/* ══ Buttons ═════════════════════════════════════════════════════════════════
   min-height 44px throughout: WCAG 2.2 target size. */

/* Measured off the approved design: IBM Plex Mono 500 at 12px, uppercase,
   0.13em tracking, a full 999px pill, 17x28 padding, and an amber glow rather
   than a flat fill. The pill and the mono label are what make these read as
   this design's buttons; a rounded rectangle with sentence-case sans is a
   different product. */
.rp-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  min-height: 44px;
  padding: 17px 28px;
  border-radius: 999px;
  font-family: var(--rp-font-mono);
  font-size: 12px;
  font-weight: 500;
  line-height: 1;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  text-decoration: none;
  border: 1px solid transparent;
  cursor: pointer;
  transition: transform 0.12s ease, background-color 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease;
}

/* The trailing arrow is part of the design's button, drawn rather than typed
   so a screen reader does not announce it. */
.rp-btn::after { content: "\2192"; font-size: 15px; line-height: 1; }
.rp-btn--noarrow::after { content: none; }

.rp-btn:hover { transform: translateY(-1px); }
.rp-btn:active { transform: translateY(0); }

/* Navy on amber is 8.1:1. Amber as a background with dark text is the only
   accessible way to use this colour for an interactive element. */
.rp-btn--primary {
  background: var(--rp-amber);
  color: #11202f;
  box-shadow: 0 14px 34px rgb(248 170 20 / 0.28);
}
.rp-btn--primary:hover { background: #ffb92e; box-shadow: 0 16px 38px rgb(248 170 20 / 0.34); }

.rp-btn--ghost { border-color: rgb(255 255 255 / 0.34); color: var(--rp-white); background: transparent; }
.rp-btn--ghost:hover { border-color: var(--rp-amber); background: rgb(255 255 255 / 0.06); }

.rp-btn--dark { background: var(--rp-navy); color: var(--rp-white); }
.rp-btn--dark:hover { background: var(--rp-navy-deep); }

.rp-btn--outline { border-color: var(--rp-navy); color: var(--rp-navy); }
.rp-btn--outline:hover { background: var(--rp-navy); color: var(--rp-white); }

.rp-btn-row { display: flex; flex-wrap: wrap; gap: 0.85rem; margin-top: 1.75rem; }

/* Text link with a moving arrow. The arrow is a pseudo-element so it is not
   read out as text by a screen reader. */
/* The design's inline CTA is a mono, uppercase, tracked-out label with a
   trailing arrow and no underline, not a bold sans link with a border. */
.rp-link {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-family: var(--rp-font-mono);
  font-size: 11.5px;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  text-decoration: none;
  border-bottom: 0;
  padding-bottom: 0;
}

.rp-link::after { content: "\2192"; transition: transform 0.15s ease; }
.rp-link:hover::after { transform: translateX(3px); }

/* ══ Hero ════════════════════════════════════════════════════════════════════ */

.rp-hero {
  background: linear-gradient(90deg, var(--rp-navy-deep), var(--rp-navy));
  color: var(--rp-white);
  padding-block: clamp(3.5rem, 9vw, 7.5rem);
  position: relative;
  overflow: hidden;
}

/* A soft teal wash on the right, echoing the prototype without the halo
   effects the vote flagged as unwanted. Decorative only, so it is hidden from
   assistive tech by being a pseudo-element with no content. */
.rp-hero::after {
  content: "";
  position: absolute;
  inset: 0 -20% 0 40%;
  background: radial-gradient(ellipse at 70% 40%, rgb(46 140 153 / 0.28), transparent 62%);
  pointer-events: none;
}

.rp-hero > * { position: relative; z-index: 1; }

.rp-hero__lockup { margin-bottom: 1.75rem; }
.rp-hero__lockup img { height: clamp(44px, 7vw, 68px); width: auto; }

.rp-hero h1 { max-width: 18ch; margin-bottom: 1.25rem; }

.rp-hero__sub {
  font-size: var(--rp-text-lead);
  color: var(--rp-blue-pale);
  max-width: 54ch;
}

.rp-hero--compact { padding-block: clamp(2.75rem, 6vw, 5rem); }

/* Form-factor chips under the hero. */
.rp-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
  margin-top: 2.25rem;
  list-style: none;
  padding: 0;
}

.rp-chips li {
  margin: 0;
  font-family: var(--rp-font-mono);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--rp-white);
  border: 1px solid rgb(255 255 255 / 0.28);
  border-radius: 999px;
  padding: 9px 17px;
  line-height: 1;
}

/* ══ Cards ═══════════════════════════════════════════════════════════════════ */

.rp-card {
  display: flex;
  flex-direction: column;
  background: var(--rp-white);
  border: 1px solid var(--rp-line);
  border-radius: var(--rp-radius);
  padding: clamp(1.4rem, 2.4vw, 2rem);
  height: 100%;
}

.rp-card__num {
  font-family: var(--rp-font-data);
  font-size: 0.75rem;
  font-weight: var(--rp-numeral-weight);
  letter-spacing: 0.13em;
  color: var(--rp-burnt);
  margin-bottom: 0.75rem;
}

.rp-card h3 { margin-bottom: 0.5rem; }
.rp-card p { color: var(--rp-slate); font-size: 0.9375rem; }

/* Push the link to the bottom so cards of different copy lengths still line
   their calls to action up with each other. */
.rp-card .rp-link { margin-top: auto; padding-top: 1.25rem; align-self: flex-start; }

.rp-section--sand .rp-card { border-color: rgb(18 33 46 / 0.09); }

.rp-card--dark {
  background: rgb(255 255 255 / 0.04);
  border-color: var(--rp-line-dark);
}

.rp-card--dark p { color: var(--rp-blue-pale); }

/* Whole-card link. The anchor covers the card via ::after so the entire
   surface is clickable, while the accessible name stays the heading text and
   the link is still a single tab stop. */
.rp-card--linked { position: relative; transition: border-color 0.15s ease, transform 0.15s ease; }
.rp-card--linked:hover { border-color: var(--rp-burnt); transform: translateY(-2px); }
.rp-card--linked:focus-within { outline: var(--rp-focus); outline-offset: 3px; }
.rp-card--linked a::after { content: ""; position: absolute; inset: 0; }
.rp-card--linked a:focus-visible { outline: none; }

.rp-card__media { margin: -1px -1px 1.25rem; border-radius: var(--rp-radius) var(--rp-radius) 0 0; overflow: hidden; }
.rp-card__media img { width: 100%; aspect-ratio: 16 / 10; object-fit: cover; }

/* ══ Stat band ═══════════════════════════════════════════════════════════════
   the data face's one job. The 2px amber-to-burnt rule above each stat is the
   design's signature detail.

   Presentation rule from the brand voice guide: verified numbers support the
   story, they do not lead it. That is why the stat band is styled to sit
   beneath a narrative section rather than as a hero element. */

.rp-stats { display: grid; gap: var(--rp-gap); grid-template-columns: repeat(auto-fit, minmax(min(100%, 11rem), 1fr)); }

.rp-stat::before {
  content: "";
  display: block;
  width: 44px;
  height: 2px;
  background: var(--rp-accent-gradient);
  margin-bottom: 1.375rem;
}

.rp-stat__value {
  font-family: var(--rp-font-data);
  font-weight: var(--rp-numeral-weight);
  font-size: var(--rp-text-stat);
  line-height: 1;
  letter-spacing: -0.02em;
  display: block;
  margin-bottom: 0.6rem;
  /* Tabular figures so a row of numbers aligns on the decimal rather than
     drifting with each glyph's natural width. */
  font-variant-numeric: tabular-nums;
}

.rp-stat__label {
  font-size: 0.8125rem;
  line-height: 1.45;
  letter-spacing: 0.04em;
  color: var(--rp-slate);
}

.rp-section--navy .rp-stat__label,
.rp-section--deep .rp-stat__label { color: var(--rp-slate-light); }

/* ══ Spec list ═══════════════════════════════════════════════════════════════ */

/* A RULED LIST, not a gapped one. The designs separate spec rows with a
   hairline and mark each with an amber dot; this was a dash and a gap, which
   reads as prose bullets rather than as a specification. */
.rp-specs { list-style: none; padding: 0; margin: 26px 0 0; font-size: 15.5px; line-height: 1.55; color: var(--rp-slate); }

.rp-specs li {
  margin: 0;
  padding: 11px 0 11px 22px;
  position: relative;
  border-top: 1px solid rgb(18 33 46 / 0.1);
  color: var(--rp-slate);
}

.rp-specs li::before {
  content: "";
  position: absolute;
  left: 0; top: 19px;
  width: 7px; height: 7px;
  border-radius: 99px;
  /* Amber as a MARK, not as text — it is 2.0:1 on white. */
  background: var(--rp-amber);
}

.rp-section--navy .rp-specs li,
.rp-section--deep .rp-specs li,
.rp-section--deepflat .rp-specs li { color: var(--rp-blue-pale); border-top-color: rgb(255 255 255 / 0.12); }

/* Definition-style spec table for the hardware pages. */
.rp-spectable { width: 100%; border-collapse: collapse; margin-top: 1.5rem; font-size: 0.9375rem; }
.rp-spectable th, .rp-spectable td { text-align: left; padding: 0.85rem 1rem; border-bottom: 1px solid var(--rp-line); vertical-align: top; }
.rp-spectable th { width: 34%; font-weight: 700; color: var(--rp-navy); }
.rp-spectable td { color: var(--rp-slate); }

/* A table is the correct element for specification pairs, but it must scroll
   on a narrow screen rather than force the page to. */
.rp-tablewrap { overflow-x: auto; }

/* ══ CTA band ════════════════════════════════════════════════════════════════ */

.rp-cta-band { text-align: center; }
.rp-cta-band .rp-container { max-width: 44rem; }
.rp-cta-band .rp-btn-row { justify-content: center; }
.rp-cta-band h2 { margin-bottom: 0.75rem; }

/* ══ Breadcrumbs ═════════════════════════════════════════════════════════════ */

.rp-breadcrumbs { padding-block: 1rem; background: var(--rp-sand); font-size: 0.8125rem; }
.rp-breadcrumbs ol { list-style: none; display: flex; flex-wrap: wrap; gap: 0.5rem; margin: 0; padding: 0; }
.rp-breadcrumbs li { margin: 0; color: var(--rp-slate); }
.rp-breadcrumbs li + li::before { content: "\203A"; margin-right: 0.5rem; color: var(--rp-blue-mid); }
.rp-breadcrumbs a { color: var(--rp-slate); }
.rp-breadcrumbs [aria-current="page"] { color: var(--rp-navy); font-weight: 600; }

/* ══ Form ════════════════════════════════════════════════════════════════════ */

.rp-form { display: grid; gap: 1.15rem; }
.rp-form__row { display: grid; gap: 1.15rem; }

@media (min-width: 34rem) {
  .rp-form__row--2 { grid-template-columns: 1fr 1fr; }
}

.rp-field { display: grid; gap: 0.4rem; }

.rp-field label { font-size: 0.875rem; font-weight: 600; color: var(--rp-white); }

/* The required marker is decorative; the real signal is the `required`
   attribute, which assistive tech announces. aria-hidden stops it being read
   as the word "asterisk" mid-label. */
.rp-field .req { color: var(--rp-amber); }

.rp-field :is(input, select, textarea) {
  font-family: inherit;
  /* 16px minimum. Anything smaller makes iOS Safari zoom the viewport on
     focus, which reads as the page jumping when a user taps a field. */
  font-size: 1rem;
  color: var(--rp-white);
  background: rgb(255 255 255 / 0.06);
  border: 1px solid var(--rp-line-dark);
  border-radius: var(--rp-radius-sm);
  padding: 0.8rem 0.95rem;
  min-height: 46px;
  width: 100%;
}

.rp-field textarea { min-height: 7rem; resize: vertical; }

.rp-field :is(input, select, textarea)::placeholder { color: rgb(255 255 255 / 0.45); }

.rp-field :is(input, select, textarea):focus-visible {
  outline: var(--rp-focus);
  outline-offset: 1px;
  background: rgb(255 255 255 / 0.1);
}

.rp-field :is(input, select, textarea):user-invalid { border-color: #ff9c7a; }

.rp-field__hint { font-size: 0.8125rem; color: var(--rp-blue-pale); }

.rp-consent { display: flex; gap: 0.75rem; align-items: flex-start; font-size: 0.875rem; color: var(--rp-blue-pale); }
.rp-consent input { width: 20px; height: 20px; min-height: 0; flex: 0 0 auto; margin-top: 0.15rem; }

/* Honeypot. Hidden from people and from assistive tech, but still submitted,
   so a bot that fills every field gives itself away. Not `display: none`,
   which some bots detect and skip. */
.rp-hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

.rp-form__note { font-size: 0.8125rem; color: var(--rp-slate-light); }

/* ══ Footer ══════════════════════════════════════════════════════════════════
   One row, measured off direction-3.html: sand, a 4px amber top edge, logo,
   four links, copyright. The design deliberately does not repeat the sitemap
   here — the mega menus carry that depth now.
   ══════════════════════════════════════════════════════════════════════════ */

.rp-footer {
  background: var(--rp-sand);
  border-top: 4px solid var(--rp-amber);
}

.rp-footer__inner {
  max-width: var(--rp-container);
  margin: 0 auto;
  padding: 52px var(--rp-gutter);
  display: flex;
  align-items: center;
  gap: 32px;
  flex-wrap: wrap;
}

.rp-footer__brand { display: inline-flex; }
.rp-footer__brand img,
.rp-footer__brand .custom-logo { height: 24px; width: auto; display: block; }

.rp-footer__nav {
  display: flex;
  gap: 26px;
  flex-wrap: wrap;
  font-family: var(--rp-font-display);
  font-stretch: 112%;
  font-size: 15px;
}

.rp-footer__nav a {
  color: var(--rp-slate);
  text-decoration: none;
  transition: color .18s ease;
}

.rp-footer__nav a:hover,
.rp-footer__nav a:focus-visible { color: var(--rp-burnt); }

.rp-footer__legal {
  margin: 0 0 0 auto;
  font-family: var(--rp-font-mono);
  font-size: 11px;
  letter-spacing: 0.12em;
  /* The design's #6b7681 measures 4.28:1 on sand and misses AA for text this
     small. --rp-slate is the same hue family at 5.53:1. */
  color: var(--rp-slate);
}

@media (max-width: 48rem) {
  .rp-footer__legal { margin-left: 0; }
}

/* ══ International notice ════════════════════════════════════════════════════
   A bar pinned to the bottom, not an interstitial: it never covers the content,
   never traps focus, and does not have to be dismissed to read the page. See
   parts/geo-banner.php for why.
   ══════════════════════════════════════════════════════════════════════════ */

.rp-geo {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 70;
  background: rgb(11 22 38 / 0.94);
  backdrop-filter: saturate(160%) blur(16px);
  border-top: 3px solid var(--rp-amber);
  color: var(--rp-white);
  /* Starts off-screen and slides up once the script un-hides it, so there is
     no flash for the majority of visitors who never see it. */
  transform: translateY(100%);
  transition: transform .28s cubic-bezier(.22, .61, .36, 1);
}

.rp-geo.is-open { transform: translateY(0); }

@media (prefers-reduced-motion: reduce) {
  .rp-geo { transition: none; }
}

.rp-geo__inner {
  max-width: var(--rp-container);
  margin: 0 auto;
  padding: 20px var(--rp-gutter);
  display: grid;
  grid-template-columns: auto 1fr auto auto;
  align-items: center;
  gap: 8px 26px;
}

.rp-geo__eyebrow {
  margin: 0;
  font-family: var(--rp-font-mono);
  font-size: var(--rp-eyebrow-size);
  font-weight: 500;
  letter-spacing: var(--rp-eyebrow-tracking);
  text-transform: uppercase;
  color: var(--rp-amber-soft);
  writing-mode: vertical-rl;
  transform: rotate(180deg);
  align-self: stretch;
  display: grid;
  place-items: center;
  padding-inline-end: 4px;
  border-inline-end: 1px solid rgb(255 255 255 / 0.18);
}

.rp-geo__copy { min-width: 0; }

.rp-geo__title {
  margin: 0;
  font-family: var(--rp-font-display);
  font-stretch: 112%;
  font-size: 17px;
  line-height: 1.25;
  color: var(--rp-white);
}

.rp-geo__body {
  margin: 5px 0 0;
  font-size: 14px;
  line-height: 1.5;
  color: var(--rp-blue-pale);
  max-width: 78ch;
}

.rp-geo__cta {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  white-space: nowrap;
  background: var(--rp-amber);
  color: var(--rp-navy);
  font-family: var(--rp-font-mono);
  font-size: 11.5px;
  font-weight: 500;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  padding: 13px 22px;
  border-radius: 999px;
  text-decoration: none;
}

.rp-geo__cta:hover { background: #ffbe3d; }

.rp-geo__close {
  background: none;
  border: 1px solid rgb(255 255 255 / 0.22);
  border-radius: 999px;
  color: var(--rp-blue-pale);
  width: 34px;
  height: 34px;
  font-size: 20px;
  line-height: 1;
  cursor: pointer;
  display: grid;
  place-items: center;
}

.rp-geo__close:hover { color: var(--rp-white); border-color: rgb(255 255 255 / 0.5); }

@media (max-width: 60rem) {
  .rp-geo__inner { grid-template-columns: 1fr auto; gap: 12px 16px; }
  .rp-geo__eyebrow { display: none; }
  .rp-geo__copy { grid-column: 1 / -1; }
  .rp-geo__body { font-size: 13.5px; }
  .rp-geo__cta { justify-self: start; }
}

/* ══ Core block bridges ══════════════════════════════════════════════════════
   The pages are built from core blocks carrying this theme's classes, so a few
   rules are needed where core's defaults and the design meet. */

/* Core stacks columns at 781px on its own. Above that it distributes them
   evenly, which is what the card rows want. The gap comes from the theme so
   every row matches regardless of how the block was inserted. */
.wp-block-columns { gap: var(--rp-gap); margin-bottom: 0; }
.wp-block-columns:not(:first-child) { margin-top: var(--rp-gap); }
.wp-block-column { min-width: 0; }

/* Cards must fill their column so a row of three lines up at the bottom even
   when one has two more lines of copy than the others. */
.rp-cards .wp-block-column { display: flex; }
.rp-cards .wp-block-column > .rp-card { flex: 1 1 auto; }

/* Stats do not need card chrome, just even distribution. On a narrow screen
   core stacks them, which is correct: five stats side by side on a phone is
   unreadable at any font size. */
.rp-stats-cols { gap: clamp(1.75rem, 3vw, 2.5rem); }
.rp-stats-cols .rp-stat p { margin-bottom: 0; }
/* 05. The gradient stub above each figure — removed on the hardware pages so
   the row reads as figures, not as four ruled columns. */
.rp-stats-cols .rp-stat::before { display: none; }

/* Section heads inside a group need their bottom margin back, because the
   group wrapper resets it. */
.rp-section__head { margin-bottom: var(--rp-gap); }
.rp-section__head > *:last-child { margin-bottom: 0; }

/* Images inside a split column should not stretch to the column height. */
.rp-split__media--plain img { border-radius: var(--rp-radius); }
.wp-block-image { margin: 0 0 1.5rem; }
.wp-block-image.rp-hero__lockup { margin-bottom: 1.75rem; }

/* ══ FAQ ═════════════════════════════════════════════════════════════════════
   <details> and <summary>: keyboard operable and screen-reader announced with
   no JavaScript, and parsed happily by search engines. The matching FAQPage
   JSON-LD is emitted from inc/seo.php. */

.rp-faqs { display: grid; gap: 0.75rem; margin-top: var(--rp-gap); }

.rp-faq {
  background: var(--rp-white);
  border: 1px solid var(--rp-line);
  border-radius: var(--rp-radius);
  overflow: hidden;
}

.rp-faq > summary {
  cursor: pointer;
  list-style: none;
  padding: 1.1rem 3rem 1.1rem 1.25rem;
  font-weight: 700;
  font-size: 1.0625rem;
  position: relative;
  min-height: 44px;
  display: flex;
  align-items: center;
}

.rp-faq > summary::-webkit-details-marker { display: none; }
.rp-faq > summary::marker { content: ""; }

/* The chevron is drawn rather than typed, so it rotates cleanly and is never
   read out as a character by a screen reader. */
.rp-faq > summary::after {
  content: "";
  position: absolute;
  right: 1.25rem;
  top: 50%;
  width: 9px; height: 9px;
  border-right: 2px solid var(--rp-burnt);
  border-bottom: 2px solid var(--rp-burnt);
  transform: translateY(-70%) rotate(45deg);
  transition: transform 0.18s ease;
}

.rp-faq[open] > summary::after { transform: translateY(-30%) rotate(-135deg); }
.rp-faq > summary:hover { background: var(--rp-sand); }
.rp-faq__a { padding: 0 1.25rem 1.25rem; }
.rp-faq__a p { margin: 0; color: var(--rp-slate); max-width: var(--rp-container-text); }

/* ══ Form wrapper ════════════════════════════════════════════════════════════ */

.rp-form-wrap {
  background: rgb(255 255 255 / 0.04);
  border: 1px solid var(--rp-line-dark);
  border-radius: var(--rp-radius);
  padding: clamp(1.5rem, 3vw, 2.25rem);
}

.rp-form-wrap h2 { margin-bottom: 1.25rem; }

/* Marketo injects its own stylesheet and inline widths. These reset the parts
   that fight a responsive layout; the rest is left alone so the form still
   looks like a Marketo form to whoever maintains it there. */
.rp-form-wrap .mktoForm { width: 100% !important; font-family: var(--rp-font-sans) !important; }
.rp-form-wrap .mktoForm .mktoFormCol,
.rp-form-wrap .mktoForm .mktoFieldWrap,
.rp-form-wrap .mktoForm .mktoFormRow { width: 100% !important; float: none !important; }
.rp-form-wrap .mktoForm input[type="text"],
.rp-form-wrap .mktoForm input[type="email"],
.rp-form-wrap .mktoForm input[type="tel"],
.rp-form-wrap .mktoForm select,
.rp-form-wrap .mktoForm textarea { width: 100% !important; }

/* ══ Core button override ════════════════════════════════════════════════════
   Core's .wp-block-button__link carries its own background, padding and radius
   from theme.json's element styles. Those win over .rp-btn on specificity
   alone, which is why the ghost button rendered as a grey slab instead of an
   outline. Rather than chase it with !important everywhere, the button classes
   are re-declared at the compound specificity core actually uses. */

/* Core's .wp-block-button__link brings its own background, radius and padding
   from theme.json element styles, at a specificity .rp-btn cannot beat. This
   re-states the DESIGN's button at that same compound specificity. An earlier
   version of this rule hard-coded an 8px radius and weight 700 and silently
   overrode the pill, which is why the buttons rendered as rounded rectangles
   long after .rp-btn had been corrected. */
.wp-block-button__link.rp-btn {
  background-color: transparent;
  border-radius: 999px;
  padding: 17px 28px;
  font-family: var(--rp-font-mono);
  font-size: 12px;
  font-weight: 500;
  line-height: 1;
  letter-spacing: 0.13em;
  text-transform: uppercase;
}

.wp-block-button__link.rp-btn--primary { background-color: var(--rp-amber); color: var(--rp-navy); }
.wp-block-button__link.rp-btn--primary:hover { background-color: #ffb92e; color: var(--rp-navy); }

.wp-block-button__link.rp-btn--ghost {
  background-color: transparent;
  border: 1px solid var(--rp-line-dark);
  color: var(--rp-white);
}

.wp-block-button__link.rp-btn--ghost:hover {
  background-color: rgb(255 255 255 / 0.08);
  border-color: var(--rp-amber);
  color: var(--rp-white);
}

.wp-block-button__link.rp-btn--outline {
  background-color: transparent;
  border: 1px solid var(--rp-navy);
  color: var(--rp-navy);
}

.wp-block-button__link.rp-btn--outline:hover { background-color: var(--rp-navy); color: var(--rp-white); }

/* Core wraps each button in .wp-block-button; the row gap comes from
   .rp-btn-row, so the individual wrappers must not add their own margin. */
.rp-btn-row .wp-block-button { margin: 0; }

/* ══ Hero with media ═════════════════════════════════════════════════════════
   The single-column hero left half the viewport empty on desktop. This is the
   two-column variant: copy left, hardware render right. It collapses to one
   column below 62rem, where a side-by-side would squeeze both. */

.rp-hero__grid { display: grid; gap: clamp(2rem, 5vw, 4rem); align-items: center; }

@media (min-width: 62rem) {
  .rp-hero__grid { grid-template-columns: 1.05fr 0.95fr; }
}

.rp-hero__media { position: relative; }

.rp-hero__media img {
  width: 100%;
  height: auto;
  /* The renders are transparent PNGs of hardware, so a drop shadow rather than
     a card: a border would box a cut-out product and look pasted on. */
  filter: drop-shadow(0 24px 48px rgb(0 0 0 / 0.45));
}

/* A soft amber glow behind the product, echoing the accent without the halo
   treatment the design review pushed back on. */
.rp-hero__media::before {
  content: "";
  position: absolute;
  inset: 12% 8%;
  background: radial-gradient(ellipse at center, rgb(248 170 20 / 0.16), transparent 68%);
  filter: blur(28px);
  z-index: -1;
}

/* ══ Section head, wide variant ══════════════════════════════════════════════
   A 46ch head against a 1200px container leaves a lot of white space on the
   right. Where a section is prose-led, the head and body sit in two columns so
   the eye has somewhere to go. */

.rp-lede { display: grid; gap: clamp(1.5rem, 4vw, 3.5rem); align-items: start; }

@media (min-width: 56rem) {
  .rp-lede { grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr); }
  .rp-lede > .rp-section__head { margin-bottom: 0; position: sticky; top: calc(var(--rp-header-h) + 2rem); }
}

/* ══ Accent rule ═════════════════════════════════════════════════════════════
   The 2px amber-to-burnt rule, reusable above any section head. */
.rp-rule::before {
  content: "";
  display: block;
  width: 56px;
  height: 2px;
  background: var(--rp-accent-gradient);
  margin-bottom: 1.5rem;
}

/* ══ Fixes found by rendering at 390px ═══════════════════════════════════════
   Three bugs, one root cause and two cosmetic. Kept at the end of the file
   with their reasoning rather than edited into place, because each one is a
   trap that will otherwise be reintroduced. */

/* BUG 1, and it was the expensive one. `.rp-header__cta` set display:none for
   mobile, but `.rp-btn` sets display:inline-flex and is declared LATER at the
   same specificity, so the hide never applied. The CTA stayed in the header at
   full width next to a 250px logo, which made the header wider than a 390px
   viewport, which gave the whole document a horizontal scroll and clipped every
   line of text on the page. It read as a broken layout; it was a cascade order
   problem in one rule.

   Fixed with a compound selector so declaration order stops mattering. */
.rp-header .rp-header__cta { display: none; }

@media (min-width: 60rem) {
  .rp-header .rp-header__cta { display: inline-flex; }
}

/* Header CTA hover: inverts to white rather than taking the ghost hover.
   Ben, 2026-08-16.

   The compound selector is load-bearing and this file has the scar tissue to
   prove it. `.rp-btn--ghost:hover` is (0,2,0) and is declared ~700 lines
   EARLIER, so a plain `.rp-header__cta:hover` — also (0,2,0) — would lose on
   source order and the button would keep the amber-bordered ghost hover with
   no visible error anywhere. Two classes plus the pseudo makes it (0,3,0),
   which wins on specificity and stops depending on where it sits in the file.

   White on navy text is 15.9:1, so the hover state is the most legible thing
   in the header rather than the least. */
.rp-header .rp-header__cta:hover,
.rp-header .rp-header__cta:focus-visible {
  background: var(--rp-white);
  border-color: var(--rp-white);
  color: var(--rp-navy);
}

/* Belt and braces on the same class of failure: the logo cannot alone exceed
   the space available beside the menu button. */
.rp-header__brand img,
.rp-header__brand .custom-logo { max-width: min(58vw, 250px); object-fit: contain; object-position: left center; }

/* BUG 2. `.rp-section__head p` (two classes plus an element) outranks
   `.rp-eyebrow` (one class), so every eyebrow inside a section head rendered
   slate grey instead of burnt orange. */
.rp-section__head .rp-eyebrow { color: var(--rp-burnt); }
.rp-section--navy .rp-section__head .rp-eyebrow,
.rp-section--deep .rp-section__head .rp-eyebrow { color: var(--rp-amber-soft); }

/* BUG 3. The hero render is a tall portrait cut-out. At full width on a phone
   it filled more than a screen on its own and pushed the first real content
   two scrolls down. Capping the height keeps the hero to roughly one viewport. */
.rp-hero__media img { max-height: min(58vh, 420px); width: auto; margin-inline: auto; }

@media (min-width: 62rem) {
  .rp-hero__media img { max-height: none; width: 100%; }
}

/* The drop shadow is removed on the hero render: these are PSD exports that
   carry their own baked shadow, and a second CSS shadow on top of it reads as
   a grey smear on navy rather than as depth. */
.rp-hero__media img { filter: none; }

/* A soft panel behind the product instead, which gives the cut-out somewhere
   to sit and makes the baked shadow look deliberate. */
.rp-hero__media {
  background: radial-gradient(ellipse at 50% 60%, rgb(255 255 255 / 0.07), transparent 70%);
  border-radius: var(--rp-radius);
  padding: clamp(1rem, 3vw, 2rem);
}

.rp-hero__media::before { display: none; }

/* Chips wrap rather than overflow on a narrow screen. */
.rp-chips { max-width: 100%; }
.rp-chips li { white-space: nowrap; }

/* Last-resort guard. If any future section introduces an element wider than
   the viewport, this contains the damage to that element instead of letting it
   give the whole document a horizontal scrollbar. */
.rp-section { overflow-x: clip; }

/* Core puts the block's className on the .wp-block-button WRAPPER as well as
   letting us set it on the link. Neutralise the wrapper so a ghost button is
   not drawn twice, for any content authored before the builder was fixed. */
.wp-block-button.rp-btn {
  border: 0;
  padding: 0;
  background: none;
  min-height: 0;
}

/* The hardware renders are PSD exports with a soft shadow baked onto a white
   backdrop. Cut out and placed on navy, that shadow reads as a pale halo under
   the product. Fading the bottom of the image hides the halo without touching
   the product itself, which sits well clear of the fade. */
.rp-hero__media img {
  -webkit-mask-image: linear-gradient(to bottom, #000 82%, transparent 99%);
  mask-image: linear-gradient(to bottom, #000 82%, transparent 99%);
}

/* ══ Fixes found by the in-page accessibility audit ══════════════════════════ */

/* `.rp-section__head p` (class + class + element) outranks `.rp-eyebrow`
   (one class), so eyebrows inside a section head were rendering at the lead
   paragraph size, 20px, instead of the intended 12px. The colour override for
   the same clash is above; this is the size half of it. */
.rp-eyebrow,
.rp-section__head .rp-eyebrow {
  font-family: var(--rp-font-mono);
  font-size: var(--rp-eyebrow-size);
  font-weight: 500;
  letter-spacing: var(--rp-eyebrow-tracking);
  line-height: 1.4;
  text-transform: uppercase;
}

/* WCAG 2.2 target size is 24x24 CSS pixels. The consent checkbox was 20x20.
   The label beside it is a much bigger hit area, but the control itself has to
   meet the floor. */
.rp-consent input[type="checkbox"] { width: 24px; height: 24px; }

/* The required asterisk is decorative and already aria-hidden, but it should
   still be legible. Amber on the dark form panel measures well; this only
   guards the case where the form is placed on a light section. */
.rp-section:not(.rp-section--navy):not(.rp-section--deep) .rp-field .req { color: var(--rp-burnt); }

/* The hero is its own component, not a `.rp-section--navy`, so the dark-surface
   eyebrow colour never reached it and the eyebrow rendered burnt orange on
   navy at 2.85:1. Soft amber on navy is 10.13:1. */
.rp-hero .rp-eyebrow,
.rp-hero .rp-section__head .rp-eyebrow { color: var(--rp-amber-soft); }

/* Same reasoning for body copy and links that end up inside a hero. */
.rp-hero p:not(.rp-hero__sub):not(.rp-eyebrow) { color: var(--rp-blue-pale); }
.rp-hero a:not(.rp-btn) { color: var(--rp-amber-soft); }

/* `.rp-menu-panel a` (class + element) outranks `.rp-btn--primary` (one class),
   so the CTA inside the mobile menu rendered white-on-amber at 1.95:1 instead
   of navy-on-amber at 8.38:1. Only visible with the menu open, which is why it
   survived visual review and was caught by the audit harness. */
.rp-menu-panel a.rp-btn--primary { color: var(--rp-navy); }
.rp-menu-panel a.rp-btn--ghost { color: var(--rp-white); }

/* ══ Card rows as a grid, not core's flex columns ════════════════════════════
   Core's columns block distributes evenly above 782px and stacks to ONE column
   below it. For a four-card row that means four ~180px columns at tablet width,
   with headings breaking into four lines, and then a jump straight to full
   width. There is no 2x2 stage, which is the one that a four-card row needs.

   Overriding to an auto-fit grid gives 4 -> 2 -> 1 for free, at whatever widths
   the content actually needs, and behaves for any number of cards. The blocks
   stay core blocks; only the layout is ours. */
.wp-block-columns.rp-cards {
  display: grid;
  /* 14rem, not 15.5rem. The container is 1200px but its own gutter leaves
     1088px of content, and four 15.5rem columns plus three 2.5rem gaps needs
     1112px, so the fourth card wrapped to a lonely second row. Sized off the
     real content width, not the container width. */
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 14rem), 1fr));
  gap: var(--rp-gap);
  align-items: stretch;
}

.wp-block-columns.rp-cards > .wp-block-column {
  flex-basis: auto !important;
  display: flex;
}

/* Same treatment for the stat row, which has the same problem with five stats. */
.wp-block-columns.rp-stats-cols {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 10.5rem), 1fr));
  gap: clamp(1.75rem, 3vw, 2.5rem);
}

.wp-block-columns.rp-stats-cols > .wp-block-column { flex-basis: auto !important; }

/* Card headings sit in a narrow column, so they take a slightly tighter scale
   than a section heading at the same level. */
.rp-card h3 {
  font-size: clamp(1.0625rem, 0.4vw + 1rem, 1.25rem);
  text-wrap: balance;
}

/* The standalone paragraph under a section head should not run the full
   container width; it is prose, and prose gets a measure. */
.rp-section > .rp-container > .wp-block-paragraph { max-width: var(--rp-container-text); }


/* ══ Heading rule ════════════════════════════════════════════════════════════
   The short amber-to-burnt bar that sits under a section heading throughout
   the design. It is decorative, so it is a pseudo-element rather than markup. */
.rp-section__head > h2::after,
.rp-lede .rp-section__head > h2::after {
  content: "";
  display: block;
  width: 64px;
  height: 2px;
  background: var(--rp-accent-gradient);
  margin-top: 1.5rem;
}

/* ══ Grain ═══════════════════════════════════════════════════════════════════
   The design lays a fine grain over its dark sections. It is what stops a
   large flat navy area reading as a plain colour block. Decorative only, and
   pointer-events none so it never intercepts a click. */
.rp-section--navy::before,
.rp-section--deep::before,
.rp-hero::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image: url("../img/grain-dark.png");
  background-size: 220px;
  opacity: 0.4;
  mix-blend-mode: overlay;
  pointer-events: none;
  z-index: 0;
}

.rp-section--sand::before,
.rp-section--sand-deep::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image: url("../img/grain-light.png");
  background-size: 220px;
  opacity: 0.5;
  pointer-events: none;
  z-index: 0;
}

.rp-section > .rp-container { position: relative; z-index: 1; }

/* ══ Hero, rebuilt to the approved design ════════════════════════════════════
   The design's hero is a full-bleed muted video with a diagonal navy wash over
   it and the copy sitting on the left. It is NOT a two-column layout with a
   product render beside the text; that was an invention of an earlier build and
   it is the single biggest reason the page did not read as this design.

   Values below are measured off the prototype, including the video's colour
   grade and the exact four-stop overlay. */

.rp-hero {
  position: relative;
  background: var(--rp-navy-deep);
  overflow: hidden;
  padding-block: clamp(4rem, 11vw, 9rem);
  color: var(--rp-white);
}

.rp-hero__bg { position: absolute; inset: 0; overflow: hidden; z-index: 0; }

.rp-hero__bg video,
.rp-hero__bg img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 60% center;
  /* Desaturated and darkened so the type stays legible over moving footage.
     Without the grade, white text over raw machinery fails contrast wherever a
     bright surface passes behind it. */
  filter: saturate(0.55) contrast(1.05) brightness(0.78);
}

.rp-hero__wash {
  position: absolute;
  inset: 0;
  background: linear-gradient(122deg,
    rgb(11 22 38 / 0.94) 0%,
    rgb(13 29 50 / 0.78) 34%,
    rgb(16 40 66 / 0.50) 60%,
    rgb(20 52 78 / 0.60) 100%);
  z-index: 1;
}

.rp-hero > .rp-container { position: relative; z-index: 2; }

/* The hero H1 is capped in characters, not pixels, so it breaks in the same
   place the design does regardless of viewport. */
.rp-hero h1 { max-width: 17ch; margin-bottom: 1.5rem; }
.rp-hero__sub { font-size: var(--rp-text-lead); color: var(--rp-blue-pale); }

/* The form-factor row: a hairline rule, then a mono label beside the chips. */
.rp-formfactors {
  margin-top: clamp(2.5rem, 5vw, 4rem);
  padding-top: 1.75rem;
  border-top: 1px solid rgb(255 255 255 / 0.16);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1rem 1.5rem;
}

.rp-formfactors__label {
  font-family: var(--rp-font-mono);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--rp-blue-mid);
  margin: 0;
}

.rp-hero .rp-chips { margin-top: 0; }

/* The hero owns its own grain via the video grade, so the generic dark-section
   grain overlay is suppressed here to avoid doubling it. */
.rp-hero::before { display: none; }

/* Motion: a looping background video is decorative, and anyone who has asked
   the OS to reduce motion should get the still instead.

   This used to swap in a CSS background image, because the markup carried only
   a <video>. The still is a real <img> in the markup now, so there is nothing
   to swap — and hero-video.js refuses to attach the clip under reduced motion,
   so it is never downloaded either. display:none alone hid it and still paid
   for it. */
@media (prefers-reduced-motion: reduce) {
  .rp-hero__bg video { display: none; }
}

/* The clip is attached by hero-video.js, so before it plays the element is
   empty — and an empty video paints as a black rectangle over the still. Hold
   it transparent until the first frame is actually decoded. */
.rp-hero__bg video { opacity: 0; transition: opacity 0.6s ease; }
.rp-hero__bg video.is-playing { opacity: 1; }

/* ══ Path cards, image-led ═══════════════════════════════════════════════════
   The design's path cards lead with a photograph carrying a numbered overlay,
   copy beneath on a dark panel, and the whole card is one link. */

.rp-paths {
  display: grid;
  gap: clamp(1.25rem, 2vw, 1.75rem);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 17rem), 1fr));
  margin-top: var(--rp-gap);
}

.rp-path {
  display: flex;
  flex-direction: column;
  text-decoration: none;
  border: 1px solid rgb(255 255 255 / 0.12);
  border-radius: 18px;
  overflow: hidden;
  background: rgb(255 255 255 / 0.03);
  transition: border-color 0.18s ease, transform 0.18s ease;
}

.rp-path:hover { border-color: rgb(248 170 20 / 0.55); transform: translateY(-3px); }
.rp-path:focus-visible { outline: var(--rp-focus); outline-offset: 3px; }

.rp-path__media { position: relative; display: block; aspect-ratio: 4 / 3; overflow: hidden; }
.rp-path__media img { width: 100%; height: 100%; object-fit: cover; }

/* The gradient darkens the foot of the image so the panel below reads as a
   continuation of it rather than a separate block. Measured off the design. */
.rp-path__media::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(178deg,
    rgb(11 22 38 / 0.18) 0%,
    rgb(11 22 38 / 0.05) 40%,
    rgb(11 22 38 / 0.72) 100%);
}

.rp-path__num {
  position: absolute;
  top: 14px; left: 16px;
  z-index: 1;
  font-family: var(--rp-font-mono);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.2em;
  color: rgb(255 255 255 / 0.82);
}

.rp-path__body {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  padding: clamp(1.1rem, 2vw, 1.5rem);
  flex: 1;
}

.rp-path__title {
  font-family: var(--rp-font-display);
  font-stretch: 112%;
  font-weight: 400;
  font-size: var(--rp-text-h3);
  letter-spacing: var(--rp-track-h3);
  color: var(--rp-white);
}

.rp-path__copy { font-size: 15px; line-height: 1.55; color: var(--rp-blue-pale); }
.rp-path .rp-link { margin-top: auto; padding-top: 0.75rem; color: var(--rp-amber); }

/* Section-level: the paths section is navy in the design, and its heading rule
   sits directly under the h2. */
.rp-section--paths .rp-section__head { max-width: none; }

/* ══ Two-tone heading and accent word ════════════════════════════════════════
   The design turns the second sentence of a display heading grey, and picks
   out single words in the warm accent. Both are colour-only emphasis, so they
   carry no semantic weight and need no extra markup beyond a span. */
.rp-h-muted { color: var(--rp-blue-mid); }
.rp-section--navy .rp-h-muted,
.rp-section--deep .rp-h-muted { color: rgb(255 255 255 / 0.42); }

.rp-accent-text { color: var(--rp-burnt); }
.rp-section--navy .rp-accent-text,
.rp-section--deep .rp-accent-text { color: var(--rp-amber); }

.rp-statement {
  display: block;
  font-family: var(--rp-font-display);
  font-stretch: 112%;
  font-weight: 600;
  font-size: clamp(20px, 1.6vw, 26px);
  letter-spacing: -0.02em;
  color: var(--rp-navy);
  margin-top: 1.75rem;
}

/* ══ Media split and image card ══════════════════════════════════════════════ */
.rp-mediasplit { display: grid; gap: clamp(2rem, 4vw, 3.5rem); align-items: center; }

@media (min-width: 56rem) {
  .rp-mediasplit { grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr); }
}

.rp-mediacard {
  position: relative;
  margin: 0;
  border-radius: 20px;
  overflow: hidden;
  box-shadow: 0 30px 60px rgb(12 25 40 / 0.16);
}

.rp-mediacard img { width: 100%; height: 100%; object-fit: cover; aspect-ratio: 4 / 3; }

/* The caption sits over the foot of the image, so it needs its own scrim to
   stay legible whatever the photograph does behind it. */
.rp-mediacard__cap {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  padding: 2.5rem 1.5rem 1.25rem;
  background: linear-gradient(transparent, rgb(11 22 38 / 0.78));
  font-family: var(--rp-font-mono);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: rgb(255 255 255 / 0.9);
}

/* ══ Header, ported to the design's measured values ══════════════════════════
   sticky / top 0 / z 60 / 79px tall, over a TRANSLUCENT navy with a saturating
   blur, and a hairline bottom border. The translucency matters: the hero video
   runs up behind the bar, which is what makes the top of the page read as one
   piece instead of a solid band sitting on a video. */
.rp-header {
  position: sticky;
  top: 0;
  z-index: 60;
  min-height: 79px;
  background: rgb(11 22 38 / 0.82);
  -webkit-backdrop-filter: saturate(1.6) blur(16px);
  backdrop-filter: saturate(1.6) blur(16px);
  border-bottom: 1px solid rgb(255 255 255 / 0.1);
}

/* Top-level nav links only. This used to be `.rp-nav a`, which was fine when
   the nav was a flat list of links — but it also matched every link inside a
   mega panel, and at equal specificity but later in the file it beat
   `.rp-mega__links a` and flattened its padding to zero. Scoped to the class
   the top-level links actually carry. The type declarations that were here are
   already on .rp-nav__link, so only the hover colour remains. */
.rp-nav__link:hover,
.rp-nav .current-menu-item > a,
.rp-nav .current_page_item > a { color: var(--rp-white); font-weight: 400; }

/* The header CTA is a smaller pill than the in-page buttons. */
.rp-header .rp-header__cta {
  padding: 13px 22px;
  font-size: 11.5px;
  min-height: 0;
  letter-spacing: 0.13em;
}

@media (min-width: 60rem) {
  .rp-header .rp-header__cta { padding: 13px 22px; }
}

/* ══ Hero geometry ═══════════════════════════════════════════════════════════
   The design puts the vertical space on the INNER container (132px top, 0
   bottom), not on the section. Matching that is what makes the hero the same
   height as the reference. */
.rp-hero { padding-block: 0; }
.rp-hero > .rp-container { padding-top: 132px; padding-bottom: 0; }

/* Hero copy block spacing, measured. */
.rp-hero .rp-eyebrow { margin-bottom: 26px; }
.rp-hero h1 { margin-bottom: 22px; }
.rp-hero__sub { margin-bottom: 0; }
.rp-hero .rp-btn-row { margin-top: 30px; }

/* ══ Measured corrections, pass 2 ════════════════════════════════════════════ */

/* Button height is 50px in the design. line-height:1 gives 46; the design
   leaves line-height at normal, which at 12px mono is ~15.6px and lands on 50. */
.rp-btn,
.wp-block-button__link.rp-btn { line-height: normal; }

/* The design's button ink is #11202f, one step off --rp-navy. */
.rp-btn--primary,
.wp-block-button__link.rp-btn--primary { color: #11202f; }

/* The hero H1 is capped at 17ch, which is what makes it break after
   "Engineering the" rather than running to the container edge. */
.rp-hero h1,
.rp-hero .wp-block-heading { max-width: 17ch; }

/* ══ Header layout, ported exactly ═══════════════════════════════════════════
   The design does NOT use space-between. It is a plain flex row with a 36px
   gap and an auto left margin on the CTA. space-between distributes the free
   space between all three children, which pushed the nav ~86px right of the
   design's position. */
.rp-header__inner {
  justify-content: normal;
  gap: 36px;
}

.rp-header .rp-header__cta { margin-left: auto; }

/* Brand mark is 26px tall in the design, not 30. */
.rp-header__brand img,
.rp-header__brand .custom-logo { height: 26px; max-width: none; }

@media (min-width: 60rem) {
  .rp-header__brand img,
  .rp-header__brand .custom-logo { height: 26px; }
}

/* ══ Hero spacing, ported element by element ═════════════════════════════════
   Measured against the reference rendered from its own directory (so its
   fonts.css and images actually load). Every value below is the design's.

   The stray 24px margins were core's default block gap, which applies to every
   child of a wp-block-group and was silently adding 24px above the container,
   the H1 and the sub-paragraph. Zeroing it inside the hero and setting the
   design's own margins explicitly is what makes the hero the same height. */
.rp-hero > .rp-container { margin-top: 0; }
.rp-hero > .rp-container > * { margin-block: 0; }

.rp-hero .rp-eyebrow      { margin: 0 0 26px; }
.rp-hero h1               { margin: 0; }
.rp-hero .rp-hero__sub    { margin: 30px 0 0; }
.rp-hero .rp-btn-row      { margin: 40px 0 0; }

.rp-hero .rp-formfactors {
  margin-top: 76px;
  padding-top: 26px;
  padding-bottom: 58px;
}

/* The design leaves line-height at `normal` on the mono micro-labels. Setting
   it to 1 shaves ~4px off every chip and ~1px off every eyebrow, which is what
   left the hero 3px short and pushed everything below it up by a pixel. */
.rp-eyebrow,
.rp-section__head .rp-eyebrow,
.rp-hero .rp-eyebrow { line-height: normal; }

.rp-chips li { line-height: normal; }

/* THE GAP AT THE TOP OF THE HERO.
   Core's default block gap applies a 24px top margin to every child of a
   block group, including the absolutely-positioned wash div. That pushed the
   overlay to y=103 while the video started at y=79, leaving a 24px strip of
   ungraded footage directly under the header. The earlier margin reset only
   covered children of the inner container, not the section's own children. */
.rp-hero > * { margin-block: 0; }

.rp-hero__bg,
.rp-hero__wash { top: 0; right: 0; bottom: 0; left: 0; margin: 0; }

/* The design lets the H1 wrap naturally. `text-wrap: balance` re-balances the
   two lines and breaks after "Engineering the" instead of after "the future",
   which is a visibly different headline shape. */
.rp-hero h1 { text-wrap: wrap; }   /* `normal` is not a valid text-wrap value */

/* ══ Section background, measured ════════════════════════════════════════════
   The design's dark sections are a FLAT #0b1626 (navy-deep), not the lighter
   #12212e and not a gradient. Sampling the rendered pixels put every dark band
   at rgb(11,22,38) exactly. */
.rp-section--deepflat {
  background: var(--rp-navy-deep);
  color: var(--rp-white);
}

.rp-section--deepflat :is(h1,h2,h3,h4) { color: var(--rp-white); }
.rp-section--deepflat p { color: var(--rp-blue-pale); }
.rp-section--deepflat .rp-eyebrow,
.rp-section--deepflat .rp-section__head .rp-eyebrow { color: var(--rp-amber-soft); }
.rp-section--deepflat a:not(.rp-btn) { color: var(--rp-amber-soft); }
.rp-section--deepflat .rp-h-muted { color: rgb(255 255 255 / 0.42); }
.rp-section--deepflat .rp-accent-text { color: var(--rp-amber); }
.rp-section--deepflat .rp-stat__label { color: var(--rp-slate-light); }

.rp-section--deepflat::before {
  content: "";
  position: absolute; inset: 0;
  background-image: url("../img/grain-dark.png");
  background-size: 220px; opacity: .4; mix-blend-mode: overlay;
  pointer-events: none; z-index: 0;
}

/* The closing CTA is sand in the design, so its type reverts to dark. */
.rp-section--sand.rp-cta-band :is(h1,h2,h3) { color: var(--rp-navy); }
.rp-section--sand.rp-cta-band p { color: var(--rp-slate); }

/* ══ Section 1 (media split), ported ═════════════════════════════════════════
   Measured: two equal 582px columns with a 76px gap inside a 1240px content
   box, a SQUARE media card, and 118px of section padding. */

.rp-section { padding-block: 118px; }

/* NO grid-template-columns HERE. It used to sit unscoped in this block, which
   re-applied the two-column desktop grid at every width and overrode the
   mobile-first single column further up — on a 375px screen that produced a
   177px column of text beside an 82px thumbnail. The columns belong in the
   query below, which already declared them; this block only carries what is
   width-independent. */
.rp-mediasplit {
  gap: clamp(2rem, 6vw, 76px);
  align-items: center;
}

@media (min-width: 56rem) {
  .rp-mediasplit { grid-template-columns: 1fr 1fr; }
}

/* The design's image card is square, not 4:3. */
.rp-mediacard img { aspect-ratio: 1 / 1; }

/* The rule under a section heading is 76x3, not 64x2, and carries 28px above
   and 30px below. */
.rp-section__head > h2::after,
.rp-lede .rp-section__head > h2::after {
  width: 76px;
  height: 3px;
  margin-top: 28px;
  margin-bottom: 30px;
}

/* Measured paragraph rhythm in the design's prose column. */
.rp-mediasplit .rp-prose p { margin-bottom: 18px; }
.rp-mediasplit .rp-prose p + p { margin-bottom: 30px; }
.rp-mediasplit .rp-prose p:last-child { margin-bottom: 0; }

/* The eyebrow sits 20px above the heading here, not 26. */
.rp-mediasplit .rp-eyebrow { margin-bottom: 20px; }

/* The section head inside a media split must not cap its own width; the
   column already does that. */
.rp-mediasplit .rp-section__head { max-width: none; margin-bottom: 0; }

/* REGRESSION GUARD. `.rp-section { padding-block: 118px }` was added after the
   hero rules and overrode `.rp-hero { padding-block: 0 }`, adding 236px to the
   hero. The hero carries its spacing on the inner container, so its section
   padding must stay zero. Declared last so nothing later re-breaks it.

   This is the third time a later rule has silently beaten an earlier one in
   this file. If a component looks wrong, check declaration order first. */
.rp-section.rp-hero { padding-block: 0; }
.rp-section.rp-hero > .rp-container { padding-top: 132px; padding-bottom: 0; }

/* ══ Stat band, ported ═══════════════════════════════════════════════════════
   Featured figure with its label beside it, then a four-up row. Measured:
   84/90 padding, eyebrow 22px clear, 56px between the two rows, four 283px
   columns. */
.rp-section--statband { padding-block: 84px 90px; }

.rp-statband .rp-eyebrow { margin: 0 0 22px; }

/* BASELINE alignment, not centre. The label's baseline sits on the numeral's,
   which is what puts it low against the figure rather than floating beside its
   middle. The second column takes the remaining width rather than a fixed
   476px, and the gap is 14px row / 56px column. All measured off the original
   after rendering both and comparing them. */
/* The lead row shares the stat row's grid rather than defining its own, so the
   paragraph's left edge lands exactly on the third stat's rule. It used to be
   `535px + 56px gap`, which put the text 47px left of that rule — two different
   grids were never going to agree, and hardcoding 638px would only hold at one
   viewport. Same track definition, so they stay locked together at every width.
   The numeral spans the first two tracks; the paragraph spans the last two. */
.rp-statband__lead {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 14px 36px;
  align-items: baseline;
  margin-bottom: 56px;
}

.rp-statband__big { grid-column: 1 / 3; }
.rp-statband__leadlabel { grid-column: 3 / -1; }

.rp-statband__big {
  font-family: var(--rp-font-data);
  font-weight: var(--rp-numeral-weight);
  font-size: clamp(56px, 7vw, 100px);
  line-height: 1;
  letter-spacing: -0.03em;
  color: var(--rp-navy);
  font-variant-numeric: tabular-nums;
}

.rp-statband__leadlabel {
  margin: 0;
  font-size: 17.5px;
  line-height: 1.55;
  color: var(--rp-slate);
}

.rp-statband__row {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 36px;
}

.rp-statband__row .rp-stat::before { margin-bottom: 18px; }
.rp-statband__row .rp-stat__value { font-size: clamp(28px, 2.6vw, 38px); }

@media (max-width: 56rem) {
  .rp-statband__lead { grid-template-columns: 1fr; gap: 16px; }
  .rp-statband__row { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* Stat band block heights, measured off the design: the featured row is 139px
   with a 109px numeral, the four-up row is 128px. Set explicitly rather than
   left to the type metrics, because the design's rows are fixed-height bands
   and letting the font decide leaves them 61px short in total. */
.rp-statband__big { font-size: clamp(56px, 7.6vw, 109px); line-height: 1; }



/* ══ Leaf-level type and colour, measured per element ═════════════════════════
   Section heights matched before this while the type inside did not, because
   the square media card was driving the height. These are the design's own
   computed values, element by element. */

/* Two-tone heading: the muted half is #7a868f, not the pale blue. */
.rp-h-muted { color: var(--rp-heading-muted); }

/* The accent word is GRADIENT-CLIPPED text, not a solid colour: a three-stop
   amber -> burnt -> teal gradient painted through the glyphs. That is the
   multi-colour word treatment in the design. */
.rp-accent-text {
  background: linear-gradient(96deg, rgb(240 144 43), rgb(196 83 15) 46%, rgb(46 140 153)) text;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

/* The closing statement is 30px at desktop, not 23. */
.rp-statement {
  font-size: var(--rp-text-statement);
  line-height: 1.2;
  letter-spacing: -0.022em;
  font-weight: 600;
  color: var(--rp-navy);
  margin-top: 0;
}

/* Second paragraph in a prose column is a lighter grey and capped at 56ch. */
.rp-mediasplit .rp-prose p { max-width: 56ch; line-height: 1.62; }
.rp-mediasplit .rp-prose p + p { color: var(--rp-body-2); }

/* Hero sub is 21px in pale blue. */
.rp-hero__sub { font-size: var(--rp-text-lead); line-height: 1.55; color: var(--rp-blue-paler); }

/* Form-factor label is the mid blue with normal leading. */
.rp-formfactors__label { color: var(--rp-blue-mid); line-height: normal; }

/* Media caption: normal leading, 0.16em tracking, near-white blue. */
.rp-mediacard__cap { line-height: normal; letter-spacing: 0.16em; color: var(--rp-caption); }

/* Dark-surface eyebrow stays soft amber; light-surface now uses the design's
   burnt orange (see the AA note in tokens.css). */
.rp-section--navy .rp-eyebrow,
.rp-section--deep .rp-eyebrow,
.rp-section--deepflat .rp-eyebrow,
.rp-hero .rp-eyebrow { color: var(--rp-amber-soft); }

/* ══ AA-safe text colours, applied consistently ══════════════════════════════
   The design's warm accents fail WCAG AA as text on its own sand backgrounds.
   These use the darkened equivalents from tokens.css. The decorative uses of
   the original hues (the amber-to-burnt rule, the accent bars) are untouched,
   so the brand mark is unchanged. */

/* Light-surface eyebrow, links and card labels. */
.rp-eyebrow,
.rp-section__head .rp-eyebrow { color: var(--rp-burnt); }
.rp-card__num { color: var(--rp-burnt); }
a { color: var(--rp-burnt); }
.rp-faq > summary::after { border-color: var(--rp-burnt); }

/* Dark surfaces keep the soft amber, which is 10:1+ on navy. */
.rp-section--navy .rp-eyebrow,
.rp-section--deep .rp-eyebrow,
.rp-section--deepflat .rp-eyebrow,
.rp-hero .rp-eyebrow,
.rp-section--navy .rp-section__head .rp-eyebrow,
.rp-section--deepflat .rp-section__head .rp-eyebrow { color: var(--rp-amber-soft); }

/* The gradient-clipped accent word: same three-stop shape as the design, with
   AA-safe stops. Painted through the glyphs, so every stop has to pass. */
.rp-accent-text {
  background: linear-gradient(96deg,
    var(--rp-grad-warm),
    var(--rp-burnt) 46%,
    var(--rp-grad-teal)) text;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

/* On a dark surface the same word uses the bright stops, which pass there. */
.rp-section--navy .rp-accent-text,
.rp-section--deep .rp-accent-text,
.rp-section--deepflat .rp-accent-text,
.rp-hero .rp-accent-text {
  background: linear-gradient(96deg, #f0902b, #f8aa14 46%, var(--rp-teal-light)) text;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

/* ══ Hero light layers, ported verbatim ══════════════════════════════════════
   Two large blurred radial lights blended with `screen`, plus a bottom fade.
   These are what make the hero read as lit rather than as a flat navy panel.

   The amber one sits bottom-left, directly under the primary CTA. The warm
   halo around that button is THIS layer. An earlier diagnosis blamed the
   button's box-shadow, which measured identical the whole time; the backdrop
   behind it was the difference, at (20,31,46) against the design's (70,69,71).

   mix-blend-mode: screen is load-bearing. Without it these paint as flat
   translucent ovals instead of light. */

.rp-hero__glow {
  position: absolute;
  border-radius: 50%;
  pointer-events: none;
  mix-blend-mode: screen;
  z-index: 1;
}

.rp-hero__glow--teal {
  top: -24%;
  right: -10%;
  width: 70%;
  height: 120%;
  background: radial-gradient(closest-side, rgb(53 183 196 / 0.30), rgb(11 22 38 / 0) 74%);
  filter: blur(70px);
}

.rp-hero__glow--amber {
  bottom: -30%;
  left: -12%;
  width: 62%;
  height: 96%;
  background: radial-gradient(closest-side, rgb(240 144 43 / 0.34), rgb(11 22 38 / 0) 74%);
  filter: blur(74px);
}

/* Bottom fade to solid navy, so the hero meets the next section cleanly. */
.rp-hero__fade {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 22%;
  background: linear-gradient(rgb(11 22 38 / 0), rgb(11 22 38) 96%);
  pointer-events: none;
  z-index: 1;
}

/* The decorative teal wash I had invented is replaced by the design's own two
   lights; remove it so they are not doubled. */
.rp-hero::after { display: none; }

/* ══ Photo section (design section 6), ported ════════════════════════════════
   Full-bleed image, a five-stop 94deg wash, a blurred teal light, then a copy
   column and a four-up fact row. All values measured off the design. */

.rp-photosection {
  position: relative;
  background: var(--rp-navy-deep);
  color: var(--rp-white);
  overflow: hidden;
  padding-block: 0;
}

.rp-photosection > .rp-container { padding-block: 120px; position: relative; z-index: 2; }

.rp-photo__bg { position: absolute; inset: 0; z-index: 0; }

.rp-photo__bg img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 68% 44%;
  filter: saturate(0.5) contrast(1.04) brightness(0.8);
}

.rp-photo__wash {
  position: absolute;
  inset: 0;
  z-index: 1;
  background: linear-gradient(94deg,
    rgb(11 22 38) 0%,
    rgb(11 22 38 / 0.96) 36%,
    rgb(11 22 38 / 0.86) 60%,
    rgb(11 22 38 / 0.74) 86%,
    rgb(11 22 38 / 0.80) 100%);
}

.rp-photo__glow {
  position: absolute;
  top: -26%; right: -8%;
  width: 62%; height: 106%;
  border-radius: 50%;
  background: radial-gradient(closest-side, rgb(53 183 196 / 0.34), rgb(11 22 38 / 0) 76%);
  filter: blur(64px);
  mix-blend-mode: screen;
  pointer-events: none;
  z-index: 1;
}

/* The generic dark-section grain would double up over the photograph. */
.rp-photosection::before { display: none; }

.rp-photo__copy { max-width: 640px; }
.rp-photo__copy .rp-eyebrow { margin: 0 0 20px; color: var(--rp-amber-soft); }
.rp-photo__copy h2 { margin: 0; color: var(--rp-white); }

.rp-photo__rule {
  width: 76px; height: 3px;
  background: var(--rp-accent-gradient);
  margin: 26px 0 28px;
}

.rp-photo__body { max-width: 542px; margin: 0; color: var(--rp-blue-pale); }
.rp-photo__copy .rp-link { color: var(--rp-amber); margin-top: 20px; display: inline-flex; }

/* Four-up fact row: 56px clear of the copy, 30px of its own top padding. */
.rp-facts {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 36px;
  margin-top: 56px;
  padding-top: 30px;
  border-top: 1px solid rgb(255 255 255 / 0.14);
}

.rp-fact { display: flex; flex-direction: column; gap: 8px; }

.rp-fact__value {
  font-family: var(--rp-font-data);
  font-weight: var(--rp-numeral-weight);
  font-size: 30px;
  line-height: 1;
  letter-spacing: -0.02em;
  color: var(--rp-white);
  font-variant-numeric: tabular-nums;
}

.rp-fact__label {
  font-family: var(--rp-font-mono);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  line-height: 1.5;
  color: var(--rp-blue-mid);
}

@media (max-width: 56rem) {
  .rp-facts { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* Core's block gap again: it put a 24px top margin on the photo section's
   absolutely-positioned wash and glow layers and on the content container,
   adding ~79px to the section. Fourth time this has bitten; the pattern is
   always an absolutely-positioned child of a wp-block-group. */
.rp-photosection > * { margin-block: 0; }
.rp-photo__wash, .rp-photo__glow, .rp-photo__bg { margin: 0; }

/* ══ Section 6 leaf type, measured ═══════════════════════════════════════════
   This section's h2 is 52px (its own clamp), the body is 18.5px and two-tone,
   and the fact labels are the body face at 13.5px, NOT the mono used elsewhere.
   That last one was the main "fonts look off" difference. */

.rp-photosection h2 {
  font-size: clamp(30px, 3.7vw, 52px);
  line-height: 1.04;
  letter-spacing: -0.03em;
}

.rp-photo__body { font-size: 18.5px; line-height: 1.56; color: var(--rp-blue-pale); }
.rp-photo__lead { color: var(--rp-white); font-weight: 400; }
.rp-photo__rest { color: var(--rp-blue-pale); }

.rp-fact__value { font-weight: var(--rp-numeral-weight); letter-spacing: -0.03em; }

/* The body face, not mono, and pale blue. */
.rp-fact__label {
  font-family: var(--rp-font-body);
  font-size: 13.5px;
  font-weight: 400;
  letter-spacing: normal;
  text-transform: none;
  line-height: 1.45;
  color: var(--rp-blue-pale);
}

/* The fourth cell is a caption: mono, 10.5px, near-white. */
.rp-fact--note { justify-content: flex-end; }
.rp-fact__note {
  font-family: var(--rp-font-mono);
  font-size: 10.5px;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  line-height: 1.6;
  color: var(--rp-caption);
}

.rp-photosection .rp-link { font-size: 11px; letter-spacing: 0.14em; color: var(--rp-amber); }

/* Hero sub measure, per Ben: 52ch at desktop. */
/* THE hero measure, and the only place it is set.
   Two values on purpose, the same split as the hero's type scale and spacing:

     homepage  57ch — the site's prose measure, --rp-container-text. The
                headline is short, so the lede carries more of the message and
                earns the extra width.
     interior  52ch — what the interior designs spec for `.lede`. The headline
                is already doing the explaining; a wider lede competes with it.

   Three conflicting max-widths used to be scattered through this file (46ch,
   62ch, 52ch) with the last quietly winning. */
.rp-hero__sub { max-width: 52ch; }
.rp-section.rp-hero:has(.rp-formfactors) .rp-hero__sub { max-width: var(--rp-container-text); }

@supports not selector(:has(*)) {
  .rp-hero__sub { max-width: var(--rp-container-text); }
}
.rp-fact--note { gap: 12px; }
.rp-fact--note .rp-link { align-self: flex-start; }

/* Section 6's rule runs amber to TEAL, not amber to burnt. The design varies
   its accent gradient by section rather than using one house rule, so this is
   set per component instead of inherited. */
.rp-photo__rule { background: var(--rp-rule-teal); }

/* ══ Section 2 (path cards), leaf-level ══════════════════════════════════════ */

/* The design grades the card photography to greyscale so the amber accents are
   the only colour in the row. */
.rp-path__media img { filter: grayscale(1) contrast(1.08) brightness(0.94); }

/* Card number is amber, 11.5px, 0.16em, not white at 82%. */
.rp-path__num {
  font-size: 11.5px;
  letter-spacing: 0.16em;
  color: var(--rp-amber-soft);
}

.rp-path__title { line-height: 1.15; }

.rp-path__copy {
  font-size: 16px;
  line-height: 1.55;
  color: #a9becf;
}

.rp-path .rp-link { font-size: 11px; letter-spacing: 0.14em; }

/* ══ Section 5 (stat band), leaf-level ═══════════════════════════════════════ */

.rp-statband__big {
  font-size: clamp(58px, 8.4vw, 122px);
  /* 25. Was line-height 0.9. The figure is gradient-CLIPPED text and a gradient
     fill paints only inside the line box, so at 0.9 the box stopped above the
     comma's tail in "550,000+" and cropped it. Padding gives the paint area
     room; the negative margin cancels it so the layout does not move. Both
     scale with the type, so the clearance holds at every screen size. */
  line-height: 0.94;
  padding-bottom: 0.12em;
  margin-bottom: -0.12em;
  letter-spacing: -0.042em;
  font-weight: var(--rp-numeral-weight);
  /* Gradient-clipped, like the accent word. Solid navy was wrong. */
  background: var(--rp-stat-gradient) text;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.rp-statband__leadlabel { font-size: 21px; line-height: 1.45; color: var(--rp-slate); }

.rp-statband__row .rp-stat__value {
  font-size: 46px;
  font-weight: var(--rp-numeral-weight);
  line-height: 1;
  letter-spacing: -0.035em;
}

.rp-statband__row .rp-stat__label {
  font-size: 14.5px;
  line-height: 1.5;
  letter-spacing: normal;
  text-transform: none;
  font-family: var(--rp-font-body);
  color: var(--rp-body-2);
}



/* ══ Stat band, corrected against the rendered original ══════════════════════
   Looking at the two side by side showed three things measurement missed:
   the accent rule above each stat was absent entirely (I had disabled it), the
   labels were pinned to the bottom of the cell instead of sitting 14px under
   the numeral, and the section's decorative light was missing.

   Values below are the design's own. */

/* A 2px bar the full width of its column, 22px above the numeral. NOT the
   44px stub used elsewhere. */
.rp-statband__row .rp-stat {
  display: block;
  min-height: 0;
}

.rp-statband__row .rp-stat::before {
  content: "";
  display: block;
  width: 100%;
  height: 2px;
  background: linear-gradient(90deg, rgb(248, 170, 20), rgb(196, 83, 15));
  margin: 0 0 22px;
}

.rp-statband__row .rp-stat__value {
  display: block;
  font-size: clamp(34px, 3.4vw, 46px);
  line-height: 1;
  letter-spacing: -0.035em;
  font-weight: var(--rp-numeral-weight);
  color: var(--rp-navy);
  margin: 0;
}

.rp-statband__row .rp-stat__label {
  margin: 14px 0 0;
  max-width: 24ch;
  text-wrap: pretty;
}

.rp-statband__row { min-height: 0; gap: 36px; }

/* The decorative light behind the band: a wide, very soft teal wash. Subtle,
   but its absence is why the reference reads as having depth here and the
   build read as flat. */
.rp-section--statband { position: relative; overflow: hidden; }

.rp-section--statband::after {
  content: "";
  position: absolute;
  top: -40%;
  left: 26%;
  width: 60%;
  height: 180%;
  border-radius: 50%;
  background: radial-gradient(closest-side, rgb(46 140 153 / 0.14), rgb(244 242 237 / 0) 74%);
  filter: blur(70px);
  pointer-events: none;
  z-index: 0;
}

.rp-section--statband > .rp-container { position: relative; z-index: 1; }

/* The lead label is capped at 476px inside its column. Without the cap it
   spans the full 649px, wraps differently, and its last line no longer drops
   below the numeral's baseline, which is exactly the 30px the section was
   short. Baseline alignment means the label's depth sets the row height. */
.rp-statband__leadlabel { max-width: 476px; }

/* The heading rule's margins vary by section in the design, they are not one
   house value: section 1 is 28/30, section 2 is 26/52. Scoped per section
   rather than left to a single default. */
.rp-section--paths .rp-section__head > h2::after { margin-top: 26px; margin-bottom: 52px; }

/* ══ Formulary carousel (design section 3), ported ═══════════════════════════
   CSS scroll-snap, no JavaScript. Arrows and dots are anchor links to slide
   ids, so swipe, keyboard and screen readers all work without script, and it
   degrades to a scrollable row if anything fails. */

/* The head is TWO columns in the design: heading left, intro right, bottom
   aligned. Not stacked. */
.rp-formulary__head {
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr);
  gap: 56px;
  align-items: end;
  margin-bottom: 52px;
}

.rp-formulary__head .rp-eyebrow { margin: 0 0 20px; }
.rp-formulary__head h2 { margin: 0; }

.rp-formulary__rule {
  width: 76px; height: 3px;
  background: linear-gradient(90deg, rgb(248, 170, 20), rgb(196, 83, 15));
  margin: 26px 0 0;
}

.rp-formulary__intro { margin: 0; color: var(--rp-slate); font-size: 17.5px; line-height: 1.62; }

@media (max-width: 56rem) {
  .rp-formulary__head { grid-template-columns: 1fr; gap: 24px; }
}

/* ── The carousel ──────────────────────────────────────────────────────────── */
.rp-carousel { position: relative; }

.rp-carousel__track {
  display: flex;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  border-radius: 22px;
  /* Hide the scrollbar without disabling scrolling. */
  scrollbar-width: none;
}

.rp-carousel__track::-webkit-scrollbar { display: none; }
.rp-carousel__track:focus-visible { outline: var(--rp-focus); outline-offset: 4px; }

.rp-slide {
  flex: 0 0 100%;
  scroll-snap-align: start;
  display: grid;
  grid-template-columns: minmax(0, 1.02fr) minmax(0, 1fr);
  align-items: center;
  min-height: 570px;
  /* The warm panel: cool blue bottom-left sweeping to warm amber top-right. */
  background: linear-gradient(342deg,
    rgb(201, 220, 236) 0%,
    rgb(228, 233, 238) 38%,
    rgb(246, 232, 210) 74%,
    rgb(251, 220, 174) 100%);
  border-radius: 22px;
  overflow: hidden;
}

.rp-slide__copy { padding: 0 0 0 96px; max-width: 560px; }

.rp-slide__eyebrow {
  font-family: var(--rp-font-mono);
  font-size: 11.5px;
  font-weight: 500;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  /* Riley, 2026-08-10. Was rgb(138,106,69) at 3.53:1 on the slide gradient. */
  color: #6A4415;
  margin: 0 0 18px;
}

.rp-slide h3 {
  font-size: clamp(30px, 3.2vw, 44px);
  line-height: 1.08;
  letter-spacing: -0.03em;
  font-weight: 400;
  color: var(--rp-navy);
  margin: 0;
}

.rp-slide__rule {
  width: 64px; height: 3px;
  background: linear-gradient(90deg, rgb(248, 170, 20), rgb(196, 83, 15));
  margin: 22px 0 20px;
}

/* Riley, 2026-08-10. --rp-slate is 5.9:1 on WHITE and body-safe there, but the
   slide sits on the warm gradient, where it measured 4.40:1. Set explicitly. */
.rp-slide__body { margin: 0 0 26px; color: #3C4854; font-size: 17px; line-height: 1.6; max-width: 42ch; }

/* Glassy white pill, matching the design's button. */
.rp-slide__cta {
  display: inline-flex;
  align-items: center;
  gap: 11px;
  border-radius: 999px;
  padding: 15px 25px;
  font-family: var(--rp-font-mono);
  font-size: 11.5px;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--rp-navy);
  background: linear-gradient(155deg, rgb(255 255 255 / 0.86), rgb(255 255 255 / 0.52));
  border: 1px solid rgb(255 255 255 / 0.9);
  -webkit-backdrop-filter: blur(14px) saturate(1.2);
  backdrop-filter: blur(14px) saturate(1.2);
  box-shadow: 0 10px 26px -14px rgb(18 33 46 / 0.42);
  transition: background 0.2s, box-shadow 0.2s;
}

.rp-slide__cta::after { content: "\2192"; }
.rp-slide__cta:hover { background: rgb(255 255 255 / 0.95); box-shadow: 0 14px 30px -14px rgb(18 33 46 / 0.5); }

/* 14. REMOVED 2026-08-16. The top-bar button used to take the frosted white
   treatment from the product cards — a white gradient, a backdrop blur and
   navy text. Ben's call was that it reads as a filled button and so competes
   with the page's own CTA, which is the thing it was introduced to avoid.

   It is deleted rather than overridden on purpose. The rule was
   `.rp-btn.rp-header__cta`, (0,2,0), which outranks `.rp-btn--ghost` at
   (0,1,0) — so leaving it in place and layering a third rule on top would
   have meant every future change to this button needing to outrank two
   competing defaults. The header CTA now simply IS a ghost button
   (see header.php), with one hover override earlier in this file.

   Point 14's original intent survives: the orange still belongs to the page's
   own calls to action, and .rp-btn--primary's amber glow is untouched. */

.rp-slide__media { align-self: stretch; }
.rp-slide__media img { width: 100%; height: 100%; object-fit: cover; object-position: center; }

/* ── Controls ──────────────────────────────────────────────────────────────── */
.rp-carousel__btn {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  z-index: 4;
  width: 48px; height: 48px;
  border-radius: 999px;
  border: 1px solid rgb(255 255 255 / 0.9);
  background: linear-gradient(155deg, rgb(255 255 255 / 0.9), rgb(255 255 255 / 0.6));
  -webkit-backdrop-filter: blur(12px);
  backdrop-filter: blur(12px);
  color: var(--rp-navy);
  font-size: 16px;
  text-decoration: none;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 10px 24px -14px rgb(18 33 46 / 0.5);
  transition: background 0.2s, color 0.2s;
}

.rp-carousel__btn--prev { left: 24px; }
.rp-carousel__btn--next { right: 24px; }
.rp-carousel__btn:hover { background: #fff; }

/* ── Dots ──────────────────────────────────────────────────────────────────── */
.rp-carousel__dots {
  display: flex;
  gap: 8px;
  justify-content: center;
  margin-top: 22px;
}



@media (max-width: 56rem) {
  .rp-slide { grid-template-columns: 1fr; min-height: 0; }
  .rp-slide__copy { padding: 40px 28px; }
  .rp-slide__media { height: 280px; }
  .rp-carousel__btn { display: none; }
}

/* Carousel corrections, from comparing the two renders:
   - the slide h3 wraps to two lines in the design; mine ran to one because it
     had no measure of its own
   - the panel is 557px tall, not the 570 min-height I guessed
   - the product image is framed wider in the design, so it needs a pulled-back
     object-position rather than a centre crop */
.rp-slide h3 { max-width: 11ch; }
.rp-slide { min-height: 557px; }
.rp-slide__media img { object-position: 30% center; }

/* ══ Slide media: masked, not butted ═════════════════════════════════════════
   The design does NOT put the photograph in a grid cell beside the copy. It
   positions it absolutely inside the panel and fades its left edge out with a
   mask, so the image dissolves into the gradient instead of meeting it at a
   hard vertical seam. That seam was the whole difference. */

.rp-slide { position: relative; display: block; }

.rp-slide__copy {
  position: relative;
  z-index: 2;
  padding: 0 0 0 96px;
  max-width: 560px;
  /* The copy is vertically centred in the panel. */
  display: flex;
  flex-direction: column;
  justify-content: center;
  min-height: 557px;
}

.rp-slide__media { position: absolute; inset: 0; z-index: 1; pointer-events: none; }

.rp-slide__media img {
  position: absolute;
  display: block;
  object-fit: cover;
  /* The soft left-edge fade. Four stops, so the dissolve is gradual rather
     than a straight ramp. */
  -webkit-mask-image: linear-gradient(90deg, transparent 0%, rgb(0 0 0 / 0.35) 16%, rgb(0 0 0 / 0.85) 30%, rgb(0 0 0) 44%);
  mask-image: linear-gradient(90deg, transparent 0%, rgb(0 0 0 / 0.35) 16%, rgb(0 0 0 / 0.85) 30%, rgb(0 0 0) 44%);
  /* Per-slide top/left/width/height come from the slide data. */
}

/* The panel needs a soft shadow, as in the design. */
.rp-slide { box-shadow: 0 26px 50px -22px rgb(18 33 46 / 0.42); }

@media (max-width: 56rem) {
  .rp-slide__copy { min-height: 0; padding: 40px 28px; }
  .rp-slide__media { position: relative; height: 280px; }
  .rp-slide__media img { position: absolute; inset: 0; width: 100% !important; height: 100% !important; left: 0 !important; top: 0 !important;
    -webkit-mask-image: none; mask-image: none; }
}

/* ══ Carousel fixes ══════════════════════════════════════════════════════════ */

/* THE BUTTON WIDTH. `.rp-slide__copy` is a flex column, which stretches its
   children to full width, so the pill ran the whole 560px column instead of
   hugging its label. The design's own rule is `align-self: flex-start` with a
   6px top margin, which I extracted early and then lost when the copy column
   was rewritten. */
.rp-slide__cta {
  align-self: flex-start;
  margin-top: 6px;
  width: auto;
}

/* Arrows now sit inside each slide, so they position against the slide rather
   than the track. */
.rp-slide > .rp-carousel__btn { position: absolute; top: 50%; transform: translateY(-50%); z-index: 3; }
.rp-slide > .rp-carousel__btn--prev { left: 24px; }
.rp-slide > .rp-carousel__btn--next { right: 24px; }

/* The dots are real links, so they need a visible focus ring and a target big
   enough to hit. The bar itself stays 4px; the hit area is padded out. */
.rp-carousel__dot {
  position: relative;
  padding: 12px 0;
  height: auto;
  background: none;
}

.rp-carousel__dot::before {
  content: "";
  display: block;
  width: 52px;
  height: 4px;
  border-radius: 2px 2px 0 0;
  background: var(--rp-sand-deep);
}



/* ══ Carousel dots ═══════════════════════════════════════════════════════════
   Two bugs fixed here.

   1. The active dot was `:first-child`, which never moves. It now follows the
      targeted slide using :has(), so it stays pure CSS. Each rule reads: when
      the carousel contains slide N as the :target, light dot N.

   2. Hover painted a solid block because an earlier rule set `background` on
      the dot element, and the element is padded out to a 28px hit area. Only
      the ::before bar carries colour now; the element itself is never painted. */

.rp-carousel__dots { display: flex; gap: 8px; justify-content: center; margin-top: 22px; }

.rp-carousel__dot {
  display: block;
  width: 52px;
  padding: 12px 0;
  background: none !important;
  border: 0;
  line-height: 0;
}

.rp-carousel__dot::before {
  content: "";
  display: block;
  width: 52px;
  height: 4px;
  border-radius: 2px 2px 0 0;
  background: var(--rp-sand-deep);
  transition: background 0.18s ease;
}

/* The no-JS rules below are all scoped with `:not(:has(.is-active))` on the
   dots container. Without it they out-SPECIFY the script's own rules further
   down: the default rule scores (0,6,1) against the script's (0,4,1), so once
   the script moved to slide 2 the first dot stayed navy and TWO dots read as
   active at once. Stand them down entirely as soon as the script is driving,
   rather than trying to win a specificity race against them. */

/* Default state, before anything is targeted: first dot active. */
.rp-carousel:not(:has(.rp-slide:target)) + .rp-carousel__dots:not(:has(.is-active)) .rp-carousel__dot:nth-child(1)::before {
  background: var(--rp-navy);
}

/* Active dot follows the targeted slide. */
.rp-carousel:has(#rp-slide-1:target) + .rp-carousel__dots:not(:has(.is-active)) .rp-carousel__dot:nth-child(1)::before,
.rp-carousel:has(#rp-slide-2:target) + .rp-carousel__dots:not(:has(.is-active)) .rp-carousel__dot:nth-child(2)::before,
.rp-carousel:has(#rp-slide-3:target) + .rp-carousel__dots:not(:has(.is-active)) .rp-carousel__dot:nth-child(3)::before,
.rp-carousel:has(#rp-slide-4:target) + .rp-carousel__dots:not(:has(.is-active)) .rp-carousel__dot:nth-child(4)::before,
.rp-carousel:has(#rp-slide-5:target) + .rp-carousel__dots:not(:has(.is-active)) .rp-carousel__dot:nth-child(5)::before,
.rp-carousel:has(#rp-slide-6:target) + .rp-carousel__dots:not(:has(.is-active)) .rp-carousel__dot:nth-child(6)::before {
  background: var(--rp-navy);
}

/* Hover and focus tint only the bar, never the hit area. */
.rp-carousel__dot:hover::before { background: var(--rp-burnt); }
.rp-carousel__dot:focus-visible { outline: var(--rp-focus); outline-offset: 2px; }

/* When the enhancement script is running it drives the active dot with a
   class, which must beat the :has() rules that handle the no-JS case. */
.rp-carousel__dots .rp-carousel__dot.is-active::before { background: var(--rp-navy); }
.rp-carousel__dots:has(.is-active) .rp-carousel__dot:not(.is-active)::before { background: var(--rp-sand-deep); }

/* ══ Section 4: one platform ═════════════════════════════════════════════════
   Copy left, product screenshot right, four cards beneath. Leaf values
   measured off the design: the eyebrow is TEAL here rather than amber, the h2
   is 56px, the lead is 19px two-tone, and the card headings are 16px weight
   600 in teal, not 20px white. */

.rp-platform__top {
  display: grid;
  grid-template-columns: minmax(0, 1.02fr) minmax(0, 1fr);
  gap: 64px;
  align-items: center;
  margin-bottom: 64px;
}

.rp-platform .rp-eyebrow,
.rp-platform .rp-section__head .rp-eyebrow { color: var(--rp-teal-light); margin: 0 0 20px; }

.rp-platform h2 {
  font-size: clamp(32px, 3.9vw, 56px);
  line-height: 1.02;
  letter-spacing: -0.03em;
  margin: 0 0 26px;
  color: var(--rp-white);
}

.rp-platform__body { font-size: 19px; line-height: 1.52; margin: 0 0 22px; }
.rp-platform__lead { color: var(--rp-white); font-weight: 400; }
.rp-platform__rest { color: var(--rp-blue-pale); }
.rp-platform__note { font-size: 16.5px; line-height: 1.6; color: var(--rp-blue-mid); margin: 0; max-width: 52ch; }

/* The screenshot sits on a light card so a white-background UI does not float
   awkwardly on navy. */
.rp-platform__cards {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--rp-col-gap);
  row-gap: var(--rp-col-row-gap);
  padding-top: 40px;
  /* 01. Hairline removed — it doubled with the card ticks below it. */
}

.rp-pcard h3 {
  font-family: var(--rp-font-display);
  font-stretch: 112%;
  font-size: 16px;
  /* 11. The one other place still heavy — now matches every other uppercase
     column heading. */
  font-weight: var(--rp-label-weight);
  line-height: 1.25;
  letter-spacing: normal;
  color: var(--rp-teal-light);
  margin: 0 0 10px;
}

.rp-pcard p { font-size: 15px; line-height: 1.55; color: var(--rp-blue-mid); margin: 0; }

@media (max-width: 62rem) {
  .rp-platform__top { grid-template-columns: 1fr; gap: 36px; }
  .rp-platform__cards { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 36rem) {
  .rp-platform__cards { grid-template-columns: 1fr; }
}

/* ══ Section 4: device frame, glow, card rules, footer row ═══════════════════
   All measured off the design. The flat navy panel I had was missing three
   layers and the whole closing row. */

/* Teal light, bottom right, well blurred. */
.rp-platform__glow {
  position: absolute;
  bottom: -42%;
  right: -12%;
  width: 74%;
  height: 78%;
  border-radius: 50%;
  background: radial-gradient(closest-side, rgb(53 183 196 / 0.5), rgb(11 22 38 / 0));
  filter: blur(60px);
  pointer-events: none;
  z-index: 0;
}

.rp-platform { position: relative; overflow: hidden; }
.rp-platform > .rp-container { position: relative; z-index: 1; }

/* Teal rule under the heading, not the amber one used on light sections. */
.rp-platform__rule {
  width: 88px;
  height: 3px;
  background: linear-gradient(90deg, rgb(127 169 178), rgb(46 140 153));
  margin: 0 0 30px;
}

/* ── The device ─────────────────────────────────────────────────────────────
   A gradient bezel with a fine diagonal stripe laid over it, and the screen
   inset on a white card. */
.rp-device {
  position: relative;
  border-radius: 20px;
  padding: 20px;
  background: linear-gradient(140deg,
    rgb(232, 240, 236) 0%,
    rgb(179, 215, 222) 22%,
    rgb(127, 169, 178) 42%,
    rgb(78, 169, 180) 60%,
    rgb(46, 140, 153) 80%,
    rgb(46, 74, 85) 100%);
  box-shadow: 0 30px 60px -28px rgb(4 12 20 / 0.7);
}

.rp-device__texture {
  position: absolute;
  inset: 0;
  border-radius: 20px;
  background: repeating-linear-gradient(120deg,
    rgb(255 255 255 / 0.18) 0px,
    rgb(255 255 255 / 0.18) 1px,
    rgb(255 255 255 / 0) 1px,
    rgb(255 255 255 / 0) 5px);
  pointer-events: none;
}

/* Core's block-gap puts a margin-block-start on every flow child after the
   first. In this section the first child is the absolutely-positioned
   background stack, so the gap lands on the CONTENT container and pushes the
   whole section 24px taller than the design. Same trap as the hero wash and
   the photo section's layers — it does not show up until you measure. */
.rp-section--platform > .rp-container,
.rp-platform > .rp-container { margin-block-start: 0; }

.rp-platform__bg,
.rp-platform__glow,
.rp-device__texture { margin: 0; }

.rp-device__screen {
  position: relative;
  margin: 0;
  border: 1px solid rgb(18 33 46 / 0.1);
  border-radius: 10px;
  overflow: hidden;
  background: #fff;
}

/* Settling the screenshot into a dark section.
 *
 * The problem: a product screenshot is a bright, near-white rectangle with a
 * hard edge, sitting on a near-black section. That luminance jump is what makes
 * it read as pasted on rather than part of the page — and because it is a real
 * screen we cannot restyle the UI to fix it.
 *
 * So the blending happens entirely on top of the image, in three parts:
 *
 *   1. A light colour grade on the image itself. Barely perceptible on its own
 *      — it just takes the glare off the whites so they are not the brightest
 *      thing on the page by a wide margin.
 *   2. A diagonal scrim running the same 128deg as the section's own gradients,
 *      transparent across the top-left (where the section's light falls) and
 *      deepening into the bottom-right, with a matching highlight raking the
 *      top-left corner. The screen therefore emerges from the lit side and
 *      sinks into the dark side instead of ending in a hard edge.
 *   3. A flat teal veil at 10%, pulling the whole screen toward the section's
 *      palette. This is the step that does most of the integrating.
 *
 * The limit worth knowing: every layer here dims the product UI, and the UI is
 * the reason the screenshot is on the page at all. These values were checked
 * against the rendered result at 3x — the accent buttons (green, orange, teal)
 * and the small type in the deepest corner all still read. Push the veil or the
 * scrim much past this and they stop. Legibility wins over atmosphere.
 */
.rp-device__screen::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  border-radius: inherit;
  background:
    /* The section's light raking across the top-left corner, so the screen
       reads as lit by the same source as everything around it. */
    linear-gradient(128deg, rgb(255 255 255 / 0.13) 0%, rgb(255 255 255 / 0) 34%),
    /* The scrim, deepening into the bottom-right. */
    linear-gradient(128deg, rgb(11 22 38 / 0) 32%, rgb(20 52 78 / 0.18) 68%, rgb(20 52 78 / 0.38) 100%),
    /* A flat teal veil pulling the whole screen toward the section's palette.
       The step that does most of the integrating. See the note above for how
       far this can go before the UI stops reading. */
    linear-gradient(0deg, rgb(46 140 153 / 0.10), rgb(46 140 153 / 0.10));
  /* A hairline of the section's light along the screen edge, plus a soft inner
     vignette so the corners do not sit flat against the bezel. */
  box-shadow: inset 0 0 0 1px rgb(255 255 255 / 0.12),
              inset 0 0 70px rgb(11 22 38 / 0.10);
}

.rp-device__screen img {
  filter: saturate(0.90) brightness(0.955) contrast(1.03);
  display: block;
  width: 100%;
  /* 4:3-ish, matching the proportions of the design's own device (478x347
     inner, ratio 1.38). My earlier 1400/620 made the frame squat and
     letterboxed the screenshot. */
  aspect-ratio: 1.38;
  object-fit: cover;
  object-position: top center;
}

/* ── Cards ──────────────────────────────────────────────────────────────────
   Uppercase teal headings with a short rule above each. */
.rp-pcard { position: relative; padding-top: 20px; }

.rp-pcard::before {
  content: "";
  position: absolute;
  top: 0; left: 0;
  width: 34px; height: 2px;
  background: linear-gradient(90deg, rgb(127 169 178), rgb(46 140 153));
}

.rp-pcard h3 { text-transform: uppercase; letter-spacing: 0.02em; }

/* ── Closing row ────────────────────────────────────────────────────────────── */
.rp-platform__foot {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 40px;
  align-items: center;
  margin-top: 56px;
}

.rp-platform__foot p { margin: 0; color: var(--rp-blue-pale); font-size: 16.5px; line-height: 1.6; max-width: 62ch; }
.rp-platform__foot .rp-link { color: var(--rp-teal-light); white-space: nowrap; }

@media (max-width: 62rem) {
  .rp-platform__foot { grid-template-columns: 1fr; gap: 18px; }
}

/* ══ Section 4 background, ported exactly ════════════════════════════════════
   Two parts, and I had previously mistaken the first for part of the device.

   1. A LIGHT SWEEP: a wide band rotated 14deg, blended with `screen`, holding
      two layers of its own. The gradient gives the pale-to-teal wash; the
      1px repeating stripe at 3deg gives it texture. Both are radially masked
      so they fade out before the edges rather than ending in a hard line.
   2. A teal glow bottom-right, heavily blurred.

   `mix-blend-mode: screen` is what makes the sweep read as light rather than
   as a translucent panel laid on top. */

.rp-platform__bg {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 0;
}

.rp-platform__sweep {
  position: absolute;
  top: -22%;
  left: 20%;
  width: 104%;
  height: 56%;
  transform: rotate(14deg);
  transform-origin: 0 50%;
  mix-blend-mode: screen;
}

.rp-platform__sweep-grad {
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg,
    rgb(232, 240, 236) 0%,
    rgb(179, 215, 222) 15%,
    rgb(127, 169, 178) 32%,
    rgb(78, 169, 180) 50%,
    rgb(46, 140, 153) 66%,
    rgb(62, 108, 121) 84%,
    rgb(46, 74, 85) 100%);
  -webkit-mask-image: radial-gradient(55% 44%, rgb(0, 0, 0) 18%, rgb(0 0 0 / 0.7) 50%, transparent 84%);
  mask-image: radial-gradient(55% 44%, rgb(0, 0, 0) 18%, rgb(0 0 0 / 0.7) 50%, transparent 84%);
  filter: blur(20px);
  opacity: 0.9;
}

.rp-platform__sweep-texture {
  position: absolute;
  inset: 0;
  background: repeating-linear-gradient(3deg,
    rgb(255 255 255 / 0.5) 0px,
    rgb(255 255 255 / 0.5) 1px,
    rgb(255 255 255 / 0) 1px,
    rgb(255 255 255 / 0) 4px);
  -webkit-mask-image: radial-gradient(50% 38%, rgb(0, 0, 0) 14%, transparent 80%);
  mask-image: radial-gradient(50% 38%, rgb(0, 0, 0) 14%, transparent 80%);
  opacity: 0.5;
}

/* The glow keeps its own position; it is a sibling of the sweep, not nested. */
.rp-platform__bg .rp-platform__glow {
  position: absolute;
  bottom: -42%;
  right: -12%;
  width: 74%;
  height: 78%;
  border-radius: 50%;
  background: radial-gradient(closest-side, rgb(53 183 196 / 0.5), rgb(11 22 38 / 0));
  filter: blur(60px);
}

/* The closing link is teal in this section; .rp-link's amber was winning. */
.rp-platform .rp-platform__foot .rp-link { color: var(--rp-teal-light); }

/* ══ Section 4, corrected against the real markup ════════════════════════════
   Ben supplied the section's HTML. Twelve values I had guessed or measured
   wrong, all corrected here to the design's own numbers. */

/* Container padding is 112px, not the 118px the generic section rule applies. */
.rp-section.rp-platform > .rp-container { padding-block: 112px; }

.rp-platform__top {
  margin-bottom: 0;
}

/* Grid is 1.02fr / 0.98fr with a 72px gap — but only where two columns fit.
   Unscoped, this overrode the stacking rule at max-width 62rem above, because
   it comes later in the file and carries the same specificity. The section
   then held its desktop grid down to 375px, squeezing the copy into 134px
   beside a 129px screenshot. */
@media (min-width: 62rem) {
  .rp-platform__top {
    grid-template-columns: minmax(0, 1.02fr) minmax(0, 0.98fr);
    gap: 72px;
  }
}

/* Rule: 76x3, pale-teal to teal, 26 above and 28 below. */
.rp-platform__rule {
  width: 76px;
  height: 3px;
  background: linear-gradient(90deg, rgb(179, 215, 222), rgb(46, 140, 153));
  margin: 26px 0 28px;
}

.rp-platform__body { max-width: 52ch; text-wrap: pretty; margin: 0; }
.rp-platform__note { margin: 22px 0 0; max-width: 52ch; }

/* The device's shadow is deep and soft: 0 40px 90px at 66% opacity. */
.rp-device { box-shadow: 0 40px 90px rgb(4 12 20 / 0.66); }

/* The screen is off-white with a 12px radius, not pure white at 10px. */
.rp-device__screen {
  background: rgb(251, 250, 248);
  border-radius: 12px;
  border: 0;
}

/* Card row: 84px clear of the panel, 34px of its own top padding, 26px gaps. */
.rp-platform__cards {
  margin-top: 84px;
  padding-top: 34px;
  gap: var(--rp-col-gap);
  row-gap: var(--rp-col-row-gap);
  /* 01. Second declaration — this is the one that was actually winning. */
}

/* Card rule is a flat 30x2 in pale teal, not a 34px gradient. */
.rp-pcard { padding-top: 0; }
.rp-pcard::before {
  position: static;
  display: block;
  width: 30px;
  height: 2px;
  background: rgb(127, 169, 178);
  margin-bottom: 18px;
}

.rp-pcard h3 { letter-spacing: normal; }

/* Closing row is a baseline-aligned flex wrap, not a two-column grid. */
.rp-platform__foot {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 16px 28px;
  margin-top: 44px;
}

.rp-platform__foot p { font-size: 16px; line-height: 1.6; color: var(--rp-blue-pale); max-width: 70ch; }
.rp-platform__foot .rp-link { font-size: 11px; letter-spacing: 0.14em; color: var(--rp-teal-light); }

/* DOUBLE PADDING. The design puts 112px on the inner container and nothing on
   the section. My generic `.rp-section { padding-block: 118px }` was adding its
   own on top, so the section carried ~230px and sat far lower than the comp.

   Same shape as the hero regression earlier: a component that owns its spacing
   on the inner wrapper has to zero the section rule, and it must be declared
   after it. */
.rp-section.rp-platform { padding-block: 0; }
.rp-section.rp-platform > .rp-container { padding-block: 112px; }

/* ═══════════════════════════════════════════════════════════════════════════
   SECTION 7 — closing call to action
   Measured off direction-3.html. A centred block on sand with a soft two-colour
   bloom sitting behind and above the heading.
   ═══════════════════════════════════════════════════════════════════════════ */

.rp-section--cta {
  position: relative;
  /* base.css sets padding-block on every .rp-section. The design puts its
     padding on the inner container (126/134, asymmetric), so the section's own
     padding has to go or it stacks on top. This has bitten three other
     sections; check it first when a section renders too tall. */
  padding-block: 0;
  background: var(--rp-sand);
  overflow: hidden;
  border-top: 1px solid rgb(18 33 46 / 0.1);
}

/* The bloom. Two blurred radials in a fixed-size box, centred on the section
   and pulled up so only the lower two thirds fall inside it. Fixed px rather
   than a percentage: the design's bloom is a constant physical size and
   scaling it with the viewport changes the whole mood of the section. */
.rp-cta__bloom {
  position: absolute;
  left: 50%;
  top: -30%;
  width: 1000px;
  height: 640px;
  transform: translateX(-50%);
  pointer-events: none;
}

.rp-cta__bloom-warm,
.rp-cta__bloom-teal {
  position: absolute;
  inset: 0;
  filter: blur(70px);
}

.rp-cta__bloom-warm {
  background: radial-gradient(closest-side, rgb(248 170 20 / 0.34), rgb(244 242 237 / 0) 72%);
}

.rp-cta__bloom-teal {
  background: radial-gradient(closest-side at 66% 46%, rgb(46 140 153 / 0.26), rgb(244 242 237 / 0) 72%);
}

.rp-section--cta > .rp-container {
  position: relative;   /* above the bloom */
  max-width: var(--rp-container);
  margin: 0 auto;
  padding: 126px var(--rp-gutter) 134px;
  text-align: center;
}

.rp-section--cta .rp-eyebrow {
  color: var(--rp-burnt);
  margin: 0 0 24px;
}

.rp-cta__heading {
  margin: 0 auto;
  max-width: 17ch;
  font-family: var(--rp-font-display);
  font-stretch: 112%;
  /* Weight 300, not 400. This is the one display heading in the design set
     lighter than the rest, and at 80px the difference is obvious. */
  font-weight: 300;
  font-size: clamp(38px, 5.4vw, 80px);
  /* 18. Was line-height 1. Gradient-CLIPPED text paints only inside the line
     box, so at exactly 1 the tail of the "g" in "challenges" fell outside it
     and was cropped. Opened, plus padding for the paint area, cancelled by a
     matching negative margin so the layout does not shift. */
  line-height: 1.08;
  padding-bottom: 0.08em;
  margin-bottom: -0.08em;
  letter-spacing: -0.036em;
  /* Gradient-CLIPPED text, so every stop is read as type and has to clear
     contrast. At 38px minimum this is large text, so the floor is 3:1. The
     design's first two stops measure 1.75 and 2.15 on sand and fail it; these
     are the darkened equivalents already used by --rp-stat-gradient, so the
     site keeps one set of oranges. Same sweep, legible. */
  background: linear-gradient(98deg,
                #bf7409 0%,
                #bd6614 24%,
                var(--rp-burnt-bright) 48%,
                #a8410c 62%,
                var(--rp-teal) 88%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.rp-cta__body {
  margin: 28px auto 0;
  max-width: 70ch;
  font-size: 18.5px;
  line-height: 1.55;
  color: var(--rp-slate);
}

.rp-cta__action { margin: 38px 0 0; }

/* The CTA button is a size up from the site's default pill: the design gives
   it 18/32 padding rather than the 17/28 the hero and card buttons use. Scoped
   here so the verified hero button is left alone. */
.rp-cta__action .rp-btn { padding: 18px 32px; border-width: 0; }

@media (max-width: 782px) {
  .rp-section--cta > .rp-container { padding-block: 84px 90px; }
  .rp-cta__bloom { width: 700px; height: 460px; top: -22%; }
}

/* ── Stat band on navy ───────────────────────────────────────────────────────
   The numeral is gradient-CLIPPED text, so every stop is read as type and has
   to clear 3:1 (large text). On SAND the design's own stops fail — 1.75 and
   2.15 — which is why --rp-stat-gradient darkens them.

   On navy the opposite is true: the design's ORIGINAL stops all pass, from
   3.58 at the burnt end to 8.38 at the amber end. So the dark variant uses the
   design's untouched gradient, and only the light one is corrected.
   ─────────────────────────────────────────────────────────────────────────── */
.rp-statband--navy .rp-statband__big {
  /* The teal END is lifted from the design's #2E8C99 to #5FC2CF. The design's
     teal was chosen against SAND; on navy it sits too close to the burnt stop
     and the tail of the numeral goes muddy grey-brown rather than reading as
     teal. #5FC2CF measures 7.88:1 on navy and 8.73:1 on deep navy, so it clears
     the 3:1 large-text floor comfortably. */
  background: linear-gradient(160deg,
                var(--rp-amber),
                #f0902b 26%,
                var(--rp-burnt-bright) 52%,
                #5fc2cf 92%);
  -webkit-background-clip: text;
  background-clip: text;
}

.rp-statband--navy .rp-statband__leadlabel,
.rp-statband--navy .rp-statband__row .rp-stat__label { color: var(--rp-blue-pale); }
.rp-statband--navy .rp-statband__row .rp-stat__value { color: var(--rp-white); }
.rp-statband--navy .rp-eyebrow { color: var(--rp-amber-soft); }

/* The section's decorative wash is tuned for a light ground; on navy it reads
   as a grey smear, so it goes. */
.rp-section--navy.rp-section--statband::after { display: none; }

/* ── Resource grid ───────────────────────────────────────────────────────────
   Values lifted from the interior designs' rp.css (.resgrid / .res). Cards are
   whole links, so the hover lift belongs to the anchor.
   ─────────────────────────────────────────────────────────────────────────── */

.rp-resgrid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 20px;
  margin-top: 44px;
}

@media (max-width: 1000px) { .rp-resgrid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 640px)  { .rp-resgrid { grid-template-columns: 1fr; } }

.rp-res {
  display: flex;
  flex-direction: column;
  background: #fff;
  border: 1px solid rgb(18 33 46 / 0.12);
  border-radius: 16px;
  padding: 24px;
  color: var(--rp-navy);
  text-decoration: none;
  transition: transform .2s ease, border-color .2s ease;
}

.rp-res:hover { transform: translateY(-3px); border-color: rgb(18 33 46 / 0.3); color: var(--rp-navy); }

.rp-res__type {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 12px;
  font-family: var(--rp-font-mono);
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  /* --rp-burnt, not the design's #C4530F: at 10px this is small text and needs
     4.5:1, which the design's rust misses on white. */
  color: var(--rp-burnt);
}

.rp-res__type::before {
  content: "";
  width: 20px;
  height: 2px;
  background: var(--rp-accent-gradient);
}

.rp-res__title { font-size: 17px; font-weight: 600; line-height: 1.3; margin: 0 0 8px; }
.rp-res__desc  { font-size: 14px; line-height: 1.55; color: var(--rp-slate); margin: 0; flex: 1; }

.rp-res__go {
  margin-top: 14px;
  font-family: var(--rp-font-mono);
  font-size: 10.5px;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--rp-burnt);
}

/* The highlighted card inverts to navy. */
.rp-res--feature { background: var(--rp-navy-deep); border: 0; color: #fff; }
.rp-res--feature:hover { color: #fff; }
.rp-res--feature .rp-res__title { color: #fff; }
.rp-res--feature .rp-res__desc  { color: var(--rp-blue-pale); }
.rp-res--feature .rp-res__type  { color: var(--rp-amber-soft); }
.rp-res--feature .rp-res__go    { color: var(--rp-amber); }

/* On a dark section the plain cards need to invert too, or they sit as white
   slabs on navy. */
.rp-section--navy .rp-res,
.rp-section--deepflat .rp-res {
  background: rgb(255 255 255 / 0.04);
  border-color: rgb(255 255 255 / 0.14);
  color: #fff;
}
.rp-section--navy .rp-res .rp-res__title,
.rp-section--deepflat .rp-res .rp-res__title { color: #fff; }
.rp-section--navy .rp-res .rp-res__desc,
.rp-section--deepflat .rp-res .rp-res__desc { color: var(--rp-blue-pale); }
.rp-section--navy .rp-res .rp-res__type,
.rp-section--deepflat .rp-res .rp-res__type { color: var(--rp-amber-soft); }
.rp-section--navy .rp-res .rp-res__go,
.rp-section--deepflat .rp-res .rp-res__go { color: var(--rp-amber); }

/* ── Interior page sections ──────────────────────────────────────────────────
   Ported from ~/Sites/rp-designs/assets/rp.css. Accent colours are the AA-safe
   tokens rather than the design's raw values: the design uses #C4530F for
   feature-list headings at 16px, which measures 4.09 on sand and misses the
   4.5 floor for normal text.
   ─────────────────────────────────────────────────────────────────────────── */

/* Feature list */
.rp-featcols { display: grid; column-gap: var(--rp-col-gap); row-gap: var(--rp-col-row-gap); margin-top: 44px; }
.rp-featcols--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.rp-featcols--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.rp-featcols--4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.rp-featcols--5 { grid-template-columns: repeat(5, minmax(0, 1fr)); }
@media (max-width: 900px) { .rp-featcols { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 560px) { .rp-featcols { grid-template-columns: 1fr; } }

.rp-feat__tick { display: none; width: 30px; height: 2px; margin-bottom: 18px; background: var(--rp-accent-gradient); }
.rp-feat__title { margin: 0 0 10px; font-size: 16px; line-height: 1.25; font-weight: var(--rp-label-weight); text-transform: uppercase; color: var(--rp-burnt); }
.rp-feat__body { margin: 0; font-size: 15px; line-height: 1.55; color: var(--rp-body-2); }

.rp-section--navy .rp-feat__tick,
.rp-section--deepflat .rp-feat__tick { background: var(--rp-teal-mid); }
.rp-section--navy .rp-feat__title,
.rp-section--deepflat .rp-feat__title { color: var(--rp-teal-light); }
.rp-section--navy .rp-feat__body,
.rp-section--deepflat .rp-feat__body { color: var(--rp-blue-pale); }

/* Two-up */
.rp-grid2 { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 76px; align-items: center; }
@media (max-width: 900px) { .rp-grid2 { grid-template-columns: 1fr; gap: 40px; } }

.rp-frame { position: relative; border-radius: 18px; overflow: hidden; background: #dde5eb; box-shadow: 0 30px 60px rgb(12 25 40 / 0.16); }
.rp-frame img { display: block; width: 100%; height: 100%; object-fit: cover; }
.rp-frame--product {
  background: linear-gradient(342deg, #c9dcec 0%, #e4e9ee 38%, #f6e8d2 74%, #fbdcae 100%);
  border: 1px solid rgb(18 33 46 / 0.1);
  box-shadow: 0 30px 64px -30px rgb(18 33 46 / 0.34);
}
.rp-frame--product img { object-fit: contain; padding: 34px; }

.rp-grid2__rule { width: 78px; height: 3px; margin: 26px 0 24px; border-radius: 2px; background: var(--rp-accent-gradient); }
.rp-grid2__copy h2 { margin: 0; font-size: var(--rp-text-h2); line-height: 1.05; letter-spacing: var(--rp-track-h2); }

/* Numbered steps */
.rp-steps { display: grid; gap: 22px; margin-top: 44px; counter-reset: rp-step; }
.rp-steps--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.rp-steps--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.rp-steps--4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
@media (max-width: 900px) { .rp-steps { grid-template-columns: 1fr; } }

/* A CARD, not a bare column. The design draws each step on white with a hairline
   border and a 16px radius, and puts the numeral inside it. The earlier port had
   the numeral floating above an unbounded column, which reads as a feature list
   rather than a sequence — and left the steps on the contact page looking like a
   different component from the ones in the designs. */
.rp-step {
  counter-increment: rp-step;
  background: #fff;
  border: 1px solid rgb(18 33 46 / 0.12);
  border-radius: 16px;
  padding: 24px;
}
.rp-step::before {
  content: counter(rp-step, decimal-leading-zero);
  display: block;
  margin-bottom: 12px;
  font-family: var(--rp-font-mono);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.16em;
  color: var(--rp-burnt);
}
.rp-step__title { margin: 0 0 8px; font-size: 17px; font-weight: 600; line-height: 1.3; color: var(--rp-navy); }
.rp-step__body  { margin: 0; font-size: 14.5px; line-height: 1.55; color: var(--rp-slate); }

.rp-section--navy .rp-step, .rp-section--deepflat .rp-step { background: rgb(255 255 255 / 0.043); border-color: rgb(255 255 255 / 0.12); }
.rp-section--navy .rp-step__title, .rp-section--deepflat .rp-step__title { color: #fff; }
.rp-section--navy .rp-step__body,  .rp-section--deepflat .rp-step__body  { color: var(--rp-blue-pale); }
.rp-section--navy .rp-step::before, .rp-section--deepflat .rp-step::before { color: var(--rp-amber-soft); }

/* Milestones */
.rp-miles { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 26px; margin-top: 44px; }
@media (max-width: 900px) { .rp-miles { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.rp-mile__num { display: block; font-family: var(--rp-font-data); font-size: 30px; font-weight: var(--rp-numeral-weight); letter-spacing: -0.03em; line-height: 1; color: #fff; }
.rp-mile__lbl { display: block; margin-top: 10px; font-size: 13.5px; line-height: 1.45; color: var(--rp-blue-pale); }
.rp-mile__note { display: block; font-family: var(--rp-font-mono); font-size: 10.5px; font-weight: 500; letter-spacing: 0.16em; text-transform: uppercase; color: var(--rp-caption); line-height: 1.6; }
.rp-section--sand .rp-mile__num { color: var(--rp-navy); }
.rp-section--sand .rp-mile__lbl { color: var(--rp-slate); }
.rp-section--sand .rp-mile__note { color: var(--rp-burnt); }

/* Tabbed screens */
.rp-tab__bar { display: flex; gap: 8px; flex-wrap: wrap; margin: 44px 0 26px; }
.rp-tab__btn {
  border: 1px solid rgb(18 33 46 / 0.18);
  background: #fff;
  color: var(--rp-slate);
  font-family: var(--rp-font-mono);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  border-radius: 999px;
  padding: 11px 18px;
  cursor: pointer;
  transition: border-color .15s ease, background-color .15s ease, color .15s ease;
}
.rp-tab__btn:hover { border-color: var(--rp-burnt); color: var(--rp-navy); }
.rp-tab__btn[aria-selected="true"] { background: var(--rp-navy-alt); border-color: var(--rp-navy-alt); color: #fff; }

/* Every pane is in the DOM. Without JS they all show, stacked — readable, just
   not tabbed. The script adds the class that hides the inactive ones. */
.rp-tabs { --rp-tabs-js: 0; }
.rp-tab__pane { display: grid; grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr); gap: 40px; align-items: center; margin-bottom: 32px; }
html.rp-tabs-js .rp-tab__pane { display: none; margin-bottom: 0; }
html.rp-tabs-js .rp-tab__pane.is-on { display: grid; }
@media (max-width: 900px) { .rp-tab__pane, html.rp-tabs-js .rp-tab__pane.is-on { grid-template-columns: 1fr; } }

.rp-tab__shot { border-radius: 14px; border: 1px solid rgb(18 33 46 / 0.12); box-shadow: 0 24px 54px -22px rgb(18 33 46 / 0.25); display: block; width: 100%; background: #fff; }
.rp-tab__lbl { display: block; margin-bottom: 8px; font-family: var(--rp-font-mono); font-size: 10.5px; font-weight: 500; letter-spacing: 0.18em; text-transform: uppercase; color: var(--rp-burnt); }
.rp-tab__pane h3 { font-size: 22px; font-weight: 600; margin: 0 0 10px; }
.rp-tab__pane p  { margin: 0; font-size: 16px; line-height: 1.62; color: var(--rp-slate); max-width: 52ch; }

/* ── Card row, video, FAQ two-column ─────────────────────────────────────────
   Ported from the interior designs. Card and FAQ accents use the AA-safe
   tokens; the design's inline #C4530F on the card label misses 4.5 on white.
   ─────────────────────────────────────────────────────────────────────────── */

.rp-cards2 { display: grid; gap: 22px; margin-top: 44px; }
.rp-cards2--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.rp-cards2--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
@media (max-width: 820px) { .rp-cards2 { grid-template-columns: 1fr; } }

.rp-card2 {
  display: flex; flex-direction: column;
  background: #fff;
  border: 1px solid rgb(18 33 46 / 0.1);
  border-radius: 18px;
  padding: 32px 26px 28px;
  transition: transform .2s ease, border-color .2s ease;
}
.rp-card2:hover { transform: translateY(-4px); border-color: rgb(18 33 46 / 0.28); }
.rp-card2__crumb { display: block; margin-bottom: 12px; font-family: var(--rp-font-mono); font-size: 11px; font-weight: 500; letter-spacing: 0.16em; text-transform: uppercase; color: var(--rp-burnt); }
.rp-card2__title { margin: 0 0 10px; font-family: var(--rp-font-display); font-stretch: 112%; font-size: 23px; line-height: 1.2; color: var(--rp-navy); }
.rp-card2__body  { margin: 0 0 22px; font-size: 16px; line-height: 1.55; color: var(--rp-slate); flex: 1; }

.rp-section--navy .rp-card2, .rp-section--deepflat .rp-card2 { background: rgb(255 255 255 / 0.043); border-color: rgb(255 255 255 / 0.12); }
.rp-section--navy .rp-card2:hover, .rp-section--deepflat .rp-card2:hover { border-color: rgb(255 255 255 / 0.3); }
.rp-section--navy .rp-card2__title, .rp-section--deepflat .rp-card2__title { color: #fff; }
.rp-section--navy .rp-card2__body,  .rp-section--deepflat .rp-card2__body  { color: var(--rp-blue-pale); }
.rp-section--navy .rp-card2__crumb, .rp-section--deepflat .rp-card2__crumb { color: var(--rp-amber-soft); }

.rp-vidembed {
  position: relative; margin-top: 44px;
  border-radius: 18px; overflow: hidden;
  background: var(--rp-navy-deep);
  aspect-ratio: 16 / 9;
  border: 1px solid rgb(18 33 46 / 0.12);
  box-shadow: 0 30px 64px -28px rgb(18 33 46 / 0.3);
}
.rp-vidembed iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }
.rp-section--navy .rp-vidembed, .rp-section--deepflat .rp-vidembed { border-color: rgb(255 255 255 / 0.1); box-shadow: 0 30px 70px -20px rgb(4 12 20 / 0.5); }
.rp-vidcap { margin: 14px 0 0; font-family: var(--rp-font-mono); font-size: 10.5px; font-weight: 500; letter-spacing: 0.14em; text-transform: uppercase; color: var(--rp-body-2); }
.rp-section--navy .rp-vidcap, .rp-section--deepflat .rp-vidcap { color: var(--rp-blue-mid); }

/* FAQ, optionally beside a resources column */
.rp-faq2 { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 64px; align-items: start; }
@media (max-width: 900px) { .rp-faq2 { grid-template-columns: 1fr; gap: 48px; } }
.rp-faq2__h { margin: 0; font-family: var(--rp-font-display); font-stretch: 112%; font-size: clamp(26px, 3vw, 40px); line-height: 1.08; letter-spacing: var(--rp-track-h2); color: var(--rp-navy); }
.rp-faq2__rule { width: 78px; height: 3px; margin: 22px 0 26px; border-radius: 2px; background: var(--rp-accent-gradient); }
.rp-section--navy .rp-faq2__h, .rp-section--deepflat .rp-faq2__h { color: #fff; }

.rp-faqlist { max-width: 880px; }
.rp-faqitem { border-bottom: 1px solid rgb(18 33 46 / 0.14); padding: 20px 0; }
.rp-faqitem summary { cursor: pointer; list-style: none; font-family: var(--rp-font-display); font-stretch: 112%; font-size: 17px; line-height: 1.35; color: var(--rp-navy); }
.rp-faqitem summary::-webkit-details-marker { display: none; }
.rp-faqitem summary::marker { content: ""; }
.rp-faqitem summary::after { content: "+"; float: right; margin-left: 16px; font-family: var(--rp-font-mono); color: var(--rp-burnt); }
.rp-faqitem[open] summary::after { content: "\2212"; }
.rp-faqitem__a { padding-top: 12px; }
.rp-faqitem__a p { margin: 0; font-size: 15.5px; line-height: 1.6; color: var(--rp-slate); }
.rp-section--navy .rp-faqitem, .rp-section--deepflat .rp-faqitem { border-bottom-color: rgb(255 255 255 / 0.14); }
.rp-section--navy .rp-faqitem summary, .rp-section--deepflat .rp-faqitem summary { color: #fff; }
.rp-section--navy .rp-faqitem__a p, .rp-section--deepflat .rp-faqitem__a p { color: var(--rp-blue-pale); }

/* Stacked variant, for the narrow resources column beside a FAQ. */
.rp-resgrid--stack { grid-template-columns: 1fr; margin-top: 0; }

/* Two-column section head: heading left, intro right. */
/* Two columns, TWO ROWS. The eyebrow gets row one to itself so the intro can
   start on row two, level with the heading rather than with the label above it
   or the rule below it. No magic offset, and it stays right when the eyebrow is
   absent or wraps to two lines. */
.rp-headsplit {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  grid-template-rows: auto auto;
  column-gap: 56px;
}
.rp-headsplit__eyebrow { grid-column: 1; grid-row: 1; }
.rp-headsplit__lead    { grid-column: 1; grid-row: 2; }
.rp-headsplit__intro   { grid-column: 2; grid-row: 2; }
@media (max-width: 900px) {
  .rp-headsplit { grid-template-columns: 1fr; grid-template-rows: auto auto auto; row-gap: 20px; }
  .rp-headsplit__eyebrow, .rp-headsplit__lead, .rp-headsplit__intro { grid-column: 1; }
  .rp-headsplit__intro { grid-row: 3; }
}
.rp-headsplit__h { margin: 0; font-family: var(--rp-font-display); font-stretch: 112%; font-size: var(--rp-text-h2); line-height: 1.05; letter-spacing: var(--rp-track-h2); color: var(--rp-navy); }
.rp-headsplit__rule { width: 78px; height: 3px; margin-top: 26px; border-radius: 2px; background: var(--rp-accent-gradient); }
.rp-headsplit__intro { margin: 0; font-size: var(--rp-text-lead); line-height: 1.55; color: var(--rp-slate); }
.rp-section--navy .rp-headsplit__h, .rp-section--deepflat .rp-headsplit__h { color: #fff; }
.rp-section--navy .rp-headsplit__intro, .rp-section--deepflat .rp-headsplit__intro { color: var(--rp-blue-pale); }

/* Stat row beneath a feature list. */
.rp-featstats { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 26px; margin-top: 64px; padding-top: 34px; border-top: 1px solid rgb(255 255 255 / 0.14); }
@media (max-width: 900px) { .rp-featstats { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.rp-featstat__value { display: block; font-family: var(--rp-font-data); font-size: clamp(28px, 2.6vw, 38px); font-weight: var(--rp-numeral-weight); line-height: 1; letter-spacing: -0.035em; color: #fff; }
.rp-featstat__label { display: block; margin-top: 14px; font-size: 14.5px; line-height: 1.5; color: var(--rp-blue-pale); }
.rp-section--sand .rp-featstats { border-top-color: rgb(18 33 46 / 0.12); }
.rp-section--sand .rp-featstat__value { color: var(--rp-navy); }
.rp-section--sand .rp-featstat__label { color: var(--rp-slate); }

/* Feature list, amber variant — what the industry pages use on dark. */
.rp-section--navy .rp-feat--amber .rp-feat__tick,
.rp-section--deepflat .rp-feat--amber .rp-feat__tick { background: var(--rp-accent-gradient); }
.rp-section--navy .rp-feat--amber .rp-feat__title,
.rp-section--deepflat .rp-feat--amber .rp-feat__title { color: var(--rp-amber-soft); }

/* The gradient rule the designs draw above each figure in a stat row. */
.rp-featstat__rule { display: none; width: 100%; max-width: 400px; height: 2px; margin-bottom: 22px; background: var(--rp-accent-gradient); }

/* Hero breadcrumb crumb, in place of a plain eyebrow. */
.rp-crumb {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin: 0 0 26px;
  /* 08 sets this to 42px on interior headers; see below. */
  font-family: var(--rp-font-mono);
  font-size: var(--rp-eyebrow-size);
  font-weight: 500;
  letter-spacing: var(--rp-eyebrow-tracking);
  text-transform: uppercase;
  color: var(--rp-blue-mid);
}
.rp-crumb__sep { color: var(--rp-blue-mid); opacity: .7; }
.rp-crumb > span:last-child { color: var(--rp-amber-soft); }

/* The bold closing statement in a hero lede. */
.rp-hero__solve { color: #fff; font-weight: 600; }

/* ── Interior hero spacing ───────────────────────────────────────────────────
   The homepage hero ends with the form-factor chip row, so its container has
   NO bottom padding — the chips provide the visual floor. An interior hero has
   no chips, so that same zero left the button sitting on the section edge.

   The interior designs spec their own hero: 96px top, 76px bottom, min-height
   430px rather than the homepage's 672px. Selected with :has() on the chips,
   so it follows the content rather than needing a flag on the block.
   ─────────────────────────────────────────────────────────────────────────── */

.rp-section.rp-hero:not(:has(.rp-formfactors)) > .rp-container {
  padding-top: 96px;
  padding-bottom: 76px;
  min-height: 430px;
  display: flex;
  flex-direction: column;
  justify-content: center;
}

/* Fallback for browsers without :has() — slightly generous rather than wrong,
   and the chips row overrides it back to 0 below. */
@supports not selector(:has(*)) {
  .rp-section.rp-hero > .rp-container { padding-bottom: 76px; }
  .rp-section.rp-hero > .rp-container:has(.rp-formfactors) { padding-bottom: 0; }
}

/* The design sets the closing statement on its OWN line, not inline. */
.rp-hero__solve { display: block; margin-top: 14px; }

/* The button row's own breathing room, from the design's .actions. */
.rp-hero .rp-btn-row { margin-top: 40px; }

/* Interior hero type: smaller than the homepage, wider measure. Same :has()
   test as the interior hero spacing — no chips means an interior page. */
.rp-section.rp-hero:not(:has(.rp-formfactors)) h1 {
  font-size: var(--rp-text-h1-sub);
  /* 23ch, Ben 2026-08-07. The design specs 19ch; the interior headlines written
     since are longer than the ones it was measured against. */
  max-width: 23ch;
}

@supports not selector(:has(*)) {
  .rp-section.rp-hero h1 { font-size: var(--rp-text-h1-sub); max-width: 23ch; }
  .rp-section.rp-hero:has(.rp-formfactors) h1 { font-size: var(--rp-text-h1); max-width: 17ch; }
}

/* ── Hardware-page components ────────────────────────────────────────────────
   Ported from ~/Sites/rp-designs/assets/rp.css for the three hardware pages.
   The survey recorded these pages as compositions of blocks that already
   existed; they are not. A gallery, an event strip, a closing cross-link and a
   photo card are components the earlier rounds never needed. Accent colours are
   the AA-safe tokens, as everywhere else.
   ─────────────────────────────────────────────────────────────────────────── */

/* Gallery. Never its own section in the designs — it trails the video or the
   feature row inside the section that already has the heading. */
.rp-gallery { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 18px; margin-top: 44px; }
@media (max-width: 800px) { .rp-gallery { grid-template-columns: 1fr; } }

.rp-gitem {
  position: relative;
  margin: 0;
  border-radius: 14px;
  overflow: hidden;
  background: var(--rp-navy-deep);
  aspect-ratio: 4 / 3;
}
.rp-gitem img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block; transition: transform .4s ease; }
@media (prefers-reduced-motion: reduce) { .rp-gitem img { transition: none; } }
.rp-gitem:hover img { transform: scale(1.04); }
.rp-gitem__cap {
  position: absolute; left: 0; right: 0; bottom: 0;
  padding: 34px 16px 12px;
  background: linear-gradient(rgb(11 22 38 / 0), rgb(11 22 38 / 0.8));
  font-family: var(--rp-font-mono);
  font-size: 10px; font-weight: 500; letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--rp-caption);
}
/* A product render is cut off by the cover crop, so it is shown whole on white.
   The caption then has no dark image under it and needs its own colour. */
.rp-gitem--contain { background: #fff; border: 1px solid rgb(18 33 46 / 0.1); }
.rp-gitem--contain img { object-fit: contain; padding: 16px; }
.rp-gitem--contain .rp-gitem__cap { background: linear-gradient(rgb(255 255 255 / 0), rgb(255 255 255 / 0.92)); color: var(--rp-burnt); }

/* The quiet cross-link at the foot of a feature row. */
.rp-reach { margin-top: 44px; display: flex; flex-wrap: wrap; align-items: baseline; gap: 16px 28px; }

/* Event strip: the Innovation Center offer under the portfolio cards. */
.rp-eventcard {
  display: flex; align-items: center; flex-wrap: wrap; gap: 28px;
  margin-top: 44px;
  padding: 28px 32px;
  border-radius: 18px;
  background: var(--rp-navy-deep);
  color: #fff;
  box-shadow: 0 26px 60px -24px rgb(4 12 20 / 0.5);
}
.rp-eventcard__when { margin: 0; font-family: var(--rp-font-mono); font-size: 10.5px; font-weight: 500; letter-spacing: 0.18em; text-transform: uppercase; color: var(--rp-amber-soft); }
.rp-eventcard__h { margin: 4px 0 2px; font-size: 22px; font-weight: 600; color: #fff; }
.rp-eventcard__where { margin: 0; font-size: 14.5px; line-height: 1.5; color: var(--rp-blue-pale); }
.rp-eventcard .rp-btn { margin-left: auto; }
@media (max-width: 700px) { .rp-eventcard .rp-btn { margin-left: 0; } }

/* Portfolio card: the same card component with a render on the warm panel and a
   spec list. The photo is edge to edge, so the padding moves to the body. */
.rp-card2--photo { padding: 0; overflow: hidden; }
.rp-card2--photo .rp-card2__bd { display: flex; flex-direction: column; flex: 1; padding: 26px 26px 28px; }
.rp-card2--photo .rp-card2__body { flex: 0 0 auto; }
/* The spec list pushes the link to the bottom, so cards of unequal copy length
   still line their links up. */
.rp-card2--photo .rp-specs { flex: 1; }
.rp-card2--photo .rp-link { margin-top: 22px; }
.rp-card2__photo {
  display: block; height: 290px;
  background: linear-gradient(342deg, #c9dcec 0%, #e4e9ee 38%, #f6e8d2 74%, #fbdcae 100%);
}
.rp-card2__photo img { width: 100%; height: 100%; object-fit: contain; padding: 26px; display: block; }
@media (max-width: 640px) { .rp-card2__photo { height: 220px; } }

/* The interior stat band: heading and prose across two columns, figures under a
   rule beneath. `--start` because this head sits ABOVE a figure row rather than
   directly on top of its own content, so the two columns align at the top; the
   default head aligns them at the baseline. */
/* --start is retained as a no-op: row alignment is now the single behaviour. */
.rp-headsplit--start { }
.rp-headsplit__intro > p { margin: 0 0 18px; font-size: var(--rp-text-base); line-height: var(--rp-lh-body); color: inherit; }
.rp-headsplit__intro > p:last-child { margin-bottom: 0; }
/* The designs set the first paragraph a shade brighter than the rest, so the
   claim leads and the qualification follows. */
.rp-section--navy .rp-headsplit__intro > p { color: var(--rp-blue-mid); }
.rp-section--navy .rp-headsplit__intro > p:first-child { color: var(--rp-blue-pale); }

/* 84px where a figure row follows a narrative, against 64 where it follows a
   feature row — both measured off the designs, which use one or the other. */
.rp-featstats--loose { margin-top: 84px; }

/* The pulled-out note: one sentence lifted out of the flow onto an amber rule.
   Amber is the RULE here, never the text — it measures 2.0:1 on white. */
.rp-callout {
  max-width: 70ch;
  margin: 52px 0 0;
  padding: 22px 26px;
  background: #fff;
  border: 1px solid rgb(18 33 46 / 0.1);
  border-left: 3px solid var(--rp-amber);
  border-radius: 0 12px 12px 0;
  font-size: var(--rp-text-base);
  line-height: var(--rp-lh-body);
  color: var(--rp-slate);
}
.rp-section--navy .rp-callout, .rp-section--deepflat .rp-callout {
  background: rgb(255 255 255 / 0.043);
  border-color: rgb(255 255 255 / 0.12);
  border-left-color: var(--rp-amber);
  color: var(--rp-blue-pale);
}

/* The section head's measure belongs on the HEADING, not on the block.
   `.rp-section__head { max-width: 46ch }` measures 46ch of BODY text — about
   390px — so a 54px display heading inside it broke a line or two earlier than
   the designs do ("Six things the wall / does differently" against "Six things
   the wall does / differently"). rp.css caps `.sechead .h-sec` at 24ch, which
   is 24 characters of the heading's own size. Same rule, applied where the
   design applies it; the lead paragraph keeps the prose measure. */
.rp-section__head { max-width: none; }
.rp-section__head :is(h2, h3) { max-width: 24ch; }
.rp-section__head p { max-width: var(--rp-container-text); }

/* The split head's intro keeps the design's 52ch measure. Without it the
   paragraph runs the full half-container and reads long beside a display
   heading that is capped at 24ch. */
.rp-headsplit__intro { max-width: 52ch; }

/* ── Interactive floor plan ──────────────────────────────────────────────────
   Ported from ~/Sites/rp-designs/assets/rp.css. The layout is the design's: a
   dark detail card at a fixed width beside the plan, dots positioned by
   percentage, a chip rail beneath.

   NO-SCRIPT BASELINE: every card is in the page. Without explorer.js they all
   show, stacked, which reads as the line described in order. `.is-on` is only
   applied once the script has run — html.rp-explorer-js is what hides the rest,
   the same pattern the tabs use.
   ─────────────────────────────────────────────────────────────────────────── */

.rp-section--explorer { position: relative; overflow: hidden; }

.rp-explorer {
  display: grid;
  grid-template-columns: minmax(320px, 400px) minmax(0, 1fr);
  gap: 44px;
  margin-top: 56px;
  align-items: start;
}
@media (max-width: 1000px) { .rp-explorer { grid-template-columns: 1fr; } }

/* The plan */
.rp-plan { position: relative; }
.rp-plan img { position: relative; display: block; width: 100%; height: auto; filter: drop-shadow(0 30px 60px rgb(0 0 0 / 0.5)); }
.rp-plan__spots { position: absolute; inset: 0; }

.rp-spot {
  position: absolute;
  transform: translate(-50%, -50%);
  width: 42px; height: 42px;
  border: 0; border-radius: 999px;
  cursor: pointer;
  background: var(--rp-amber);
  color: var(--rp-navy);
  font-family: var(--rp-font-mono);
  font-size: 12.5px; font-weight: 500;
  display: flex; align-items: center; justify-content: center;
  box-shadow: 0 8px 20px rgb(0 0 0 / 0.45);
  transition: transform .18s ease, background-color .18s ease;
  z-index: 2;
}
.rp-spot::before { content: ""; position: absolute; inset: 0; border-radius: 999px; animation: rp-spot-pulse 2.4s infinite; pointer-events: none; }
@keyframes rp-spot-pulse {
  0%   { box-shadow: 0 0 0 0 rgb(248 170 20 / 0.4); }
  70%  { box-shadow: 0 0 0 13px rgb(248 170 20 / 0); }
  100% { box-shadow: 0 0 0 0 rgb(248 170 20 / 0); }
}
.rp-spot:hover { transform: translate(-50%, -50%) scale(1.15); z-index: 6; }
.rp-spot[aria-selected="true"] { background: #fff; color: var(--rp-navy); }
.rp-spot[aria-selected="true"]::before { animation: none; box-shadow: 0 0 0 6px rgb(255 255 255 / 0.18); }
.rp-spot--software { background: var(--rp-teal); color: #fff; }
.rp-spot--software::before { animation-name: rp-spot-pulse-teal; }
@keyframes rp-spot-pulse-teal {
  0%   { box-shadow: 0 0 0 0 rgb(46 140 153 / 0.45); }
  70%  { box-shadow: 0 0 0 13px rgb(46 140 153 / 0); }
  100% { box-shadow: 0 0 0 0 rgb(46 140 153 / 0); }
}
/* A dot on a plan is a 42px target and the pulse is decorative, so both are
   dropped for anyone who has asked for less movement. */
@media (prefers-reduced-motion: reduce) {
  .rp-spot::before { animation: none; }
  .rp-spot { transition: none; }
}

.rp-spot__tip {
  position: absolute; bottom: calc(100% + 10px); left: 50%;
  transform: translateX(-50%);
  white-space: nowrap;
  background: #fff; color: var(--rp-navy);
  box-shadow: 0 8px 22px rgb(0 0 0 / 0.4);
  font-family: var(--rp-font-mono);
  font-size: 10px; letter-spacing: 0.08em; text-transform: uppercase;
  border-radius: 8px; padding: 6px 11px;
  opacity: 0; pointer-events: none; transition: opacity .15s ease;
}
.rp-spot:hover .rp-spot__tip,
.rp-spot:focus-visible .rp-spot__tip { opacity: 1; }

/* The detail card */
.rp-xpanel {
  background: var(--rp-navy);
  border: 1px solid rgb(255 255 255 / 0.1);
  border-radius: 18px;
  overflow: hidden;
  color: #fff;
  box-shadow: 0 30px 70px -24px rgb(0 0 0 / 0.5);
  display: flex; flex-direction: column;
}
html.rp-explorer-js .rp-xpanel__card { display: none; }
html.rp-explorer-js .rp-xpanel__card.is-on { display: block; }

/* overflow:hidden is load-bearing — the ambient iframe below is deliberately
   wider than this box and relies on being clipped. */
.rp-xpanel__media { position: relative; overflow: hidden; background: var(--rp-navy-deep); aspect-ratio: 16 / 10; }
.rp-xpanel__media video,
.rp-xpanel__media .rp-xpanel__poster { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; border: 0; display: block; }

/* The fallback image sits UNDER the player. Nothing swaps it out: if Vimeo is
   unreachable the iframe paints nothing and this is simply what shows. */
.rp-xpanel__poster { z-index: 0; }
.rp-xpanel__media video,
.rp-xpanel__media iframe { z-index: 1; }

/* object-fit does NOTHING to an iframe — the Vimeo player letterboxes itself
   inside whatever box it is handed, which is why a 16:9 clip showed bars in
   this 16:10 panel. To crop-to-fill instead, match the panel's HEIGHT and let
   the width overflow: a 16:9 rectangle as tall as a 16:10 one of the same
   width is 10/9 = 111.12% of its width. The overflow is clipped above.
   pointer-events:none because there are no controls to click and the card
   underneath is the thing meant to receive the click. */
.rp-xpanel__media iframe {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  height: 100%;
  width: 111.12%;
  min-width: 100%;
  border: 0;
  display: block;
  pointer-events: none;
}
.rp-xpanel__media--empty {
  display: flex; align-items: center; justify-content: center;
  font-family: var(--rp-font-mono);
  font-size: 10px; letter-spacing: 0.18em; text-transform: uppercase;
  color: var(--rp-blue-mid);
}
.rp-xpanel__divider { height: 2px; background: var(--rp-rule-teal); flex: none; }
.rp-xpanel__bd { padding: 22px 24px 24px; }
.rp-xpanel__no { margin: 0 0 8px; font-family: var(--rp-font-mono); font-size: 10.5px; font-weight: 500; letter-spacing: 0.18em; text-transform: uppercase; color: var(--rp-amber-soft); }
.rp-xpanel__h { margin: 0 0 4px; font-size: 22px; font-weight: 600; color: #fff; }
.rp-xpanel__sub { margin: 0 0 12px; font-size: 14px; font-weight: 500; color: var(--rp-teal-light); }
.rp-xpanel__desc { margin: 0; font-size: 15px; line-height: 1.6; color: var(--rp-blue-pale); }

.rp-xpanel__foot {
  margin-top: auto;
  padding: 16px 24px;
  border-top: 1px solid rgb(255 255 255 / 0.12);
  display: flex; align-items: center; gap: 12px;
}
.rp-xpanel__count { font-family: var(--rp-font-mono); font-size: 10.5px; letter-spacing: 0.14em; text-transform: uppercase; color: var(--rp-blue-mid); margin-right: auto; }
.rp-xarrow {
  width: 40px; height: 40px;
  border-radius: 999px;
  border: 1px solid rgb(255 255 255 / 0.28);
  background: transparent;
  color: var(--rp-blue-paler);
  font-size: 15px; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  transition: border-color .15s ease, color .15s ease;
}
.rp-xarrow:hover { border-color: var(--rp-amber); color: var(--rp-amber); }
.rp-xpanel__cta {
  display: block;
  padding: 14px 24px;
  background: rgb(255 255 255 / 0.04);
  border-top: 1px solid rgb(255 255 255 / 0.1);
  font-family: var(--rp-font-mono);
  font-size: 10.5px; font-weight: 500; letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--rp-amber);
  text-decoration: none;
}
.rp-xpanel__cta:hover { color: var(--rp-amber-soft); }

/* The chip rail */
.rp-xlegend { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 40px; align-items: center; }
.rp-xchip, .rp-xtour {
  border: 1px solid rgb(255 255 255 / 0.24);
  background: rgb(255 255 255 / 0.04);
  color: var(--rp-blue-paler);
  font-family: var(--rp-font-mono);
  font-size: 10.5px; letter-spacing: 0.1em; text-transform: uppercase;
  border-radius: 999px; padding: 11px 18px;
  cursor: pointer;
  transition: border-color .15s ease, background-color .15s ease, color .15s ease;
}
.rp-xchip:hover, .rp-xtour:hover { border-color: var(--rp-amber); color: #fff; }
.rp-xchip[aria-selected="true"] { background: #fff; border-color: #fff; color: var(--rp-navy); }
.rp-xtour::before { content: "\25B6"; margin-right: 8px; font-size: 9px; }
.rp-xtour[aria-pressed="true"]::before { content: "\25A0"; }
/* The rail is the only control on a phone: the dots are 42px on a plan that has
   shrunk to a third of its width, which is not a usable target. */
@media (max-width: 700px) {
  .rp-plan__spots { display: none; }
}

/* ── Axona: software-side variants ───────────────────────────────────────────
   Teal is the software accent throughout. It is the AA-safe --rp-grad-teal on
   light surfaces and --rp-teal-light on dark, never the design's raw #2E8C99,
   which measures 3.52 on sand.
   ─────────────────────────────────────────────────────────────────────────── */

.rp-hero--teal .rp-eyebrow { color: var(--rp-teal-light); }
/* align-self, and it is doing the real work here. The hero's container is a
   flex column, so a block-level item with `width: auto` stretches to the cross
   axis — the 480x148 wordmark came out 1240x44, squashed flat across the whole
   hero. `width: auto` alone cannot prevent that; opting out of the stretch can.
   The class is on the <img> itself: b_image() takes no wrapper, which is why
   the older `.rp-hero__lockup img` rule above matches nothing. */
.rp-hero__lockup { display: block; align-self: flex-start; width: auto; height: 44px; margin-bottom: 14px; }

/* A screenshot in a two-up: a hairline and a shadow, no gradient panel. */
.rp-shot { margin: 0; align-self: start; }
.rp-shot img {
  display: block; width: 100%; height: auto;
  border-radius: 14px;
  border: 1px solid rgb(18 33 46 / 0.12);
  box-shadow: 0 30px 64px -22px rgb(18 33 46 / 0.3);
}
.rp-shot .rp-vidcap { margin-top: 14px; }

/* Two headings side by side, each carrying its own argument. */
.rp-duo { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 76px; align-items: start; }
@media (max-width: 900px) { .rp-duo { grid-template-columns: 1fr; gap: 40px; } }
.rp-duo__h { margin: 0; font-family: var(--rp-font-display); font-stretch: 112%; font-size: var(--rp-text-h2); line-height: 1.05; letter-spacing: var(--rp-track-h2); color: var(--rp-navy); }
.rp-duo__rule { width: 78px; height: 3px; margin: 26px 0 24px; border-radius: 2px; background: var(--rp-accent-gradient); }
.rp-duo__rule--teal { background: var(--rp-rule-teal); }
.rp-duo__body { font-size: var(--rp-text-base); line-height: var(--rp-lh-body); color: var(--rp-slate); max-width: 56ch; }
.rp-duo__body p { margin: 0 0 18px; }
.rp-duo__body p:last-child { margin-bottom: 0; }

.rp-eyebrow--teal { color: var(--rp-grad-teal); }

.rp-section--navy .rp-duo__h, .rp-section--deepflat .rp-duo__h { color: #fff; }
.rp-section--navy .rp-duo__body, .rp-section--deepflat .rp-duo__body { color: var(--rp-blue-pale); }
.rp-section--navy .rp-eyebrow--teal, .rp-section--deepflat .rp-eyebrow--teal { color: var(--rp-teal-light); }

/* The second heading is the subordinate one in the designs, set a size down. */
.rp-duo__col:nth-child(2) .rp-duo__h { font-size: clamp(24px, 2.6vw, 34px); }

/* The quiet closing paragraph in a two-up: smaller, greyer, and clearly a
   footnote to the list above it rather than another item in it. */
.rp-note { font-size: 15px; color: var(--rp-body-2); }
.rp-grid2__rule--teal { background: var(--rp-rule-teal); }
.rp-headsplit--teal .rp-headsplit__rule { background: var(--rp-rule-teal); }

/* A feature row that follows TWO heads is separated from them by a rule, as in
   the design's plain `.featcols`. Everywhere else on this site the row follows
   a single head and sits flush, which is the design's `.featcols.nogap` — that
   is what .rp-featcols already is, so this adds the divider back rather than
   taking it away. */
.rp-duo + .rp-featcols { margin-top: 84px; padding-top: 34px; border-top: 1px solid rgb(255 255 255 / 0.14); }
.rp-section--sand .rp-duo + .rp-featcols,
.rp-section--paper .rp-duo + .rp-featcols { border-top-color: rgb(18 33 46 / 0.12); }

/* The two heritage marks on why-robopharma: each on its own white card, so a
   dark logo and a colour logo sit together without one of them disappearing
   into the sand background. */
.rp-marks { display: flex; flex-wrap: wrap; gap: 14px; margin: 26px 0 22px; }
.rp-mark {
  display: inline-flex; align-items: center;
  background: #fff;
  border: 1px solid rgb(18 33 46 / 0.12);
  border-radius: 12px;
  padding: 14px 22px;
}
.rp-mark img { display: block; width: auto; height: 30px; }

/* ── Marketo form ────────────────────────────────────────────────────────────
   The consultation form is Marketo's markup, restyled to the design's `.cfform`.
   assets/js/marketo-form.js strips Marketo's stylesheets and its inline widths
   first; without that step none of this wins, because inline styles beat every
   selector. `.is-styled` is added by that script, so if it never runs the form
   keeps Marketo's own styling rather than getting half of each.
   ─────────────────────────────────────────────────────────────────────────── */

.rp-mkto.is-styled {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 22px 24px;
  width: 100% !important;
  max-width: none;
  font-family: var(--rp-font-body);
}
@media (max-width: 760px) { .rp-mkto.is-styled { grid-template-columns: 1fr; } }

/* Marketo does NOT emit one row per field — it pairs them, and correctly:
   FirstName+LastName, Company+Title, Email+Phone, CountryCode+StateCode are
   each a single .mktoFormRow holding two .mktoFormCol. Treating the ROW as the
   grid cell therefore stacked each pair vertically inside one half-width cell,
   while the single-field rows sat alongside — which is what put Company next to
   First Name and Country next to Email.

   `display: contents` drops the row box out of the layout so each COLUMN
   becomes the grid item. Marketo's own pairing then lands two to a line by
   itself, and the pairs are the ones the form already intends. */
.rp-mkto.is-styled .mktoFormRow { display: contents; }
.rp-mkto.is-styled .mktoFormCol { min-width: 0; width: 100% !important; }

/* A row that carries no visible control — the utm tracking fields are hidden
   inputs — would otherwise contribute empty cells and punch holes in the grid.
   :has() on the row still works: it is display:contents, not display:none. */
.rp-mkto.is-styled .mktoFormCol:not(:has(input:not([type="hidden"]), select, textarea, .mktoCheckboxList, .mktoHtmlText)) {
  display: none;
}
.rp-mkto.is-styled .mktoFieldWrap { display: flex; flex-direction: column; gap: 8px; min-width: 0; width: 100% !important; }

.rp-mkto.is-styled .mktoLabel {
  width: auto !important;
  float: none;
  font-family: var(--rp-font-mono);
  font-size: 10.5px;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--rp-slate);
  line-height: 1.4;
}
.rp-mkto.is-styled .mktoAsterix { float: none; display: inline; padding: 0 0 0 2px; color: var(--rp-burnt); }

.rp-mkto.is-styled .mktoField,
.rp-mkto.is-styled input[type="text"],
.rp-mkto.is-styled input[type="email"],
.rp-mkto.is-styled input[type="tel"],
.rp-mkto.is-styled select,
.rp-mkto.is-styled textarea {
  width: 100% !important;
  height: auto;
  font-family: var(--rp-font-body);
  font-size: 15.5px;
  color: var(--rp-navy);
  background: #fff;
  border: 1px solid rgb(18 33 46 / 0.18);
  border-radius: 10px;
  padding: 14px 15px;
  appearance: none;
  transition: border-color .18s ease, box-shadow .18s ease;
}
.rp-mkto.is-styled textarea { min-height: 140px; resize: vertical; }
.rp-mkto.is-styled ::placeholder { color: var(--rp-slate-light); }

.rp-mkto.is-styled select {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2355636E' stroke-width='2'><path d='M6 9l6 6 6-6'/></svg>");
  background-repeat: no-repeat;
  background-position: right 14px center;
  background-size: 16px;
  padding-right: 42px;
}

.rp-mkto.is-styled :is(input, select, textarea):focus {
  outline: none;
  border-color: var(--rp-amber);
  box-shadow: 0 0 0 3px rgb(248 170 20 / 0.22);
}

/* A textarea, the opt-in and the button each take the full width, as in the
   design. Marketo marks the textarea row with mktoTextArea on the field. */
/* Full-width fields. These target the COLUMN, not the row: the row is
   display:contents above, so it is not a grid item and grid-column on it would
   do nothing at all. The comments box and the opt-in checkbox both span. */
.rp-mkto.is-styled .mktoFormCol:has(textarea),
.rp-mkto.is-styled .mktoFormCol:has(.mktoCheckboxList),
.rp-mkto.is-styled .mktoFormCol:has(.mktoHtmlText),
.rp-mkto.is-styled .mktoButtonRow { grid-column: 1 / -1; }

/* Opt-in checkbox */
.rp-mkto.is-styled .mktoCheckboxList { display: flex; gap: 12px; align-items: flex-start; width: 100% !important; padding: 0; }
.rp-mkto.is-styled .mktoCheckboxList input[type="checkbox"] {
  width: 18px !important; height: 18px; flex: none; margin-top: 2px;
  accent-color: var(--rp-burnt); appearance: auto; padding: 0; border-radius: 3px;
}
.rp-mkto.is-styled .mktoCheckboxList label { font-family: var(--rp-font-body); font-size: 14px; line-height: 1.55; text-transform: none; letter-spacing: 0; color: var(--rp-slate); }

/* Any rich text Marketo carries — consent copy, fine print. */
.rp-mkto.is-styled .mktoHtmlText { width: 100% !important; font-size: 14px; line-height: 1.55; color: var(--rp-slate); }
.rp-mkto.is-styled .mktoHtmlText a { color: var(--rp-burnt); text-decoration: underline; }

/* The submit button, wearing the site's primary button. */
.rp-mkto.is-styled .mktoButtonRow { display: flex; }
.rp-mkto.is-styled .mktoButtonWrap { margin-left: 0 !important; }
.rp-mkto.is-styled .mktoButton {
  font-family: var(--rp-font-mono) !important;
  font-size: 11px !important;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--rp-navy) !important;
  background: var(--rp-amber) !important;
  background-image: none !important;
  border: 0 !important;
  border-radius: 999px !important;
  padding: 16px 30px !important;
  cursor: pointer;
  box-shadow: 0 12px 34px rgb(248 170 20 / 0.35);
  transition: transform .15s ease, box-shadow .15s ease;
}
.rp-mkto.is-styled .mktoButton:hover { transform: translateY(-1px); box-shadow: 0 16px 40px rgb(248 170 20 / 0.45); }

/* Validation. Marketo's own error bubble is positioned absolutely off inline
   styles we have just removed, so it is pinned back under its field. */
.rp-mkto.is-styled .mktoError { position: static !important; grid-column: 1 / -1; }
.rp-mkto.is-styled .mktoErrorMsg {
  display: block; margin-top: 6px;
  background: none; border: 0; box-shadow: none; text-shadow: none;
  font-size: 13px; color: #a1140c;
}
.rp-mkto.is-styled .mktoErrorArrow { display: none; }

/* The card the consultation form sits in. */
.rp-formcard {
  max-width: 900px;
  margin: 0 auto;
  background: var(--rp-paper);
  border: 1px solid rgb(18 33 46 / 0.12);
  border-radius: 18px;
  padding: clamp(26px, 4vw, 48px);
  box-shadow: 0 30px 64px -30px rgb(18 33 46 / 0.34);
  text-align: left;
}
.rp-section--form .rp-section__head { margin-bottom: 32px; }

/* Marketo puts the required asterisk FIRST in the label's DOM; the design puts
   it after the text. Flex plus order moves it without touching Marketo's
   markup, which is theirs to change, not ours. */
.rp-mkto.is-styled .mktoLabel { display: flex; align-items: baseline; gap: 3px; }
.rp-mkto.is-styled .mktoAsterix { order: 2; }

/* The opt-in's label is the consent sentence, not a field name, so it should
   not wear the uppercase mono treatment the other labels do. Matched on the row
   actually containing a checkbox rather than on a Marketo class, because which
   wrapper class it uses depends on how the field was built in Marketo. */
.rp-mkto.is-styled .mktoFormRow:has(input[type="checkbox"]) .mktoLabel {
  display: block;
  font-family: var(--rp-font-body);
  font-size: 14px;
  font-weight: 400;
  line-height: 1.55;
  letter-spacing: 0;
  text-transform: none;
  color: var(--rp-slate);
}
.rp-mkto.is-styled .mktoFormRow:has(input[type="checkbox"]) .mktoAsterix { display: none; }

/* Marketo renders the opt-in as label THEN checkbox, stacked. The design has
   the box beside the sentence, so the row becomes a flex and the box is
   ordered first. */
.rp-mkto.is-styled .mktoFormRow:has(input[type="checkbox"]) .mktoFieldWrap {
  flex-direction: row;
  align-items: flex-start;
  gap: 12px;
}
.rp-mkto.is-styled .mktoFormRow:has(input[type="checkbox"]) .mktoLogicalField,
.rp-mkto.is-styled .mktoFormRow:has(input[type="checkbox"]) .mktoCheckboxList { order: -1; width: auto !important; flex: none; }
.rp-formcard .rp-eventcard { margin-top: 0; }

/* Under the form, the event strip lines up with the card rather than the
   container — the design gives it the card's 900px measure. */
.rp-section--form .rp-eventcard { max-width: 900px; margin-inline: auto; }

/* The install map. Same explorer, on a light section: the markers are plain
   discs rather than numbered, and the panel's subtitle is the daily figure, so
   it takes the numeral face. */
.rp-explorer--sites { grid-template-columns: minmax(300px, 380px) minmax(0, 1fr); }
.rp-explorer--sites .rp-spot { width: 26px; height: 26px; font-size: 0; }
.rp-explorer--sites .rp-xpanel__sub {
  font-family: var(--rp-font-data);
  font-size: 30px;
  font-weight: var(--rp-numeral-weight);
  letter-spacing: -0.03em;
  color: #fff;
  margin: 6px 0 14px;
}
.rp-explorer--sites .rp-xpanel__media { aspect-ratio: 16 / 10; }
.rp-explorer--sites .rp-xpanel__media img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
/* NO PLATE behind the map. The export is a navy cut-out on transparency, so it
   reads as land shapes floating on the light section — which is the design.
   Boxing it in a navy panel turned the sea into a slab. The drop shadow the
   floor plan carries goes too: a flat map does not cast one. */
.rp-explorer--sites .rp-plan img { filter: none; }
/* On a light section the chip rail needs light-surface colours. */
.rp-section--paper .rp-xchip, .rp-section--sand .rp-xchip,
.rp-section--paper .rp-xtour, .rp-section--sand .rp-xtour {
  border-color: rgb(18 33 46 / 0.18);
  background: #fff;
  color: var(--rp-slate);
}
.rp-section--paper .rp-xchip:hover, .rp-section--sand .rp-xchip:hover,
.rp-section--paper .rp-xtour:hover, .rp-section--sand .rp-xtour:hover { border-color: var(--rp-burnt); color: var(--rp-navy); }
.rp-section--paper .rp-xchip[aria-selected="true"], .rp-section--sand .rp-xchip[aria-selected="true"] {
  background: var(--rp-navy); border-color: var(--rp-navy); color: #fff;
}

/* A PHOTOGRAPH fills the card's panel; a cut-out render sits contained on the
   warm gradient with padding. Using the render treatment for a photograph
   leaves it floating small in the middle of a gradient it was never shot for. */
.rp-card2--cover .rp-card2__photo { background: var(--rp-navy-deep); }
.rp-card2--cover .rp-card2__photo img { object-fit: cover; padding: 0; }

/* Photographs in a card wear the same treatment as the path cards: shipped in
   colour, greyscaled here, so one asset serves both and the palette stays the
   amber-on-navy one the design specifies. Matches .rp-path__media img. */
.rp-card2--cover .rp-card2__photo img { filter: grayscale(1) contrast(1.08) brightness(0.94); }

/* ── Legal prose ────────────────────────────────────────────────────────────
   Privacy policy, cookie policy, terms. One column at the site's reading
   measure, because a policy is read rather than scanned and full-width legal
   text is the most reliably unread thing on any website. Type comes from the
   tokens; only rhythm and the list treatment are set here. */
/* The MEASURE belongs to the text, not to the block. Constraining the whole
   body was right when this only held policies — every child was a paragraph —
   but it traps a data table in a 57ch column and leaves a third of the page
   empty beside it. Prose keeps the measure; tables get the full container. */
.rp-legal__body { max-width: none; }
.rp-legal__body > p,
.rp-legal__body > ul,
.rp-legal__body > ol,
.rp-legal__body > h3,
.rp-legal__body > h4,
.rp-legal__body > .rp-legal__toc { max-width: var(--rp-container-text); }
.rp-legal__body > *:first-child { margin-top: 0; }

/* Two related tables side by side, stacking on narrow viewports. */
.rp-tablepair { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 20px 48px; margin-bottom: 1.6em; }
.rp-tablepair .rp-tablewrap { margin-bottom: 0; }
.rp-tablepair .rp-table { min-width: 0; }
@media (max-width: 900px) { .rp-tablepair { grid-template-columns: 1fr; gap: 34px; } }
.rp-legal__body h3 {
  font-family: var(--rp-font-display);
  font-size: clamp(1.25rem, 1.1rem + 0.6vw, 1.6rem);
  line-height: 1.2;
  margin: 2.4em 0 0.7em;
}
.rp-legal__body h4 {
  font-family: var(--rp-font-body);
  font-weight: 600;
  font-size: 1.0625rem;
  margin: 1.8em 0 0.5em;
}
.rp-legal__body p { margin: 0 0 1.1em; }
.rp-legal__body ul { margin: 0 0 1.4em; padding: 0; list-style: none; }
.rp-legal__body ul li {
  position: relative;
  padding-left: 1.4em;
  margin-bottom: 0.7em;
}
.rp-legal__body ul li::before {
  content: "";
  position: absolute;
  left: 0.15em;
  top: 0.62em;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--rp-amber);
}
.rp-legal__body a { color: var(--rp-burnt); text-decoration: underline; text-underline-offset: 2px; }
.rp-legal__body a:hover { text-decoration-thickness: 2px; }
/* The contents list at the top: a plain index, not bulleted prose. */
.rp-legal__toc ul li { padding-left: 0; margin-bottom: 0.4em; }
.rp-legal__toc ul li::before { display: none; }

/* Policy links sit with the copyright rather than in the footer nav, so they
   read as fine print and do not compete with the site links beside them. */
.rp-footer__policy { margin-left: 1.1em; text-decoration: underline; text-underline-offset: 2px; }
.rp-footer__policy:hover { text-decoration-thickness: 2px; }

/* ── Data table ─────────────────────────────────────────────────────────────
   Used by the cookie policy (what each cookie does) and the project-type pages
   (inputs and their owners). Deliberately generic and not scoped to .rp-legal,
   because the two callers are a legal page and a marketing page.
   Scrolls inside its own wrapper so a narrow viewport never scrolls the page. */
.rp-tablewrap { overflow-x: auto; margin: 0 0 1.6em; -webkit-overflow-scrolling: touch; }
.rp-table { width: 100%; border-collapse: collapse; font-size: 0.9375rem; min-width: 34rem; }
.rp-table caption { text-align: left; font-family: var(--rp-font-mono); font-size: 11.5px;
  letter-spacing: 0.16em; text-transform: uppercase; color: var(--rp-burnt); padding-bottom: 0.9em; }
.rp-table th, .rp-table td { text-align: left; padding: 0.7em 1.1em 0.7em 0; vertical-align: top;
  border-bottom: 1px solid var(--rp-line); }
.rp-table th { font-weight: 600; white-space: nowrap; }
.rp-table thead th { font-family: var(--rp-font-mono); font-size: 11.5px; letter-spacing: 0.12em;
  text-transform: uppercase; font-weight: 500; }
.rp-table tbody tr:last-child th, .rp-table tbody tr:last-child td { border-bottom: 0; }
.rp-table code { font-family: var(--rp-font-mono); font-size: 0.9em; }

/* A photograph in the two-up frame. Fills it edge to edge and takes a fixed
   aspect so the copy beside it stays balanced whatever the source crop. */
.rp-frame--photo { aspect-ratio: 4 / 3; }
@media (max-width: 900px) { .rp-frame--photo { aspect-ratio: 16 / 10; } }

/* ── 08. Room beneath the breadcrumb on interior page headers ────────────────
   26px -> 42px. The homepage is excluded with the test the theme already uses
   at .rp-section.rp-hero:has(.rp-formfactors) — its header carries the
   form-factor chip bar and interior headers do not — rather than a new
   page-specific rule. Covers both the breadcrumb and the plain-label headers,
   and is placed last because .rp-hero .rp-eyebrow is declared several times
   further up and the later declaration is the one that wins. */
.rp-hero:not(:has(.rp-formfactors)) .rp-crumb,
.rp-hero:not(:has(.rp-formfactors)) .rp-eyebrow {
  margin-bottom: 42px;
}
