/* rx-block: rx-resources */

/* Above the rings. The featured block below is positioned, so by default it
   paints over this in-flow heading and the outer arcs cut straight through
   the type. Figma paints the heading after the three large ellipses for the
   same reason — legibility wins over the decoration. */
.rx-resources__heading {
  position: relative;
  z-index: 1;
  max-width: 34ch;
  font-size: var(--rx-text-2xl);
  font-weight: 400;
}

/* --- Introduction ----------------------------------------------------------
   The shared blocks list, rendered by partials/atoms.html. Same measure pairs
   card-deck uses, so "Narrow" is one line length on every block offering it.
   The heading's own 34ch above stays the default measure. */
.rx-resources__intro {
  position: relative;
  z-index: 1;
  display: grid;
  gap: var(--rx-space-4);
  margin-block-end: var(--rx-space-6);
}

.rx-resources__intro .rx-resources__heading { margin: 0; max-width: var(--rx-resources-intro-heading-measure, 34ch); }
.rx-resources__lead,
.rx-resources__copy { max-width: var(--rx-resources-intro-copy-measure, 40em); }
.rx-resources__copy { font-size: calc(1em * var(--rx-copy-scale, 1)); }

.rx-resources__intro--c-narrow {
  --rx-resources-intro-heading-measure: 14em;
  --rx-resources-intro-copy-measure: 26em;
}

.rx-resources__intro--c-wide {
  --rx-resources-intro-heading-measure: 34em;
  --rx-resources-intro-copy-measure: 50em;
}

.rx-resources__intro--c-full {
  --rx-resources-intro-heading-measure: none;
  --rx-resources-intro-copy-measure: none;
}

.rx-resources__intro--center {
  justify-items: center;
  text-align: center;
}

.rx-resources__intro--center .rx-resources__actions {
  justify-content: center;
}

/* --- featured panel ------------------------------------------------------
   Figma 3098:4750, measured. This supersedes 3078:3846, where a layer had
   been nudged by accident:

     image  510.73 x 444 at x 136.04, y 7453.41
     card   700    x 444 at x 666.77, y 7453.41

   So: TOP-ALIGNED, EQUAL HEIGHT, AND A 20px GUTTER between them
   (666.77 - 646.77). The image is not square.

   Three earlier readings of this panel were wrong, all from the nudged node:
   an aspect-ratio of 1/1, a 13.34px overlap, and a 29.44px vertical offset.
   The overlap and the offset were both artifacts of the moved layer and are
   gone. What survives from chasing them is the STRUCTURE — see the rows
   below — because a card and a picture that must match heights should never
   have been two independently-sized boxes in the first place. */

/* The rings reach ~353px left of the column, which is off-canvas at 1512 by
   design (their group starts at x -231 in a 1512 frame). Clipped rather than
   left to open a horizontal scrollbar. `clip` not `hidden`: hidden on an axis
   makes the other axis a scroll container, which would trap the sticky
   header. */
.rx-resources { overflow-x: clip; }

/* Two columns in the measured 510.73 : 700 ratio with the measured 20px
   gutter, and ONE row both items share.

   The shared row is the whole point. The picture and the card are the same
   height in the design, and the only way two boxes stay the same height at
   every width is if neither one sizes itself: the row is floored at the
   measured 444 and raised by whichever needs more, and both stretch to it.
   An earlier pass gave the picture an `aspect-ratio` instead, so its height
   came from its own width while the card's came from its content — they
   agreed at 1512 and diverged everywhere else, the picture reaching twice
   the card's height by 2000. That is the bug _text-media.css was fixed for
   twice; the note there on why the media has a HEIGHT and not a ratio is the
   same lesson.

   The columns use fr rather than the literal widths, so the composition fills
   the 1240 column. Figma's own spans are 1230.73 here, but the section's left
   edges disagree with each other by more than that 9px — the heading starts
   at 148.05 and the recent row at 164.29 — so snapping to the container is
   better than reproducing which layer landed where. */

.rx-resources__featured {
  position: relative;
  /* The rings, the picture and the card all carry a z-index, so the featured
     block owns its own stacking order instead of competing with the section
     above it. */
  isolation: isolate;
  display: grid;
  grid-template-columns: minmax(0, 510.73fr) minmax(0, 700fr);
  /* px, not a percentage: percentage row tracks resolve against the
     container's HEIGHT, which is indefinite here, so they collapse to auto. */
  grid-template-rows: minmax(444px, auto);
  gap: 20px;   /* measured, 646.77 -> 666.77 */
  margin-top: var(--rx-space-7);
}

