/**
 * Rhythmarkable — Block styles
 * Every section block renders full-width (align="full") and contains its
 * own `.rm-container` to constrain inner content — see inc/block-helpers.php.
 */

.rm-section {
  position: relative;
  width: 100%;
  padding-block: var(--rm-section-padding);
}

.rm-section--reduced-padding {
  padding-top: 1.5rem;
}

/* Rich text (WYSIWYG) body copy: normal text renders at the dimmed
   secondary/tertiary tone (as before), but bold text should always read as
   fully legible — full-opacity primary colour (midnight on light
   backgrounds, white on dark, via --rm-text-primary) at weight 600 rather
   than the browser default 700. Scoped to the rich-text wrappers so it
   never affects headings/eyebrows, which manage their own weight/colour. */
.rm-hero__description strong,
.rm-hero__description b,
.rm-split__text strong,
.rm-split__text b,
.rm-page-heading__description strong,
.rm-page-heading__description b,
.rm-features__description strong,
.rm-features__description b,
.rm-feature-card__description strong,
.rm-feature-card__description b {
  font-weight: 600;
  color: var(--rm-text-primary);
}

/* Rich text (WYSIWYG) description/text fields render their own <p> tags
   inside a wrapper div (see rm_the_rich_text() in inc/block-helpers.php).
   Reset the default paragraph spacing so multi-paragraph copy reads with a
   consistent rhythm, matching the single-<p> look these wrappers used to
   have. */
.rm-hero__description p,
.rm-split__text p,
.rm-page-heading__description p,
.rm-features__description p,
.rm-feature-card__description p {
  margin: 0 0 0.75em;
}

.rm-hero__description p:last-child,
.rm-split__text p:last-child,
.rm-page-heading__description p:last-child,
.rm-features__description p:last-child,
.rm-feature-card__description p:last-child {
  margin-bottom: 0;
}


/* ================= Section background color options ================= */
/* Reusable background palette (see rm_get_background_color_field() in
   inc/block-helpers.php) — any section block can opt in to these classes
   without redefining the colours itself. */
.rm-bg-midnight {
  background: var(--rm-palette-midnight);
}

.rm-bg-dark-navy {
  background: var(--rm-palette-dark-navy);
}

.rm-bg-dahlia-purple {
  background: var(--rm-palette-dahlia-purple);
}

.rm-bg-light-gray {
  background: var(--rm-palette-light-gray);
}

.rm-bg-white {
  background: var(--rm-palette-white);
}

.rm-bg-cosmic-purple {
  background: var(--rm-palette-cosmic-purple);
}

.rm-bg-cosmic-navy {
  background: var(--rm-palette-cosmic-navy);
}

/* Contrast flip: light background choices swap every text/line colour
   token to midnight, so headings, body copy, eyebrows, borders and the
   underline CTA/nav links all stay legible without per-component overrides. */
.rm-bg--on-light {
  --rm-text-primary: var(--rm-palette-midnight);
  --rm-text-secondary: rgba(15, 27, 40, 0.7);
  --rm-text-tertiary: rgba(15, 27, 40, 0.5);
  --rm-border: rgba(15, 27, 40, 0.12);
  --rm-border-strong: rgba(15, 27, 40, 0.2);
  /* --rm-button-text is defined once in tokens.css as var(--rm-text-primary)
     at :root, so it's resolved against the root value and won't pick up
     this scope's flipped --rm-text-primary on its own — override it
     directly here so CTA buttons (and anything else using the button
     token) also flip to midnight on light backgrounds. */
  --rm-button-text: var(--rm-palette-midnight);
}


/* ================= Hero ================= */
.rm-hero {
  position: relative;
  display: flex;
  align-items: center;
  width: 100%;
  min-height: 100vh;
  padding-top: var(--rm-header-height);
  background-size: cover;
  background-position: center;
  overflow: hidden;
}

.rm-hero--auto-height {
  min-height: 0;
  padding-block: calc(var(--rm-header-height) + var(--rm-space-2xl)) var(--rm-space-2xl);
}

.rm-hero__overlay {
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(17, 24, 39, 0.2) 0%, rgba(17, 24, 39, 0.75) 100%);
  pointer-events: none;
}

