/* Latest — the blog. latest/index.html (the index) and latest/<slug>/
   (a post). Both are WordPress templates in waiting: the index is
   `home.php`, the post is `single.php`, and the card is `content-card.php`.
   The team keeps posting in WordPress, so nothing here asks the editor for a
   class — `.rdk-post__body` styles the BARE ELEMENTS `the_content()` emits
   (h2, p, ul, blockquote, figure, table…) plus the handful of block classes
   the editor adds on its own (`.wp-block-image`, `.alignwide`, `.alignfull`,
   `.wp-block-embed`, `.wp-block-pullquote`).

   Built from the current blog's anatomy (redonkmarketing.com/blog: a featured
   post, a two-up grid of cards with author, date, title, excerpt and a "Read
   the article" link, Load more; and on a post: hero, share, body, previous /
   next, "About the author" with "More by") in the new site's vocabulary:

     hero          the work index's green band
     white panel   the work index's shouldered panel and its filter bar
     featured post the work tile — page ground, 24 radius, artwork inset 16
     cards         the same tile in the grid display, on the off-white tint
     labels        Satoshi 700 13 uppercase, the work bar's label size
     post layout   the services page's two columns: sticky meta, 776 measure
     author card   the services page's dark aside
     pills         the About CTA (Load more, See all) — plain, no chip:
                   they recur, so by the style guide's rule they do not shout

   --u everywhere; the phone block is straight px, as on every other page. */

/* ============================================================
   shared: labels, avatars, the tile hover
   ============================================================ */

/* Category · date. The work bar's 13/700 label, uppercase and tracked like
   the 15 labels, in green on light and lime on dark. */
.rdk-latest__label,
.rdk-post__meta-label,
.rdk-post-nav__label,
.rdk-post-author__label,
.rdk-post__related-label {
  margin: 0;
  font-family: var(--rdk-font-body);
  font-weight: 700;
  font-size: calc(13 * var(--u));
  line-height: 1.2;
  letter-spacing: calc(1.3 * var(--u));
  font-feature-settings: "frac" 1;
  text-transform: uppercase;
  color: var(--rdk-green);
}

/* The main Redonk green, not lime (client, 2026-09-08) — the whole author
   aside now, label, chevrons and hover alike. */
.rdk-post-author__label {
  color: var(--rdk-green);
}

/* ---------- the card's meta row (2026-09-08) ----------
   The category is an outlined pill and the date sits beside it, and the two
   plus the author's name all take ONE ink — full --rdk-dark (client). The
   uppercase green run they replace is still what the POST's own head uses;
   only the cards changed.

   Geometry is the site's tag pill verbatim (css/work.css .rdk-work__chip,
   css/latest.css .rdk-latest__chip): 36 tall, 999 radius, Satoshi 700 13/1,
   16 side padding. Symmetric padding, because the 18/14 correction in
   work.css is for the icon those chips carry and these do not. base.css is
   border-box, so the 1.5 border sits inside the 36 rather than making it 39. */
.rdk-post-card__meta,
.rdk-post-feature__meta,
.rdk-post__meta-line,
.rdk-post-author__meta {
  display: flex;
  align-items: center;
  gap: calc(14 * var(--u));
  margin: 0;
}

.rdk-post-card__cat,
.rdk-post-feature__cat,
.rdk-post__cat {
  display: inline-flex;
  align-items: center;
  height: calc(36 * var(--u));
  padding: 0 calc(16 * var(--u));
  border: calc(1.5 * var(--u)) solid rgba(0, 35, 0, 0.18);
  border-radius: 999px;
}

.rdk-post-card__cat,
.rdk-post-card__date,
.rdk-post-feature__cat,
.rdk-post-feature__date,
.rdk-post__cat,
.rdk-post__date {
  font-family: var(--rdk-font-body);
  font-weight: 700;
  font-size: calc(13 * var(--u));
  line-height: 1;
  white-space: nowrap;
  color: var(--rdk-dark);
}

/* The separator between category and date is a dot, so the two never read
   as one phrase. */
.rdk-latest__sep {
  display: inline-block;
  margin: 0 calc(8 * var(--u));
  opacity: 0.5;
}

/* THE GREEN IS A BACKGROUND, so it only shows through a headshot that carries
   alpha — which every avatar on the site now does (client's cut-outs,
   2026-09-08: 200 square RGBA, and their soft edge averages RGB (192,155,122),
   hair and skin rather than the ground they were cut from, so they hold on the
   author card's near-black as well as on white).

   It is on `.rdk-avatar` itself, so every instance takes it: the grid cards,
   the featured post, the post's own head byline and the author card. Scoping it
   to the cards left the other two as bare cut-outs on their own ground, which
   was a look nobody had chosen — just what swapping opaque photos for cut-outs
   does on its own. */
.rdk-avatar {
  background: var(--rdk-green);
  display: block;
  flex: none;
  width: calc(40 * var(--u));
  height: calc(40 * var(--u));
  max-width: none;
  object-fit: cover;
  border-radius: 50%;
}

/* Name beside an avatar: Satoshi 700 at the card's own 15. */
.rdk-byline {
  display: flex;
  align-items: center;
  gap: calc(12 * var(--u));
  font-family: var(--rdk-font-body);
  font-weight: 700;
  font-size: calc(15 * var(--u));
  line-height: 1.2;
  letter-spacing: calc(0.15 * var(--u));
}

/* The work tile's artwork: rests enlarged, uncrops slowly on hover. */
.rdk-post-card__shot,
.rdk-post-feature__shot {
  display: block;
  width: 100%;
  height: 100%;
  max-width: none;
  object-fit: cover;
  scale: 1.09;
  transition: scale 2.4s cubic-bezier(0.22, 1, 0.36, 1);
}

@media (hover: hover) and (pointer: fine) {
  .rdk-post-card:hover .rdk-post-card__shot,
  .rdk-post-feature:hover .rdk-post-feature__shot { scale: 1; }
}

/* The author card's pill. The article cards HAD one of these and lost it with
   their box (2026-09-08): the whole card is the link, and the title turning
   green with the artwork uncropping is the affordance — which is what the
   reference this was drawn from relies on too. */
.rdk-post-author__go {
  display: inline-flex;
  flex: none;
  align-items: center;
  justify-content: center;
  gap: calc(12 * var(--u));
  height: calc(56 * var(--u));
  padding: 0 calc(28 * var(--u));
  font-family: var(--rdk-font-brand);
  font-weight: 700;
  font-size: calc(15.272 * var(--u));
  line-height: 1;
  white-space: nowrap;
  border: calc(2 * var(--u)) solid currentColor;
  border-radius: 999px;
  transition: background-color 0.24s ease, color 0.24s ease;
}

.rdk-post-author__go svg {
  width: calc(5.878 * var(--u));
  height: calc(8.928 * var(--u));
}

/* ============================================================
   1. the index — hero
   ============================================================
   NODE 438:7249 (2026-09-08). 591.3 tall, "Latest." at 88 over a lime
   standfirst, and the two DONKs with a thought bubble where three of the
   flocked service objects used to be.

   THE FRAME IS A 0.937 SCALE OF THE 1600 DESIGN, so every number here is the
   node's value x 1.0673. Checkable rather than assumed: the node's nav links
   come back 18.739 and the wordmark 142.408, which are the site's own 20 and
   152 at that scale. */
.rdk-latest-hero {
  position: relative;
  height: calc(591.3 * var(--u));
  background: var(--rdk-green);
  overflow: clip;
}