/* NO COVER SET. The media column is 510.73fr of blank white otherwise, which
   reads as a broken image rather than as an empty field — and it read as
   correct locally right up until it was opened in the portal editor, because
   the field's default omits `src` and the preview harness fills the gap with
   an FPO tile. One column, and the card takes the row. */
.rx-resources__featured--noimage {
  grid-template-columns: minmax(0, 1fr);
}

.rx-resources__featured--noimage .rx-resources__featured-body {
  grid-area: 1 / 1 / 2 / 2;
}

.rx-resources__featured-media {
  position: relative;
  z-index: 1;
  grid-area: 1 / 1 / 2 / 2;
  /* No aspect-ratio. The row gives it its height and .rx-media's
     object-fit: cover fills whatever it gets, so the picture cannot disagree
     with the card beside it. */
  border-radius: var(--rx-radius-md);
}

/* THE IMAGE IS OUT OF FLOW, AND THAT IS LOAD-BEARING — the same reason
   .rx-tm__media absolutely positions its children. In flow, the <img>'s
   INTRINSIC height becomes the row's max-content contribution, so
   minmax(444px, auto) stops being a floor and a tall source file drags the
   row (and the card beside it) to whatever the photograph happens to be. Out
   of flow it contributes nothing, the row is floored at the measured 444 and
   raised only by the card's own copy. */
.rx-resources__featured-media img {
  position: absolute;
  inset: 0;
}

.rx-resources__featured-body {
  position: relative;
  z-index: 3;
  grid-area: 1 / 2 / 2 / 3;
  /* THREE ZONES, not a stack: badge pinned top, copy CENTRED, arrow pinned
     bottom. Measured on 3098:4702 — the title+summary block runs 7602.91 to
     7747.91, whose midpoint is 7675.41, and the card runs 7453.41 to 7897.41,
     whose midpoint is also 7675.41. Exactly centred, not coincidence.

     An earlier pass stacked all four from the top with fixed margins, which
     matches the design only at one length of summary; the arrow floated up
     under short copy instead of holding the card's bottom edge. */
  display: flex;
  flex-direction: column;
  /* Asymmetric, and measured: 50.94 above the badge, but the arrow's own box
     ends 27.42 above the card's bottom (7869.99 against 7897.41). */
  padding: calc(50.94 / 1240 * 100%) calc(56.95 / 1240 * 100%) calc(27.42 / 1240 * 100%);
  border-radius: var(--rx-radius-card);   /* 20px (measured) */
  background-color: var(--rx-surface);
  /* Figma 3098:4703 casts 0 4px 32px rgba(48,43,32,.05). --rx-shadow-card is
     0 4px 44px rgba(42,42,42,.06) — the same shadow to within a blur step, so
     this reuses the token rather than adding a near-duplicate beside it. */
  box-shadow: var(--rx-shadow-card);
}

/* The card tint travels to the featured card too: Figma draws it white on
   Home (3098:4750) and light blue on the Resources listing (3079:3847). One
   field driving both keeps the featured card and the row below it agreeing. */
/* blue/tint-2, measured on the listing (3079:3916) — not tint-5, which is
   almost white and made the card read as unfilled. */
.rx-resources__featured-body--blue  { background-color: var(--rx-blue-t2); }
.rx-resources__featured-body--gold  { background-color: var(--rx-gold-t5); }
.rx-resources__featured-body--white { background-color: var(--rx-surface); }

/* --- rings ---------------------------------------------------------------
   THREE concentric circles, sharing a centre 14px left of the 1240 column's
   left edge and 149.5px below the picture's top:

     214.27  1px  light-blue/base   (3098:4700)
     168.27  2px  light-blue/base   (3098:4717)
     115.72  2px  gold/base         (3098:4716)

   Figma draws five. The two faint gold/tint-2 hairlines at 553.73 and 706.52
   are GONE, replaced by the travelling pulse below, which occupies the same
   outer territory. Keeping both was too many circles at once — the static
   pair and the moving pair read as clutter rather than as one idea. The outer
   BOUND is unchanged: the pulse still dissolves at 706.52, so the set
   occupies exactly the space the design allots it.

   THE STACK IS SPLIT ACROSS THE PHOTOGRAPH. In Figma the first three are
   painted before the image rect and the last two after it, so the 115.72 and
   the 168.27 cross the picture while the three larger ones are cut by its
   edge. An element cannot sit both behind and in front of one sibling, so
   there are two containers with the image between them.

   An earlier pass drew all five as ONE radial-gradient with hard stops. That
   is a good way to draw concentric rings and the wrong shape here twice over:
   it puts every ring on the same side of the picture, and it gives the
   entrance nothing to animate — a gradient has no per-ring element to reveal.

   Not a stack of spread-only box-shadows either, which is the obvious first
   reading and does not work at all: a spread shadow is a filled DISC, and a
   transparent one after it does not punch a hole, it just paints nothing. The
   result is five opaque discs, largest on top — a beige circle swallowing the
   heading. */

