/* ============================================================================
   BLOG CARD HOVER — EXPLORATION (2026-09-08)

   Alternative hover treatments for the blog's cards, switchable live so they
   can be compared on the real page against real content. ONE gets picked and
   folded into css/latest.css; this file and js/latest-hover-lab.js then go,
   along with their two tags per page.

   IT IS INERT UNLESS SOMETHING SETS `data-hover` ON <body>. Only
   js/latest-hover-lab.js does that, and only under `?tune` or `?hover=N`, so
   an ordinary page load is byte-for-byte the shipped hover. That is also why
   every rule here is scoped to the attribute rather than to the components:
   deleting the file cannot leave a stray declaration behind, which is the
   residue a "revert" usually misses.

   The cards it covers: the featured post, the index grid, the post page's
   related grid (same component) and the previous/next cards.

   Lift, Rule sweep and Backer were cut on 2026-09-08 (client). The numbering
   of what survives is UNCHANGED — 0-3 still mean what they meant — and the
   new Burst took the freed 4 rather than everything shuffling down. Renumbering
   is free to write and expensive to talk about once someone has looked at them.

   ---------------------------------------------------------------------------
   THE PADDING IS SHARED, AND THAT IS DELIBERATE

   The article cards have no box — it was removed on 2026-09-08, because a
   tinted ground behind an article was the thing that was wrong. A card that
   FILLS on hover needs a body for the fill to occupy, and padding that only
   appears on hover would shove the type around under the pointer.

   So the padding is present at rest in every variant and pulled straight back
   out with a matching negative margin. The layout is identical to the shipped
   one — verified by measuring — and on the white panel an invisible 20u of
   white padding is exactly nothing until a variant paints it.

   Keeping it OUTSIDE the variants also means switching between them cannot
   move anything, so what is being compared is the effect and not the spacing.
   20 rather than 24: the column gap is 48, so two neighbouring cards keep 8u
   of daylight between their painted edges instead of touching.
   ============================================================================ */

/* ---------- shared scaffolding ---------- */

[data-hover] .rdk-post-card {
  position: relative;
  margin: calc(-20 * var(--u));
  padding: calc(20 * var(--u));
  border-radius: calc(40 * var(--u));            /* art 20 + the padding, so the two are concentric */
  transition: background-color 0.32s ease, color 0.32s ease;
}

/* The feature's own margin/padding carry the 24 above and 96 below that
   separate it from the filter bar and the grid. Both are re-expressed so the
   20 of padding comes out of them rather than adding to them: 4+20 = 24,
   76+20 = 96, -20+20 = 0. The box is unchanged.

   The 4 tracks css/latest.css's feature top margin — if that moves, this moves
   with it, or every variant shifts the card relative to the shipped page and
   the comparison stops being fair. */
[data-hover] .rdk-post-feature {
  position: relative;
  margin: calc(4 * var(--u)) calc(-20 * var(--u)) calc(76 * var(--u));
  padding: calc(20 * var(--u));
  border-radius: calc(44 * var(--u));
  transition: background-color 0.32s ease, color 0.32s ease;
}

/* The previous/next cards already have a box, so they need no scaffolding —
   only the transition. */
[data-hover] .rdk-post-nav__card {
  position: relative;
  transition: background-color 0.32s ease, color 0.32s ease;
}

/* Anything that has to sit above a slab drawn by ::before. This is also what
   hides Burst's green behind the artwork at rest, so it is load-bearing there
   rather than merely tidy. */
[data-hover] .rdk-post-card__art,
[data-hover] .rdk-post-card__body,
[data-hover] .rdk-post-feature__art,
[data-hover] .rdk-post-feature__body,
[data-hover] .rdk-post-nav__text,
[data-hover] .rdk-post-nav__chip {
  position: relative;
  z-index: 1;
}

/* The pieces that have to answer a fill. The pill's outline and the avatar's
   backing are both drawn against the white panel, so both disappear into a
   flooded card unless they are told otherwise. */
[data-hover] .rdk-post-card__cat,
[data-hover] .rdk-post-feature__cat {
  transition: border-color 0.32s ease, background-color 0.32s ease, color 0.32s ease;
}

[data-hover] .rdk-avatar { transition: background-color 0.32s ease; }


