/**
 * CF Flex Card Block — six-mode framework per CF_MODULE_GUIDE §8.
 *
 * Modes:
 *   .cf-flex-card-block--light-sky    Briefing-grade default
 *   .cf-flex-card-block--light-slate  Analytical / operational
 *   .cf-flex-card-block--light-paper  Editorial / long-form (white bg)
 *   .cf-flex-card-block--light-mint   Positive outcome / growth
 *   .cf-flex-card-block--dark-navy    Brand authority anchor
 *   .cf-flex-card-block--dark-ops     GSOC / command center
 *
 * Override variables:
 *   --cffcb-section-bg  section background
 *   --cffcb-eyebrow     small uppercase label color
 *   --cffcb-heading     section heading + card title (default state)
 *   --cffcb-body        card summary + section intro body color
 *   --cffcb-thumb-bg    sky-blue thumbnail panel behind cf_hero_image
 *   --cffcb-meta        card meta (when used)
 *   --cffcb-line        section header rule + dot/arrow neutral
 *   --cffcb-hover       card title hover color + active dot color
 *
 * 3-column desktop, 1-column mobile. Breakpoint via cf_core/brand
 * (--cf-breakpoint-desktop). Card thumbnail is always 16:10.
 */

.cf-flex-card-block {
  /* Base defaults = light_sky. Mode classes below override.
     --cffcb-thumb-bg is the panel shown behind the card image; the
     image covers it once loaded, so this is effectively the loading
     placeholder color. Light modes use a neutral grey so the
     placeholder reads as "image loading" rather than as a branded
     color block. Dark modes keep a dark surface so the section
     doesn't flash light before the image arrives. */
  --cffcb-section-bg: var(--cf-sky-light);
  --cffcb-eyebrow: var(--cf-sky-mid);
  --cffcb-heading: var(--cf-navy);
  --cffcb-body: var(--cf-blue-gray);
  --cffcb-thumb-bg: var(--cf-blue-gray-tint);
  --cffcb-meta: var(--cf-blue-gray);
  --cffcb-line: var(--cf-blue-gray-tint);
  --cffcb-hover: var(--cf-sky-mid);

  background: var(--cffcb-section-bg);
  color: var(--cffcb-body);
  padding: 48px 24px 96px;
  font-family: var(--cf-font-stack);
  box-sizing: border-box;
  /* Don't refuse to shrink when placed inside a parent flex
     container. See the same comment block in
     cf-flex-card-block-sections.css for the full rationale. */
  min-width: 0;
}

.cf-flex-card-block *,
.cf-flex-card-block *::before,
.cf-flex-card-block *::after {
  box-sizing: inherit;
}

/* Content container: matches the __inner pattern used by cf-hero,
   cf-stats, cf-services-strip and cf-featured-report. The outer
   .cf-flex-card-block carries the section background and padding;
   .cf-flex-card-block__inner caps content width so the heading,
   card grid and pagination line up horizontally with content in
   the surrounding sections (which also constrain to ~1200px).
   Override per-section by setting --cffcb-inner-max-width on the
   .cf-flex-card-block element. */
.cf-flex-card-block__inner {
  max-width: var(--cffcb-inner-max-width, 1200px);
  margin-inline: auto;
  width: 100%;
  /* Final link in the min-width: 0 chain. The full chain from
     the outside in is: cf-flex-card-block-sections →
     cf-flex-card-block-sections__section → cf-flex-card-block
     (the <section>) → cf-flex-card-block__inner →
     cf-flex-card-block__wrapper → cf-flex-card-block__item.
     Each link must opt out of min-width: auto so the wrapper
     can shrink below its content's intrinsic size in narrow
     columns. */
  min-width: 0;
}

/* ── Light: Sky ─────────────────────────────────────────────────────── */
.cf-flex-card-block--light-sky {
  --cffcb-section-bg: var(--cf-sky-light);
  --cffcb-eyebrow: var(--cf-sky-mid);
  --cffcb-heading: var(--cf-navy);
  --cffcb-body: var(--cf-blue-gray);
  --cffcb-thumb-bg: var(--cf-blue-gray-tint);
  --cffcb-meta: var(--cf-blue-gray);
  --cffcb-line: var(--cf-blue-gray-tint);
  --cffcb-hover: var(--cf-sky-mid);
}