.rx-resources__rings {
  position: absolute;
  /* Sized to the outermost ring, then offset so its CENTRE — not its corner —
     lands 14px left of the column edge and 149.5px below the picture's top.
     Both containers are identical so the two halves stay concentric. */
  inline-size: 706.52px;
  block-size: 706.52px;
  left: calc(-14px - 353.26px);
  top: calc(149.5px - 353.26px);
}

.rx-resources__rings--back  { z-index: 0; }
.rx-resources__rings--front { z-index: 2; }

/* Centred rather than nested: the entrance scales each ring, and nesting
   would compound one ring's transform onto every ring inside it. */
.rx-resources__ring {
  position: absolute;
  top: 50%;
  left: 50%;
  aspect-ratio: 1 / 1;
  border-radius: var(--rx-radius-pill);
  /* `translate`, not a translate inside `transform` — the reveal system owns
     `transform`, so keeping centring on its own property means the two
     cannot fight. Same construction as .rx-posthero__ring. */
  translate: -50% -50%;
}

/* Widths as a share of the 706.52 container, so the five stay concentric and
   correctly proportioned however the block is scaled. */
/* Colours come from the editor as .rx-ink-- classes on the two containers,
   so every ring here draws in currentColor. The outer one is the SECOND ring's
   colour weakened rather than a third choice: three independent hues on three
   hairlines 46px apart is a decision nobody can make well, and the design's own
   set is two colours.

   The default is 100%, i.e. NO fade: the drawn set is what ships, so a page
   that is not edited renders exactly what it rendered before this field
   existed. Turn it down per page with --rx-resources-ring-fade.

   Applied in the BORDER COLOUR, never as `opacity` on the element: the reveal
   driver animates opacity, so an opacity here is overwritten the moment the
   ring is revealed and the ring lands at full strength. Same trap
   product-hero's far ring records. */
.rx-resources__rings { --rx-resources-ring-fade: 100%; }

.rx-resources__ring--r214 { width: 30.33%;  border: 1px solid; border-color: color-mix(in srgb, currentColor var(--rx-resources-ring-fade), transparent); }
.rx-resources__ring--r168 { width: 23.82%;  border: 2px solid; }
.rx-resources__ring--r116 { width: 16.38%;  border: 2px solid; }

/* --- ring entrance -------------------------------------------------------
   A ripple OUTWARD from the shared centre, innermost first, on a ~110ms step.
   Outward because the two that lead are the two in front of the picture, so
   the move starts on top of the photograph and spreads off it; run inward,
   the first thing to arrive would be the faint 706 ring nobody is looking at.

   This is the post-hero vocabulary, not a new one — concentric circles
   expanding from a shared centre, each opting out of the focal
   transform-origin with data-rx-reveal-origin="self" because there is no
   data-rx-reveal-focus scope here and they should grow about the centre they
   actually share.

   Bigger rings start from further out and take longer, so the ripple reads as
   one wave rather than five separate arrivals. Durations stay under 700ms for
   the reason spelled out on the post-hero entrance: over a long duration an
   ease-out spends most of its time barely moving and stops reading as a
   curve. Reduced motion is handled by the shared system. */

.rx-resources__ring--r116 { --rx-reveal-delay:   0ms; --rx-reveal-duration: 480ms; --rx-reveal-from: 0.88; }
.rx-resources__ring--r168 { --rx-reveal-delay: 110ms; --rx-reveal-duration: 520ms; --rx-reveal-from: 0.84; }
.rx-resources__ring--r214 { --rx-reveal-delay: 220ms; --rx-reveal-duration: 560ms; --rx-reveal-from: 0.80; }

