/* ==========================================================================
   RapidFoundry — the studio's own design language.
   ==========================================================================
   This is the whole frontend design. The ONLY things inherited from the
   shared startup-cms base are the navbar and the footer markup; both are
   retuned here with colour-level CSS only and are never forked.

   Structure
     1  Brand tokens
     2  Framework retune (admin-guarded) — navbar, footer, buttons follow
     3  Page shell + full-bleed band system
     4  Typography
     5  Hero
     6  Media frames
     7  Cards, stats, products, the loop, FAQ
     8  CTA bands
     9  Contact page
    10  Motion
    11  Responsive

   EVERY rule that can reach a framework element carries the admin guard
   `:not(:has(.admin-container))`. /admin/* must stay framework-default.
   ========================================================================== */

/* ── 1  Brand tokens ──────────────────────────────────────────────────────
   RapidFoundry is DARK ONLY. There is no light palette: the tokens below are
   declared once on :root and re-asserted on `body.theme-light` in section 2,
   so even a stored `theme=light` preference (or the framework default
   changing) still renders the dark design. The navbar theme switch is hidden
   for the same reason.

   Colour policy: the UI is monochrome — white, grey, black. The ONE red is
   reserved for the primary call to action and nothing else. Do not reach for
   it for links, borders, icons or labels.
   ------------------------------------------------------------------------ */

:root {
  --rf-canvas: #000000;
  --rf-canvas-alt: #0a0a0b;
  --rf-canvas-deep: #000000;
  --rf-ink: #f5f5f7;
  --rf-ink-muted: #a1a1a6;
  --rf-ink-dim: #6e6e73;

  /* The single accent. #d92d20 clears 4.5:1 against white label text; the
     brighter reds (#ff3b30) do not, and this text is a button label. */
  --rf-accent: #d92d20;
  --rf-accent-hover: #b42318;

  --rf-hairline: rgba(255, 255, 255, 0.12);
  --rf-hairline-strong: rgba(255, 255, 255, 0.24);
  --rf-surface: rgba(255, 255, 255, 0.045);
  --rf-surface-hover: rgba(255, 255, 255, 0.085);
  /* Inset panel fill, flipped by .rf-band--light. */
  --rf-plate: rgba(10, 10, 11, 0.72);

  --rf-radius: 18px;
  --rf-radius-lg: 28px;
  --rf-radius-pill: 980px;

  --rf-band-pad: clamp(88px, 11vw, 176px);
  --rf-gutter: clamp(20px, 5vw, 40px);
  --rf-measure: 1120px;
  --rf-measure-narrow: 780px;

  --rf-font:
    'Geist', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui,
    sans-serif;
  --rf-font-mono: 'Geist Mono', var(--font-monospace);

  --rf-ease: cubic-bezier(0.32, 0.72, 0, 1);
}

/* ── 2  Framework retune ────────────────────────────────────────────────────
   base_style.css derives nearly everything from --primary-blue, and
   base_elements.css paints .btn-primary from --cta-gradient-*. Redefining
   those variables re-themes the navbar, footer, links, modals, dropdowns,
   auth pages and the user panel in one move — which is why the button rules
   below are scoped ONLY by the admin guard and never by .rf-page. Scoping
   them to the page wrapper would leave every framework modal on the old
   palette.

   Both theme classes get the SAME (dark) values: that is what makes the light
   theme unreachable rather than merely non-default.
   ------------------------------------------------------------------------ */