.rm-hero__inner {
  position: relative;
  z-index: 1;
  max-width: var(--rm-container);
  margin-inline: auto;
  padding-inline: var(--rm-container-gutter);
  width: 100%;
}

.rm-hero__content {
  max-width: 42rem;
}

/* Quick fade-in on load. Pure CSS (no opacity:0 inline/JS-dependent reveal),
   so the heading/copy stay fully present and crawlable in the server-rendered
   HTML — this only affects paint, not content. animation-fill-mode:
   backwards applies the 0% frame before the animation starts (preventing any
   flash of unstyled/full-opacity content), but — unlike 'both' — releases
   control of transform/opacity once the animation ends, so the scroll
   parallax below (applied to this same element via inline styles) can take
   over afterwards instead of being silently overridden forever. */
@keyframes rm-hero-fade-in {
  from {
    opacity: 0;
    transform: translateY(0.75rem);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.rm-hero__content {
  animation: rm-hero-fade-in 0.5s var(--rm-ease) backwards;
  will-change: transform, opacity;
}

@media (prefers-reduced-motion: reduce) {
  .rm-hero__content {
    animation: none;
    transform: none !important;
    opacity: 1 !important;
  }
}

.rm-hero__heading-line {
  display: block;
}

.rm-hero__heading-line--dim {
  opacity: 0.7;
}

/* ---- Hero: column image placement ---- */
.rm-hero--image-left .rm-hero__inner,
.rm-hero--image-right .rm-hero__inner {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--rm-space-xl);
  align-items: center;
}

.rm-hero--image-left .rm-hero__media {
  order: -1;
}

.rm-hero__media img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: var(--rm-radius-md, 0.5rem);
}

/* Edge-to-edge (default): the media column bleeds past the container's
   padding + centring gap so the image touches the viewport edge. */
.rm-hero--image-bleed .rm-hero__media img {
  border-radius: 0;
}

.rm-hero--image-bleed.rm-hero--image-right .rm-hero__media {
  margin-right: calc(-2 * ((100vw - min(100vw, var(--rm-container))) / 2 + var(--rm-container-gutter)));
}

.rm-hero--image-bleed.rm-hero--image-left .rm-hero__media {
  margin-left: calc(-2 * ((100vw - min(100vw, var(--rm-container))) / 2 + var(--rm-container-gutter)));
}

/* Let the bleed image sit flush with the bottom of the hero */
.rm-hero--image-bleed .rm-hero__media {
  align-self: flex-end;
}

.rm-hero--image-bleed .rm-hero__media img {
  vertical-align: bottom;
}

/* ---- Hero media: tint + edge fade overlays ---- */
.rm-hero--media-tint .rm-hero__media,
.rm-hero--media-edge-fade .rm-hero__media {
  position: relative;
}

.rm-hero--media-tint .rm-hero__media::before {
  content: '';
  position: absolute;
  inset: 0;
  background: rgba(32, 42, 56, 0.45);
  pointer-events: none;
  z-index: 1;
}

/* Subtle opaque → transparent fade on the inner edge (the side facing the
   content column). The overlay is painted with the actual page background
   (flat or gradient, viewport-fixed to match the body) and a mask controls
   the opaque → transparent falloff — so it always blends seamlessly. */
.rm-hero--media-edge-fade .rm-hero__media::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 1;
  background: var(--rm-page-background) fixed;
}

.rm-hero--media-edge-fade.rm-hero--image-right .rm-hero__media::after {
  -webkit-mask-image: linear-gradient(
    90deg,
    rgba(0, 0, 0, 1) 0%,
    rgba(0, 0, 0, 1) 8%,
    rgba(0, 0, 0, 0.85) 20%,
    rgba(0, 0, 0, 0.55) 35%,
    rgba(0, 0, 0, 0.25) 50%,
    rgba(0, 0, 0, 0) 70%
  );
  mask-image: linear-gradient(
    90deg,
    rgba(0, 0, 0, 1) 0%,
    rgba(0, 0, 0, 1) 8%,
    rgba(0, 0, 0, 0.85) 20%,
    rgba(0, 0, 0, 0.55) 35%,
    rgba(0, 0, 0, 0.25) 50%,
    rgba(0, 0, 0, 0) 70%
  );
}