/* THE COPY UNDER THE ARTWORK IS INSET, THE ARTWORK IS NOT (client, 2026-09-08).

   On a filled card the green reaches 20 past the content on every side, and at
   that distance the title, standfirst and byline read as crowded against the
   edge — the artwork does not, because a photograph has its own frame and the
   type does not.

   THE FIX IS ON THE TYPE, NOT ON THE GREEN. Growing the fill was tried first
   and moves the problem rather than solving it: every card gets wider, the
   cards crowd each other across the 48 column gap, and the type is still the
   same distance from the edge it was. Insetting the copy puts the space
   exactly where the crowding is — the text ends up 36 clear of the green while
   the picture stays at 20, so the image reads as bleeding and the words as
   set in.

   AT REST IT COSTS A VISIBLE ALIGNMENT: the title no longer starts on the
   photograph's left edge. That is the trade, and it is why this lives here
   rather than in css/latest.css — the shipped page has no green to clear, so
   the inset would buy it nothing.

   Shared across every variant rather than scoped to the filling ones, so
   flipping between them cannot move the type and the comparison stays about
   the effect. The featured article is excluded: its copy sits in its own
   column beside the artwork, not under it, and already carries 48. */
[data-hover] .rdk-post-card__body { padding-inline: calc(16 * var(--u)); }


/* ============================================================================
   0 — THE SHIPPED HOVER, PLUS A GREEN PILL OUTLINE

   The title goes green and the artwork uncrops, both as they do today, and the
   category pill's outline goes green with them.

   The outline only, not a fill — the pill is a quiet piece of furniture beside
   the date, and filling it makes it the loudest thing on a card whose title is
   38px. Its ink stays --rdk-dark for the same reason: green-on-white at 13px
   bold is ~2.6:1, fine for a border and not for a label.
   ============================================================================ */

[data-hover="0"] .rdk-post-card:hover .rdk-post-card__cat,
[data-hover="0"] .rdk-post-card:focus-visible .rdk-post-card__cat,
[data-hover="0"] .rdk-post-feature:hover .rdk-post-feature__cat,
[data-hover="0"] .rdk-post-feature:focus-visible .rdk-post-feature__cat {
  border-color: var(--rdk-green);
}

/* A DARKER GREEN FOR THE TITLE (client, 2026-09-08). #00ad00 rather than the
   brand's #00bf00, and it buys something real: 3.13:1 on white against
   #00bf00's 2.66:1, so a 38px title clears the 3:1 large-text bar where the
   brand green does not. Literal rather than a token, because it is this
   variant's answer to a legibility question and not a new site colour.

   THE PILL'S OUTLINE ABOVE IS STILL #00bf00. That is deliberate — a border is
   not text and has no bar to clear — but the two greens are 18 apart in one
   component, so if they should match it is this value in both places. */
[data-hover="0"] .rdk-post-card:hover .rdk-post-card__title,
[data-hover="0"] .rdk-post-card:focus-visible .rdk-post-card__title,
[data-hover="0"] .rdk-post-feature:hover .rdk-post-feature__title,
[data-hover="0"] .rdk-post-feature:focus-visible .rdk-post-feature__title,
[data-hover="0"] .rdk-post-nav__card:hover .rdk-post-nav__title {
  color: #00ad00;
}


/* ============================================================================
   1, 2 + 4 — THE CARD FILLS GREEN
   3        — THE CARD FILLS DARK

   One set of flip rules, two palettes, chosen by custom property. The three
   green variants differ only in HOW the green arrives.

   THE INK IS DARK ON GREEN, NOT WHITE. White on #00bf00 is 2.48:1 and fails
   even the 3:1 large-text bar — it is the one contrast this project already
   knows it has and has chosen to live with, on the hero, where the client
   asked for a bare landing view. There is no reason to repeat it on body copy.
   --rdk-dark on the same green is ~7.8:1.
   ============================================================================ */

[data-hover="1"],
[data-hover="2"],
[data-hover="4"] {
  --hv-fill: var(--rdk-green);
  --hv-ink: var(--rdk-black-green);
  --hv-title: var(--rdk-black-green);
  --hv-line: rgba(0, 20, 7, 0.32);
  --hv-avatar: var(--rdk-black-green);
}

/* BURST KEEPS THE LIME ACCENTS (client, 2026-09-08); the flood and the wipe go
   back to the dark ones. The pill's outline and the avatar's backing are both
   green-family marks that sink into a green card — the backing especially,
   since it is what a cut-out headshot reads against — and lime lifts them off
   it. At 1.7:1 on #00bf00 that is low for type and right for these two: a
   hairline and a disc behind a photograph, wanted as a brighter green rather
   than a legible one.

   Scoped to Burst because that is where it was asked for. 1 and 2 reach an
   identical green card, so adding them to this selector is the whole change if
   they should match. Nothing lime happens at REST in any variant. */