body.theme-light:not(:has(.admin-container)),
body.theme-dark:not(:has(.admin-container)) {
  /* Monochrome: the framework's "primary" hue becomes ink, so chevrons,
     focus rings and inline links read as white/grey rather than blue. */
  --primary-blue: var(--rf-ink);
  --primary-blue-hover: #ffffff;
  --primary-color: var(--rf-ink);
  --primary-hover: #ffffff;
  --link: var(--rf-ink);
  --link-hover: #ffffff;
  --text-color: var(--rf-ink);
  --text-primary: var(--rf-ink);
  --text-secondary: var(--rf-ink-muted);
  --muted-text: var(--rf-ink-muted);
  --heading-color: var(--rf-ink);
  --heading-sub: var(--rf-ink);
  --border-color: var(--rf-hairline);
  --container-bg: var(--rf-canvas);
  --card-bg: var(--rf-surface);
  --input-bg: #0e0e10;
  --dropdown-bg: #0e0e10;
  --bg-dark: #000000;
  --footer-nav-bg: var(--rf-canvas-alt);
  --footer-bottom-bg: var(--rf-canvas-alt);
  --footer-section-bg: var(--rf-canvas-alt);
  --footer-border: var(--rf-hairline);
  --shadow-elev: 0 12px 40px rgba(0, 0, 0, 0.6);

  /* base_modal.css declares --modal-surface on :root as
     `var(--card-bg, var(--container-bg, #ffffff))`. Custom properties do not
     inherit upward, so at :root neither --card-bg nor --container-bg (both
     body-level) is visible and the modal fell through to the #ffffff
     fallback. Declaring it here, on the same element that owns those tokens,
     is what actually makes the dialog dark. */
  --modal-surface: #0e0e10;
  --modal-backdrop: rgba(0, 0, 0, 0.72);

  /* The one red. Flat, not a gradient — all three stops are the same colour,
     which also keeps the navbar CTA (--nb-cta-*, same variables) in sync. */
  --cta-gradient-start: var(--rf-accent);
  --cta-gradient-mid: var(--rf-accent);
  --cta-gradient-end: var(--rf-accent);
  --btn-gradient: var(--rf-accent);
  --btn-gradient-hover: var(--rf-accent-hover);

  background: var(--rf-canvas) !important;
  color: var(--rf-ink);
  font-family: var(--rf-font);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

/* The framework paints a light radial --bg-gradient on body.theme-light. */
body.theme-light:not(:has(.admin-container)) {
  --bg-gradient: none;
}

/* Every .btn-primary variant the framework ships, site-wide. base_elements.css
   sets these with !important on each declaration, so the override needs it
   too. This is the only red on the site. */
body:not(:has(.admin-container)) .btn-primary,
body:not(:has(.admin-container)) a.btn-primary,
body:not(:has(.admin-container)) button.btn-primary,
body:not(:has(.admin-container)) .button-primary,
body:not(:has(.admin-container)) a.button-primary,
body:not(:has(.admin-container)) button.button-primary,
body:not(:has(.admin-container)) .btn-primary-action {
  background: var(--rf-accent) !important;
  border-color: var(--rf-accent) !important;
  color: #ffffff !important;
  border-radius: var(--rf-radius-pill) !important;
  font-weight: 500 !important;
  letter-spacing: 0 !important;
  box-shadow: none !important;
  text-decoration: none !important;
  transition: background 0.25s var(--rf-ease);
}

body:not(:has(.admin-container)) .btn-primary:hover,
body:not(:has(.admin-container)) a.btn-primary:hover,
body:not(:has(.admin-container)) button.btn-primary:hover,
body:not(:has(.admin-container)) .button-primary:hover,
body:not(:has(.admin-container)) a.button-primary:hover,
body:not(:has(.admin-container)) button.button-primary:hover,
body:not(:has(.admin-container)) .btn-primary-action:hover {
  background: var(--rf-accent-hover) !important;
  border-color: var(--rf-accent-hover) !important;
}

/* Remapping --primary-blue to ink (for the monochrome UI) breaks an
   assumption the framework makes in ~24 places: "fill with --primary-blue and
   put white text on it". With ink as the fill that is white-on-white — which
   is exactly what made the consent banner's "Accept all" unreadable.

   Two fixes, by intent rather than per-selector patching:
     - a real primary action gets the site's red with white text;
     - active/selected indicators inverse instead (ink fill, black label), so
       they stay monochrome and still have contrast.
   Admin keeps the framework default via the guard. */
body:not(:has(.admin-container)) .base-consent__btn--accent {
  background: var(--rf-accent) !important;
  border-color: var(--rf-accent) !important;
  color: #ffffff !important;
}

body:not(:has(.admin-container)) .base-consent__btn--accent:hover {
  background: var(--rf-accent-hover) !important;
  border-color: var(--rf-accent-hover) !important;
}

body:not(:has(.admin-container)) .base-sidebar__button--primary,
body:not(:has(.admin-container)) .base-sidebar__quick-jump-btn,
body:not(:has(.admin-container)) .base-sidebar-toggle,
body:not(:has(.admin-container)) .dt-paging-button.current,
body:not(:has(.admin-container)) .dropdown-item.active,
body:not(:has(.admin-container))
  .tab-container.variant-pills
  .tab-button.active,
body:not(:has(.admin-container)) .selectable-card-badge,
body:not(:has(.admin-container)) .bdp-panel .bdp-day.is-selected,
body:not(:has(.admin-container)) .blog-feedback .sf-fb__btn.is-active {
  background: var(--rf-ink) !important;
  border-color: var(--rf-ink) !important;
  color: #000000 !important;
}

/* Navbar and footer: colour only. No layout, no structure, no fork.
   The framework navbar is <header class="nb-root"> (base_navbar.css, `nb-`
   prefix) — NOT `.navbar`. */
body:not(:has(.admin-container)) .nb-root {
  --nb-font: var(--rf-font);
  --nb-link-font: var(--rf-font);
  --nb-link-weight: 500;
  --nb-link-tracking: 0;
  --nb-row-font: var(--rf-font);
  border-bottom: 1px solid var(--rf-hairline);
}

/* Dark-only site: the light/dark switch has nothing to switch to. Hidden
   rather than removed, because the control lives in the shared navbar and
   this project must not fork it. */
body:not(:has(.admin-container)) .nb-theme {
  display: none !important;
}

/* The shared navbar sizes its lockup for projects with a wordmark logo; this
   one is a small mark plus plain text, and at the base size it out-weighed the
   nav links beside it. */
body:not(:has(.admin-container)) .nb-brand__badge {
  background: #141416 !important;
  border-color: var(--rf-hairline) !important;
  width: 28px !important;
  height: 28px !important;
  border-radius: 8px !important;
}

body:not(:has(.admin-container)) .nb-brand__img {
  width: 18px !important;
  height: 18px !important;
}

body:not(:has(.admin-container)) .nb-brand__text {
  font-size: 16px !important;
  font-weight: 600 !important;
  letter-spacing: -0.2px !important;
}

body:not(:has(.admin-container)) .footer {
  background: var(--rf-canvas-alt) !important;
  border-top: 1px solid var(--rf-hairline) !important;
}

body:not(:has(.admin-container)) .footer::before {
  display: none !important;
}

/* ── 3  Page shell + band system ───────────────────────────────────────────
   .rf-main replaces the framework's .container wrapper entirely, so bands
   run edge to edge and each one caps its own content width. `main` itself
   only carries `flex: 1` in the base sheet, so nothing else needs undoing.
   ------------------------------------------------------------------------ */

.rf-main {
  width: 100%;
  max-width: 100%;
  padding: 0;
  margin: 0;
  overflow-x: clip;
}

.rf-page {
  color: var(--rf-ink);
  font-family: var(--rf-font);
  font-size: 17px;
  line-height: 1.55;
}

.rf-band {
  position: relative;
  width: 100%;
  padding: var(--rf-band-pad) var(--rf-gutter);
  overflow: hidden;
  background: var(--rf-canvas);
  isolation: isolate;
}

/* Every section is image-backed. The plate sits behind the content and is
   dimmed hard so body copy keeps its contrast without a flat grey scrim
   killing the highlight in the artwork. */
.rf-band__bg {
  position: absolute;
  inset: 0;
  z-index: -2;
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: grayscale(18%) brightness(0.38);
}

.rf-band::after {
  position: absolute;
  inset: 0;
  z-index: -1;
  content: '';
  background: linear-gradient(
    180deg,
    rgba(0, 0, 0, 0.86) 0%,
    rgba(0, 0, 0, 0.62) 42%,
    rgba(0, 0, 0, 0.88) 100%
  );
}

/* Copy sits on the left half; the plate carries the right. */
.rf-band--right::after {
  background: linear-gradient(
    90deg,
    rgba(0, 0, 0, 0.92) 0%,
    rgba(0, 0, 0, 0.72) 46%,
    rgba(0, 0, 0, 0.34) 100%
  );
}

/* A quieter plate for sections whose content is dense (steps, product lists). */
.rf-band--quiet .rf-band__bg {
  filter: grayscale(40%) brightness(0.22);
}

.rf-band__inner {
  width: 100%;
  max-width: var(--rf-measure);
  margin: 0 auto;
}

.rf-band__inner--narrow {
  max-width: var(--rf-measure-narrow);
}

/* A pale band. The site has no light theme — this is a section surface used
   two or three times a page so the dark run does not read as one long block.
   It re-declares the ink tokens locally, so every child (cards, hairlines,
   inset panels) flips with it and nothing needs a per-element override. */
.rf-band--light {
  background: #f5f5f7;
  --rf-ink: #1d1d1f;
  --rf-ink-muted: #6e6e73;
  --rf-ink-dim: #86868b;
  --rf-hairline: rgba(0, 0, 0, 0.1);
  --rf-hairline-strong: rgba(0, 0, 0, 0.2);
  --rf-surface: rgba(0, 0, 0, 0.03);
  --rf-surface-hover: rgba(0, 0, 0, 0.055);
  --rf-plate: rgba(255, 255, 255, 0.82);
  color: var(--rf-ink);

  /* The framework tokens have to be re-declared HERE, not just inherited.
     `--heading-color: var(--rf-ink)` on body computes to the dark ink at body
     level and then inherits as a fixed value, so a framework component inside
     a pale band (a collapse row, an input, a badge) kept painting white text
     on white. Re-declaring them on this element resolves them against the
     light values above. */
  --text-color: var(--rf-ink);
  --text-primary: var(--rf-ink);
  --text-secondary: var(--rf-ink-muted);
  --muted-text: var(--rf-ink-muted);
  --heading-color: var(--rf-ink);
  --heading-sub: var(--rf-ink);
  --border-color: var(--rf-hairline);
  --card-bg: var(--rf-surface);
  --item-bg: var(--rf-surface);
  /* base_elements.css paints buttons `var(--container-bg) !important`, which
     was still the black canvas here — that is what turned the carousel arrows
     into black discs with a black arrow on them. */
  --rf-canvas: #f5f5f7;
  --container-bg: #f5f5f7;
  --input-bg: #ffffff;
  --dropdown-bg: #ffffff;
  --primary-blue: var(--rf-ink);
  --primary-color: var(--rf-ink);
  --link: var(--rf-ink);
  --link-hover: #000000;
}

/* The plate stays, but as a pale texture rather than a photograph. */
.rf-band--light .rf-band__bg {
  filter: grayscale(100%) brightness(1.9) contrast(0.7);
  opacity: 0.32;
}

.rf-band--light::after {
  background: linear-gradient(
    180deg,
    rgba(245, 245, 247, 0.9) 0%,
    rgba(245, 245, 247, 0.72) 42%,
    rgba(245, 245, 247, 0.94) 100%
  );
}

.rf-band--light.rf-band--right::after {
  background: linear-gradient(
    90deg,
    rgba(245, 245, 247, 0.95) 0%,
    rgba(245, 245, 247, 0.8) 46%,
    rgba(245, 245, 247, 0.5) 100%
  );
}

/* Statement and quote are painted white for the dark bands; on a pale band
   they have to follow the local ink instead. */
.rf-band--light .rf-statement,
.rf-band--light .rf-quote blockquote {
  color: var(--rf-ink);
}

/* In-page anchors ("See our products") glide rather than jump. Scoped with
   :has() to pages that actually carry .rf-page, so framework and admin pages
   keep their default jump behaviour. Skipped entirely under reduced motion. */
@media (prefers-reduced-motion: no-preference) {
  html:has(.rf-page) {
    scroll-behavior: smooth;
  }
}

/* The navbar is fixed, so an anchored section has to stop clear of it. */
.rf-page [id] {
  scroll-margin-top: 90px;
}

/* ── 4  Typography ─────────────────────────────────────────────────────── */

.rf-display {
  margin: 0 0 24px;
  font-size: clamp(42px, 6.4vw, 80px);
  font-weight: 600;
  line-height: 1.05;
  letter-spacing: -2px;
  color: var(--rf-ink);
  text-wrap: balance;
}

.rf-h2 {
  margin: 0 0 20px;
  font-size: clamp(32px, 4.2vw, 52px);
  font-weight: 600;
  line-height: 1.08;
  letter-spacing: -1px;
  color: var(--rf-ink);
  text-wrap: balance;
}

.rf-h3 {
  margin: 0 0 10px;
  font-size: 20px;
  font-weight: 600;
  line-height: 1.3;
  color: var(--rf-ink);
}

.rf-lead {
  max-width: 62ch;
  margin: 0 0 32px;
  font-size: clamp(18px, 1.6vw, 21px);
  font-weight: 400;
  line-height: 1.5;
  color: var(--rf-ink-muted);
  text-wrap: pretty;
}

.rf-body {
  max-width: 66ch;
  margin: 0 0 16px;
  font-size: 17px;
  line-height: 1.6;
  color: var(--rf-ink-muted);
}

.rf-band__head {
  max-width: var(--rf-measure-narrow);
  margin: 0 0 clamp(40px, 5vw, 72px);
}

.rf-band__head--center {
  margin-left: auto;
  margin-right: auto;
  text-align: center;
}

.rf-band__head--center .rf-lead {
  margin-left: auto;
  margin-right: auto;
}

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

.rf-hero {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: min(92vh, 900px);
  padding: calc(var(--navbar-offset) + 48px) var(--rf-gutter) 96px;
  overflow: hidden;
  background: var(--rf-canvas-deep);
  color: var(--rf-ink);
  text-align: center;
}

.rf-hero__media {
  position: absolute;
  inset: 0;
  z-index: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Only a light touch: the footage IS the hero, so it is barely dimmed. The
     headline gets its contrast from the scrim below, which is shaped to stay
     out of the way of the moving parts. */
  filter: saturate(108%) brightness(0.9);
}

.rf-hero__scrim {
  position: absolute;
  inset: 0;
  z-index: 1;
  /* A vertical wash rather than a centred radial: it darkens the top and
     bottom (where the copy sits) and leaves the middle of the frame open so
     the animation stays visible. */
  background: linear-gradient(
    180deg,
    rgba(0, 0, 0, 0.82) 0%,
    rgba(0, 0, 0, 0.34) 38%,
    rgba(0, 0, 0, 0.34) 62%,
    rgba(0, 0, 0, 0.88) 100%
  );
}

/* The headline sits over moving footage, so it carries its own soft shadow
   instead of relying on a heavier scrim. */
.rf-hero .rf-display,
.rf-hero .rf-lead {
  text-shadow: 0 2px 24px rgba(0, 0, 0, 0.6);
}

.rf-hero__inner {
  position: relative;
  z-index: 2;
  max-width: 900px;
}

.rf-hero .rf-display {
  color: #ffffff;
  font-size: clamp(44px, 7vw, 88px);
}

.rf-hero .rf-lead {
  margin-left: auto;
  margin-right: auto;
  color: rgba(255, 255, 255, 0.78);
}

.rf-hero /* ── Buttons owned by this design (not framework .btn-primary) ─────────── */

.rf-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  align-items: center;
}