.rm-hero--media-edge-fade.rm-hero--image-left .rm-hero__media::after {
  -webkit-mask-image: linear-gradient(
    270deg,
    rgba(0, 0, 0, 1) 0%,
    rgba(0, 0, 0, 1) 8%,
    rgba(0, 0, 0, 0.85) 20%,
    rgba(0, 0, 0, 0.55) 35%,
    rgba(0, 0, 0, 0.25) 50%,
    rgba(0, 0, 0, 0) 70%
  );
  mask-image: linear-gradient(
    270deg,
    rgba(0, 0, 0, 1) 0%,
    rgba(0, 0, 0, 1) 8%,
    rgba(0, 0, 0, 0.85) 20%,
    rgba(0, 0, 0, 0.55) 35%,
    rgba(0, 0, 0, 0.25) 50%,
    rgba(0, 0, 0, 0) 70%
  );
}

/* Full-height media column (default): the image column stretches the full
   height of the hero, image covers it. Desktop only. */
@media (min-width: 48.0625rem) {
  .rm-hero--media-full-height {
    align-items: stretch;
  }

  .rm-hero--media-full-height .rm-hero__inner {
    align-items: stretch;
  }

  .rm-hero--media-full-height .rm-hero__content {
    align-self: center;
  }

  .rm-hero--media-full-height .rm-hero__media {
    align-self: stretch;
    /* cancel the hero's top headroom so the image runs edge to edge vertically */
    margin-top: calc(-1 * var(--rm-header-height));
  }

  .rm-hero--media-full-height .rm-hero__media img {
    width: 100%;
    height: 100%;
    object-fit: cover;
  }
}

@media (max-width: 48rem) {
  .rm-hero--image-left .rm-hero__inner,
  .rm-hero--image-right .rm-hero__inner {
    grid-template-columns: 1fr;
    gap: var(--rm-space-lg);
  }

  /* Mobile: above / below text content */
  .rm-hero--image-mobile-above .rm-hero__media {
    order: -1;
  }

  .rm-hero--image-mobile-below .rm-hero__media {
    order: 1;
  }

  /* Mobile edge-to-edge: bleed both sides of the stacked column */
  .rm-hero--image-bleed.rm-hero--image-left .rm-hero__media,
  .rm-hero--image-bleed.rm-hero--image-right .rm-hero__media {
    margin-inline: calc(-2 * var(--rm-container-gutter));
    align-self: stretch;
  }

  /* Mobile edge fade: fade the edge facing the text content */
  .rm-hero--media-edge-fade.rm-hero--image-mobile-above .rm-hero__media::after {
    -webkit-mask-image: linear-gradient(
      0deg,
      rgba(0, 0, 0, 1) 0%,
      rgba(0, 0, 0, 0.85) 15%,
      rgba(0, 0, 0, 0.4) 35%,
      rgba(0, 0, 0, 0) 60%
    );
    mask-image: linear-gradient(
      0deg,
      rgba(0, 0, 0, 1) 0%,
      rgba(0, 0, 0, 0.85) 15%,
      rgba(0, 0, 0, 0.4) 35%,
      rgba(0, 0, 0, 0) 60%
    );
  }

  .rm-hero--media-edge-fade.rm-hero--image-mobile-below .rm-hero__media::after {
    -webkit-mask-image: linear-gradient(
      180deg,
      rgba(0, 0, 0, 1) 0%,
      rgba(0, 0, 0, 0.85) 15%,
      rgba(0, 0, 0, 0.4) 35%,
      rgba(0, 0, 0, 0) 60%
    );
    mask-image: linear-gradient(
      180deg,
      rgba(0, 0, 0, 1) 0%,
      rgba(0, 0, 0, 0.85) 15%,
      rgba(0, 0, 0, 0.4) 35%,
      rgba(0, 0, 0, 0) 60%
    );
  }
}

.rm-hero__eyebrow {
  font-size: var(--rm-font-size-sm);
  letter-spacing: var(--rm-letter-spacing-meta);
  text-transform: uppercase;
  color: var(--rm-text-secondary);
  margin-bottom: var(--rm-space-sm);
}