/* --- emanating pulse -----------------------------------------------------
   THE FIVE DESIGN RINGS DO NOT MOVE. They hold the radii Figma draws.

   An earlier pass animated them — every ring sweeping 115.72 -> 706.52, a 6x
   range, phase-staggered. It was wrong twice: it destroyed the composition,
   because the design's radii are deliberately uneven (a tight 116/168/214
   cluster, then a jump to 554/707) and a smooth sweep spreads them evenly
   instead; and it dragged full-size circles across the photograph, which only
   the two small rings are ever meant to touch. "Don't grow the footprint"
   meant the circles themselves, not just the outer bound.

   So the motion is a SEPARATE, additional ring that is born small at the
   shared centre, travels out through the static set and dissolves at the rim
   — a new one arriving as the last fades. The designed set is the subject;
   this is the thing passing through it.

   Two of them, half a cycle apart, so one is always somewhere in the travel.

   IN THE BACK CONTAINER ONLY, which is what keeps it quiet: the photograph is
   opaque and sits above that layer, so the pulse is cut at the picture's edge
   exactly like the design's own large rings. It reads in the left margin and
   never crosses the image.

   Animates `inline-size`, not `scale`: a scaled ring scales its own border,
   and across this range a 1px hairline would render at 0.15px at the centre
   and thicken as it travelled, which is backwards for something dissipating.
   It also leaves `transform` to the reveal system, so the entrance underneath
   is untouched.

   Scroll, not time — on a view() timeline the scroll IS the progress, so it
   moves when the reader moves. Same mechanism as .rx-frame and .rx-tm--travel.
   Where view() is unsupported the pulse simply never runs and the block is the
   static design, which is the correct fallback. */

.rx-resources__pulse {
  position: absolute;
  top: 50%;
  left: 50%;
  inline-size: 80px;
  aspect-ratio: 1 / 1;
  border-radius: var(--rx-radius-pill);
  border: 1px solid;
  border-color: color-mix(in srgb, currentColor var(--rx-resources-ring-fade), transparent);
  translate: -50% -50%;
  /* Invisible until the timeline drives it, so an unsupported browser gets
     the static design rather than a stray extra circle. */
  opacity: 0;
}

@keyframes rx-resources-pulse {
  0%   { inline-size: 80px;     opacity: 0; }
  15%  { opacity: 0.55; }
  70%  { opacity: 0.35; }
  100% { inline-size: 706.52px; opacity: 0; }
}

@supports (animation-timeline: view()) {
  .rx-resources__pulse {
    animation: rx-resources-pulse linear 3 both;
    animation-timeline: view();
    animation-range: var(--rx-resources-pulse-start, entry 0%) exit 100%;
  }
}

/* One pulse in each of the two chosen colours — the pair the block drew before
   the colours were editable, and no third hue introduced by the motion. */
.rx-resources__pulse--b { --rx-resources-pulse-start: entry 18%; }

/* The picture and the card ride the same wave. Rings arriving on their own
   while the two things they decorate snap in reads as a loading glitch rather
   than an entrance — the decoration cannot be the only animated thing in the
   block. They start nearly at full size: these are large surfaces, and the
   travel that suits a 116px ring is a lurch on a 700px card. */
.rx-resources__featured-media {
  --rx-reveal-delay: 60ms;
  --rx-reveal-duration: 560ms;
  --rx-reveal-from: 0.97;
}

.rx-resources__featured-body {
  --rx-reveal-delay: 180ms;
  --rx-reveal-duration: 600ms;
  --rx-reveal-from: 0.97;
}

/* --- featured badge ------------------------------------------------------ */

.rx-resources__badge {
  display: flex;
  align-items: center;
  gap: var(--rx-space-2);
  /* No bottom margin: the copy block below is centred in the leftover space,
     so a margin here would just shove the centring off. */
  flex: none;
  margin: 0;
  font-size: var(--rx-text-xs);   /* 12px (measured) */
  font-weight: 600;
  line-height: 1.09;
  color: var(--rx-text);
}

/* 32px light-blue/tint-3 pill at 75%, holding a bare 20.18px bookmark glyph
   (3098:4712). It draws its OWN circle here — unlike chip-route.svg, which
   ships one baked into the asset. */
.rx-resources__badge-icon {
  flex: none;
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  border-radius: var(--rx-radius-pill);
  background-color: color-mix(in srgb, var(--rx-blue-t3) 75%, transparent);
}