.rf-actions--center {
  justify-content: center;
}

.rf-btn {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding: 14px 27px;
  border-radius: var(--rf-radius-pill);
  font-family: inherit;
  font-size: 16px;
  font-weight: 500;
  line-height: 1;
  text-decoration: none;
  cursor: pointer;
  transition:
    background 0.25s var(--rf-ease),
    color 0.25s var(--rf-ease),
    border-color 0.25s var(--rf-ease),
    transform 0.25s var(--rf-ease);
}

.rf-btn {
  text-decoration: none;
}

.rf-btn:hover {
  transform: translateY(-1px);
}

.rf-btn--fill {
  background: var(--rf-accent);
  color: #ffffff;
}

.rf-btn--fill:hover {
  background: var(--rf-accent-hover);
  color: #ffffff;
}

.rf-btn--ghost {
  background: transparent;
  color: var(--rf-ink);
}

.rf-btn--ghost:hover {
  background: var(--rf-surface);
}

.rf-hero .rf-btn {
  padding: 18px 34px;
  font-size: 17px;
}

.rf-hero .rf-btn--ghost {
  color: #ffffff;
}

.rf-hero .rf-btn--ghost:hover {
  background: rgba(255, 255, 255, 0.12);
}

/* Text link with the Apple chevron affordance. */
.rf-link {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  color: var(--rf-accent);
  font-size: 17px;
  font-weight: 500;
  text-decoration: none;
}