[data-hover="4"] {
  --hv-line: var(--rdk-lime);
  --hv-avatar: var(--rdk-lime);
}

[data-hover="3"] {
  --hv-fill: var(--rdk-black-green);
  --hv-ink: var(--rdk-white);
  --hv-title: var(--rdk-green);
  --hv-line: rgba(255, 255, 255, 0.28);
  --hv-avatar: var(--rdk-green);
}

/* 2 and 4 paint their fill on the ::before instead, so they are excluded here
   and take the ink flip on its own further down. */
:is([data-hover="1"], [data-hover="3"]) :is(.rdk-post-card, .rdk-post-feature, .rdk-post-nav__card):hover,
:is([data-hover="1"], [data-hover="3"]) :is(.rdk-post-card, .rdk-post-feature, .rdk-post-nav__card):focus-visible {
  background-color: var(--hv-fill);
  color: var(--hv-ink);
}

:is([data-hover="1"], [data-hover="2"], [data-hover="3"], [data-hover="4"]) .rdk-post-card:hover .rdk-post-card__title,
:is([data-hover="1"], [data-hover="2"], [data-hover="3"], [data-hover="4"]) .rdk-post-card:focus-visible .rdk-post-card__title,
:is([data-hover="1"], [data-hover="2"], [data-hover="3"], [data-hover="4"]) .rdk-post-feature:hover .rdk-post-feature__title,
:is([data-hover="1"], [data-hover="2"], [data-hover="3"], [data-hover="4"]) .rdk-post-feature:focus-visible .rdk-post-feature__title,
:is([data-hover="1"], [data-hover="2"], [data-hover="3"], [data-hover="4"]) .rdk-post-nav__card:hover .rdk-post-nav__title {
  color: var(--hv-title);
}

:is([data-hover="1"], [data-hover="2"], [data-hover="3"], [data-hover="4"]) :is(.rdk-post-card, .rdk-post-feature):hover :is(.rdk-post-card__cat, .rdk-post-feature__cat),
:is([data-hover="1"], [data-hover="2"], [data-hover="3"], [data-hover="4"]) :is(.rdk-post-card, .rdk-post-feature):focus-visible :is(.rdk-post-card__cat, .rdk-post-feature__cat) {
  border-color: var(--hv-line);
  color: inherit;
}

/* The avatars are cut-outs with real alpha, so their backing IS what makes
   them read. Left alone on a green card the green backing merges into the
   green card and the headshot floats. */
:is([data-hover="1"], [data-hover="2"], [data-hover="3"], [data-hover="4"]) :is(.rdk-post-card, .rdk-post-feature):hover .rdk-avatar,
:is([data-hover="1"], [data-hover="2"], [data-hover="3"], [data-hover="4"]) :is(.rdk-post-card, .rdk-post-feature):focus-visible .rdk-avatar {
  background-color: var(--hv-avatar);
}

/* THE EYEBROW HAS TO FLIP TOO, AND IT IS THE ONE RUN THAT DOES NOT DO IT ON
   ITS OWN (client QA, bug tracker row 97: "on hover, eyebrow disappears since
   it's the same color as the background"). Exactly right, and it is the
   shipped variant: `.rdk-post-nav__label` carries an explicit
   `color: var(--rdk-green)` from css/latest.css, so when the card floods
   --hv-fill — which in 1, 2 and 4 IS --rdk-green — it is green on green and
   simply gone. The title beside it was already covered, because it takes
   --hv-title; only the label declares its own colour and so ignores the ink
   flip the card hands down.

   `inherit` rather than a named colour: the card sets --hv-ink on itself for
   2 and 4 and --hv-title-family inks elsewhere, so inheriting means the
   eyebrow can never disagree with the type under it, in any variant. */
:is([data-hover="1"], [data-hover="2"], [data-hover="3"], [data-hover="4"]) .rdk-post-nav__card:hover .rdk-post-nav__label,
:is([data-hover="1"], [data-hover="2"], [data-hover="3"], [data-hover="4"]) .rdk-post-nav__card:focus-visible .rdk-post-nav__label {
  color: inherit;
}

/* The prev/next chip inverts with the rest rather than keeping its own
   green-on-white hover, which would be the one un-flipped thing on the card. */