.rdk-latest-hero__shapes {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

.rdk-latest-hero__shape {
  position: absolute;
  max-width: none;
  width: calc(var(--w) * var(--u));
  height: calc(var(--h) * var(--u));
  left: calc(var(--x) * var(--u));
  top: calc(var(--y) * var(--u));
  will-change: transform;
}

/* THE ASSET IS THE WHOLE GROUP NOW — 679 x 824, node 927:144886 (client,
   2026-09-18: "the thought bubbles are cut off, can you reexport Donk and make
   sure he's not cut off"). It was 679 x 554, and that 554 was a SLICE: Figma
   cuts an export at its parent frame's edge, so the group came back as only the
   part the section could show. Checked the old file's alpha and it ran to the
   canvas edge at BOTH ends — 68 rows off the top, which is the bubble, and 202
   off the bottom.

   THE SLICE SAT AT ROWS 68..622 OF THE NEW RENDER, established by sliding the
   old file over the new one and scoring the alpha: a perfect match (score 0) at
   dy 68, with 2.85/255 of colour drift on the overlap, i.e. ordinary WebP loss.
   That is what makes the reposition below exact rather than eyeballed.

   IMAGE ADJUSTMENTS ARE IN IT, and that was verified rather than assumed:
   `get_screenshot` with `contentsOnly: true` renders the node as the design
   does, and its opaque mean is (87,137,75) against the raw fill's (160,187,151)
   — the deep grade the design applies, which `rawImages` would have lost.

   THE OLD "NEVER LIFT IT OFF THE BOTTOM EDGE" RULE IS GONE WITH THE SLICE. The
   bottom of this file is the drawing's real bottom, not a cut, so the artwork
   no longer has to be pinned anywhere for the join to work — the hero's own
   `overflow: clip` does the cropping the export used to do.

   `--y` IS -27, NOT 0, AND THAT IS THE COST OF SHOWING THE BUBBLE. The ink
   starts 44 rows down (47 design units at this scale), so the artwork has to
   hang 27 above the hero for the bubble's top to land 20 inside it. Everything
   moves down ~42 against where the sliced asset sat. THE DESIGN ITSELF CROPS
   THE BUBBLE (node 438:7249 renders it cut by the hero's top edge), so this is
   a deliberate deviation on the client's instruction, not a correction.

   The entrance is still safe: it enters from BELOW (y: 46) while scaling
   0.9 -> 1, so the net offset stays positive for the whole tween — and with the
   bottom no longer a cut there is nothing for a stray lift to expose anyway. */
.rdk-latest-hero__shape--donks { --w: 724.7; --h: 879.5; --x: 310.6; --y: -27; }

/* ---------- the three knobs js/latest-tuner.js drives ----------
   `--donk-k` scales the drawn box and `--donk-dx` / `--donk-dy` move it, in
   whatever unit the breakpoint counts in — design units here, px on the phone,
   which is why the panel keeps a set per context.

   THE FOUR DESIGNED NUMBERS STAY IN `--w/--h/--x/--y` and are not written by
   the panel, so the tuning is always readable as an offset FROM the design
   rather than replacing it. Reset is the three going back to 1 / 0 / 0.

   It scales from the box's TOP-LEFT here, because that is the corner `left` and
   `top` pin; the phone pins top-RIGHT, so it grows the other way there. */
.rdk-latest-hero__shape--donks {
  /* The client's own pass, 2026-09-18. */
  --donk-k: 0.98;
  --donk-dx: -20;
  --donk-dy: -26;
  width: calc(var(--w) * var(--donk-k) * var(--u));
  height: calc(var(--h) * var(--donk-k) * var(--u));
  left: calc((var(--x) + var(--donk-dx)) * var(--u));
  top: calc((var(--y) + var(--donk-dy)) * var(--u));
}

  /* Display/L, from the file's own variables: 88 / lh 1 / tracking -4%.
     Tracking in that file is a PERCENTAGE, so -4 on 88 is -3.52 -- it was read
     as literal px here and shipped at -5.28, i.e. -6%, 50% tighter than the
     token and tighter than Display/XL above it. Corrected 2026-09-09; do not
     put -5.28 back. */
.rdk-latest-hero__title {
  position: absolute;
  left: calc(89.52 * var(--u));
  top: calc(389.6 * var(--u));
  z-index: 1;
  margin: 0;
  font-family: var(--rdk-font-brand);
  font-weight: 700;
  font-size: calc(88 * var(--du));
  line-height: 1;
  letter-spacing: calc(-3.52 * var(--du));
  color: var(--rdk-white);
}

/* Heading/S — the file's token resolves to 24 in a frame drawn at 0.937, which
   is 25.6 at the design's own width. Tracking is a PERCENTAGE there (-1%), so
   it is -0.256 at this size and not -1. Lime, not white: the node binds it to
   lime/400, which is --rdk-lime — the first use of that token outside the
   footer CTA's border. */
.rdk-latest-hero__standfirst {
  position: absolute;
  left: calc(89.52 * var(--u));
  top: calc(492.1 * var(--u));
  z-index: 1;
  margin: 0;
  font-family: var(--rdk-font-brand);
  font-weight: 700;
  font-size: calc(25.6 * var(--u));
  line-height: 1.2;
  letter-spacing: calc(-0.256 * var(--u));
  color: var(--rdk-lime);
}

/* ============================================================
   2. the index — the white panel
   ============================================================ */
.rdk-latest,
.rdk-post {
  position: relative;
  z-index: 1;
  background: var(--rdk-white);
}

/* Green only behind the shoulders — see css/work.css for why the whole
   section must not be painted. The POST has no strip: its shoulders ride
   over the featured image and the notches show the image, not green. */
.rdk-latest::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  height: calc(120 * var(--u));
  background: var(--rdk-green);
}

.rdk-latest__panel,
.rdk-post__panel {
  position: relative;
  background: var(--rdk-white);
  border-radius: calc(93.5 * var(--u)) calc(93.5 * var(--u)) 0 0;
}

.rdk-latest__panel {
  /* The work panel's 24 / 88 / 160. */
  padding: calc(24 * var(--u)) calc(88 * var(--u)) calc(160 * var(--u));
}

/* ---------- the bar (the work index's, node 314:55859) ----------
   Filter by category. In WordPress these chips are the site's categories:
   `get_categories()`, each linking to its archive, which renders this same
   template. The prototype filters the cards on the page instead. */
/* THE UNDERLINE IS GONE and the bar's own padding is what spaces it now
   (client, 2026-09-08), replacing a 117 min-height it used to centre inside.

   THE SPACE ABOVE AND BELOW THE CHIPS IS EQUAL, and it is made of two pieces
   at each end rather than one: above is the panel's 24 of top padding plus
   this 40; below is this 40 plus the featured post's 24 of top margin. Both
   come to 64. That is why .rdk-post-feature's top margin is 24 and not the 64
   it was — the old value put 104 under the chips against 64 over them, which
   is the gap that read as the articles sitting too low.

   Keep the three numbers in step if any of them moves: panel-top + bar-pad
   must equal bar-pad + feature-top. */
.rdk-latest__bar {
  display: flex;
  align-items: center;
  gap: calc(16 * var(--u));
  padding: calc(40 * var(--u)) 0;
}

.rdk-latest__bar-label {
  font-family: var(--rdk-font-body);
  font-weight: 700;
  font-size: calc(13 * var(--u));
  line-height: calc(15 * var(--u));
  color: var(--rdk-dark);
}

.rdk-latest__chips {
  display: flex;
  flex-wrap: wrap;
  gap: calc(8 * var(--u));
}

/* The work chip without its icon, so its padding is symmetric — the
   optical correction there was for the icon. */
.rdk-latest__chip {
  display: inline-flex;
  align-items: center;
  height: calc(36 * var(--u));
  padding: 0 calc(16 * var(--u));
  font-family: var(--rdk-font-body);
  font-weight: 700;
  font-size: calc(13 * var(--u));
  line-height: 1;
  color: var(--rdk-dark);
  background: rgba(0, 35, 0, 0.06);
  border: 0;
  border-radius: 999px;
  cursor: pointer;
  transition: background-color 0.2s ease, color 0.2s ease;
}

.rdk-latest__chip:hover {
  background: rgba(0, 35, 0, 0.12);
}

.rdk-latest__chip.is-on {
  color: var(--rdk-white);
  background: var(--rdk-dark);
}

/* ---------- the featured post ----------
   The card's box is gone (client, 2026-09-08 — the tinted ground behind an
   article was the thing that was wrong). Artwork on the left, the type block
   on the right, both straight on the white panel.

   Its own bottom padding is what separates it from the grid — it used to
   lean on the first grid row's top rule, which no longer exists. */
.rdk-post-feature {
  display: flex;
  align-items: flex-start;
  gap: 4%;
  height: auto;
  margin: calc(24 * var(--u)) 0 0;
  padding: 0 0 calc(96 * var(--u));
  color: var(--rdk-dark);
  background: none;
  border-radius: 0;
  overflow: visible;
  text-decoration: none;
}

.rdk-post-feature__art {
  position: relative;
  flex: none;
  width: 58%;
  aspect-ratio: 3 / 2;
  margin: 0;
  border-radius: calc(24 * var(--u));
  overflow: clip;
}

/* THE COPY COLUMN IS THE ARTWORK'S HEIGHT, and its three groups are placed by
   auto margins rather than by a fixed rhythm (client, 2026-09-08): category and
   date at the top, title and standfirst centred, the byline on the bottom.

   `align-self: stretch` is what makes that possible at all. The row is
   `align-items: flex-start`, so without it the column is only as tall as its
   own copy and there is no free space for an auto margin to absorb — the
   spacing would resolve to the old stack however it was written.

   TWO AUTO MARGINS, NOT `justify-content: space-between`. Space-between spreads
   all FOUR children evenly, which pulls the title away from the standfirst it
   belongs to; `margin-top: auto` on the title and `margin-bottom: auto` on the
   excerpt split the leftover space equally above and below that PAIR, which is
   what centring the middle group means when the group is two elements and the
   markup is staying as it is (it maps onto WordPress template tags, so extra
   wrappers cost more here than a pair of margins).

   The meta keeps a real bottom margin and the foot its top one, so those gaps
   have a floor: on a card whose copy runs long the free space goes to zero and
   the auto margins with it, and without the floors the three groups would butt
   together rather than simply stop being centred. */