.rf-link:hover {
  text-decoration: underline;
  text-underline-offset: 3px;
}

.rf-link i {
  font-size: 12px;
  transition: transform 0.25s var(--rf-ease);
}

.rf-link:hover i {
  transform: translateX(3px);
}

/* Outlines on anchor-based components are drawn with an inset box-shadow, not
   a border. base_style.css ends every non-navbar link with
   `a:not(:where([class*='nb-'])) { border-bottom: none !important }`, so a
   real border silently loses its bottom edge; fighting that with !important
   on each side turned into a mess of colour overrides. A box-shadow ring is
   immune to it, needs no !important, and does not affect layout. */
.rf-btn,
.rf-feature,
.rf-product {
  border: 0;
}

.rf-btn--ghost {
  box-shadow: inset 0 0 0 1px var(--rf-hairline-strong);
}

.rf-btn--ghost:hover {
  box-shadow: inset 0 0 0 1px var(--rf-ink);
}

.rf-hero .rf-btn--ghost {
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.4);
}

.rf-hero .rf-btn--ghost:hover {
  box-shadow: inset 0 0 0 1px #ffffff;
}

.rf-feature,
.rf-product {
  box-shadow: inset 0 0 0 1px var(--rf-hairline);
}

.rf-feature:hover,
.rf-product:hover {
  box-shadow: inset 0 0 0 1px var(--rf-hairline-strong);
}

/* ── 6  Media frames ───────────────────────────────────────────────────── */

.rf-figure {
  position: relative;
  overflow: hidden;
  border-radius: var(--rf-radius-lg);
  background: var(--rf-canvas-deep);
  line-height: 0;
}

.rf-figure img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.rf-figure--wide {
  aspect-ratio: 21 / 9;
}

.rf-figure--stage {
  aspect-ratio: 16 / 9;
}

/* Two-up: copy beside a full-height image. */
.rf-split {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(32px, 5vw, 72px);
  align-items: center;
}

.rf-split--reverse .rf-split__media {
  order: -1;
}

.rf-split__copy .rf-lead:last-child,
.rf-split__copy .rf-body:last-child {
  margin-bottom: 0;
}

/* Image behind copy, edge to edge — the cinematic beat. */
.rf-showcase {
  position: relative;
  display: flex;
  align-items: flex-end;
  min-height: min(78vh, 720px);
  padding: clamp(48px, 8vw, 96px);
  overflow: hidden;
  border-radius: var(--rf-radius-lg);
  color: #ffffff;
}

