/* ============================================================================
   fig_story_body — customer-story article body.  Session 75.
   Every value from figured-tokens.css. See module.html for why this is not
   fig_document, and for the one thing deliberately duplicated from it.
   ============================================================================ */

/* 🔴 WHITE IS THE BASE — there is no background option (s76). Mark: "Same for
   fig story body - no need for a background colour option - just white by
   default." The `--white` / `--pale` modifiers and the `body_bg` field and
   column are deleted. Neither live story used pale.
   ⚠️ Keep this EXPLICIT rather than transparent: `--bleed` needs an opaque
   background to sit against the hero's gradient, and a transparent body would
   let the gradient show through the whole article. */
.fig-story-body{padding:var(--fig-section-md,88px) 0;background:#fff}

/* 760px is the site's practised PROSE measure (the wide container is 1180px —
   see _project-docs/DESIGN_SYSTEM_OPEN.md). At the 16px body size that is
   ~70 characters, inside the comfortable 45–75 range. */
.fig-story-body__measure{max-width:760px;margin:0 auto;padding:0 32px}
@media(max-width:540px){.fig-story-body__measure{padding:0 20px}}

/* The standfirst is the one place an 18px tier is right below a hero: it is
   the hero-subheadline size (session 57's three tiers), doing the same job one
   section further down. */
.fig-story-body__stand{
  font-size:18px;font-weight:700;line-height:1.5;letter-spacing:-.01em;
  color:var(--fig-color-navy,#102C58);margin:0 0 28px;text-wrap:pretty;
}

/* ── prose ──────────────────────────────────────────────────────────────── */
.fig-story-body__prose{font-size:16px;line-height:1.7;color:var(--fig-color-ink,#314257)}
.fig-story-body__prose > :first-child{margin-top:0}
.fig-story-body__prose > :last-child{margin-bottom:0}

/* 🔴 h2 AND h3 ARE SEPARATE LEVELS (fixed s78). They used to share one rule at
   22px/700, so a section header and its sub-sections rendered IDENTICALLY and
   read as peers — Mark: "this headline hierarchy doesn't work… the bullets are
   on the same level as the sub header and they should be beneath it."
   The original comment said "h3 only… an author who pastes an h2 gets demoted",
   which was a fair assumption when every story was a flat blog post. The Erin
   Heath PDF is not: it has named SECTIONS (The Challenge, The Vision, The
   Approach…) each containing numbered sub-sections. Two levels are real, so the
   scale has to show them.
   ⚠️ The hero still owns h1, so h2 stays well below it — 26px against a body of
   16px is a section header, not a competing title. */
.fig-story-body__prose h2{
  font-size:26px;font-weight:700;line-height:1.25;letter-spacing:-.015em;
  color:var(--fig-color-navy,#102C58);margin:52px 0 14px;text-wrap:balance;
}
.fig-story-body__prose h3{
  font-size:19px;font-weight:700;line-height:1.35;letter-spacing:-.005em;
  color:var(--fig-color-navy,#102C58);margin:32px 0 10px;text-wrap:balance;
}
/* ── "Label: Sentence" headings ──────────────────────────────────────────
   🔴 A LONG COLON HEADING CANNOT WRAP WELL, so it is split instead of fought.
   "The Challenge: Why Traditional Approaches to Farm Accounting Aren't Working"
   is 73 characters; in a 760px prose column at 26px that is two lines however it
   is set, and every option was poor — `balance` broke before "to Farm
   Accounting", `pretty` and normal split "Farm / Accounting", and forcing the
   break at the colon orphaned "Working" onto a third line. Measured, not guessed
   (s78).
   ✅ The label becomes an EYEBROW above the heading, so the heading is only the
   sentence. Four of the five section headings in the Erin Heath story then fit
   on one line, and the pattern is consistent across all of them.
   ⚠️ Deliberately the SITE eyebrow standard — 12px/700/.14em/uppercase, and
   `--fig-color-action` because this sits on a LIGHT ground (MODULE_REFERENCE
   "Eyebrow standard"). Do not restyle it here. */
.fig-story-body__prose h2 .fig-story-body__h2-label{
  display:block;font-size:12px;font-weight:700;letter-spacing:.14em;
  text-transform:uppercase;color:var(--fig-color-action,#0075C0);
  margin:0 0 8px;line-height:1.2;
}

/* the first heading in the prose should not push a big gap under the standfirst */
.fig-story-body__prose > h2:first-child,
.fig-story-body__prose > h3:first-child{margin-top:0}
.fig-story-body__prose h4{
  font-size:17px;font-weight:700;line-height:1.35;
  color:var(--fig-color-navy,#102C58);margin:28px 0 8px;
}
.fig-story-body__prose p{margin:0 0 18px;line-height:inherit;font-size:inherit;color:inherit}
.fig-story-body__prose a{color:var(--fig-color-action,#0075C0);text-decoration:underline}
.fig-story-body__prose a:hover{color:var(--fig-color-action-hover,#005FA3)}
.fig-story-body__prose strong,.fig-story-body__prose b{font-weight:700;color:var(--fig-color-navy,#102C58)}
.fig-story-body__prose em,.fig-story-body__prose i{font-style:italic}

/* ── 🔴 LIST MARKERS — COPIED VERBATIM FROM fig_document ──────────────────
   Decision #61 resets `list-style: none` site-wide in figured-base.css, so an
   authored list renders with NO markers, NO numbering and NO indent unless a
   module draws them. That is the entire reason fig_document's prose stylesheet
   exists, and it applies to ANY authored richtext — including this one.
   These rules are the same logic under a different class name, including the
   two-level nested counters and the hollow nested bullet.
   ⚠️ THEY ARE NOW IN TWO FILES. If #61's reset changes, BOTH need the edit.
   ➡️ Proper fix: a shared prose partial in figured-modules.css. Not V1 work. */
.fig-story-body__prose ul,
.fig-story-body__prose ol{margin:0 0 20px;padding:0;list-style:none}
.fig-story-body__prose li{position:relative;margin:0 0 10px;padding-left:26px;line-height:1.7}
.fig-story-body__prose li:last-child{margin-bottom:0}
.fig-story-body__prose ol{counter-reset:fig-story-ol}
.fig-story-body__prose ol > li{counter-increment:fig-story-ol}
.fig-story-body__prose ul > li::before{
  content:'';position:absolute;left:7px;top:.66em;width:5px;height:5px;
  border-radius:50%;background:var(--fig-color-action,#0075C0);
}
.fig-story-body__prose ol > li::before{
  content:counter(fig-story-ol) ".";position:absolute;left:0;top:0;
  font-weight:700;color:var(--fig-color-action,#0075C0);
}
.fig-story-body__prose li > ul,
.fig-story-body__prose li > ol{margin:10px 0 0}
.fig-story-body__prose li > ol{counter-reset:fig-story-ol-2}
.fig-story-body__prose li > ol > li{counter-increment:fig-story-ol-2}
.fig-story-body__prose li > ol > li::before{content:counter(fig-story-ol-2,lower-alpha) "."}
/* hollow dot, so a nested item reads as subordinate at a glance */
.fig-story-body__prose li > ul > li::before{
  background:none;border:1.5px solid var(--fig-color-action,#0075C0);
  width:6px;height:6px;top:.6em;
}

/* ── pull quote ─────────────────────────────────────────────────────────── */
/* A left rule rather than big quote glyphs: the site uses no decorative
   typography anywhere else, and the body already carries quoted speech inline.
   ⚠️ Quotes are NEVER trimmed or tightened (Decision #130) — if one is too long
   for the measure that is a conversation with the quote owner, not a silent
   edit. So this has to hold a long quote gracefully. */
.fig-story-body__prose blockquote{
  margin:32px 0;padding:4px 0 4px 22px;
  border-left:3px solid var(--fig-color-action,#0075C0);
  font-size:19px;font-weight:700;line-height:1.5;letter-spacing:-.01em;
  color:var(--fig-color-navy,#102C58);
}
.fig-story-body__prose blockquote p{font-size:inherit;line-height:inherit;color:inherit;margin:0 0 10px}
.fig-story-body__prose blockquote p:last-child{margin-bottom:0}
.fig-story-body__prose blockquote cite,
.fig-story-body__prose blockquote footer{
  display:block;margin-top:10px;font-style:normal;
  font-size:14px;font-weight:400;color:var(--fig-color-muted,#5A6B80);
}

/* ── inline images ──────────────────────────────────────────────────────── */
/* `display:block` because an author pasting from a doc gets an inline <img>
   that sits on the text baseline and leaves a gap beneath it.
   No aspect-ratio on purpose — an author's photo keeps its own proportions, so
   Decision #131 does not apply (that is about ratio boxes, and this is not one). */
.fig-story-body__prose img{
  display:block;max-width:100%;height:auto;
  margin:32px auto;border-radius:var(--fig-radius-image,12px);
}
.fig-story-body__prose figure{margin:32px 0}
.fig-story-body__prose figure img{margin:0}
.fig-story-body__prose figcaption{
  margin-top:10px;font-size:13px;line-height:1.5;
  color:var(--fig-color-muted,#5A6B80);text-align:center;
}

/* ── tables: minimal, and restacking ────────────────────────────────────── */
/* A case study rarely has one, but if it does it must not blow the measure. */
.fig-story-body__prose table{width:100%;border-collapse:collapse;margin:28px 0;font-size:15px}
.fig-story-body__prose th,.fig-story-body__prose td{
  text-align:left;padding:10px 12px;border-bottom:1px solid var(--fig-color-border,#D6E2EC);
}
.fig-story-body__prose th{font-weight:700;color:var(--fig-color-navy,#102C58)}

@media(max-width:900px){.fig-story-body{padding:var(--fig-section-sm,64px) 0}}

/* ── the video ────────────────────────────────────────────────────────────
   Sits above the standfirst: on a video-led story the video IS the lead and
   the copy is a summary, which is how the three recent published stories read.
   16:9 with an explicit width and a min-height floor — Decision #131. */
/* ⚠️ EXPLICIT TOP MARGIN, and it is not optional. The video used to sit ABOVE
   everything, so it only carried a bottom margin. Once it moved BELOW the
   summary copy (s75) that left it butted flat against the last paragraph with
   ZERO gap — because `.fig-story-body__prose > :last-child` deliberately zeroes
   that paragraph's bottom margin, and the video had no top margin to supply
   one. Neither rule is wrong alone; the gap only existed in the old order.
   36px sits between the 32px used for inline images and pull-quotes and the
   40px before an h3, which is right for a block this dominant. */
.fig-story-body__video{
  width:100%;aspect-ratio:16/9;min-height:200px;
  margin:36px 0;border-radius:var(--fig-radius-lg,16px);overflow:hidden;
  background:var(--fig-color-navy,#102C58);
}
/* If the video is the FIRST thing in the measure — a story with a video and no
   summary copy — it should not push away from the section's own top padding. */
.fig-story-body__measure > .fig-story-body__video:first-child{margin-top:0}
.fig-story-body__video-el{
  display:block;width:100%;height:100%;border:0;
}

/* ── transcript ───────────────────────────────────────────────────────────
   Same prose rules, but visually subordinate: it is a verbatim record under
   the video rather than the article's argument. The heading matches the body's
   h3 scale so it reads as a peer of the article's own subheads. */
.fig-story-body__transcript-heading{
  font-size:22px;font-weight:700;line-height:1.3;letter-spacing:-.01em;
  color:var(--fig-color-navy,#102C58);margin:40px 0 12px;
}
.fig-story-body__prose--transcript{color:var(--fig-color-muted,#5A6B80)}
.fig-story-body__prose--transcript b,
.fig-story-body__prose--transcript strong{color:var(--fig-color-navy,#102C58)}

/* ── the story photo, when it lives in the body rather than the hero ──────
   Same 16:10 as the hero cell and the listing card, so ONE supply fits all
   three positions with nothing cropped (Mark's requirement, s75).
   Breaks out of the 760px prose measure to the 1180px container width — a
   photo held to the reading measure looks like an afterthought, and this is
   the article's lead image when the hero has none.
   ⚠️ Decision #131: explicit width plus a min-height floor. */
/* 🔴 BREAKS OUT OF THE 760px PROSE MEASURE to the 1180px container width.
   ⚠️ The comment above previously CLAIMED this and the rule was never written —
   the figure sat at ~696px inside its 760px parent, which is why the bleed
   looked half-finished. Caught by Mark at s75.
   `margin-left:50%` + `translateX(-50%)` is the standard escape from a narrow
   centred parent: it re-centres on the parent's centre line, which is also the
   page's, then the width is free of the parent's max-width. `max-width:none`
   is required or the 100% above still caps it. */
.fig-story-body__figure{
  /* 56px, not the 36px used for in-flow images and the video: this is the
     article's LEAD image and the copy beneath it is the start of the story, so
     it needs a clearer break than a mid-article figure (Mark, s75). */
  margin:0 0 56px;
  width:min(1180px, calc(100vw - 64px));
  max-width:none;
  margin-left:50%;
  transform:translateX(-50%);
  aspect-ratio:1.91/1;min-height:200px;
  overflow:hidden;border-radius:var(--fig-radius-lg,16px);
  background:var(--fig-color-pale-bg,#F3F7FB);
}
@media(max-width:540px){
  .fig-story-body__figure{width:calc(100vw - 40px)}
  .fig-story-body__related{width:calc(100vw - 40px)}
}
.fig-story-body__figure img{width:100%;height:100%;object-fit:cover;object-position:center;display:block}

/* ── BLEED: the figure rises into the hero's gradient ─────────────────────
   Paired with `fig-story-hero--bleed`, which adds exactly this much bottom
   padding to the band. ⚠️ CHANGE BOTH OR NEITHER — the hero's extra padding
   and this negative margin are the same 140px, and if they drift the photo
   either floats clear of the gradient or eats the chips above it.
   `position:relative` + `z-index` are required: the figure has to paint OVER
   the hero section, and without a stacking context it is painted under it.
   The section's own top padding goes to zero here, otherwise it fights the
   negative margin and the overlap silently halves. */
/* 🔴 `display:flow-root` IS LOAD-BEARING — WITHOUT IT THE BLEED DOES NOT WORK.
   With `padding-top:0` and no border, the figure's negative top margin
   COLLAPSES THROUGH this section and moves the SECTION up by 140px — so its
   white background slides up and covers the bottom of the hero's gradient,
   instead of the figure rising over it. The visible result is a gradient that
   looks 140px too short and a photo that barely overlaps: exactly what Mark
   reported twice. `flow-root` establishes a block formatting context, so the
   child's margin stays the child's and only the figure moves.
   ⚠️ Do not "simplify" this to `padding-top:0` alone, and do not add a top
   padding back — either one silently returns the bug. */
.fig-story-body--bleed{padding-top:0;display:flow-root}
.fig-story-body--bleed .fig-story-body__figure{
  position:relative;z-index:2;
  /* ⚠️ margin-top only — do NOT restate margin here, or it wipes the
     margin-left:50% that the breakout above depends on. */
  margin-top:-140px;
  /* A hairline keeps the photo's edge legible where it sits on the gradient —
     without it a dark photo blends into the navy and the radius disappears. */
  box-shadow:0 0 0 1px rgba(255,255,255,.22), 0 18px 40px -18px rgba(2,26,62,.45);
}
@media(max-width:900px){
  .fig-story-body--bleed .fig-story-body__figure{margin-top:-80px}
}

/* ════════════════════════════════════════════════════════════════════════
   SCROLL-LINKED NARROWING OF THE LEAD IMAGE  (session 75, Mark's request)
   The figure starts at the 1180px container width and narrows to the 760px
   prose measure as you scroll down, widening again on the way back up.

   🔴 WHY CSS SCROLL-DRIVEN ANIMATION AND NOT A SCROLL LISTENER. Mark asked to
   "make the resizing fit with the scrolling speed (unless there is a best
   practice/standard way to do that)" — there is, and this is it.
   `animation-timeline: view()` binds the animation to the element's POSITION in
   the viewport rather than to elapsed time. So it tracks scroll speed exactly,
   reverses on scroll-up for free, and never needs a scroll event. A JS
   listener would run on the main thread on every scroll frame and is the
   classic source of scroll jank.

   🔴 IT ANIMATES `width`, AND THAT IS THE THIRD ATTEMPT. The route matters
   because each earlier one failed for a reason worth not repeating:
     1. `clip-path: inset()` — compositor-friendly and no reflow, but it CROPS
        the sides rather than resizing, so the height never changed. Mark: "only
        the width of the image changes, it needs to be the width and height."
     2. `transform: scale()` — proportional and still compositor-friendly, but a
        transform DOES NOT CHANGE THE LAYOUT BOX, so the figure kept its
        full-size footprint while shrinking visually and left up to ~260px of
        dead space above the copy. Mark: "the big gap … is unacceptable."
     3. `width`, with `aspect-ratio: 16/10` taking the height down with it. The
        box genuinely gets smaller, so there is NO GAP — the copy sits directly
        under the image at every size.
   ⚠️ THE COST, and it is unavoidable: `width` is a layout property, so this
   reflows each frame and the copy below RISES as the image shrinks — it moves
   up slightly faster than you are scrolling. That is the price of closing the
   gap; a transform cannot close it and a layout property cannot avoid it. It is
   one element with a fixed ratio, so the reflow is cheap, and being
   scroll-linked it is smooth rather than jumpy.
   ⚠️ NO `will-change` here on purpose — `width` is not compositable, so the
   hint buys nothing and just holds a layer.
   ⚠️ `translateX(-50%)` stays OUT of the keyframes now. With `margin-left:50%`
   it keeps the figure centred as it narrows, for free — and a transform inside
   a keyframe would replace the whole property and fling it sideways.

   THE NUMBERS: from the container width to the 760px prose measure. Change the
   measure and the `to` value must change with it.

   ⚠️ PROGRESSIVE ENHANCEMENT, deliberately. Behind @supports, so a browser
   without scroll-driven animations (Firefox at time of writing) simply shows
   the image at full width — which is the design, not a broken state.
   ⚠️ Honours prefers-reduced-motion: a scroll-linked size change is exactly
   the kind of motion that setting exists for.
   ⚠️ NOT VERIFIABLE FROM HERE — headless Chrome on this machine cannot be
   trusted for viewport-dependent behaviour (Decision #131), and this is
   scroll-dependent as well. Needs a real scroll in a real browser. */
@keyframes fig-story-figure-narrow{
  from{ width:min(1180px, calc(100vw - 64px)); }
  to  { width:760px; }
}
@supports (animation-timeline: view()){
  /* ⚠️ DESKTOP ONLY: below ~900px the figure is already `100vw - 40px` and the
     prose measure is effectively the same width, so there is nothing to narrow
     to. Mark, s75: "probably not really required on mobile, right?" 900px is
     the site's real primary breakpoint. */
  @media (min-width: 900px) and (prefers-reduced-motion: no-preference){
    .fig-story-body__figure{
      animation:fig-story-figure-narrow linear both;
      animation-timeline:view();
      animation-range:cover 20% cover 75%;
    }
  }
}

/* ── FURTHER READING — a pale aside, not a second CTA band ────────────────
   Differentiates promotional links from the transcript above it. Three things
   do the work, and each is deliberate:
     * a PALE WASH rather than white, so the boundary is visible before you
       read a word — which is the whole point (Mark, s75: the "Read more…" line
       "is actually a separate bit of content to the transcript, it's kind of a
       CTA");
     * an UPPERCASE EYEBROW, so it announces itself as an aside without a
       heading that has to say so;
     * the PROSE MEASURE, not full width. It stays part of the article. A
       full-width band here would be a third promotional block stacked above the
       gradient final CTA, which is the same mistake three times.
   ⚠️ Ink, not muted: unlike the transcript this is meant to be read and acted
   on, so it takes the standard body colour. */
.fig-story-body__further{
  margin:44px 0 0;padding:24px 28px;
  background:var(--fig-color-pale-bg,#F3F7FB);
  border-radius:var(--fig-radius-md,14px);
}
.fig-story-body__further-heading{
  font-size:12px;font-weight:700;letter-spacing:.14em;text-transform:uppercase;
  color:var(--fig-color-action,#0075C0);margin:0 0 10px;
}
.fig-story-body__prose--further{font-size:16px;color:var(--fig-color-ink,#314257)}
.fig-story-body__prose--further p:last-child{margin-bottom:0}

/* ── KEEP READING: up to three related customer stories (session 76) ───────
   Replaces the inherited promo that used to end each transcript. Mark, s76:
   "we could list some 'related' customer stories (up to 3) for people to
   continue reading."

   🔴 DELIBERATELY NOT THE LISTING CARD. `fig_story_grid` already owns a full
   card component — border, shadow, blurb, hover lift — and building a second
   one here would fork it, the same debt as this module duplicating
   `fig_document`'s list markers. So these are lighter by design: no border, no
   shadow, no blurb. They read as "keep reading", not as a second listing.
   ⚠️ Which also means: do NOT "unify" these with .fig-story-grid__card. The
   difference is the point.

   🔴 THE THUMBNAIL IS 16:10 — the SAME ratio as the listing card and the
   article's lead figure, because it is the SAME FILE. Mark, s76: "we can't be
   creating or managing separate images for this … same image, fit into the area
   perfectly." A 16:10 supply therefore fills all three cells exactly with
   nothing cropped (Decision #146). Change this ratio and you break that
   contract in the one place it is least likely to be noticed.
   ⚠️ Decision #131: an `aspect-ratio` box needs a DEFINITE width. A grid track
   supplies one, so this resolves — the `min-height` floor stays as the cheap
   half of that defence, since a failed ratio must leave a visible box rather
   than nothing. */
/* 🔴 BREAKS OUT OF THE 760px PROSE MEASURE, same escape as the lead figure.
   Mark, s78: "the keep reading section is great but it's a bit narrow since it
   follows the width of the article. Could we make it the same width as they
   appear in the listing page?" Yes — and it is not weird: the article BODY needs
   a reading measure, a card rail does not. Inside 760px the three cards were
   ~240px each; at the container width they are the same size as on the listing,
   so a reader meets the identical card in both places.
   ⚠️ Gap is 28px to match `.fig-story-grid__grid` exactly. If the listing's gap
   changes, change this with it or the two drift apart silently. */
.fig-story-body__related{
  margin:44px 0 0;padding:26px 0 0;
  border-top:1px solid var(--fig-color-border,#D6E2EC);
  /* ⚠️ margin-left MUST come after the `margin` shorthand above — the
     shorthand resets it to 0 and the break-out silently does nothing. */
  /* 🔴 1116px, NOT the 1180px the lead figure uses. The listing's cards sit
     INSIDE `.fig-container`, which is `max-width:1180px; padding:0 32px` — so
     its usable width is min(1180, 100vw) − 64, i.e. `min(1116px, 100vw − 64px)`.
     Copying the figure's 1180px made these cards 64px wider than the listing's
     (374.7px against 353.3px at a 1440px viewport, measured) — Mark: "looks
     wider than how they are presented in the listing page". The ≤540px rule
     above is already correct: the container drops to 20px padding at exactly
     that breakpoint, which is what `calc(100vw - 40px)` matches.
     ⚠️ The FIGURE keeps 1180px on purpose — it is a lead image that bleeds
     past the container by design, not a card that must line up with anything. */
  width:min(1116px, calc(100vw - 64px));max-width:none;
  margin-left:50%;transform:translateX(-50%);
}
.fig-story-body__related-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:28px}
.fig-story-body__related-card{
  display:flex;flex-direction:column;text-decoration:none;
}
.fig-story-body__related-card,.fig-story-body__related-card *{text-decoration:none!important}
.fig-story-body__related-thumb{
  display:block;aspect-ratio:1.91/1;min-height:64px;flex-shrink:0;
  overflow:hidden;border-radius:10px;
  /* ⚠️ load-bearing for the video badge — see fig_story_grid's note. */
  position:relative;
  /* 🔴 THE GAP BELOW THE IMAGE BELONGS TO THE IMAGE. It used to come from the
     TAG's `margin:12px 0 5px`, so on the four firm-profile stories — which have
     no farm type — the tag self-hid and the story name butted straight against
     the photo, looking like a rendering fault (Mark, s76: "where a farm type is
     not selected a card looks like it has an error").
     ⚠️ Decision #147 exactly: never borrow vertical space from a neighbour,
     because a self-hiding neighbour is not a fact. Fourth instance on this page
     type. */
  margin-bottom:12px;
  background:var(--fig-color-pale-bg,#F3F7FB);
}
/* 🔴 THE ZOOM STAYS HERE, AND IS GONE FROM THE LISTING — deliberate, not drift.
   Mark, s78: "you could also have the image zoom effect to the images in the
   'keep reading' section - since there is no card to lift".
   He is right and it reverses my first pass, which removed it from both for
   consistency. The two cards are identical in SIZE but not in CHROME: the
   listing card is a bordered white panel that lifts 4px with a shadow on hover,
   so it already has a cue and the zoom was a second one. THESE cards have no
   panel, no border and no background — there is nothing to lift, so without the
   zoom the only hover feedback is the name changing colour.
   ⚠️ So do not "unify" these two on the grounds that the cards match. They
   match visually and differ in what they can animate. */
.fig-story-body__related-thumb img{
  width:100%;height:100%;object-fit:cover;display:block;
  transition:transform .3s ease;
}
.fig-story-body__related-card:hover .fig-story-body__related-thumb img{transform:scale(1.04)}

/* ── "Has a video" badge — the listing's, one size down for the smaller thumb.
   ⚠️ `pointer-events:none` matters here: the whole card is an <a>, and a badge
   that swallowed the pointer would kill the zoom on hover directly over it. */
.fig-story-body__related-video{
  position:absolute;left:10px;bottom:10px;
  width:34px;height:34px;border-radius:50%;
  display:flex;align-items:center;justify-content:center;
  /* .72 + a backdrop blur, matching the listing's — see its note. */
  background:rgba(255,255,255,.72);color:var(--fig-color-navy,#102C58);
  -webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px);
  box-shadow:0 1px 5px rgba(9,26,50,.22);
  pointer-events:none;
}
.fig-story-body__related-video svg{width:17px;height:17px;fill:currentColor;display:block}
.fig-story-body__related-video--bare{background:var(--fig-color-navy,#102C58);color:#fff;box-shadow:none;-webkit-backdrop-filter:none;backdrop-filter:none}
/* 🔴 TYPE MATCHES `.fig-story-grid__` EXACTLY — tag 12px/.14em, name
   clamp(18px,1.6vw,20px), where 13px, 10px between each. These were 11 / 15 /
   12.5px, sized for the narrow 760px prose column this block used to sit in.
   Once the block was widened to the listing's own 1116px the small type looked
   undersized against the bigger photos — Mark: "the case study title and the
   country indicator ... seem small compared to the now increased size of the
   image". Same card at the same width now reads at the same size.
   ⚠️ If the listing's card type changes, change these with it. */
.fig-story-body__related-tag{
  display:block;font-size:12px;font-weight:700;letter-spacing:.14em;text-transform:uppercase;
  color:var(--fig-color-action,#0075C0);margin:0 0 10px;
  /* The row is RESERVED even when empty, so the three names sit on the same
     line whether or not a story has a farm type. Without it the tagless card's
     name rides ~16px higher than its neighbours' and the row reads as broken in
     a different way. The element is always emitted; only its text is optional.
     ⚠️ Raised 14 → 15px with the font — a 14px line box clips a 12px cap. */
  min-height:15px;line-height:15px;
}
.fig-story-body__related-name{
  display:block;margin:0;font-size:clamp(18px,1.6vw,20px);font-weight:700;line-height:1.25;
  color:var(--fig-color-navy,#102C58);text-wrap:balance;
}
/* The hover cue lives on the NAME, not a "read more" line: three of those
   stacked under three cards is a lot of repeated furniture for one idea. */
.fig-story-body__related-card:hover .fig-story-body__related-name{
  color:var(--fig-color-action,#0075C0);
}
.fig-story-body__related-where{
  display:block;font-size:13px;font-weight:400;
  color:var(--fig-color-muted,#5A6B80);margin:10px 0 0;
}
@media(max-width:760px){
  /* Two across, then one. At three the names wrap to four lines on a phone. */
  .fig-story-body__related-grid{grid-template-columns:repeat(2,1fr);gap:16px}
}
@media(max-width:480px){
  .fig-story-body__related-grid{grid-template-columns:1fr;gap:18px}
  .fig-story-body__related{margin-top:34px;padding-top:22px}
}