.rdk-post-feature__body {
  flex: 1 1 auto;
  align-self: stretch;
  display: flex;
  flex-direction: column;
  min-width: 0;
  padding: calc(48 * var(--u)) 0;
}

.rdk-post-feature__meta { margin-bottom: calc(24 * var(--u)); }

.rdk-post-feature__title {
  margin: auto 0 calc(20 * var(--u));
  font-family: var(--rdk-font-brand);
  font-weight: 700;
  font-size: calc(46 * var(--du));
  line-height: 1.04;
  letter-spacing: calc(-1.15 * var(--du));
  text-wrap: balance;
  transition: color 0.24s ease;
}

/* The hover the "Read the article" pill used to carry.

   GATED ON A REAL HOVER (client, 2026-09-18: "on mobile, remove the hover, it's
   distracting and not needed"). An ungated `:hover` STICKS after a tap on
   touch, so the card a reader had just pressed stayed green behind them. The
   artwork's uncrop above was already gated; these two titles were missed.
   `:focus-visible` stays OUT of the query — a keyboard needs it at every
   width. */
.rdk-post-feature:focus-visible .rdk-post-feature__title {
  color: var(--rdk-green);
}

@media (hover: hover) and (pointer: fine) {
  .rdk-post-feature:hover .rdk-post-feature__title { color: var(--rdk-green); }
}

/* The standfirst runs short of its column — a full measure under a title this
   size reads as a paragraph rather than as a standfirst. */
.rdk-post-feature__excerpt,
.rdk-post-card__excerpt {
  margin: 0;
  max-width: calc(480 * var(--u));
  font-family: var(--rdk-font-body);
  font-weight: var(--rdk-body-weight);
  font-size: var(--rdk-body-s);
  line-height: var(--rdk-body-lh);
  letter-spacing: var(--rdk-body-track);
  opacity: 0.8;
}

/* The lower half of the feature's centred pair — see the body rule above. */
.rdk-post-feature__excerpt { margin-bottom: auto; }

/* No box means no bottom edge to pin the byline to, so the foot follows the
   standfirst instead of being pushed down by `margin-top: auto`. */
.rdk-post-feature__foot,
.rdk-post-card__foot {
  display: flex;
  align-items: center;
  gap: calc(16 * var(--u));
  margin-top: calc(24 * var(--u));
  padding-top: 0;
}

/* ---------- the grid of cards ----------
   The tinted card is gone: artwork with its own radius, then the type
   straight on the white panel, with a hairline above each row.

   THE HAIRLINE ABOVE EACH ROW IS GONE (client, 2026-09-08). Its SPACING is
   not: the row gap absorbs the 48 of padding the rule used to sit above, so
   the rhythm is unchanged and only the line has left. That is also why there
   is no :nth-child anywhere here — with nothing to draw, there is nothing to
   suppress on the first row. */
.rdk-latest__grid,
.rdk-post__related-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  column-gap: calc(48 * var(--u));
  row-gap: calc(96 * var(--u));
  margin: 0;
  padding: 0;
  list-style: none;
}

.rdk-post-card {
  display: flex;
  flex-direction: column;
  gap: calc(28 * var(--u));
  height: auto;
  padding: 0;
  color: var(--rdk-dark);
  background: none;
  border-radius: 0;
  overflow: visible;
  text-decoration: none;
}

.rdk-post-card__art {
  position: relative;
  margin: 0;
  aspect-ratio: 982.4 / 593.5;
  border-radius: calc(20 * var(--u));
  overflow: clip;
  background: var(--rdk-off-white);
}

.rdk-post-card__body {
  flex: 1 1 auto;
  min-width: 0;
  padding: 0;
}

  /* Heading/L (40). Was 38 -- see the display ladder in css/tokens.css. 38 and
     40 were two steps 1.05x apart, where every other rung of the ladder is
     1.10-1.22x, and the work index used BOTH on one page. Merged onto 40
     (client, 2026-09-09). The tracking moves with it: -4% of 40 is -1.6, the
     same as every other run at this step. */
.rdk-post-card__title {
  margin: calc(20 * var(--u)) 0 calc(16 * var(--u));
  font-family: var(--rdk-font-brand);
  font-weight: 700;
  font-size: calc(40 * var(--du));
  line-height: 1.04;
  letter-spacing: calc(-0.91 * var(--du));
  text-wrap: balance;
  transition: color 0.24s ease;
}

.rdk-post-card:focus-visible .rdk-post-card__title {
  color: var(--rdk-green);
}

@media (hover: hover) and (pointer: fine) {
  .rdk-post-card:hover .rdk-post-card__title { color: var(--rdk-green); }
}

/* Filtered out (prototype) — by attribute, as the work index does it.

   THE FEATURE NEEDS ITS OWN GUARD: it is `display: flex`, and an author
   `display` beats the UA's `[hidden] { display: none }`, so without this line
   js/latest.js sets the attribute and nothing happens. Same trap the contact
   dialog's error message already carries a note about. */
.rdk-latest__grid > li[hidden] { display: none; }
.rdk-post-feature[hidden] { display: none; }

/* ---------- Load more ----------
   The About CTA's pill without its chip — Load more recurs, so it is a plain
   pill by the style guide's rule, and the colour swap is its hover. In
   WordPress it is the existing `js-load-more-posts` AJAX call, or plainly
   `next_posts_link()` — either way it is one button. */
.rdk-latest__more {
  display: flex;
  justify-content: center;
  margin-top: calc(72 * var(--u));
}

.rdk-latest__more-btn,
.rdk-post-nav__link {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: calc(80 * var(--u));
  padding: 0 calc(56 * var(--u));
  font-family: var(--rdk-font-brand);
  font-weight: 700;
  font-size: calc(23 * var(--u));
  line-height: 1.2;
  letter-spacing: calc(-0.23 * var(--u));
  white-space: nowrap;
  color: var(--rdk-black-green);
  background: none;
  border: calc(4 * var(--u)) solid var(--rdk-green);
  border-radius: 999px;
  cursor: pointer;
  transition: background-color 0.3s ease, color 0.3s ease;
}

.rdk-latest__more-btn:hover,
.rdk-latest__more-btn:focus-visible {
  color: var(--rdk-white);
  background: var(--rdk-green);
}

/* ============================================================
   3. a post — hero
   ============================================================
   The project page's hero (css/project.css): the featured image, full bleed,
   at the blog's own 1600 x 879, and nothing on it — the title lives in the
   white panel that rides up over its foot. `the_post_thumbnail('full')`. */
.rdk-post-hero {
  position: relative;
  aspect-ratio: 1600 / 879;
  background: var(--rdk-black-green);
  overflow: clip;

  /* See the scrim note below. --scrim-a: 0 is an exact revert. */
  --scrim-a: 0.45;
  --scrim-hold: calc(96 * var(--u));
  --scrim-fade: calc(300 * var(--u));
}

.rdk-post-hero__shot {
  display: block;
  width: 100%;
  height: 100%;
  max-width: none;
  object-fit: cover;
}

/* ------------------------------------------------------------
   THE NAV SCRIM (2026-09-14) — TRIAL, and one property to revert.

   The nav is reversed out white over a hero the EDITOR chooses, so the
   backdrop is not ours to predict. Measured across the ten featured
   images we have, white ink fails 3:1 on up to 100% of the nav band and
   dark ink on up to 96% — the About wall's finding again: no single ink
   clears a photograph, because the photograph varies within itself. An
   ink chosen per post cannot fix that; a backdrop can.

   So the top of the hero is darkened just enough that white is ALWAYS
   right, and the per-post decision disappears.

   `--scrim-a` IS THE WHOLE CONTROL. 0 is an exact revert — the gradient
   still renders but every stop is transparent, so nothing paints.

   WHY 0.45. The threshold is not a preference, it is where a PURE WHITE
   pixel clears 3:1 against white ink: 0.416 for black, solved rather than
   eyeballed (0.535 if the 15px links are held to body-text 4.5:1). Anything below
   it leaves some image somewhere that still fails, and the failure is
   invisible until the post that has it is published. Measured over all
   ten images at 0.45: 0% of the band under 3:1 on every one. At 0.35,
   four of the ten still fail on a third or more of it.

   It holds full strength past the nav's own box (which ends at 83) and
   then eases out. The stops approximate an ease-out rather than ramping
   linearly — a straight ramp puts its steepest change in the middle of
   the fade, which reads as a visible band edge on a flat sky. The last
   stop is the reason `--scrim-fade` exists at all: end it too early and
   the join is a line; too late and it reaches the panel's shoulders.

   IT IS FLAT BLACK, NOT THE SITE'S DARK INK (client, 2026-09-14: "can we
   do flat black so color doesn't come through"). It was --rdk-black-green
   for one commit, justified on a claim that turned out to be false — that
   the scrim sits next to the white panel's notches, which show the page
   ground through, so a neutral dark would read cold against them. It does
   not sit next to them: the scrim is at the hero's TOP and the notches are
   at its FOOT, measured 398px apart at 1600x900. There was never anything
   for it to match.

   And the tint is real rather than theoretical. #001407 is a GREEN dark,
   so at 0.45 it pushes a neutral grey +9 green and +4 blue — on this
   post's white wall, (230,230,230) becomes (127,136,130) instead of a
   neutral (127,127,127). Over a photograph the editor chose, that is the
   scrim editorialising the colour. Black takes luminance out and leaves
   hue alone, which is the whole job.

   Black is also marginally more efficient — the 3:1 floor is 0.416
   against #001407's 0.442 (4.5:1: 0.535 against 0.568) — so there is room
   to lighten it later. 0.45 is kept for headroom rather than sitting on
   the floor. */