.rf-showcase__media {
  position: absolute;
  inset: 0;
  z-index: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.rf-showcase::after {
  position: absolute;
  inset: 0;
  z-index: 1;
  content: '';
  background: linear-gradient(
    0deg,
    rgba(0, 0, 0, 0.82) 0%,
    rgba(0, 0, 0, 0.35) 48%,
    rgba(0, 0, 0, 0.1) 100%
  );
}

.rf-showcase__inner {
  position: relative;
  z-index: 2;
  max-width: 640px;
}

.rf-showcase .rf-h2,
.rf-showcase .rf-display {
  color: #ffffff;
}

.rf-showcase .rf-lead,
.rf-showcase .rf-body {
  margin-bottom: 0;
  color: rgba(255, 255, 255, 0.8);
}

/* ── 7  Cards, stats, products, the loop, FAQ ──────────────────────────── */

.rf-stats {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1px;
  overflow: hidden;
  border: 1px solid var(--rf-hairline);
  border-radius: var(--rf-radius);
  background: var(--rf-hairline);
}

.rf-stat {
  padding: clamp(28px, 3.4vw, 44px) 24px;
  background: var(--rf-canvas);
  text-align: center;
}

.rf-stat__value {
  margin: 0 0 6px;
  font-size: clamp(36px, 3.6vw, 52px);
  font-weight: 600;
  line-height: 1;
  letter-spacing: -2px;
  color: var(--rf-ink);
  font-variant-numeric: tabular-nums;
}

.rf-stat__label {
  margin: 0;
  font-size: 15px;
  line-height: 1.35;
  color: var(--rf-ink-muted);
}

.rf-grid {
  display: grid;
  gap: clamp(20px, 2.4vw, 32px);
}

.rf-grid--2 {
  grid-template-columns: repeat(2, 1fr);
}

.rf-grid--3 {
  grid-template-columns: repeat(3, 1fr);
}

.rf-grid--4 {
  grid-template-columns: repeat(4, 1fr);
}

.rf-card {
  display: flex;
  flex-direction: column;
  padding: clamp(26px, 2.6vw, 36px);
  border: 1px solid var(--rf-hairline);
  border-radius: var(--rf-radius);
  background: var(--rf-surface);
  transition:
    border-color 0.3s var(--rf-ease),
    background 0.3s var(--rf-ease),
    transform 0.3s var(--rf-ease);
}

.rf-card__num {
  margin: 0 0 14px;
  font-family: var(--rf-font-mono);
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.8px;
  color: var(--rf-ink-dim);
}

.rf-card p {
  margin: 0;
  font-size: 16px;
  line-height: 1.55;
  color: var(--rf-ink-muted);
}

/* Product tiles — the one place a remote favicon appears. */
.rf-product {
  display: flex;
  text-align: left;
  flex-direction: column;
  gap: 14px;
  padding: 28px;
  border-radius: var(--rf-radius);
  background: var(--rf-surface);
  color: inherit;
  text-decoration: none;
  transition:
    border-color 0.3s var(--rf-ease),
    background 0.3s var(--rf-ease),
    transform 0.3s var(--rf-ease);
}

.rf-product:hover {
  background: var(--rf-surface-hover);
  transform: translateY(-3px);
}

.rf-product__mark {
  display: grid;
  place-items: center;
  width: 72px;
  height: 72px;
  overflow: hidden;
}

.rf-product__mark img {
  width: 100%;
  height: 100%;
  object-fit: contain;
}

.rf-product__name {
  margin: 0;
  font-size: 19px;
  font-weight: 600;
  color: var(--rf-ink);
}

.rf-product__desc {
  margin: 0;
  font-size: 15px;
  line-height: 1.55;
  color: var(--rf-ink-muted);
}

/* The loop — a numbered process rail. */
.rf-steps {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 0;
  margin: 0;
  padding: 0;
  list-style: none;
  counter-reset: rf-step;
}

.rf-step {
  position: relative;
  padding: 32px 28px 0 0;
  border-top: 1px solid var(--rf-hairline);
  counter-increment: rf-step;
}

.rf-step::before {
  display: block;
  margin-bottom: 16px;
  content: counter(rf-step, decimal-leading-zero);
  font-family: var(--rf-font-mono);
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.8px;
  color: var(--rf-ink-dim);
}

.rf-step h3 {
  margin: 0 0 8px;
  font-size: 19px;
  font-weight: 600;
  color: var(--rf-ink);
}

.rf-step p {
  margin: 0;
  font-size: 15px;
  line-height: 1.55;
  color: var(--rf-ink-muted);
}

/* About-page variant: three dated milestones rather than four numbered steps,
   so the auto-counter is suppressed in favour of the explicit date label. */
.rf-steps--3 {
  grid-template-columns: repeat(3, 1fr);
}

.rf-steps--3 .rf-step::before {
  content: none;
}

.rf-step__when {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  align-items: center;
  margin: 0 0 16px;
  font-family: var(--rf-font-mono);
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.8px;
  color: var(--rf-ink-dim);
}

/* Requirement bullets inside an expanded job listing. */
.rf-list {
  margin: 0 0 24px;
  padding-left: 20px;
  color: var(--rf-ink-muted);
}

.rf-list li {
  margin-bottom: 8px;
  font-size: 16px;
  line-height: 1.55;
}

/* FAQ and job rows — hairline rows, no boxes.
   base_collapse.css draws the container outline with `box-shadow: inset 0 0 0
   1px`, not a border, so `border: 0` alone leaves the rounded rectangle
   visible; the shadow has to be cleared too (including its :hover and .open
   variants). Padding goes on `.collapse-content-inner`, never on
   `.collapse-content` — that element is the animated max-height wrapper, and
   padding on it keeps a gap open while the row is collapsed. */
.rf-faq,
.rf-jobs {
  border-top: 1px solid var(--rf-hairline);
}

.rf-faq .collapse-container,
.rf-jobs .collapse-container,
.rf-faq .collapse-container:hover,
.rf-jobs .collapse-container:hover,
.rf-faq .collapse-container.open,
.rf-jobs .collapse-container.open {
  margin: 0 !important;
  border: 0 !important;
  border-bottom: 1px solid var(--rf-hairline) !important;
  border-radius: 0 !important;
  background: transparent !important;
  box-shadow: none !important;
}

.rf-faq .collapse-header,
.rf-jobs .collapse-header {
  padding: 26px 0 !important;
  background: transparent !important;
  color: var(--rf-ink) !important;
  font-weight: 500 !important;
}

.rf-faq .collapse-header {
  font-size: 19px !important;
}

.rf-jobs .collapse-header {
  font-size: 21px !important;
}

.rf-faq .collapse-content,
.rf-jobs .collapse-content {
  padding: 0 !important;
  background: transparent !important;
}

.rf-faq .collapse-content-inner,
.rf-jobs .collapse-content-inner {
  padding: 0 0 28px !important;
  color: var(--rf-ink-muted) !important;
  font-size: 16px !important;
  line-height: 1.6;
}

.rf-job__meta {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin: 0 0 20px;
  padding: 0;
  list-style: none;
}

.rf-job__meta li {
  padding: 6px 13px;
  border: 1px solid var(--rf-hairline);
  border-radius: var(--rf-radius-pill);
  font-size: 13px;
  color: var(--rf-ink-muted);
}

/* Carousel: the framework component keeps its behaviour, loses its chrome. */
.rf-page .base-carousel-cards {
  background: transparent !important;
}

/* Structural rhythm between the blocks a band stacks. Kept as sibling rules
   rather than utility classes on the markup so the templates stay free of
   layout decisions (and of inline styles). */
.rf-stats + .rf-figure,
.rf-split + .rf-grid,
.rf-showcase + .rf-grid {
  margin-top: clamp(40px, 5vw, 72px);
}

.rf-band__head + .rf-figure {
  margin-bottom: clamp(40px, 5vw, 64px);
}

.rf-showcase__inner .rf-actions {
  margin-top: 28px;
}

/* A deep band that carries a full-bleed image behind centred copy. Used for
   the closing CTA, where a .rf-showcase (bottom-left aligned) would fight the
   centred layout. */
.rf-band--media {
  position: relative;
  overflow: hidden;
}

.rf-band__media {
  position: absolute;
  inset: 0;
  z-index: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: brightness(0.5);
}

.rf-band--media::after {
  position: absolute;
  inset: 0;
  z-index: 1;
  content: '';
  background: radial-gradient(
    ellipse at 50% 50%,
    rgba(0, 0, 0, 0.35) 0%,
    rgba(0, 0, 0, 0.78) 100%
  );
}

.rf-band--media > .rf-band__inner {
  position: relative;
  z-index: 2;
}

/* ── 7b  Alternating loop rows ──────────────────────────────────────────────
   Replaces the four-across step rail: image left / copy right, then mirrored,
   so each step gets its own frame and its own generated plate. */
.rf-loop {
  display: grid;
  gap: clamp(56px, 7vw, 104px);
  margin: 0;
  padding: 0;
  list-style: none;
  counter-reset: rf-loop;
}

.rf-loop__row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(32px, 5vw, 72px);
  align-items: center;
  counter-increment: rf-loop;
}

/* Mirror every second row: the plate moves to the right column. */
.rf-loop__row:nth-child(even) .rf-loop__media {
  order: 2;
}