.rx-resources__badge-icon img {
  display: block;
  width: 20.18px;
  height: 20.18px;
}

/* Takes all the space the badge and arrow do not, and centres its contents
   in it. This is what pins the other two to the card's edges. */
.rx-resources__featured-text {
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
}

.rx-resources__featured-title {
  margin: 0;
  font-size: var(--rx-text-xl-alt);   /* 26px (measured) */
  font-weight: 500;
  line-height: 1.22;
  color: var(--rx-heading);
}

/* Stretched over the whole body card, the same trick the resource card uses,
   so the featured block is one target rather than a title-sized one. */
.rx-resources__featured-link {
  color: inherit;
  text-decoration: none;
}

.rx-resources__featured-link::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
}

/* 18px / 1.5, and NARROWER than the card: Figma sets it to 503.42 inside a
   700 card whose content box is 586. Left long it runs to a measure the
   design does not use. */
.rx-resources__summary {
  max-width: calc(503.42 / 586 * 100%);
  margin: var(--rx-space-5) 0 0;
  font-size: var(--rx-text-lg-alt);
  line-height: 1.5;
  color: var(--rx-text);
}

/* A bare 48px arrow, no disc — the exported chip's ellipse group is empty.
   An earlier pass gave this a white circle and --rx-shadow-pill, which is
   the same mistake already documented for the resource card's arrow. */
.rx-resources__go {
  display: block;
  flex: none;
  width: 48px;
  height: 48px;
  /* Pinned to the bottom by the flex column above, not by a fixed margin. */
  margin-top: 0;
  /* The hover nudge gives this a transform, which paints it ABOVE the
     title link's stretched ::after — so the arrow, and only the arrow,
     stopped taking the click. It is decoration; let clicks pass through. */
  pointer-events: none;
  transition: transform var(--rx-duration) var(--rx-ease);
}

.rx-resources__go img { display: block; width: 48px; height: 48px; }

.rx-resources__featured:hover .rx-resources__go { transform: translateX(3px); }

/* --- recent row ---------------------------------------------------------- */

/* No rule above it. Figma draws none (3078:3846) — the section separates on
   whitespace, and with the cards below now surface-less a hairline was the
   only drawn edge in the whole lower half. */
.rx-resources__bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--rx-space-5);
  margin-top: var(--rx-space-8);
}

.rx-resources__bar > * { margin: 0; }

.rx-resources__list {
  margin-top: var(--rx-space-6);
  padding: 0;
  list-style: none;
}

.rx-resources__list > li { display: flex; }
.rx-resources__list > li > * { width: 100%; }

@media (max-width: 1024px) {
  /* Stacked, the four columns and three rows describe nothing — the overlap
     column would pull the card sideways off the picture rather than over it.
     Back to one column, and the two elements are placed in flow. */
  .rx-resources__featured {
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: auto auto;
  }

  .rx-resources__featured-media {
    grid-area: 1 / 1 / 2 / 2;
    /* A ratio IS right here: stacked, the picture has no card beside it to
       agree with, so its own width is the only thing that can set its
       height. */
    aspect-ratio: 16 / 9;
  }

  .rx-resources__featured-body {
    grid-area: 2 / 1 / 3 / 2;
    /* NO OVERLAP once stacked. It used to carry the desktop inlay turned
       through 90 degrees — a -32px margin pulling the panel up over the
       picture. Side by side that reads as an inlay; stacked it just crops the
       photograph's bottom corners and looks like a layout fault. The two sit
       flush instead, which is what a card under a picture should do. */
    margin-top: 0;
    padding: var(--rx-space-7) var(--rx-space-6);
  }

  .rx-resources__summary { max-width: none; }

  /* The rings are drawn against a 1512 composition; below it they crowd the
     stacked card rather than sitting behind a picture. */
  .rx-resources__rings { display: none; }
}

@media (max-width: 767px) {
  .rx-resources__featured-body { padding: var(--rx-space-6) var(--rx-space-5); }
  .rx-resources__bar { flex-direction: column; align-items: flex-start; }
}

@media (prefers-reduced-motion: reduce) {
  .rx-resources__go { transition: none; }
  .rx-resources__featured:hover .rx-resources__go { transform: none; }

  /* The ripple is the one thing here that never stops on its own, which is
     exactly what this query exists for. The shared reveal system already
     handles the entrance; this is the loop's own exit. */
  .rx-resources__pulse { animation: none; opacity: 0; }
}