/* ── Light: Slate ───────────────────────────────────────────────────── */
.cf-flex-card-block--light-slate {
  --cffcb-section-bg: var(--cf-blue-gray-lightest);
  --cffcb-eyebrow: var(--cf-navy);
  --cffcb-heading: var(--cf-navy);
  --cffcb-body: var(--cf-blue-gray);
  --cffcb-thumb-bg: var(--cf-blue-gray-tint);
  --cffcb-meta: var(--cf-blue-gray);
  --cffcb-line: var(--cf-blue-gray-tint);
  --cffcb-hover: var(--cf-navy);
}

/* ── Light: Paper ───────────────────────────────────────────────────── */
.cf-flex-card-block--light-paper {
  --cffcb-section-bg: var(--cf-white);
  --cffcb-eyebrow: var(--cf-navy);
  --cffcb-heading: var(--cf-navy);
  --cffcb-body: var(--cf-blue-gray);
  --cffcb-thumb-bg: var(--cf-blue-gray-tint);
  --cffcb-meta: var(--cf-blue-gray);
  --cffcb-line: var(--cf-blue-gray-tint);
  --cffcb-hover: var(--cf-navy);
}

/* ── Light: Mint (positive outcome / growth) ────────────────────────── */
.cf-flex-card-block--light-mint {
  --cffcb-section-bg: var(--cf-apple-pale);
  --cffcb-eyebrow: var(--cf-leaf);
  --cffcb-heading: var(--cf-navy);
  --cffcb-body: var(--cf-blue-gray);
  --cffcb-thumb-bg: var(--cf-blue-gray-tint);
  --cffcb-meta: var(--cf-blue-gray);
  --cffcb-line: var(--cf-blue-gray-tint);
  --cffcb-hover: var(--cf-leaf);
}

/* ── Dark: Navy ─────────────────────────────────────────────────────── */
.cf-flex-card-block--dark-navy {
  --cffcb-section-bg: var(--cf-navy);
  --cffcb-eyebrow: var(--cf-sky);
  --cffcb-heading: var(--cf-navy-lightest);
  --cffcb-body: color-mix(in srgb, var(--cf-navy-lightest) 75%, transparent);
  --cffcb-thumb-bg: var(--cf-navy-lifted);
  --cffcb-meta: color-mix(in srgb, var(--cf-navy-lightest) 60%, transparent);
  --cffcb-line: rgba(255, 255, 255, 0.10);
  --cffcb-hover: var(--cf-sky);
}

/* ── Dark: Ops ──────────────────────────────────────────────────────── */
.cf-flex-card-block--dark-ops {
  --cffcb-section-bg: var(--cf-slate-section);
  --cffcb-eyebrow: var(--cf-golden-orange);
  --cffcb-heading: var(--cf-blue-gray-tint);
  --cffcb-body: var(--cf-blue-gray-soft);
  --cffcb-thumb-bg: var(--cf-slate-card);
  --cffcb-meta: var(--cf-blue-gray-soft);
  --cffcb-line: rgba(255, 255, 255, 0.08);
  --cffcb-hover: var(--cf-golden-orange);
}

/* ── Section header (eyebrow + h2 + bottom rule) ────────────────────── */
.cf-flex-card-block__header {
  display: flex;
  flex-direction: column;
  margin-bottom: 64px;
  padding-bottom: 32px;
  border-bottom: 1px solid var(--cffcb-line);
}

.cf-flex-card-block__eyebrow {
  font-size: 12px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  font-weight: 600;
  color: var(--cffcb-eyebrow);
  margin-bottom: 16px;
}

.cf-flex-card-block__heading {
  font-size: clamp(36px, 4vw, 52px);
  line-height: 1.1;
  letter-spacing: -0.01em;
  font-weight: 600;
  color: var(--cffcb-heading);
  margin: 0;
}

/* ── Grid: 1-col mobile, 3-col at desktop breakpoint ────────────────── */
.cf-flex-card-block__wrapper {
  display: grid;
  grid-template-columns: 1fr;
  gap: 48px 32px;
  /* min-width: 0 is needed because grid items default to
     min-width: auto which means "don't shrink below content's
     min-content size". With migrated images carrying explicit
     width="1600" attributes for CLS prevention, the grid track
     would otherwise grow to ~1600px and overflow the column. */
  min-width: 0;
}

.cf-flex-card-block__item {
  /* Same reasoning: each grid item should be allowed to shrink
     below its intrinsic image width. Prevents the cards-grid
     wrapper from blowing past its parent's width on viewports
     narrower than the image's HTML width attribute. */
  min-width: 0;
}