.rf-loop__copy .rf-h3 {
  font-size: clamp(24px, 2.6vw, 34px);
  font-weight: 600;
  letter-spacing: -1px;
}

.rf-loop__num {
  display: block;
  margin: 0 0 14px;
  font-family: var(--rf-font-mono);
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.8px;
  color: var(--rf-ink-dim);
}

.rf-loop__copy p {
  max-width: 52ch;
  margin: 0;
  font-size: 17px;
  line-height: 1.6;
  color: var(--rf-ink-muted);
}

/* ── 7c  Full-bleed product ─────────────────────────────────────────────────
   One product per band-width plate, name and at most two lines of copy laid
   over the bottom of the image. Replaces the product card carousel. */
.rf-showcases {
  display: grid;
  gap: clamp(20px, 2.4vw, 32px);
}

/* [hidden] is only a UA-level `display: none`, so the author `display: flex`
   below silently beat it and every slide rendered at once. The switcher hides
   slides with the attribute, so it has to win here. */
.rf-feature[hidden] {
  display: none !important;
}

.rf-feature {
  position: relative;
  display: flex;
  align-items: flex-end;
  min-height: min(62vh, 560px);
  padding: clamp(28px, 4vw, 56px);
  overflow: hidden;
  border-radius: var(--rf-radius-lg);
  color: var(--rf-ink);
  text-decoration: none;
  isolation: isolate;
  transition: border-color 0.35s var(--rf-ease);
}

.rf-feature__media {
  position: absolute;
  inset: 0;
  z-index: -2;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.7s var(--rf-ease);
}

.rf-feature:hover .rf-feature__media {
  transform: scale(1.03);
}

.rf-feature::after {
  position: absolute;
  inset: 0;
  z-index: -1;
  content: '';
  background: linear-gradient(
    0deg,
    rgba(0, 0, 0, 0.88) 0%,
    rgba(0, 0, 0, 0.45) 46%,
    rgba(0, 0, 0, 0.12) 100%
  );
}

.rf-feature__body {
  max-width: 640px;
}

.rf-feature__name {
  margin: 0 0 10px;
  font-size: clamp(24px, 2.4vw, 34px);
  font-weight: 600;
  line-height: 1.1;
  letter-spacing: -1px;
  color: #ffffff;
}

/* Hard two-line cap: the whole point of this treatment is that the image
   carries the section and the copy stays a caption. */
/* Roughly 60% of .rf-feature__name's clamp(24px, 2.4vw, 34px) — the repo bans
   em units, so the ratio is expressed as a parallel clamp instead. */
.rf-feature__tld {
  font-size: clamp(15px, 1.45vw, 21px);
  color: rgba(255, 255, 255, 0.55);
  font-weight: 400;
  letter-spacing: 0;
}

.rf-product__name .rf-feature__tld {
  font-size: 13px;
  color: var(--rf-ink-muted);
}

.rf-feature__desc {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  margin: 0;
  font-size: 17px;
  line-height: 1.5;
  color: rgba(255, 255, 255, 0.78);
}

/* Each product plate is that product's own splash screen in a phone, built
   from its repo's mascot and wordmark. The mascot also sits in front of the
   phone as a cut-out, with a wash of the product's own colour behind it — the
   site's red stays reserved for the primary CTA. */
.rf-feature--eduloo {
  --rf-brand: #fb596e;
}

.rf-feature--caltide {
  --rf-brand: #1583e6;
}

.rf-feature__mascot {
  position: absolute;
  right: clamp(16px, 3.5vw, 54px);
  bottom: 0;
  z-index: 1;
  width: auto;
  height: clamp(140px, 26vw, 250px);
  object-fit: contain;
  filter: drop-shadow(0 22px 44px rgba(0, 0, 0, 0.6));
  transition: transform 0.5s var(--rf-ease);
}