.rdk-post-hero::after {
  content: '';
  position: absolute;
  inset: 0 0 auto 0;
  height: var(--scrim-fade);
  /* Above the pixel-reveal canvas (z 2), so the nav has its backdrop
     whatever the reveal is doing underneath. */
  z-index: 3;
  pointer-events: none;
  /* Flat black, and deliberately NOT a token — see above. No token here
     is neutral: every dark the palette carries is a green dark. */
  background: linear-gradient(to bottom,
    rgba(0, 0, 0, var(--scrim-a))                        0,
    rgba(0, 0, 0, var(--scrim-a))                        var(--scrim-hold),
    rgba(0, 0, 0, calc(var(--scrim-a) * 0.72))           40%,
    rgba(0, 0, 0, calc(var(--scrim-a) * 0.38))           62%,
    rgba(0, 0, 0, calc(var(--scrim-a) * 0.14))           80%,
    rgba(0, 0, 0, 0)                                     100%);
}

/* SOME HEROES MUST NOT HAVE IT, and which ones is derived — run
   `python3 tools/hero-scrim.py`, which measures every featured image and
   stamps this attribute.

   The scrim is nearly invisible over a photograph (the eye has no flat
   reference to miss) and very obvious over flat colour, so applying it
   everywhere charges the flat heroes full price for a problem most of them
   do not have. A hero is left bare when its band is FLAT and white is
   already as legible on it as the site accepts elsewhere — in practice
   that means Redonk green, which is 2.55:1 and is the house style on every
   other hero on this site.

   FLAT IS NOT THE SAME AS SAFE, which is the trap this rule exists to
   avoid: two of the ten featured images are flat LIME, and white on that
   is 1.35:1 — worse than any photograph in the set and worse than the
   green the site has decided to live with. They are flat AND they get the
   scrim. Do not simplify this to "graphics are exempt".

   Reusing --scrim-a: 0 rather than `display: none` keeps ONE revert path:
   the property is the control in both directions. */
.rdk-post-hero[data-hero-scrim="off"] { --scrim-a: 0; }

/* ============================================================
   4. a post — the white panel
   ============================================================ */
/* The panel rides 96 up over the hero, exactly as the project intro does —
   so this section's own ground is TRANSPARENT for the top 120 (where the
   shoulders' notches show the image through) and white below that, which is
   what keeps the join to the footer seamless. */
.rdk-post {
  margin-top: calc(-96 * var(--u));
  background: linear-gradient(to bottom,
    transparent calc(120 * var(--u)), var(--rdk-white) calc(120 * var(--u)));
}

.rdk-post__panel {
  /* The project page's 40 inset; the top is the head's own 96. */
  padding: 0 calc(40 * var(--u)) calc(160 * var(--u));
}

/* ---------- the head: crumb, label, title, byline ----------
   The project introduction's left column (node 314:64862), across the whole
   panel: the crumb at 88 from the edge (48 inside the panel's 40), the title
   at 96 from the panel's top — which is the frame's 897, the hero's foot. */
.rdk-post__head {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: calc(24 * var(--u));
  padding: calc(96 * var(--u)) calc(48 * var(--u)) 0;
  color: var(--rdk-dark);
}

/* The project page's crumb, verbatim. */
.rdk-post__crumb {
  display: flex;
  align-items: center;
  gap: calc(16 * var(--u));
  margin: 0;
  font-family: var(--rdk-font-brand);
  font-weight: 700;
  font-size: calc(18 * var(--u));
  line-height: 1.4;
  letter-spacing: calc(0.18 * var(--u));
  color: var(--rdk-green);
  transition: color 0.24s ease;
}

.rdk-post__crumb:hover,
.rdk-post__crumb:focus-visible {
  color: var(--rdk-dark);
}

.rdk-post__crumb svg {
  flex: none;
  width: calc(3.89577 * var(--u));
  height: calc(7.79154 * var(--u));
  overflow: visible;
  scale: -1 1;
  transition: translate 0.28s cubic-bezier(0.33, 1, 0.68, 1);
}

.rdk-post__crumb:hover svg {
  translate: calc(3 * var(--u)) 0;
}

/* THE HEAD'S CATEGORY RUN IS THE CARDS' (client, 2026-09-08) — an outlined
   pill for the category, the date and the read time beside it, all in one ink.
   It replaces the uppercase green run, which now belongs only to the SECTION
   eyebrows on this page (Share, Previous article, About the author, More from
   Latest); those are a different job and keep it.

   It joins the cards' own rules rather than restating them, so the pill cannot
   drift between the index and the article. The 24 is what `.rdk-post__label`
   used to carry — on top of the head's own 24 gap, so the run sits 48 under
   the crumb. */
.rdk-post__meta-line {
  margin-top: calc(24 * var(--u));
}

/* Between the About headline's 62 and the section titles' 88: a post title
   runs to fourteen words on this blog, and 72 keeps that to three lines
   across the 1180 measure. `balance` so a two-line title is two even lines. */
.rdk-post__title {
  max-width: calc(1180 * var(--u));
  margin: 0;
  font-family: var(--rdk-font-brand);
  font-weight: 700;
  font-size: calc(72 * var(--du));
  line-height: 0.98;
  letter-spacing: calc(-2.47 * var(--du));
  text-wrap: balance;
  color: var(--rdk-dark);
}

.rdk-post__byline {
  margin-top: calc(16 * var(--u));
  font-size: calc(18 * var(--u));
}

.rdk-post__byline .rdk-avatar {
  width: calc(56 * var(--u));
  height: calc(56 * var(--u));
}

.rdk-post__byline small {
  display: block;
  margin-top: calc(4 * var(--u));
  font-weight: 500;
  font-size: calc(15 * var(--u));
  opacity: 0.7;
}

/* ---------- the two columns ----------
   The services page's arrangement with a narrower first column: 400 that
   pins (client, 2026-09-01 — it was the services page's 560), 88 gap, and
   the body on an 800 measure. The 48 inside the panel's 40 lands the text at
   the site's 88. */
.rdk-post__layout {
  display: grid;
  grid-template-columns: calc(400 * var(--u)) minmax(0, 1fr);
  gap: calc(88 * var(--u));
  /* The head above carries the panel's 96; this is the gap below the byline,
     the project introduction's own 80 between its rows. */
  padding: calc(80 * var(--u)) calc(48 * var(--u)) 0;
}

/* NOT STICKY (client, 2026-09-08) — a rail that tracks you down the page
   competes with the article for attention, which is the one thing the column
   exists not to do. `align-self: start` stays: it stops the aside stretching to
   the body's full height, which is what a grid item does by default. */
.rdk-post__meta {
  align-self: start;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: calc(40 * var(--u));
  max-width: calc(360 * var(--u));
  color: var(--rdk-dark);
}

.rdk-post__meta-row {
  display: flex;
  flex-direction: column;
  gap: calc(12 * var(--u));
}

/* ---------- share: the footer's social buttons, on white ----------
   The footer draws its icons as white `<img>`s inside a 52 box with a lime
   outline (css/footer.css). On the white panel the same SVGs are painted as
   MASKS in `currentColor`, so one file serves the footer and this rail —
   LinkedIn and Facebook are the footer's own; X and the link are drawn to
   match them in assets/img/latest/. */
.rdk-post__share {
  display: flex;
  flex-wrap: wrap;
  gap: calc(12 * var(--u));
  margin: 0;
  padding: 0;
  list-style: none;
}

.rdk-post__share a,
.rdk-post__share button {
  display: flex;
  align-items: center;
  justify-content: center;
  width: calc(52 * var(--u));
  height: calc(52 * var(--u));
  padding: 0;
  color: var(--rdk-dark);
  border: calc(2 * var(--u)) solid rgba(0, 35, 0, 0.12);
  border-radius: calc(8 * var(--u));
  cursor: pointer;
  transition: border-color 0.25s ease, background-color 0.25s ease, color 0.25s ease;
}

.rdk-post__share a::before,
.rdk-post__share button::before {
  content: "";
  width: calc(32 * var(--u));
  height: calc(32 * var(--u));
  background: currentColor;
  mask: var(--share-icon) no-repeat center / contain;
  -webkit-mask: var(--share-icon) no-repeat center / contain;
}