@media (min-width: 1024px) {
  .cf-flex-card-block__wrapper {
    grid-template-columns: repeat(3, 1fr);
    gap: 64px 48px;
  }
}

.cf-flex-card-block__item.is-hidden {
  display: none;
}

/* FOUC prevention: server-render the correct first-page state per
   breakpoint. These two classes are emitted by the Twig template on
   cards beyond cards_per_page_* for the matching viewport. The
   carousel JS strips them on init and takes over with its own
   `is-hidden` tracking. No-JS users keep the first-page state at
   their viewport — graceful degradation rather than a giant stacked
   column. */
@media (max-width: 1023.98px) {
  .cf-flex-card-block__item.is-hidden-mobile { display: none; }
}
@media (min-width: 1024px) {
  .cf-flex-card-block__item.is-hidden-desktop { display: none; }
}

.cf-flex-card-block__empty {
  grid-column: 1 / -1;
  text-align: center;
  color: var(--cffcb-body);
  padding: 64px 0;
  font-size: 15px;
}

/* ── Card ───────────────────────────────────────────────────────────── */
.cf-flex-card {
  display: block;
  text-decoration: none;
  color: inherit;
  cursor: pointer;
  position: relative;
  border-radius: 4px;
  transition: transform 0.2s ease, box-shadow 0.2s ease;
}

.cf-flex-card:hover,
.cf-flex-card:focus-visible {
  transform: translateY(-4px);
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.10);
  outline: none;
}

/* Touch-device affordance: hover state never fires on phones, so the
   card loses its visual cue of being tappable. Replace it with a
   persistent border + soft shadow only when the pointer is coarse
   (touch screens). Desktop / laptop / trackpad pointers keep the
   cleaner hover-only treatment. */
@media (hover: none) and (pointer: coarse) {
  .cf-flex-card {
    border: 1px solid var(--cffcb-line);
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.06);
  }
  /* Side layout opts out of the mobile-touch affordance — the
     image-left/text-right composition already provides a strong
     visual anchor that signals "tappable" without an outline.
     A border on these cards reads as redundant chrome. */
  .cf-flex-card--layout-side {
    border: 0;
    box-shadow: none;
  }
}

.cf-flex-card__media {
  background: var(--cffcb-thumb-bg);
  margin-bottom: 24px;
  border-radius: 4px;
  overflow: hidden;
  /* No aspect-ratio lock here — image style determines card shape.
     The carousel layout-shift that previously required a lock is now
     prevented by explicit width/height attributes on the <img>,
     populated by TeaserQueryService::resolveImageData() from the
     image style's derivative dimensions. The browser reserves the
     correct box before bytes arrive, so lazy-loaded cards no longer
     collapse to 0px tall on carousel advance.

     If you ever want to force a uniform card shape regardless of
     image style (e.g. for a curated overlay-style section), set the
     `--cffcb-card-aspect` custom property on the section — see the
     layout-stacked-aspect-ratio override below for the recipe. */
}

/* Image renders at its natural style dimensions; width caps at the
   card width so narrow viewports never overflow. height:auto lets
   the browser keep the intrinsic aspect ratio from the width/height
   attributes — crucial for the no-CLS guarantee. */
.cf-flex-card__media img {
  display: block;
  width: 100%;
  height: auto;
  transition: transform 0.4s ease;
}

.cf-flex-card:hover .cf-flex-card__media img,
.cf-flex-card:focus-visible .cf-flex-card__media img {
  transform: scale(1.04);
}

.cf-flex-card__body {
  padding: 0 20px 20px;
}

/* Card tag (first taxonomy term name) styled as an eyebrow — same
   visual treatment as the section-level .cf-flex-card-block__eyebrow
   so the two read as the same typographic system at different scales.
   Sits above the card title. */
.cf-flex-card__tag {
  font-size: 12px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  font-weight: 600;
  color: var(--cffcb-eyebrow);
  margin: 0 0 8px;
}

/* Title and summary are line-clamped so every card on every page has
   the same total height. Combined with the fixed 16:10 image ratio
   this makes the grid height per page constant — which keeps the
   pagination controls below from jumping up and down as the user
   pages through cards with different copy lengths. */