.rf-feature__mascot + .rf-feature__body::before {
  position: absolute;
  right: clamp(16px, 3.5vw, 54px);
  bottom: -60px;
  z-index: -1;
  width: clamp(200px, 30vw, 340px);
  height: clamp(200px, 30vw, 340px);
  content: '';
  border-radius: 50%;
  background: radial-gradient(
    circle,
    color-mix(in srgb, var(--rf-brand, #ffffff) 30%, transparent) 0%,
    transparent 68%
  );
  transform: translateX(50%);
  pointer-events: none;
}

.rf-feature:hover .rf-feature__mascot {
  transform: translateY(-8px);
}

/* Copy keeps clear of the phone and the mascot on the right. */
.rf-feature__body {
  position: relative;
  z-index: 1;
  max-width: min(560px, 58%);
}

.rf-feature__soon {
  display: inline-flex;
  align-items: center;
  margin-top: 18px;
  padding: 6px 14px;
  border-radius: var(--rf-radius-pill);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.28);
  background: rgba(255, 255, 255, 0.08);
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  color: #ffffff;
}

/* ── 7d  Statement band and pull-quote ────────────────────────────────────── */

.rf-statement {
  max-width: 24ch;
  margin: 0 auto;
  font-size: clamp(28px, 4vw, 52px);
  font-weight: 600;
  line-height: 1.12;
  letter-spacing: -1px;
  text-align: center;
  color: #ffffff;
  text-wrap: balance;
}

.rf-quote {
  max-width: 900px;
  margin: 0 auto;
  text-align: center;
}

/* base_style.css styles bare <blockquote> with a brand left bar, a tinted
   background, italics and a masked quote glyph. None of that belongs here, so
   it is all unwound rather than worked around. */
.rf-quote blockquote {
  max-width: 20ch;
  margin: 0 auto 26px;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: none;
  font-size: clamp(28px, 3.8vw, 46px);
  font-style: normal;
  font-weight: 500;
  line-height: 1.16;
  letter-spacing: -1px;
  color: #ffffff;
  text-wrap: balance;
}

.rf-quote blockquote::before {
  display: none;
}

.rf-quote figcaption {
  font-family: var(--rf-font-mono);
  font-size: 13px;
  letter-spacing: 0.8px;
  text-transform: uppercase;
  color: var(--rf-ink-muted);
}

/* ── 7e  Hero stat strip ────────────────────────────────────────────────────
   The old "studio at a glance" band folded into the hero, so the numbers cost
   no section of their own. */
.rf-hero__stats {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: clamp(24px, 4vw, 56px);
  margin-top: clamp(40px, 5vw, 64px);
  padding-top: 28px;
  border-top: 1px solid rgba(255, 255, 255, 0.16);
}

.rf-hero__stat b {
  display: block;
  font-size: clamp(24px, 2.6vw, 32px);
  font-weight: 600;
  line-height: 1;
  letter-spacing: -1px;
  color: #ffffff;
  font-variant-numeric: tabular-nums;
}

.rf-hero__stat span {
  font-size: 14px;
  color: rgba(255, 255, 255, 0.62);
}

/* ── 7f  Fact list and the products dialog ────────────────────────────────── */

.rf-facts {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: clamp(18px, 2vw, 26px);
  max-width: 900px;
  margin: 0;
}

.rf-fact {
  overflow: hidden;
  border: 1px solid var(--rf-hairline);
  border-radius: var(--rf-radius);
  background: var(--rf-plate);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
}

.rf-fact__media {
  display: block;
  width: 100%;
  /* The width/height attributes on the <img> map to a UA `height: 720px`, and
     aspect-ratio only fills in a MISSING dimension - so without this the card
     images rendered 720px tall. */
  height: auto;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  border-bottom: 1px solid var(--rf-hairline);
}

.rf-fact__body {
  padding: 22px 26px 26px;
}

.rf-fact dt {
  margin: 0 0 8px;
  font-size: 17px;
  font-weight: 600;
  color: var(--rf-ink);
}

.rf-fact dd {
  margin: 0;
  font-size: 15px;
  line-height: 1.55;
  color: var(--rf-ink-muted);
}

.rf-products__more {
  margin-top: clamp(32px, 4vw, 52px);
}

/* Product switcher: one full-bleed plate at a time, arrows either side of a
   position counter. Order comes from the shared admin panel — a badge_label
   pins a product first, then sort_order ASC (SharedProduct.get_active). */
.rf-products__nav {
  display: flex;
  gap: 18px;
  align-items: center;
  justify-content: center;
  margin-top: clamp(28px, 3.4vw, 44px);
}

.rf-nav-btn {
  display: grid;
  place-items: center;
  width: 46px;
  height: 46px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  box-shadow: inset 0 0 0 1px var(--rf-hairline-strong);
  /* !important to beat base_elements.css's `background: var(--container-bg)
     !important` on <button>. */
  background: transparent !important;
  color: var(--rf-ink);
  font-size: 15px;
  cursor: pointer;
  transition:
    background 0.25s var(--rf-ease),
    box-shadow 0.25s var(--rf-ease);
}

.rf-nav-btn:hover {
  box-shadow: inset 0 0 0 1px var(--rf-ink);
  background: var(--rf-surface) !important;
}

.rf-products__count {
  margin: 0;
  min-width: 62px;
  font-family: var(--rf-font-mono);
  font-size: 14px;
  text-align: center;
  color: var(--rf-ink-muted);
  font-variant-numeric: tabular-nums;
}

/* ── 7g  Hiring section ───────────────────────────────────────────────────
   Built from the same split + numbered-rail pieces as the story and process
   sections, so it carries the same weight as the rest of the page. */

/* auto-fit with a capped track, so this reads correctly whether there is one
   point or three — a single item stays a column instead of stretching its
   image across the whole band. */
.rf-perks {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(0, 340px));
  justify-content: center;
  gap: clamp(20px, 2.4vw, 34px);
  margin: clamp(48px, 6vw, 80px) 0 0;
  padding: 0;
  list-style: none;
  text-align: center;
}

/* The image is the widest thing in the column, so centring the text alone
   would leave it visibly off-axis. */
.rf-perks li {
  margin: 0 auto;
}

.rf-perks li {
  padding-top: 0;
}

.rf-perks__media {
  display: block;
  width: 100%;
  /* height: auto so aspect-ratio governs — the width/height attributes
     otherwise map to a UA height and the plate renders 720px tall. */
  height: auto;
  aspect-ratio: 16 / 9;
  margin-bottom: 20px;
  border-radius: 14px;
  object-fit: cover;
  box-shadow: inset 0 0 0 1px var(--rf-hairline);
}

.rf-perks strong {
  display: block;
  margin-bottom: 8px;
  font-size: 19px;
  font-weight: 600;
  color: var(--rf-ink);
}

.rf-perks__desc {
  display: block;
  font-size: 15px;
  line-height: 1.55;
  color: var(--rf-ink-muted);
}

/* ── 8  CTA bands ──────────────────────────────────────────────────────── */

.rf-cta {
  text-align: center;
}

.rf-cta .rf-band__inner {
  max-width: var(--rf-measure-narrow);
}

.rf-cta .rf-lead {
  margin-left: auto;
  margin-right: auto;
}

/* Legal / company facts — quiet, monospaced. */
.rf-legal {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 1px;
  overflow: hidden;
  border: 1px solid var(--rf-hairline);
  border-radius: var(--rf-radius);
  background: var(--rf-hairline);
}

.rf-legal__row {
  display: flex;
  flex-direction: column;
  gap: 5px;
  padding: 22px 26px;
  background: var(--rf-canvas);
}

.rf-legal__key {
  font-size: 13px;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  color: var(--rf-ink-muted);
}

.rf-legal__val {
  font-family: var(--rf-font-mono);
  font-size: 15px;
  color: var(--rf-ink);
}

/* ── 9  Contact page ───────────────────────────────────────────────────────
   /contact is framework-rendered and must not be forked, so it is rebuilt in
   CSS against the real markup:

     .contact-bottom
       .contact-info-panel      (framework: position:absolute, translateY(-50%))
       .contact-form-panel      (framework: margin-left ~190-240px !important)
         .contact-form-bg       (decorative orbs + dot grid, previous design)
         .contact-form-card
           .contact-form-inner

   The framework floats the info panel over the form's left edge. That overlap
   is what made this page look unfinished here, so the panel is taken out of
   absolute positioning and both become real columns of one grid.
   ------------------------------------------------------------------------ */

body:not(:has(.admin-container)) .contact-page {
  position: relative;
  padding: clamp(56px, 7vw, 96px) var(--rf-gutter) clamp(56px, 6vw, 88px);
  font-family: var(--rf-font);
  color: var(--rf-ink);
}

/* Section plate. Fixed rather than absolute: .contact-page sits inside main,
   so an absolute layer could not reach full-bleed without changing the
   framework's layout. url() bypasses asset_url(), hence the raw path. */
body:not(:has(.admin-container)) .contact-page::before {
  position: fixed;
  inset: 0;
  z-index: -2;
  content: '';
  background-image: url('/assets/img/site/contact-cta.webp');
  background-position: center;
  background-size: cover;
  background-repeat: no-repeat;
  filter: grayscale(12%) brightness(0.7);
}