:is([data-hover="1"], [data-hover="2"], [data-hover="4"]) .rdk-post-nav__card:hover .rdk-post-nav__chip {
  color: var(--rdk-green);
  background: var(--rdk-black-green);
  border-color: var(--rdk-black-green);
}

[data-hover="3"] .rdk-post-nav__card:hover .rdk-post-nav__chip {
  color: var(--rdk-black-green);
  background: var(--rdk-green);
  border-color: var(--rdk-green);
}

/* 2 and 4: the ink cannot wait for the fill to arrive, or the type is
   unreadable against a green that is already half way across it. */
:is([data-hover="2"], [data-hover="4"]) :is(.rdk-post-card, .rdk-post-feature, .rdk-post-nav__card):hover,
:is([data-hover="2"], [data-hover="4"]) :is(.rdk-post-card, .rdk-post-feature, .rdk-post-nav__card):focus-visible {
  color: var(--hv-ink);
}


/* THE CATEGORY LABEL FILLS, it does not merely outline (client, 2026-09-08).
   Its ink goes to the card's own near-black: lime is bright enough to carry
   dark type at 12.6:1, so the pill becomes the one solid, high-contrast mark on
   a green card rather than a hairline on it.

   Later than the shared flip rule and at the same specificity, so it wins on
   order — the shared rule sets border-color and inherits the ink, and this
   replaces both. */
[data-hover="4"] .rdk-post-card:hover .rdk-post-card__cat,
[data-hover="4"] .rdk-post-card:focus-visible .rdk-post-card__cat,
[data-hover="4"] .rdk-post-feature:hover .rdk-post-feature__cat,
[data-hover="4"] .rdk-post-feature:focus-visible .rdk-post-feature__cat {
  background-color: var(--rdk-lime);
  border-color: var(--rdk-lime);
  color: var(--rdk-black-green);
  animation: rdk-burst-pop 0.46s cubic-bezier(0.34, 1.3, 0.64, 1);
}

/* THE BOUNCE HAS TO LAND ON SOMETHING THAT STAYS ON SCREEN. The fill's own
   overshoot is invisible by construction: its edges travel past the card and
   the card clips them, so there is nothing to watch spring back. The pill is
   the one element already announcing itself as the green arrives, so the pop
   goes there — it reads as the card's reaction rather than as a second effect.

   A KEYFRAME, NOT A TRANSITION. A transition can only land on a value and hold
   it, and a permanently enlarged pill is not the ask; `animation-name` going
   none -> name on hover is also the only thing that restarts a CSS animation,
   so it fires on every arrival. */
@keyframes rdk-burst-pop {
  0%   { scale: 1; }
  42%  { scale: 1.07; }
  100% { scale: 1; }
}


/* ---------- 2 — the same green, WIPED UP from the bottom edge ----------
   A fill that fades is a state changing; a fill that arrives from an edge is
   something moving.

   Drawn on ::before so GSAP — which owns `transform` on the feature card and
   on every grid <li> for their entrances — cannot clear it. A pseudo-element's
   own transform is CSS's alone. */
[data-hover="2"] .rdk-post-card::before,
[data-hover="2"] .rdk-post-feature::before,
[data-hover="2"] .rdk-post-nav__card::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 0;
  background: var(--hv-fill);
  border-radius: inherit;
  transform: scaleY(0);
  transform-origin: 50% 100%;
  transition: transform 0.42s cubic-bezier(0.22, 1, 0.36, 1);
}

[data-hover="2"] .rdk-post-card:hover::before,
[data-hover="2"] .rdk-post-card:focus-visible::before,
[data-hover="2"] .rdk-post-feature:hover::before,
[data-hover="2"] .rdk-post-feature:focus-visible::before,
[data-hover="2"] .rdk-post-nav__card:hover::before {
  transform: scaleY(1);
}