.cf-flex-card__title {
  font-size: 22px;
  line-height: 1.3;
  font-weight: 600;
  color: var(--cffcb-heading);
  margin: 0 0 16px;
  transition: color 0.2s ease;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  /* Reserve 2 lines of space even when the title is only 1 line, so
     short-title cards still occupy the same height. */
  min-height: calc(22px * 1.3 * 2);
}

.cf-flex-card:hover .cf-flex-card__title {
  color: var(--cffcb-hover);
}

.cf-flex-card__summary {
  color: var(--cffcb-body);
  font-size: 15px;
  line-height: 1.55;
  display: -webkit-box;
  -webkit-line-clamp: 3;
  line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
  min-height: calc(15px * 1.55 * 3);
}

.cf-flex-card__summary p {
  margin: 0;
  /* When the rendered field outputs <p> wrappers the line-clamp on the
     parent still applies because the <p> doesn't break the box's line
     accounting; this rule just removes paragraph margins. */
}

/* ── Pagination (arrows + dots) ─────────────────────────────────────── */
.cf-flex-card-block__pagination {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 24px;
  margin-top: 64px;
}

/* Per-breakpoint fit modifiers: when every card already fits in the
   current viewport's grid, hide the pagination controls there. The
   DOM stays rendered so the carousel JS can still react to a resize
   that crosses the breakpoint into a viewport that needs pagination
   (e.g. desktop → phone with cards_per_page_mobile=1). */
@media (max-width: 1023.98px) {
  .cf-flex-card-block__pagination--fits-mobile {
    display: none;
  }
}
@media (min-width: 1024px) {
  .cf-flex-card-block__pagination--fits-desktop {
    display: none;
  }
}

.cf-flex-card-block__nav {
  background: transparent;
  border: 1px solid var(--cffcb-line);
  color: var(--cffcb-heading);
  /* Locked to a 44×44 circle regardless of viewport. Without these
     flex / min-* / aspect-ratio constraints the flex-shrink default
     of 1 squeezes the buttons into ovals on narrow screens. */
  flex: 0 0 44px;
  width: 44px;
  height: 44px;
  min-width: 44px;
  min-height: 44px;
  aspect-ratio: 1 / 1;
  border-radius: 50%;
  font-size: 18px;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  transition: border-color 0.2s ease, color 0.2s ease;
}

.cf-flex-card-block__nav:hover:not([disabled]) {
  border-color: var(--cffcb-hover);
  color: var(--cffcb-hover);
}

.cf-flex-card-block__nav[disabled] {
  opacity: 0.35;
  cursor: not-allowed;
}

.cf-flex-card-block__dots {
  display: flex;
  gap: 10px;
}

.cf-flex-card-block__dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  border: none;
  background: var(--cffcb-line);
  padding: 0;
  cursor: pointer;
  transition: background-color 0.2s ease, transform 0.2s ease;
}

.cf-flex-card-block__dot:hover {
  background: var(--cffcb-hover);
}

.cf-flex-card-block__dot.is-active {
  background: var(--cffcb-hover);
  transform: scale(1.4);
}

/* ── High-count tier: progress track + thumb ────────────────────────────
   Renders only when total_pages ≥ 8. The track is a thin horizontal
   bar; the thumb is fixed-width (12% of track) regardless of page
   count, so its width never leaks the total. Position = currentPage /
   (totalPages - 1). The track is also a clickable / draggable jump
   target — the track element carries role="slider" and pointer/keyboard
   handlers in JS.                                                       */
.cf-flex-card-block__track {
  position: relative;
  /* Use flex sizing instead of an explicit width: the track grows to
     fill whatever space the pagination row has, capped at 280px on
     wider viewports. The previous `width: 280px; max-width: 60vw`
     gave the track a *definite* intrinsic size that propagated up
     the flex chain — combined with the two 44px arrow buttons and
     gaps, the pagination's min-content was ~442px, which forced
     `.layout__region--first` (a flex item with default
     `min-width: auto`) to overflow its 398px container. flex-basis
     of 0 + min-width 0 means the track contributes 0 to min-content,
     so the pagination can collapse to just the buttons on narrow
     viewports. */
  flex: 1 1 0;
  min-width: 0;
  max-width: 280px;
  height: 18px;                       /* generous hit target */
  display: flex;
  align-items: center;
  cursor: pointer;
  /* The actual visible bar is drawn via ::before so the track element
     itself stays a comfortable click/touch target (18px tall) without
     making the visible rule that thick. */
}
.cf-flex-card-block__track::before {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  top: 50%;
  height: 3px;
  margin-top: -1.5px;
  background: var(--cffcb-line);
  border-radius: 2px;
}
.cf-flex-card-block__track:focus-visible {
  outline: 2px solid var(--cffcb-hover);
  outline-offset: 6px;
  border-radius: 2px;
}
.cf-flex-card-block__track.is-dragging {
  cursor: grabbing;
}