body:not(:has(.admin-container)) .contact-page::after {
  position: fixed;
  inset: 0;
  z-index: -1;
  content: '';
  background: linear-gradient(
    180deg,
    rgba(0, 0, 0, 0.74) 0%,
    rgba(0, 0, 0, 0.42) 45%,
    rgba(0, 0, 0, 0.86) 100%
  );
}

body:not(:has(.admin-container)) .contact-bottom {
  display: grid;
  grid-template-columns: minmax(0, 330px) minmax(0, 1fr);
  gap: clamp(20px, 2.4vw, 32px);
  align-items: stretch;
  width: 100%;
  max-width: var(--rf-measure);
  margin: 0 auto;
}

/* Out of absolute flow, so it can be a grid column. */
body:not(:has(.admin-container)) .contact-info-panel {
  position: static !important;
  top: auto !important;
  left: auto !important;
  width: auto !important;
  transform: none !important;
  margin: 0 !important;
  justify-content: flex-start;
}

/* The framework reserves room for the floating panel; not needed any more. */
body:not(:has(.admin-container)) .contact-form-panel {
  margin-left: 0 !important;
  padding: 0 !important;
  background: none !important;
  border: 0 !important;
  box-shadow: none !important;
}

body:not(:has(.admin-container)) .contact-info-panel,
body:not(:has(.admin-container)) .contact-form-card {
  padding: clamp(28px, 3vw, 44px);
  border: 0;
  border-radius: var(--rf-radius-lg);
  background: rgba(10, 10, 11, 0.76);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  box-shadow: inset 0 0 0 1px var(--rf-hairline);
}

/* Orbs and dot grid belong to the previous design language. */
body:not(:has(.admin-container)) .contact-form-bg {
  display: none;
}

body:not(:has(.admin-container)) .contact-info-title {
  margin: 0 0 10px;
  font-size: clamp(22px, 2.2vw, 28px);
  font-weight: 600;
  letter-spacing: -1px;
  color: var(--rf-ink);
}

body:not(:has(.admin-container)) .contact-info-subtitle {
  margin: 0;
  font-size: 16px;
  line-height: 1.55;
  color: var(--rf-ink-muted);
}

body:not(:has(.admin-container)) .contact-info-card {
  display: flex;
  gap: 14px;
  align-items: center;
  padding: 18px 0 0;
  border: 0;
  border-top: 1px solid var(--rf-hairline);
  border-radius: 0;
  background: transparent;
  box-shadow: none;
  color: var(--rf-ink);
}

body:not(:has(.admin-container)) .contact-info-icon {
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  flex: 0 0 auto;
  border-radius: 11px;
  background: var(--rf-surface);
  box-shadow: inset 0 0 0 1px var(--rf-hairline);
  color: var(--rf-ink);
}

body:not(:has(.admin-container)) .contact-form-header h1,
body:not(:has(.admin-container)) .contact-form-header h2 {
  margin: 0 0 6px;
  font-size: clamp(28px, 3.2vw, 40px);
  font-weight: 600;
  line-height: 1.1;
  letter-spacing: -1px;
  color: var(--rf-ink);
}

body:not(:has(.admin-container)) .contact-page input,
body:not(:has(.admin-container)) .contact-page textarea,
body:not(:has(.admin-container)) .contact-page select {
  border: 0;
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.05);
  box-shadow: inset 0 0 0 1px var(--rf-hairline);
  color: var(--rf-ink);
  font-family: var(--rf-font);
}

body:not(:has(.admin-container)) .contact-page input:focus,
body:not(:has(.admin-container)) .contact-page textarea:focus {
  box-shadow: inset 0 0 0 1px var(--rf-ink);
  outline: none;
}

body:not(:has(.admin-container)) .contact-powered-by {
  color: var(--rf-ink-dim);
}

@media (max-width: 900px) {
  body:not(:has(.admin-container)) .contact-bottom {
    grid-template-columns: 1fr;
  }
}

/* ── 10  Motion ────────────────────────────────────────────────────────── */

.rf-reveal {
  opacity: 0;
  transform: translateY(24px);
  transition:
    opacity 0.7s var(--rf-ease),
    transform 0.7s var(--rf-ease);
}

.rf-reveal.is-revealed {
  opacity: 1;
  transform: none;
}

/* No JS, no reveal: never leave content invisible. rf_site.js sets this flag
   on <html> as its first act, so a script failure or a blocked file simply
   renders everything statically. */
html:not(.rf-js) .rf-reveal {
  opacity: 1;
  transform: none;
  transition: none;
}

@media (prefers-reduced-motion: reduce) {
  .rf-reveal,
  .rf-reveal.is-revealed {
    opacity: 1;
    transform: none;
    transition: none;
  }

  .rf-btn:hover,
  .rf-product:hover {
    transform: none;
  }
}

/* ── 11  Responsive ────────────────────────────────────────────────────── */

@media (max-width: 1024px) {
  .rf-grid--4 {
    grid-template-columns: repeat(2, 1fr);
  }

  .rf-grid--3 {
    grid-template-columns: repeat(2, 1fr);
  }

  .rf-steps,
  .rf-steps--3 {
    grid-template-columns: repeat(2, 1fr);
  }

  .rf-stats {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (max-width: 760px) {
  .rf-split,
  .rf-loop__row {
    grid-template-columns: 1fr;
  }

  /* Plate always leads on narrow screens, whichever column it sat in. */
  .rf-loop__row:nth-child(even) .rf-loop__media {
    order: 0;
  }

  .rf-feature {
    min-height: 60vh;
  }

  .rf-feature__body {
    max-width: 100%;
  }

  .rf-feature__mascot {
    right: 8px;
    height: 120px;
    opacity: 0.92;
  }

  .rf-statement {
    max-width: none;
  }

  /* Image always leads on narrow screens, whichever side it sat on. */
  .rf-split--reverse .rf-split__media {
    order: 0;
  }

  .rf-grid--2,
  .rf-grid--3,
  .rf-grid--4,
  .rf-facts {
    grid-template-columns: 1fr;
  }

  .rf-steps,
  .rf-steps--3 {
    grid-template-columns: 1fr;
  }

  .rf-stats {
    grid-template-columns: 1fr;
  }

  .rf-legal {
    grid-template-columns: 1fr;
  }

  .rf-hero {
    min-height: 78vh;
    text-align: left;
  }

  .rf-hero .rf-lead {
    margin-left: 0;
  }

  .rf-actions--center {
    justify-content: flex-start;
  }

  .rf-showcase {
    min-height: 60vh;
    padding: 32px;
  }

  .rf-figure--wide {
    aspect-ratio: 16 / 10;
  }
}