.rm-hero__heading {
  font-size: var(--rm-font-size-display);
  line-height: var(--rm-line-height-display);
  letter-spacing: var(--rm-letter-spacing-display);
  margin-bottom: var(--rm-space-sm);
}

.rm-hero__subheading {
  font-size: var(--rm-font-size-xl);
  color: var(--rm-text-secondary);
  margin-bottom: var(--rm-space-md);
}

.rm-hero__description {
  font-size: var(--rm-font-size-lead);
  color: var(--rm-text-secondary);
  max-width: 36rem;
  margin-bottom: var(--rm-space-lg);
}

/* ================= Buttons ================= */
.rm-button {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0 0 var(--rm-button-padding-bottom);
  background: none;
  color: var(--rm-button-text);
  border: none;
  border-bottom: var(--rm-button-underline-width) solid currentColor;
  border-radius: 0;
  font-size: var(--rm-font-size-lg);
  font-weight: 600;
  transition: opacity var(--rm-duration-fast) var(--rm-ease),
    gap var(--rm-duration-fast) var(--rm-ease);
}

.rm-button svg,
.rm-button i {
  width: var(--rm-button-icon-size);
  height: var(--rm-button-icon-size);
}

.rm-button:hover {
  opacity: 0.75;
  gap: 0.75rem;
}

/* ================= Page heading ================= */
.rm-page-heading__inner {
  max-width: var(--rm-container-narrow);
  margin-inline: auto;
  text-align: center;
}

.rm-page-heading__eyebrow {
  font-size: var(--rm-font-size-sm);
  letter-spacing: var(--rm-letter-spacing-meta);
  text-transform: uppercase;
  color: var(--rm-text-secondary);
  margin-bottom: var(--rm-space-sm);
}

.rm-page-heading__title {
  font-size: var(--rm-font-size-3xl);
  margin-bottom: var(--rm-space-sm);
}

.rm-page-heading__description {
  font-size: var(--rm-font-size-lg);
  color: var(--rm-text-secondary);
}

.rm-page-heading--center {
  text-align: center;
}

.rm-page-heading--center .rm-page-heading__inner {
  margin-inline: auto;
}

/* ================= Split ================= */
.rm-split__inner {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--rm-space-xl);
  align-items: center;
}

/* DOM order is always media, then content — which naturally places the
   image on the left (the default). "Image Position: Right" flips that by
   pushing the media column after the content column via grid order, so the
   visual layout always matches the selected setting, even before an image
   is uploaded (the empty .rm-split__media column still reserves its grid
   track). */
.rm-split__media {
  grid-column: 1;
  grid-row: 1;
  overflow: hidden;
  /* Desktop value by default; the mobile custom property (set below, inside
     the mobile media query) takes over under 64rem. Both properties are
     supplied inline per-block (see blocks/split/render.php) via the "Max
     Image Height" / "Max Image Height — Mobile" fields, and always apply
     — including in Edge-to-Edge Image mode, where they're what keeps the
     bled image (and therefore the section) from growing to the image's
     full natural height. This max-height is a Split-only control; it has
     nothing to do with the Hero block's dedicated 100vh/100dvh full-height
     treatment. */
  max-height: var(--rm-split-media-max-height, none);
}

.rm-split__content {
  grid-column: 1;
  grid-row: 2;
}

.rm-split__media img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: var(--rm-radius-lg);
}

/* "Fit Image (no crop)": scale the image to fit within the max-height
   without stretching/cropping to fill the column width. The column no
   longer forces the image to 100% width/height — it just caps the height
   and lets the image keep its natural aspect ratio, centred in the track. */
.rm-split--image-fit .rm-split__media {
  display: flex;
  justify-content: center;
}

.rm-split--image-fit .rm-split__media img {
  width: auto;
  max-width: 100%;
  height: auto;
  max-height: inherit;
  object-fit: contain;
}

/* "Edge-to-Edge Image": bleeds the media column past the container's
   padding + centring gap on its outer side so the image touches the
   viewport edge, matching the hero block's bleed technique. */