.cf-flex-card-block__thumb {
  position: relative;
  width: 12%;
  min-width: 28px;                    /* never shrink below a usable size */
  height: 8px;
  background: var(--cffcb-hover);
  border-radius: 4px;
  pointer-events: none;               /* JS uses the track for hit-testing */
  transition: transform 0.25s ease;
  will-change: transform;
}

@media (prefers-reduced-motion: reduce) {
  .cf-flex-card-block__thumb { transition: none; }
}

/* ── Layout variant: side ───────────────────────────────────────────────
 * Side layout: image on the left, title + summary on the right.
 *
 * Mobile (<1024px): image is a narrow left column (35% of card width).
 * Designed for portrait-oriented image styles like A4 report covers —
 * a full-width A4 stacked on a 375px phone produces a ~530px-tall card,
 * which dwarfs the title/summary block. Keeping the image in a 35%
 * column caps card height at ~200px regardless of image aspect ratio.
 *
 * Desktop (≥1024px): image switches to intrinsic-size column (width
 * follows image style's native dimensions). For A4 portrait at
 * cf_card_portrait sizing this is ~280px wide, leaving the body
 * column comfortable for clamp-controlled title + 3-line summary.
 *
 * Six theme-mode rules above continue to apply unchanged because the
 * mode classes live on the section wrapper.
 */
.cf-flex-card-block--layout-side .cf-flex-card-block__wrapper {
  grid-template-columns: 1fr;             /* mobile: 1 column */
  gap: 32px;
}

@media (min-width: 1024px) {
  .cf-flex-card-block--layout-side .cf-flex-card-block__wrapper {
    grid-template-columns: repeat(2, 1fr); /* desktop: 2 columns (was 3 in stacked) */
    gap: 48px 32px;
  }
}

/* Mobile baseline: side-by-side from the smallest viewport.
   align-items: stretch lets the image column visually anchor to the
   body column's top edge while still allowing the image to render
   at its natural ratio without distortion. */
.cf-flex-card--layout-side {
  display: flex;
  flex-direction: row;
  align-items: flex-start;
  gap: 16px;
}

/* Mobile image column: fixed 35% width. Image inside renders at
   100% of the column with auto height (browser uses the explicit
   width/height attributes from resolveImageData to keep ratio). */
.cf-flex-card--layout-side .cf-flex-card__media {
  flex: 0 0 35%;
  margin-bottom: 0;
}
.cf-flex-card--layout-side .cf-flex-card__media img {
  width: 100%;
  height: auto;
}

/* Mobile body: takes remaining width; tighter padding than the
   stacked default so the narrower column still feels generous. */
.cf-flex-card--layout-side .cf-flex-card__body {
  flex: 1 1 auto;
  padding: 4px 16px 16px 8px;
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
}

@media (min-width: 1024px) {
  .cf-flex-card--layout-side {
    gap: 0;                               /* desktop uses body padding instead */
  }
  .cf-flex-card--layout-side .cf-flex-card__media {
    flex: 0 0 auto;                       /* width follows the image style's intrinsic width */
  }
  .cf-flex-card--layout-side .cf-flex-card__media img {
    width: auto;                          /* don't scale to column — render at image style width */
    height: auto;
    max-width: 100%;
  }
  .cf-flex-card--layout-side .cf-flex-card__body {
    padding: 4px 20px 20px 24px;
  }
}

.cf-flex-card--layout-side .cf-flex-card__title {
  font-size: clamp(20px, 2vw, 26px);
  font-weight: 600;
  text-align: left;
  margin: 0 0 12px;
}

/* ── Layout variant: tag ────────────────────────────────────────────────
 * Tag layout: no image, large typography, term name dominant.
 *
 * Use case: taxonomy/topic clusters where the editorial focus is the
 * tag itself — "Trends," "Industries," "Insights by Topic," etc. The
 * preset still queries nodes (filtered by vocabulary or term IDs) but
 * the rendered card foregrounds the term name and uses the node title
 * as supporting copy.
 *
 * Grid: tag cards are visually denser than stacked cards, so the
 * desktop grid grows to 4 columns instead of 3.
 *
 * Card surface: filled with --cffcb-thumb-bg (the same tint used as
 * the loading placeholder on stacked cards), giving each tag card a
 * tile-like presence on the section background.
 */