.rdk-post__share [data-icon="linkedin"] { --share-icon: url("../assets/img/footer/icon-linkedin.svg"); }
.rdk-post__share [data-icon="facebook"] { --share-icon: url("../assets/img/footer/icon-facebook.svg"); }
.rdk-post__share [data-icon="x"]        { --share-icon: url("../assets/img/latest/icon-x.svg"); }
.rdk-post__share [data-icon="link"]     { --share-icon: url("../assets/img/latest/icon-link.svg"); }

/* The footer's hover — the outline goes and a fill takes its place — in the
   site green at the tint the intro chip uses. */
.rdk-post__share a:hover,
.rdk-post__share a:focus-visible,
.rdk-post__share button:hover,
.rdk-post__share button:focus-visible {
  border-color: transparent;
  background: rgba(0, 191, 0, 0.15);
}

/* Copied: the fill goes solid for a moment. */
.rdk-post__share button.is-copied {
  color: var(--rdk-white);
  border-color: transparent;
  background: var(--rdk-green);
}

/* ---------- the body ----------
   THIS IS `the_content()`. Every rule targets a bare element or a class
   WordPress adds on its own, so an editor never has to know a class exists.
   The base is the site's body copy a step down for long reading: Satoshi 500
   at 20 / 1.5 with the two stylistic sets, in the dark ink at 85%. */
/* TYPOGRAPHY FROM NODE 446:14833 (client, 2026-09-08).

   THE FRAME IS THE 0.937 SCALE AGAIN, so every value is the node's x 1.0673 —
   the same as the hero's. Two independent anchors say so: its measure is
   749.5, which is our 800, and its h2 renders 43.099, which is the 46 this
   page already used. The spacing then lands on round numbers (28 / 92 / 56 /
   16 / 10 / 32 / 8), which a wrong scale would not do.

   THE TOKEN-BOUND SIZES REPORT THEIR RAW VALUES, NOT WHAT THEY RENDER, and
   that had to be measured rather than read: `var(--body/m, 18px)` and
   `var(--heading/s, 24px)` are the variables' own numbers. Dividing the text
   nodes' boxes by their line counts gives the truth — the body paragraph is
   108 over 4 lines = 27, and 27 / 1.5 is 18; the lead is 145 over 5 = 29, and
   29 / 1.2 is 24. Both therefore render AT the raw value, so scaled up they
   are 19.2 and 25.6 here.

   One inconsistency in the file is deliberately not reproduced: its list items
   are literals at 18.739 (= 20 here) where its paragraphs are the 18 token
   (= 19.2). That is a token-versus-literal artefact rather than an intent, so
   the list inherits the paragraph size. */
.rdk-post__body {
  max-width: calc(800 * var(--u));
  font-family: var(--rdk-font-body);
  font-weight: var(--rdk-body-weight);
  font-size: var(--rdk-body-m);
  line-height: var(--rdk-body-lh);
  letter-spacing: var(--rdk-body-track);
  font-feature-settings: "ss03" 1, "ss02" 1;
  color: var(--rdk-dark);
}

.rdk-post__body > * {
  margin: 0;
}

/* The rhythm is in design units rather than ems now: the node states it
   directly, and an em-relative value drifts the moment a size moves. */
.rdk-post__body > * + * {
  margin-top: calc(28 * var(--u));
}

.rdk-post__body p,
.rdk-post__body li {
  opacity: 0.85;
}

/* The lede — the first paragraph in Redonk Avant Garde (client, 2026-09-01),
   at the aside title's 28, so the article opens in the site's own voice and
   settles into Satoshi from the second paragraph. In WordPress this is
   `.rdk-post__body > p:first-child`, i.e. whatever the author writes first;
   no class, no block. */
.rdk-post__body > p:first-child {
  font-family: var(--rdk-font-brand);
  font-weight: 700;
  font-size: calc(25.6 * var(--u));
  line-height: 1.2;
  letter-spacing: calc(-0.256 * var(--u));
  font-feature-settings: normal;
  opacity: 1;
}

/* Headings in the brand face, on the site's own scale: the project headline's
   46 (one step up from the work intro's 38 — client, 2026-09-01), the
   aside's 32 → 28, the CTA's 23 → 22. Extra space above so a heading
   belongs to what follows it, not what precedes it. */
.rdk-post__body h2,
.rdk-post__body h3,
.rdk-post__body h4,
.rdk-post__body h5,
.rdk-post__body h6 {
  font-family: var(--rdk-font-brand);
  font-weight: 700;
  line-height: 1.1;
  color: var(--rdk-dark);
  text-wrap: balance;
}

.rdk-post__body h2 {
  margin-top: calc(92 * var(--u));
  font-size: calc(46 * var(--du));
  letter-spacing: calc(-1.15 * var(--du));
}

/* Heading/S, whose tracking the file states as a PERCENTAGE (-1%) — so it is
   -0.256 at this size, not -1. Its 1.2 overrides the shared 1.1 above. */
.rdk-post__body h3 {
  margin-top: calc(56 * var(--u));
  font-size: calc(25.6 * var(--u));
  line-height: 1.2;
  letter-spacing: calc(-0.256 * var(--u));
}

.rdk-post__body h4,
.rdk-post__body h5,
.rdk-post__body h6 {
  margin-top: 1.8em;
  font-size: calc(22 * var(--u));
  letter-spacing: calc(-0.22 * var(--u));
}

.rdk-post__body h2 + *,
.rdk-post__body h3 + *,
.rdk-post__body h4 + * {
  margin-top: calc(16 * var(--u));
}

/* Links: green, with a real underline the reader can find. */
.rdk-post__body a {
  color: var(--rdk-green);
  text-decoration: underline;
  text-decoration-thickness: calc(2 * var(--u));
  text-underline-offset: calc(4 * var(--u));
  transition: color 0.2s ease;
}

.rdk-post__body a:hover {
  color: var(--rdk-dark);
}

.rdk-post__body strong,
.rdk-post__body b {
  font-weight: 700;
}

.rdk-post__body ul,
.rdk-post__body ol {
  padding-left: 1.4em;
}

.rdk-post__body li + li {
  margin-top: calc(10 * var(--u));
}

.rdk-post__body li::marker {
  color: var(--rdk-green);
  font-weight: 700;
}

/* Quotes in the brand face with the green rule — the case-study rule turned
   on its side. `.wp-block-quote` is what the editor emits; the bare element
   covers pasted HTML. */
.rdk-post__body blockquote,
.rdk-post__body .wp-block-quote {
  margin: calc(56 * var(--u)) 0;
  padding: calc(8 * var(--u)) 0 calc(8 * var(--u)) calc(32 * var(--u));
  border-left: calc(3.88 * var(--u)) solid var(--rdk-green);
  font-family: var(--rdk-font-brand);
  font-weight: 700;
  font-size: calc(25.6 * var(--u));
  line-height: 1.2;
  letter-spacing: calc(-0.256 * var(--u));
  font-feature-settings: normal;
}

.rdk-post__body blockquote p {
  margin: 0;
  opacity: 1;
}

.rdk-post__body blockquote p + p {
  margin-top: 0.8em;
}

.rdk-post__body blockquote cite {
  display: block;
  margin-top: 1em;
  font-family: var(--rdk-font-body);
  font-weight: 700;
  font-style: normal;
  font-size: calc(13 * var(--u));
  letter-spacing: calc(1.3 * var(--u));
  text-transform: uppercase;
  color: var(--rdk-green);
}

/* A pull quote stands alone and centred, as a section headline would. */
.rdk-post__body .wp-block-pullquote {
  margin: 2.5em 0;
  padding: calc(48 * var(--u)) 0;
  border-top: 1px solid rgba(0, 35, 0, 0.1);
  border-bottom: 1px solid rgba(0, 35, 0, 0.1);
  text-align: center;
}

.rdk-post__body .wp-block-pullquote blockquote {
  margin: 0;
  padding: 0;
  border: 0;
  font-size: calc(38 * var(--du));
  letter-spacing: calc(-1.14 * var(--du));
  color: var(--rdk-green);
}

/* Images and figures: the work tile's 24 radius. Wide and full alignments
   both take the column here — the sticky meta column is beside it, so there
   is nothing to bleed into. */
.rdk-post__body img {
  display: block;
  max-width: 100%;
  height: auto;
  border-radius: calc(24 * var(--u));
}

.rdk-post__body figure,
.rdk-post__body .wp-block-image {
  margin: 2em 0;
}

.rdk-post__body figcaption {
  margin-top: calc(12 * var(--u));
  font-size: var(--rdk-body-xs);
  line-height: var(--rdk-body-lh);
  letter-spacing: var(--rdk-body-track);
  opacity: 0.6;
}

.rdk-post__body .alignwide,
.rdk-post__body .alignfull {
  width: 100%;
}

.rdk-post__body .has-text-align-center { text-align: center; }
.rdk-post__body .has-text-align-right  { text-align: right; }