.rm-split--image-bleed .rm-split__media img {
  border-radius: 0;
}

.rm-split--image-bleed.rm-split--image-right .rm-split__media {
  margin-right: calc(-2 * ((100vw - min(100vw, var(--rm-container))) / 2 + var(--rm-container-gutter)));
}

.rm-split--image-bleed:not(.rm-split--image-right) .rm-split__media {
  margin-left: calc(-2 * ((100vw - min(100vw, var(--rm-container))) / 2 + var(--rm-container-gutter)));
}

@media (max-width: 63.9375rem) {
  /* Mobile height cap: independent of the desktop Max Image Height field. */
  .rm-split__media {
    max-height: var(--rm-split-media-max-height-mobile, var(--rm-split-media-max-height, none));
  }

  /* Mobile: image column position relative to text (default DOM order is
     always media then content, which places the mobile grid-row values
     below as 1/2 — image above text. "Below Text" swaps those grid-row
     values instead of using the `order` property, since `order` has no
     effect once grid-row is explicitly assigned, as it is here). Scoped to
     this mobile-only media query so it doesn't leak into — and override —
     the desktop two-column grid-row assignments below. */
  .rm-split--image-mobile-below .rm-split__media {
    grid-row: 2;
  }

  .rm-split--image-mobile-below .rm-split__content {
    grid-row: 1;
  }

  /* Mobile: bleed both sides of the stacked column */
  .rm-split--image-bleed .rm-split__media {
    margin-inline: calc(-2 * var(--rm-container-gutter));
  }

  /* Edge-to-Edge Image, mobile: remove the section's own vertical padding
     so the bled image also reaches the top/bottom edge of the section
     (not just the left/right viewport edges), moving that padding onto
     the text content column instead — the same technique used for the
     desktop two-column layout below. */
  .rm-split--image-bleed {
    padding-block: 0;
  }

  .rm-split--image-bleed .rm-split__content {
    padding-block: var(--rm-section-padding);
  }

  /* Edge-to-Edge Image, mobile, overrides "Fit Image (no crop)": Fit mode's
     object-fit:contain (plus auto width/height, flex-centred track) is
     meant for a column that stops at the container margin — combined with
     the bleed margins above it instead letterboxes/pillarboxes the image
     inside the bled width, leaving visible background on the sides rather
     than a true edge-to-edge fill. Edge-to-Edge always wins on mobile: the
     image covers the full bled width/height, cropping as needed. */
  .rm-split--image-bleed.rm-split--image-fit .rm-split__media {
    display: block;
  }

  .rm-split--image-bleed.rm-split--image-fit .rm-split__media img {
    width: 100%;
    height: 100%;
    object-fit: cover;
  }
}

.rm-split__eyebrow {  font-size: var(--rm-font-size-sm);
  letter-spacing:2px;
  text-transform: uppercase;
  color: var(--rm-text-secondary);
  margin-bottom: var(--rm-space-sm);
  font-weight: 600;
}

.rm-split__heading {
  font-size: var(--rm-font-size-3xl);
  margin-bottom: var(--rm-space-sm);
}

.rm-split__text {
  color: var(--rm-text-secondary);
  margin-bottom: var(--rm-space-md);
  max-width: 90%;
}

@media (min-width: 64rem) {
  .rm-split__inner {
    grid-template-columns: 1fr 1fr;
    gap: var(--rm-space-2xl);
  }

  .rm-split__media,
  .rm-split__content {
    grid-row: 1;
  }

  .rm-split__media {
    grid-column: 1;
  }

  .rm-split__content {
    grid-column: 2;
  }

  .rm-split--image-right .rm-split__media {
    grid-column: 2;
  }

  .rm-split--image-right .rm-split__content {
    grid-column: 1;
  }

  /* Edge-to-Edge Image: stretch the media column to match the full height
     of the row (driven by the content column) instead of centring at its
     own natural/capped height, so the bled image reaches both the outer
     viewport edge and the top/bottom of the row. The section's own
     vertical padding is moved onto the content column so the row (and
     therefore the stretched image) extends the full height of the
     section, edge to edge, with the copy still sitting at the usual
     inset. */
  .rm-split--image-bleed {
    padding-block: 0;
  }

  .rm-split--image-bleed .rm-split__content {
    padding-block: var(--rm-section-padding);
  }

  .rm-split--image-bleed .rm-split__media {
    align-self: stretch;
    /* Without this, a grid item's automatic minimum size defaults to its
       content size — for an image that's its natural intrinsic height —
       so the row (and the whole section) would grow to fit the image at
       full/uncropped height instead of being capped at the content
       column's (much shorter) height, making the section balloon to
       near-100vh on tall images. min-height:0 lets the track size purely
       off the content column, and the image (height:100% below) simply
       crops via object-fit:cover to whatever that height ends up being.
       The max-height set above still caps how far this stretch can grow —
       this is all Split-only sizing logic and has nothing to do with the
       Hero block's intentional 100vh/100dvh full-height treatment. */
    min-height: 0;
  }

  .rm-split--image-bleed .rm-split__media img {
    height: 100%;
  }
}