.cf-flex-card-block--layout-tag .cf-flex-card-block__wrapper {
  grid-template-columns: 1fr;
  gap: 16px;
}

@media (min-width: 640px) {
  .cf-flex-card-block--layout-tag .cf-flex-card-block__wrapper {
    grid-template-columns: repeat(2, 1fr);
    gap: 20px;
  }
}

@media (min-width: 1024px) {
  .cf-flex-card-block--layout-tag .cf-flex-card-block__wrapper {
    grid-template-columns: repeat(4, 1fr);
    gap: 24px;
  }
}

.cf-flex-card--layout-tag {
  background: var(--cffcb-thumb-bg);
  padding: 28px 24px;
  border-radius: 6px;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  min-height: 180px;
}

/* Term name (the `tag` field) reads as the dominant label on the card —
   larger and sharper than the stacked-card eyebrow treatment. Sits at
   the top, anchors the visual rhythm. */
.cf-flex-card--layout-tag .cf-flex-card__tag {
  font-size: 11px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  font-weight: 700;
  color: var(--cffcb-eyebrow);
  margin: 0 0 16px;
}

/* Title is the node label — secondary to the tag, but still the
   clickable headline. clamp lets short titles look airy and long
   titles wrap to a generous 4 lines without forcing min-height. */
.cf-flex-card--layout-tag .cf-flex-card__title {
  font-size: clamp(20px, 2vw, 26px);
  line-height: 1.25;
  font-weight: 600;
  color: var(--cffcb-heading);
  margin: 0;
  -webkit-line-clamp: 4;
  line-clamp: 4;
  min-height: 0;                          /* override stacked card's 2-line reservation */
}

/* Summary is hidden by default on tag layout — keeps the card visually
   simple and emphasizes the term/title hierarchy. If a future preset
   needs a 1-line teaser, remove this rule and set line-clamp: 1. */
.cf-flex-card--layout-tag .cf-flex-card__summary {
  display: none;
}

/* Body is the whole inner wrapper here — the card itself provides
   padding, so reset the body's stacked-default padding. */
.cf-flex-card--layout-tag .cf-flex-card__body {
  padding: 0;
}

/* Hover lift is gentler since tag cards are smaller / denser than
   stacked cards — strong lifts feel jumpy on a 4-up row. */
.cf-flex-card--layout-tag:hover,
.cf-flex-card--layout-tag:focus-visible {
  transform: translateY(-2px);
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.08);
}

/* ── Layout variant: overlay ────────────────────────────────────────────
 * Overlay layout: image fills the card, text sits on a gradient scrim
 * at the bottom. Card is locked to a 4:5 portrait aspect ratio so the
 * grid stays rhythmic regardless of source image proportions.
 *
 * Use case: featured / editorial highlights where the image is the
 * primary visual hook. Pair with a high-resolution 4:5 image style
 * (default_image_style_overlay) so the image doesn't pixelate when
 * scaled across the card.
 *
 * Markup is identical to stacked — only CSS differs. .__media gets
 * absolutely positioned to fill the card; .__body absolutely
 * positioned at the bottom with a black gradient behind it for
 * legibility.
 */
.cf-flex-card-block--layout-overlay .cf-flex-card-block__wrapper {
  grid-template-columns: 1fr;
  gap: 24px;
}

@media (min-width: 640px) {
  .cf-flex-card-block--layout-overlay .cf-flex-card-block__wrapper {
    grid-template-columns: repeat(2, 1fr);
    gap: 28px;
  }
}

@media (min-width: 1024px) {
  .cf-flex-card-block--layout-overlay .cf-flex-card-block__wrapper {
    grid-template-columns: repeat(3, 1fr);
    gap: 32px;
  }
}

.cf-flex-card--layout-overlay {
  position: relative;
  overflow: hidden;
  border-radius: 6px;
  aspect-ratio: 4 / 5;
  background: var(--cffcb-thumb-bg);     /* loading placeholder + no-image fallback */
  display: block;                         /* override flex from side layout if cascaded */
}