/* Embeds (YouTube, Vimeo) at 16:9 in the same rounded box. */
.rdk-post__body iframe,
.rdk-post__body .wp-block-embed__wrapper {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  border: 0;
  border-radius: calc(24 * var(--u));
  overflow: clip;
}

.rdk-post__body .wp-block-embed__wrapper iframe {
  width: 100%;
  height: 100%;
  border-radius: 0;
}

.rdk-post__body hr {
  height: 1px;
  margin: 3em 0;
  border: 0;
  background: rgba(0, 35, 0, 0.1);
}

/* There is deliberately no mono face in the project (css/tokens.css), so
   code takes the system's. */
.rdk-post__body code,
.rdk-post__body pre {
  font-family: ui-monospace, Menlo, Consolas, monospace;
  font-size: 0.9em;
}

.rdk-post__body code {
  padding: 0.1em 0.4em;
  background: var(--rdk-off-white);
  border-radius: calc(6 * var(--u));
}

.rdk-post__body pre {
  padding: calc(32 * var(--u));
  background: var(--rdk-off-white);
  border-radius: calc(24 * var(--u));
  overflow-x: auto;
  line-height: 1.5;
}

.rdk-post__body pre code {
  padding: 0;
  background: none;
}

.rdk-post__body table {
  letter-spacing: var(--rdk-body-track);
  line-height: var(--rdk-body-lh);
  width: 100%;
  border-collapse: collapse;
  font-size: var(--rdk-body-s);
}

.rdk-post__body th,
.rdk-post__body td {
  padding: calc(14 * var(--u)) calc(16 * var(--u));
  text-align: left;
  vertical-align: top;
  border-bottom: 1px solid rgba(0, 35, 0, 0.1);
}

.rdk-post__body th {
  font-family: var(--rdk-font-brand);
  font-weight: 700;
  font-size: calc(16 * var(--u));
  letter-spacing: calc(-0.16 * var(--u));
}

/* ---------- after the body ---------- */
.rdk-post__after {
  display: flex;
  flex-direction: column;
  gap: calc(120 * var(--u));
  padding: calc(120 * var(--u)) calc(48 * var(--u)) 0;
}

/* Previous / next: two off-white cards with the CTA's chip as the arrow. In
   WordPress: `get_previous_post()` / `get_next_post()`. */
.rdk-post-nav {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: calc(22 * var(--u));
  margin: 0;
  padding: 0;
  list-style: none;
}

/* THE TWO CARDS ARE NOT MIRRORS, and that is deliberate (client, 2026-09-08).
   The PREVIOUS card reads chip-then-title as one phrase, so the two sit
   together at the left — `space-between` pushed them to opposite ends of a
   700-wide card and left a gap you had to read across. The BACK TO card keeps
   its chevron out at the far edge, mirroring where the previous card's chip
   sits, with its copy left-aligned at the card's own edge. */
.rdk-post-nav__card {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: calc(32 * var(--u));
  min-height: calc(200 * var(--u));
  padding: calc(40 * var(--u));
  color: var(--rdk-dark);
  background: var(--rdk-off-white);
  border-radius: calc(24 * var(--u));
  text-decoration: none;
}

.rdk-post-nav__card--prev {
  justify-content: flex-start;
}

.rdk-post-nav__card--next {
  flex-direction: row-reverse;
  text-align: left;
}

.rdk-post-nav__text {
  display: flex;
  flex-direction: column;
  gap: calc(16 * var(--u));
  min-width: 0;
}

.rdk-post-nav__title {
  margin: 0;
  font-family: var(--rdk-font-brand);
  font-weight: 700;
  font-size: calc(28 * var(--du));
  line-height: 1.05;
  letter-spacing: calc(-0.52 * var(--du));
  text-wrap: balance;
  transition: color 0.24s ease;
}

.rdk-post-nav__card:hover .rdk-post-nav__title {
  color: var(--rdk-green);
}

/* The About CTA's chip, static, at 64. */
.rdk-post-nav__chip {
  display: flex;
  flex: none;
  align-items: center;
  justify-content: center;
  width: calc(64 * var(--u));
  height: calc(64 * var(--u));
  color: var(--rdk-black-green);
  border: calc(4 * var(--u)) solid var(--rdk-green);
  border-radius: 50%;
  transition: background-color 0.24s ease, color 0.24s ease;
}

.rdk-post-nav__chip svg {
  width: calc(8.8 * var(--u));
  height: calc(14.2 * var(--u));
}

.rdk-post-nav__card--prev .rdk-post-nav__chip svg {
  scale: -1 1;
}

.rdk-post-nav__card:hover .rdk-post-nav__chip {
  color: var(--rdk-white);
  background: var(--rdk-green);
}

/* ---------- about the author ----------
   The services page's dark aside, two columns: who they are, and more of
   theirs. In WordPress: `get_the_author_meta()` and a second `WP_Query` on
   the author, three posts, excluding this one. */
.rdk-post-author {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: calc(88 * var(--u));
  padding: calc(64 * var(--u));
  color: var(--rdk-white);
  background: var(--rdk-black-green);
  border-radius: calc(24 * var(--u));
}

.rdk-post-author__who {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: calc(24 * var(--u));
}

.rdk-post-author__who .rdk-avatar {
  width: calc(96 * var(--u));
  height: calc(96 * var(--u));
}

  /* Heading/L (40). Was 38 -- see the display ladder in css/tokens.css. 38 and
     40 were two steps 1.05x apart, where every other rung of the ladder is
     1.10-1.22x, and the work index used BOTH on one page. Merged onto 40
     (client, 2026-09-09). The tracking moves with it: -4% of 40 is -1.6, the
     same as every other run at this step. */
.rdk-post-author__name {
  margin: 0;
  font-family: var(--rdk-font-brand);
  font-weight: 700;
  font-size: calc(40 * var(--du));
  line-height: 1.05;
  letter-spacing: calc(-0.91 * var(--du));
}

.rdk-post-author__bio {
  margin: 0;
  max-width: calc(520 * var(--u));
  font-family: var(--rdk-font-body);
  font-weight: var(--rdk-body-weight);
  font-size: var(--rdk-body-m);
  line-height: var(--rdk-body-lh);
  letter-spacing: var(--rdk-body-track);
  opacity: 0.8;
}

.rdk-post-author__go {
  margin-top: calc(8 * var(--u));
  color: var(--rdk-white);
}

.rdk-post-author__go:hover,
.rdk-post-author__go:focus-visible {
  color: var(--rdk-black-green);
  background: var(--rdk-white);
}

.rdk-post-author__more {
  display: flex;
  flex-direction: column;
  gap: calc(24 * var(--u));
}

.rdk-post-author__list {
  margin: 0;
  padding: 0;
  list-style: none;
}

/* The case studies' 0.5u row rule between entries. */
.rdk-post-author__list li {
  padding: calc(24 * var(--u)) 0;
  border-top: calc(0.5 * var(--u)) solid rgba(85, 85, 85, 1);
}

.rdk-post-author__list li:last-child {
  border-bottom: calc(0.5 * var(--u)) solid rgba(85, 85, 85, 1);
}

.rdk-post-author__list a {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: calc(24 * var(--u));
  color: var(--rdk-white);
  text-decoration: none;
}

.rdk-post-author__list a > span {
  display: flex;
  flex-direction: column;
  gap: calc(10 * var(--u));
}

.rdk-post-author__entry {
  margin: 0;
  font-family: var(--rdk-font-brand);
  font-weight: 700;
  font-size: calc(23 * var(--u));
  line-height: 1.1;
  letter-spacing: calc(-0.23 * var(--u));
  transition: color 0.24s ease;
}

.rdk-post-author__list a:hover .rdk-post-author__entry {
  color: var(--rdk-green);
}

.rdk-post-author__list svg {
  flex: none;
  width: calc(5.878 * var(--u));
  height: calc(8.928 * var(--u));
  color: var(--rdk-green);
  transition: translate 0.28s cubic-bezier(0.33, 1, 0.68, 1);
}

.rdk-post-author__list a:hover svg {
  translate: calc(4 * var(--u)) 0;
}

/* THE SAME PILL ON THE DARK CARD. The category run in "More by Amanda" is
   category-plus-date like the head's and the index cards', so it takes their
   treatment — but the pill's own border and ink are drawn for the white panel
   (rgba(0,35,0,.18) on --rdk-dark) and would be invisible here. Only those two
   values flip; the geometry and the type come from the shared rules, so the
   pill cannot drift between the light surfaces and this one.

   Ink is full --rdk-white rather than something dimmer, matching the cards,
   where the meta and the title share one ink. */
.rdk-post-author__list .rdk-post__cat {
  border-color: rgba(255, 255, 255, 0.28);
}

.rdk-post-author__list .rdk-post__cat,
.rdk-post-author__list .rdk-post__date {
  color: var(--rdk-white);
}

/* ---------- more from Latest ----------
   Three of the index's cards. In WordPress: a `WP_Query` of three recent
   posts, excluding this one — or `get_the_category()` for related-by-category. */