/* ================= Features ================= */
.rm-features__heading-row {
  max-width: var(--rm-container-narrow);
  margin-inline: auto;
  margin-bottom: var(--rm-space-xl);
  text-align: center;
}

.rm-features__eyebrow {
  font-size: var(--rm-font-size-sm);
  letter-spacing: var(--rm-letter-spacing-meta);
  text-transform: uppercase;
  color: var(--rm-text-secondary);
  margin-bottom: var(--rm-space-sm);
  font-weight: 600;
}

.rm-features__heading {
  font-size: var(--rm-font-size-3xl);
  margin-bottom: var(--rm-space-sm);
}

.rm-features__subheading {
  font-size: var(--rm-font-size-xl);
  color: var(--rm-text-secondary);
  margin-bottom: var(--rm-space-sm);
}

.rm-features__description {
  color: var(--rm-text-secondary);
}

.rm-features__grid {
  display: grid;
  grid-template-columns: repeat(1, 1fr);
  gap: var(--rm-space-lg);
}

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

@media (min-width: 48rem) {
  .rm-features__grid--2 { grid-template-columns: repeat(2, 1fr); }
  .rm-features__grid--3 { grid-template-columns: repeat(2, 1fr); }
  .rm-features__grid--4 { grid-template-columns: repeat(2, 1fr); }
}

@media (min-width: 64rem) {
  .rm-features__grid--3 { grid-template-columns: repeat(3, 1fr); }
  .rm-features__grid--4 { grid-template-columns: repeat(4, 1fr); }
}

.rm-feature-card {
  background: var(--rm-surface-subtle);
  border: 1px solid var(--rm-border);
  border-radius: var(--rm-radius-sm);
  /* Card padding lives on .rm-feature-card__body instead of the card
     itself, so an edge-to-edge .rm-feature-card__media can bleed flush
     with the card's own rounded corners (clipped via overflow:hidden)
     while the text content keeps its inset. Icon-only cards (no media)
     behave identically to before — the body simply fills the whole card. */
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

.rm-feature-card__body {
  padding: var(--rm-space-md);
  /* Flex column so a per-item CTA button (if present) can be pinned to the
     bottom via margin-top:auto below, keeping buttons aligned along the
     bottom edge of each row even when descriptions vary in length. */
  display: flex;
  flex-direction: column;
  flex-grow: 1;
}

/* "Item Media: Image" — gives the image noticeably more visual presence
   than an icon: it spans the full card width at a generous aspect ratio,
   bleeding flush with the card's edges (top edge when above the text,
   bottom edge when below) rather than sitting inset like a small icon. */
.rm-feature-card__media {
  flex-shrink: 0;
}

.rm-feature-card__media img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 10;
  object-fit: cover;
}

.rm-feature-card__icon {
  display: inline-flex;
  align-items: center;
  height: 2.75rem;
  flex-shrink: 0;
}

.rm-feature-card__icon svg {
  width: 1.75rem;
  height: 1.75rem;
  color: var(--rm-text-primary);
}

/* Icon Layout: positions the icon relative to the title within
   .rm-feature-card__heading-row. All four directions are achieved purely
   via flex-direction (no DOM reordering needed) — gap provides consistent
   spacing in every direction, replacing the icon's own margin-bottom. */