/* Image fills the card. The width/height attributes on <img> already
   declare an aspect ratio for CLS protection, but the card itself owns
   the final shape via aspect-ratio above — image gets cropped to fit
   with object-fit: cover. */
.cf-flex-card--layout-overlay .cf-flex-card__media {
  position: absolute;
  inset: 0;
  margin: 0;
  border-radius: 0;
  background: transparent;
}
.cf-flex-card--layout-overlay .cf-flex-card__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* Body sits at the bottom over a gradient scrim. The scrim is on the
   card (not the body) so it covers the lower 60% of the image and
   fades cleanly. Body padding keeps text off the card edges. */
.cf-flex-card--layout-overlay::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(
    to bottom,
    rgba(0, 0, 0, 0) 25%,
    rgba(0, 0, 0, 0.45) 50%,
    rgba(0, 0, 0, 0.80) 75%,
    rgba(0, 0, 0, 0.92) 100%
  );
  pointer-events: none;
}

.cf-flex-card--layout-overlay .cf-flex-card__body {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  padding: 24px 24px 28px;
  z-index: 1;                             /* above the scrim */
  color: #fff;
}

/* Tag is small, light, all-caps — same eyebrow rhythm as the rest of
   the family, just always white because the scrim background is fixed
   dark regardless of theme mode. */
.cf-flex-card--layout-overlay .cf-flex-card__tag {
  font-size: 11px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  font-weight: 600;
  color: rgba(255, 255, 255, 0.85);
  margin: 0 0 10px;
}

/* Title is the dominant element — generous size, tight leading.
   No clamp min-height: short titles look airy, long titles wrap
   naturally up to 4 lines before clipping. */
.cf-flex-card--layout-overlay .cf-flex-card__title {
  font-size: clamp(22px, 2.4vw, 30px);
  line-height: 1.2;
  font-weight: 600;
  color: #fff;
  margin: 0;
  -webkit-line-clamp: 4;
  line-clamp: 4;
  min-height: 0;
}

/* Summary sits below the title on the scrim. Clamped to 2 lines and
   slightly dimmed so the title stays dominant — the summary is
   supporting copy, not the headline. */
.cf-flex-card--layout-overlay .cf-flex-card__summary {
  margin-top: 8px;
  font-size: 14px;
  line-height: 1.5;
  color: rgba(255, 255, 255, 0.88);
  -webkit-line-clamp: 2;
  line-clamp: 2;
  min-height: 0;
}

/* Summary HTML often wraps in <p> — keep it inline-margin-free so
   the clamp accounting matches the rendered visual. */
.cf-flex-card--layout-overlay .cf-flex-card__summary p {
  margin: 0;
}

/* Hover: subtle image zoom + slight lift. The base .cf-flex-card
   hover already lifts -4px; we keep that and let the image zoom add
   editorial polish. */
.cf-flex-card--layout-overlay:hover .cf-flex-card__media img,
.cf-flex-card--layout-overlay:focus-visible .cf-flex-card__media img {
  transform: scale(1.05);
}

/* Title-color shift on hover doesn't apply to overlay (text is already
   white over a scrim — a hover color would fight the scrim). Suppress
   the inherited .__hover rule. */
.cf-flex-card--layout-overlay:hover .cf-flex-card__title,
.cf-flex-card--layout-overlay:focus-visible .cf-flex-card__title {
  color: #fff;
}

/* No-image fallback: title fills the full card width.
   Applies at all viewports now that side layout is side-by-side from
   mobile. Modern browsers support :has(); older browsers fall back to
   side layout with an empty image well — unobtrusive because no
   .cf-flex-card__media div renders at all when image is NULL. */
.cf-flex-card--layout-side:not(:has(.cf-flex-card__media)) .cf-flex-card__body {
  flex: 1 1 100%;
  padding-left: 0;
}

/* ── Reduced motion ─────────────────────────────────────────────────────
 * Honors RULE-A2 from the design playbook. Title color shift is preserved
 * (color isn't motion) — lift, shadow, and image zoom are suppressed.
 */
@media (prefers-reduced-motion: reduce) {
  .cf-flex-card,
  .cf-flex-card__media img {
    transition: none !important;
  }
  .cf-flex-card:hover,
  .cf-flex-card:focus-visible {
    transform: none !important;
    box-shadow: none !important;
  }
  .cf-flex-card:hover .cf-flex-card__media img,
  .cf-flex-card:focus-visible .cf-flex-card__media img {
    transform: none !important;
  }
}