.rdk-post__related {
  display: flex;
  flex-direction: column;
  gap: calc(48 * var(--u));
}

.rdk-post__related-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: calc(24 * var(--u));
}

.rdk-post__related-title {
  margin: calc(16 * var(--u)) 0 0;
  font-family: var(--rdk-font-brand);
  font-weight: 700;
  font-size: calc(46 * var(--du));
  line-height: 1;
  letter-spacing: calc(-1.15 * var(--du));
  color: var(--rdk-dark);
}

/* The project crumb, pointing forward: "All articles". */
.rdk-post__related-all {
  display: flex;
  align-items: center;
  gap: calc(16 * var(--u));
  font-family: var(--rdk-font-brand);
  font-weight: 700;
  font-size: calc(18 * var(--u));
  line-height: 1.4;
  letter-spacing: calc(0.18 * var(--u));
  white-space: nowrap;
  color: var(--rdk-green);
  transition: color 0.24s ease;
}

.rdk-post__related-all:hover {
  color: var(--rdk-dark);
}

.rdk-post__related-all svg {
  width: calc(3.89577 * var(--u));
  height: calc(7.79154 * var(--u));
  overflow: visible;
  transition: translate 0.28s cubic-bezier(0.33, 1, 0.68, 1);
}

.rdk-post__related-all:hover svg {
  translate: calc(3 * var(--u)) 0;
}

/* TWO ACROSS, AND THEREFORE THE INDEX'S CARD EXACTLY (client, 2026-09-08).
   This grid used to force three columns, with a 26 title and no standfirst —
   both of those were consequences of the narrower column, not decisions about
   what a related card is. At two across the cards are 688 wide, the same as
   the index's, so the shared rules are simply left to apply and there is
   nothing here to keep in step. The only override left is the mobile title,
   which is about the phone's single column rather than about this grid. */

@media (prefers-reduced-motion: reduce) {
  .rdk-post-card__shot,
  .rdk-post-feature__shot,
  .rdk-post-card__title,
  .rdk-post-feature__title,
  .rdk-post-nav__title,
  .rdk-post-nav__chip,
  .rdk-post__crumb svg,
  .rdk-post-author__list svg,
  .rdk-post__related-all svg {
    transition: none;
  }
}

/* ============================================================
   MOBILE — straight px, after the other pages' phone frames
   ============================================================ */