.rm-feature-card__heading-row {
  display: flex;
  gap: var(--rm-space-sm);
  margin-bottom: var(--rm-space-xs);
}

.rm-feature-card--icon-top .rm-feature-card__heading-row,
.rm-feature-card--icon-bottom .rm-feature-card__heading-row {
  flex-direction: column;
  align-items: flex-start;
  gap: var(--rm-space-md);
}

.rm-feature-card--icon-bottom .rm-feature-card__heading-row {
  /* DOM order is always icon, then title — column-reverse flips the
     visual order so the title renders first (top) and the icon last
     (bottom), without needing separate markup per layout. */
  flex-direction: column-reverse;
}

.rm-feature-card--icon-left .rm-feature-card__heading-row {
  flex-direction: row;
  align-items: center;
}

.rm-feature-card--icon-right .rm-feature-card__heading-row {
  /* Same DOM-order trick as --icon-bottom, but on the row axis: row-reverse
     puts the title first/left and the icon last/right. */
  flex-direction: row-reverse;
  align-items: center;
}

.rm-feature-card__title {
  font-size: var(--rm-font-size-lg);
  margin-bottom: var(--rm-space-xs);
}

.rm-feature-card__description {
  font-size: var(--rm-font-size-sm);
  color: var(--rm-text-secondary);
}

/* Per-item CTA: pinned to the bottom of the card body (see
   .rm-feature-card__body's flex-column above) so it lines up along the
   bottom of each row regardless of description length, with a little
   breathing room above it. Smaller size than the block-level CTA below
   since it's a secondary, per-card action. */
.rm-feature-card__cta {
  margin-top: var(--rm-space-md);
  font-size: var(--rm-font-size-sm);
}

/* Whole-grid CTA: a single button shown once for the entire block, either
   above or below the grid (see $cta_position in render.php). Centred to
   match the heading row above it. */
.rm-features__cta {
  text-align: center;
}

.rm-features__cta--above {
  margin-bottom: var(--rm-space-xl);
}

.rm-features__cta--below {
  margin-top: var(--rm-space-xl);
}

/* ================= Services ================= */
/* Eyebrow sits left-aligned at the top of the section (unlike Features'
   centred heading-row) — no max-width/mx-auto centring here. */
.rm-services__eyebrow {
  font-size: var(--rm-font-size-sm);
  letter-spacing: var(--rm-letter-spacing-meta);
  text-transform: uppercase;
  color: var(--rm-text-secondary);
  font-weight: 600;
  margin-bottom: var(--rm-space-xl);
}

/* Each row is separated by a hairline rule (rather than a card background)
   so a long list reads as one continuous, editorial list rather than a
   stack of boxes — border-top on every row but the first avoids a doubled
   line between rows. Mobile gets a slightly tighter vertical rhythm than
   desktop (var(--rm-space-lg) vs. --rm-space-xl) since the stacked
   image+text layout already reads as more spacious without a large gap
   between rows too. */
.rm-service-row {
  padding-block: var(--rm-space-lg);
}

@media (min-width: 64rem) {
  .rm-service-row {
    padding-block: var(--rm-space-xl);
  }
}

.rm-service-row + .rm-service-row {
  border-top: 1px solid var(--rm-border);
}

.rm-services__list > .rm-service-row:first-child {
  padding-top: 0;
}

.rm-services__list > .rm-service-row:last-child {
  padding-bottom: 0;
}

.rm-service-row__inner {
  display: flex;
  flex-direction: column;
  gap: var(--rm-space-lg);
}

/* DOM order is always media, then content — on mobile (no hover affordance
   to reveal it) the image is simply always shown, stacked above the text.
   The image renders as a background-image on a fixed-ratio box (set inline
   in render.php), fully decoupling the image's rendered size from layout
   sizing — the box is the image. */
.rm-service-row__media {
  border-radius: var(--rm-radius-lg);
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  width: 100%;
  aspect-ratio: 4 / 3;
}

.rm-service-row__heading {
  font-size: var(--rm-font-size-3xl);
  margin-bottom: var(--rm-space-sm);
}