/* ============================================================================
   4 — BURST

   The green is already there at rest, sitting in exactly the artwork's box and
   hidden behind the photograph. On hover it springs out past the picture's
   edges and floods the rest of the card.

   IT IS AN `inset` ANIMATION, NOT A SCALE, and that is what makes the start
   position exact. A scale would have to know the card's proportions to land on
   the artwork's box, and every card is a different height because the titles
   wrap differently. Animating the four insets means the rest state IS the
   artwork's box, whatever shape the card happens to be.

   THE FOUR REST INSETS ARE MEASURED IN JS (`--art-t/r/b/l`), for the same
   reason: the artwork's height cannot be expressed in CSS relative to the card,
   because a percentage on `bottom` resolves against the card's HEIGHT while the
   artwork's height comes from its own WIDTH and aspect. js/latest-hover-lab.js
   writes the four, re-measures whenever a card's box changes, and falls back to
   0 — an ordinary flood — if it has not run.

   THE BOUNCE OVERSHOOTS TO NEGATIVE INSETS, so the card has to clip. Without
   `overflow: clip` the green springs out past the card's own edges and over
   whatever is beside it, which is not a bounce but a bug. Clipping also means
   the overshoot is felt in the growth rather than seen as a wobble at the end,
   which is the right way round: what is being described is the green bursting
   out, not the card breathing.

   A DISC FROM THE ARTWORK'S CENTRE AND A UNIFORM SCALE OF THE ARTWORK'S OWN
   SHAPE were both built after this and both dropped. Recorded so they are not
   re-derived: the disc read as a different object arriving rather than the
   card filling, and the uniform scale had to overshoot the card sideways by
   2.4x to cover it, because the card is portrait and the artwork landscape.
   ============================================================================ */

[data-hover="4"] .rdk-post-card,
[data-hover="4"] .rdk-post-feature { overflow: clip; }


[data-hover="4"] .rdk-post-card::before,
[data-hover="4"] .rdk-post-feature::before {
  content: '';
  position: absolute;
  z-index: 0;
  inset: var(--art-t, 0px) var(--art-r, 0px) var(--art-b, 0px) var(--art-l, 0px);
  background: var(--hv-fill);
  border-radius: calc(20 * var(--u));            /* the artwork's own radius, so it is
                                                    the picture's shape that swells */
  transition: inset 0.42s cubic-bezier(0.34, 1.68, 0.64, 1),
              border-radius 0.42s cubic-bezier(0.34, 1.68, 0.64, 1);
}

[data-hover="4"] .rdk-post-feature::before { border-radius: calc(24 * var(--u)); }

[data-hover="4"] .rdk-post-card:hover::before,
[data-hover="4"] .rdk-post-card:focus-visible::before,
[data-hover="4"] .rdk-post-feature:hover::before,
[data-hover="4"] .rdk-post-feature:focus-visible::before {
  inset: 0;
  border-radius: inherit;
}

/* The prev/next cards carry no artwork, so there is nothing for the green to
   come out from behind. They take the plain flood rather than an invented
   origin. */
[data-hover="4"] .rdk-post-nav__card:hover,
[data-hover="4"] .rdk-post-nav__card:focus-visible { background-color: var(--hv-fill); }


/* ---------- reduced motion ----------
   The colour changes stay — they are the affordance, and a fill is not what
   this request is asking to be spared. Only the things that TRAVEL are cut,
   and Burst's fill still arrives, just without the spring. */
@media (prefers-reduced-motion: reduce) {
  [data-hover] .rdk-post-card::before,
  [data-hover] .rdk-post-feature::before,
  [data-hover] .rdk-post-nav__card::before { transition: none; }

  [data-hover="4"] .rdk-post-card:hover .rdk-post-card__cat,
  [data-hover="4"] .rdk-post-feature:hover .rdk-post-feature__cat { animation: none; }

  [data-hover="4"] .rdk-post-card::before,
  [data-hover="4"] .rdk-post-feature::before { inset: 0; border-radius: inherit; opacity: 0; }

  [data-hover="4"] .rdk-post-card:hover::before,
  [data-hover="4"] .rdk-post-feature:hover::before { opacity: 1; }
}


/* ---------- the phone ----------
   Straight px, not --u: the design unit is min(100vw/1600, 1px), so a 20u
   padding is 4.9px at 390 and the fill would have no body at all.

   16 rather than 20, and that is what makes the fill full-bleed here: the grid
   already sits at `margin: 0 16px`, so a -16px pull reaches the screen edge
   exactly. */
@media (max-width: 767px) {
  [data-hover] .rdk-post-card {
    margin: -16px;
    padding: 16px;
    border-radius: 28px;                          /* art 12 + the padding */
  }

  [data-hover] .rdk-post-feature {
    margin: 16px 0 48px;                          /* 16+16 = 32 above, 48+16 = 64 below */
    padding: 16px;
    border-radius: 28px;
  }

  [data-hover] .rdk-post-card__body { padding-inline: 12px; }

  [data-hover="4"] .rdk-post-card::before,
  [data-hover="4"] .rdk-post-feature::before { border-radius: 12px; }
}