@media (max-width: 767px) {

  /* ---------- shared ---------- */
  .rdk-latest__label,
  .rdk-post__meta-label,
  .rdk-post-nav__label,
  .rdk-post-author__label,
  .rdk-post__related-label {
    font-size: 11px;
    letter-spacing: 1.1px;
  }

  /* Straight px, like every other mobile block here: --u is 100vw/1600, so a
     13u pill label is 3.2px at 390. */
  .rdk-post-card__meta,
  .rdk-post-feature__meta,
  .rdk-post__meta-line,
  .rdk-post-author__meta { gap: 10px; }

  .rdk-post-card__cat,
  .rdk-post-feature__cat,
  .rdk-post__cat {
    height: 30px;
    padding: 0 12px;
    border-width: 1.5px;
  }

  .rdk-post-card__cat,
  .rdk-post-card__date,
  .rdk-post-feature__cat,
  .rdk-post-feature__date,
  .rdk-post__cat,
  .rdk-post__date { font-size: 12px; }

  .rdk-avatar { width: 32px; height: 32px; }
  .rdk-byline { gap: 10px; font-size: 14px; }

  .rdk-post-author__go {
    height: 48px;
    padding: 0 20px;
    font-size: 14px;
    border-width: 2px;
  }

  .rdk-post-author__go svg { width: 5px; height: 8px; }

  /* ---------- index hero: the work hero's phone frame ---------- */
  .rdk-latest-hero { height: 289px; }

  /* The title lifts to make room for the standfirst under it. */
  .rdk-latest-hero__title {
    top: auto;
    left: 20px;
    bottom: 62px;
    font-size: 68px;
    line-height: 0.94;
    letter-spacing: -2.72px;
    white-space: nowrap;
  }

  .rdk-latest-hero__standfirst {
    top: auto;
    left: 20px;
    bottom: 24px;
    font-size: 17px;
    letter-spacing: -0.17px;
  }

  /* NO MOBILE FRAME FOR THIS — 438:7249 is desktop only, so the placement is
     invented. ONE constraint carries over and it is the only one: the artwork's
     bottom edge is a CUT (see the desktop rule), so it must stay pinned to the
     hero's bottom, where the white panel covers it. The SIZE is free — the cut
     is the asset's own bottom edge, so it lands on the hero's bottom whatever
     the artwork is scaled to. Resize it as you like; just never lift it off
     that edge.

     At this size the width is 1.2256x the height, which on a 390 screen is most
     of the width, so the standfirst crosses a DONK's flank rather than sitting
     clear of it as it does at 1600. Shrinking the artwork moves its left edge
     right and buys some of that back if it wants tuning.

     `left`/`top` must be released explicitly: the base rule sets both, and an
     absolutely positioned box given all four is stretched between them. */
  /* 320 wide at -56 (client, 2026-09-18: slightly smaller and slightly to the
     right), and 388.4 tall on the WHOLE-GROUP asset — see the desktop rule.

     THE WIDTH IS UNCHANGED AND THE DONKS ARE THE SAME SIZE AS BEFORE. 388.4 is
     261.1 * 824/554: the old file's 554 rows still render at the 261.1 they
     did, and the extra height is the 270 rows of bubble and body the slice was
     throwing away. So this reveals the bubble rather than rescaling anything.

     ANCHORED BY `top`, NOT `bottom`, WHICH THE OLD ASSET COULD NOT BE. Its
     bottom edge was a cut that had to land on the panel; this one is the real
     bottom, so the hero's `overflow: clip` crops it and the top is free to be
     placed. -4 puts the ink's top 16.7 inside the hero — the artwork's first
     20.7 is empty canvas above the bubble. */
  .rdk-latest-hero__shape--donks {
    left: auto;
    bottom: auto;
    /* The same three knobs as the desktop rule, counted in px here. `--donk-dx`
       means "move right" at BOTH breakpoints, so it is SUBTRACTED from a
       right-anchored inset — the sign lives here rather than in the panel. */
    /* ITS OWN SET, and it has to be STATED — the three knobs are declared on
       this same selector in the base rule, so without these the phone would
       inherit the desktop's numbers, which are counted in design units and
       mean something else here. The client's own pass, 2026-09-18. */
    --donk-k: 0.94;
    --donk-dx: -26;
    --donk-dy: -4;
    right: calc(-56px - var(--donk-dx) * 1px);
    top: calc(-4px + var(--donk-dy) * 1px);
    width: calc(320px * var(--donk-k));
    height: calc(388.4px * var(--donk-k));
  }

  /* ---------- the panels ---------- */
  .rdk-latest::before,
  .rdk-post::before { height: 60px; }

  .rdk-latest__panel {
    padding: 0 0 64px;
    border-radius: 32px 32px 0 0;
  }

  /* The chips scroll sideways in one row rather than dropping behind a
     toggle — there is no icon here and no second group, so a strip is
     enough and needs no JS. */
  .rdk-latest__bar {
    gap: 12px;
    min-height: 0;
    padding: 24px 16px;
    border-bottom: 0;
  }

  .rdk-latest__bar-label { display: none; }

  /* THE SCROLLER BLEEDS OUT THROUGH THE BAR'S PADDING (client, 2026-09-18:
     "don't cut off the category filters before the right edge of the device").
     It was `width: 100%` inside a bar padded 16 a side, so a chip mid-scroll
     was clipped 16 SHORT of the screen — which reads as a broken row rather
     than as more to come. Negative margins put it back on the device's edges
     and the inset moves onto the content.

     THE TRAILING INSET IS A MARGIN ON THE LAST CHIP, NOT PADDING ON THE
     SCROLLER. Trailing padding on a scroll container is dropped from
     `scrollWidth` by several engines — the trap css/cases.css records for the
     case-study strip, which solves it with padding on a `max-content` TRACK.
     There is no track here (this element is both the scroller and the flex
     container), so the inset goes on the content itself, where it is always
     reachable. */
  .rdk-latest__chips {
    flex-wrap: nowrap;
    gap: 8px;
    width: calc(100% + 32px);
    margin-inline: -16px;
    padding-inline-start: 16px;
    overflow-x: auto;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
  }

  .rdk-latest__chips > :last-child { margin-inline-end: 16px; }

  .rdk-latest__chips::-webkit-scrollbar { display: none; }

  .rdk-latest__chip {
    flex: none;
    height: 44px;
    padding: 0 18px;
    font-size: 14px;
    letter-spacing: -0.14px;
  }

  /* ---------- the featured post: the phone work tile ---------- */
  .rdk-post-feature {
    flex-direction: column;
    gap: 16px;
    height: auto;
    margin: 32px 16px 0;
    padding: 0 0 64px;
  }

  .rdk-post-feature__art {
    width: 100%;
    aspect-ratio: 326 / 218.347;
    border-radius: 12px;
  }

  .rdk-post-feature__body { padding: 0; }

  /* The phone stacks the feature, so the copy column is content-height and the
     desktop's auto margins have no free space to divide. Zeroed explicitly
     rather than left to resolve to 0 on their own. */
  .rdk-post-feature__meta { margin-bottom: 0; }
  .rdk-post-feature__excerpt { margin-bottom: 0; }

  .rdk-post-feature__title {
    margin: 12px 0;
    font-size: 34px;
    line-height: 1.05;
    letter-spacing: -1.02px;
  }

  .rdk-post-feature__excerpt,
  .rdk-post-card__excerpt {
    max-width: none;
  }

  .rdk-post-feature__foot,
  .rdk-post-card__foot { margin-top: 18px; }

  /* ---------- the grid ---------- */
  .rdk-latest__grid,
  .rdk-post__related-grid {
    grid-template-columns: minmax(0, 1fr);
    column-gap: 0;
    row-gap: 64px;
    margin: 0 16px;
  }

  .rdk-post-card { gap: 20px; padding: 0; }
  .rdk-post-card__art { aspect-ratio: 326 / 218.347; border-radius: 12px; }
  .rdk-post-card__body { padding: 0; }

  .rdk-post-card__title {
    margin: 12px 0 10px;
    font-size: 26px;
    line-height: 1.06;
    letter-spacing: -0.78px;
  }

  .rdk-latest__more { margin-top: 40px; padding: 0 16px; }

  .rdk-latest__more-btn,
  .rdk-post-nav__link {
    width: 100%;
    height: 64px;
    padding: 16px 40px;
    font-size: 18px;
    letter-spacing: normal;
    border-width: 4px;
  }

  /* ---------- post hero: the project page's phone frame ----------
     453, not 420 — the extra 33 is what the panel's shoulders ride up over;
     see css/project.css. */
  .rdk-post-hero { aspect-ratio: 390 / 453; }

  .rdk-post {
    margin-top: -33px;
    background: linear-gradient(to bottom, transparent 60px, var(--rdk-white) 60px);
  }

  .rdk-post__head {
    gap: 14px;
    padding: 56px 8px 0;
  }

  .rdk-post__crumb { font-size: 15px; gap: 12px; letter-spacing: 0.15px; }
  .rdk-post__crumb svg { width: 3.5px; height: 7px; }
  .rdk-post__meta-line { margin-top: 12px; }

  .rdk-post__title {
    max-width: none;
    font-size: 34px;
    line-height: 1;
    letter-spacing: -1.02px;
  }

  .rdk-post__byline { margin-top: 8px; font-size: 16px; }
  .rdk-post__byline .rdk-avatar { width: 44px; height: 44px; }
  .rdk-post__byline small { font-size: 13px; }

  /* ---------- post panel ---------- */
  .rdk-post__panel {
    padding: 0 12px 72px;
    border-radius: 32px 32px 0 0;
  }

  .rdk-post__layout {
    grid-template-columns: minmax(0, 1fr);
    gap: 40px;
    padding: 40px 8px 0;
  }

  /* Not sticky on a phone: the column is the full width and would cover the
     copy it introduces. */
  .rdk-post__meta {
    position: static;
    gap: 24px;
    max-width: none;
  }

  .rdk-post__meta-row { gap: 12px; }

  /* The footer's phone sizes for the same buttons. */
  .rdk-post__share { gap: 12px; }
  .rdk-post__share a,
  .rdk-post__share button { width: 56px; height: 56px; border-width: 1.788px; border-radius: 8.616px; }
  .rdk-post__share a::before,
  .rdk-post__share button::before { width: 34.459px; height: 34.459px; }

  .rdk-post__body {
    max-width: none;
  }

  /* SIZES ARE THE PHONE'S OWN — 446:14833 is desktop only — but the TRACKING
     follows the node's ratios, because those are a rule rather than a size:
     Heading/S is -1% (the lede, h3, the quote) and its h2 is -2.148%. The
     phone had a flat -3% on all of them. h4-h6 were already at -1%. */
  .rdk-post__body > p:first-child { font-size: 21px; line-height: 1.2; letter-spacing: -0.21px; }
  .rdk-post__body h2 { font-size: 32px; letter-spacing: -0.687px; }
  .rdk-post__body h3 { font-size: 22px; letter-spacing: -0.22px; }
  .rdk-post__body h4,
  .rdk-post__body h5,
  .rdk-post__body h6 { font-size: 18px; letter-spacing: -0.18px; }

  .rdk-post__body blockquote,
  .rdk-post__body .wp-block-quote {
    padding-left: 20px;
    border-left-width: 3px;
    font-size: 22px;
    letter-spacing: -0.22px;         /* Heading/S's -1%, as above */
  }

  .rdk-post__body .wp-block-pullquote blockquote { font-size: 26px; }
  .rdk-post__body img,
  .rdk-post__body iframe,
  .rdk-post__body .wp-block-embed__wrapper,
  .rdk-post__body pre { border-radius: 16px; }
  .rdk-post__body pre { padding: 20px; }

  .rdk-post__after {
    gap: 56px;
    padding: 56px 8px 0;
  }

  .rdk-post-nav { grid-template-columns: minmax(0, 1fr); gap: 12px; }

  .rdk-post-nav__card {
    gap: 20px;
    min-height: 0;
    padding: 24px;
    border-radius: 20px;
  }

  .rdk-post-nav__title { font-size: 22px; letter-spacing: -0.66px; }
  .rdk-post-nav__chip { width: 48px; height: 48px; border-width: 3px; }
  .rdk-post-nav__chip svg { width: 7px; height: 11.3px; }

  .rdk-post-author {
    grid-template-columns: minmax(0, 1fr);
    gap: 32px;
    padding: 28px 24px;
    border-radius: 20px;
  }

  .rdk-post-author__who { gap: 16px; }
  .rdk-post-author__who .rdk-avatar { width: 64px; height: 64px; }
  .rdk-post-author__name { font-size: 28px; letter-spacing: -0.84px; }
  /* The 520u measure collapses to ~120px here — see css/work.css. */
  .rdk-post-author__bio { max-width: none; }
  .rdk-post-author__list li { padding: 16px 0; border-top-width: 0.5px; }
  .rdk-post-author__list li:last-child { border-bottom-width: 0.5px; }
  .rdk-post-author__entry { font-size: 18px; letter-spacing: -0.18px; }
  .rdk-post-author__go { width: 100%; }

  .rdk-post__related { gap: 24px; }
  .rdk-post__related-head { flex-direction: column; align-items: flex-start; gap: 12px; }
  .rdk-post__related-title { margin-top: 8px; font-size: 32px; letter-spacing: -0.96px; }
  .rdk-post__related-all { font-size: 15px; gap: 12px; }
  .rdk-post__related-all svg { width: 3.5px; height: 7px; }
  /* NOT the index grid's `0 16px`: this one sits inside the post panel, which
     already carries its own side padding, so 16 more double-insets it — the
     related cards came out 10px narrower than the index's and 10 further in. */
  .rdk-post__related-grid { margin: 0; }
}


/* ============================================================================
   LAUNCH HOLD — THE AUTHOR ARCHIVE DOES NOT EXIST
   Client QA, bug tracker rows 48 and 98: "this button does nothing", "should
   we hide for launch until that page is designed/built?". `.rdk-post-author__go`
   points at `#` because there is no author archive — not a missing href, a
   missing PAGE: nobody has designed or built one, so the WordPress port has no
   template to give `get_author_posts_url()` either.

   THE OTHER TWO CONTROLS THE SAME QA FILED ARE DELIBERATELY NOT IN HERE, and
   the difference is worth stating because it is not visible from the symptom.
   All three "do nothing" in this prototype; only one of them is missing a
   design.

     row 46  Load more      inert here because the prototype has nine posts
                            and no page 2. In WordPress it is
                            `next_posts_link()` over the real archive and it
                            works. Hiding it would hide a working control.
     row 99  More by X      three `href="#"` for the same reason — those posts
                            exist on the live blog, they are just not built as
                            static pages. A `WP_Query` on the author fills it.

   So those two are a property of the STATIC STAND-IN, and this one is a
   property of the SITE. Hiding them is one line each if the client would
   rather not ship a prototype that has them; raised rather than assumed.

   REVERSING THIS IS DELETING THIS BLOCK — the markup is untouched and still
   carries its `<!-- WordPress: … -->` note, so the link comes back whole.

   NO GRID CHANGE GOES WITH IT. `__go` sits inside `__who`, the left column, so
   the aside keeps both columns and its proportions. (Hiding `__more` as well
   WOULD need one, and it is not the tidy change it looks: the bio carries a
   520u measure, so a single-column aside leaves ~540px of empty card at a 1024
   window — measured — which reads worse than the dead link did.)
   ============================================================================ */
.rdk-post-author__go { display: none; }