/* Description and the hover-only Details line overlap via simple
   position:relative/absolute (no grid) — the in-flow description sets the
   container's height; the details line is absolutely layered on top of it
   and crossfaded in on desktop hover. On mobile the Details line stays
   hidden since there's no hover state to reveal it. */
.rm-service-row__text-stack {
  position: relative;
  margin-bottom: var(--rm-space-md);
}

.rm-service-row__description,
.rm-service-row__details {
  transition: opacity var(--rm-duration) var(--rm-ease),
    transform var(--rm-duration) var(--rm-ease);
}

.rm-service-row__description {
  font-size: var(--rm-font-size-lead);
  color: var(--rm-text-secondary);
  margin-bottom: 0;
}

.rm-service-row__details {
  position: absolute;
  inset-block-start: 0;
  inset-inline-start: 0;
  font-size: var(--rm-font-size-lead);
  color: var(--rm-text-secondary);
  opacity: 0;
  pointer-events: none;
  transform: translateY(0.25rem);
  margin: 0;
}

@media (min-width: 64rem) {
  .rm-service-row__inner {
    flex-direction: row;
    align-items: center;
    /* Clips the media column while it sits off-canvas at rest (see the
       negative margin on .rm-service-row__media below). */
    overflow: hidden;
  }

  /* Simple, fixed-size background-image box: 9rem × 6.75rem (4:3). Its
     size never changes — the hide/reveal is purely positional: a negative
     inline-start margin equal to its own width pulls it fully off-canvas
     at rest (clipped by the inner's overflow:hidden); on hover the margin
     animates to 0 and the gap to the text opens on the other side. */
  .rm-service-row__media {
    flex: 0 0 auto;
    width: 9rem;
    height: 6.75rem;
    aspect-ratio: auto;
    margin-inline-start: -9rem;
    margin-inline-end: 0;
    opacity: 0;
    transition: margin var(--rm-duration-slow) var(--rm-ease),
      opacity var(--rm-duration) var(--rm-ease);
  }

  .rm-service-row:hover .rm-service-row__media,
  .rm-service-row:focus-within .rm-service-row__media {
    margin-inline-start: 0;
    margin-inline-end: var(--rm-space-2xl);
    opacity: 1;
  }

  .rm-service-row__content {
    flex: 1 1 auto;
    min-width: 0;
  }

  /* Keeps long descriptions from stretching the full width of the text
     column on desktop — reads better as a measured paragraph rather than
     edge-to-edge lines. */
  .rm-service-row__description,
  .rm-service-row__details {
    max-width: 50%;
  }

  /* On hover/focus, crossfade the description out and the bullet-separated
     Details line in (see .rm-service-row__text-stack above for why this
     doesn't jump the row's height). */
  .rm-service-row:hover .rm-service-row__description,
  .rm-service-row:focus-within .rm-service-row__description {
    opacity: 0;
    pointer-events: none;
    transform: translateY(-0.25rem);
  }

  .rm-service-row:hover .rm-service-row__details,
  .rm-service-row:focus-within .rm-service-row__details {
    opacity: 1;
    pointer-events: auto;
    transform: translateY(0);
  }

  /* "Image Position: Right of Text" — DOM order is always media then
     content; `order` flips the visual order to put the image after the
     text/CTA column instead, without needing separate markup per layout.
     The off-canvas pull and animated gap both flip sides: at rest the
     column is pulled off the RIGHT edge (negative inline-end margin);
     on hover it slides back in with the gap opening on its inline-start
     side, toward the text column to its left. */
  .rm-services--image-right .rm-service-row__media {
    order: 2;
    margin-inline-start: 0;
    margin-inline-end: -9rem;
  }

  .rm-services--image-right .rm-service-row__content {
    order: 1;
  }

  .rm-services--image-right .rm-service-row:hover .rm-service-row__media,
  .rm-services--image-right .rm-service-row:focus-within .rm-service-row__media {
    margin-inline-start: var(--rm-space-2xl);
    margin-inline-end: 0;
  }
}

@media (prefers-reduced-motion: reduce) {
  .rm-service-row__media,
  .rm-service-row__description,
  .rm-service-row__details {
    transition: opacity var(--rm-duration-fast) linear;
  }
}
