/* The record surfaces' stylesheet — WP-L3, R56-D-2/D-2a.
 *
 * Why it lives in this block's folder. D-2 requires per-block delivery through
 * block.json rather than a sitewide always-on file. Two of the three groups
 * below are shared by twelve blocks, and copying them into twelve folders would
 * be twelve copies of one idea; a file at blocks/*.css is not per-block
 * delivery at all. `rere/page-nav` is the one block composed on every route and
 * country page and on no other surface, so its stylesheet arrives exactly when
 * a record section does and never anywhere else. The hub's own collapsible
 * list therefore keeps user-agent defaults — that surface is WP-L4's.
 *
 * Preset and custom vars only: no hex, no design px anywhere here. The 1px rule
 * width is the same structural exception theme.json already takes for its
 * border tokens (there is no width token in Token Contract v1). Every rule is
 * justified where it sits; the running budget total is in rere-core/README.md.
 */

/* --- Box model on this plugin's block wrappers (UX-2) --------------------- */

/* One declaration, and it is the whole of audit finding E. theme.json's layout
   gives a constrained or wide block its token as `max-width`; the card-flat,
   notice-*, trust-strip-quiet and callout-citation variations then add padding
   and a hairline on top of it. At the initial `content-box` the browser counts
   both *outside* the token, so on /countries/austria/ at 1768px a 1600 card
   rendered 1650 and overhung the page gutter by 25px on each side, the 768
   stamp and sources panel rendered 816, and this nav rendered 785. border-box
   makes the token the whole box — which is what every core block beside them
   already does. No width, spacing or padding *value* moves; only the side of
   the border the padding is counted on.

   The selector is the only handle these wrappers share: each one is emitted by
   get_block_wrapper_attributes(), so each carries `wp-block-rere-{name}` and no
   common class. Naming the twelve individually would be twelve lines for one
   idea. It lives here, and not in a sitewide stylesheet, for the reason given
   at the top of this file and because D-2 forbids always-on CSS: `rere/page-nav`
   is composed on every country and route record and nowhere else, which is
   exactly the set of pages the padded wrappers appear on. The family hub has no
   page-nav, so its citation panel takes the same line in the comparison table's
   own stylesheet.

   Corrected 2026-08-20 (UX-7), because the last sentence's premise is wrong and
   a future package would otherwise duplicate a rule for nothing. The hub has no
   `rere/page-nav` — that part is true — but it does load *this file*:
   `rere_enqueue_section_style()` requests the `rere-page-nav-style` handle from
   the helper that emits a record section, not from the nav, and the hub's
   citation panel is a record section. Confirmed in the served HTML —
   /routes/investment/ carries `<link id='rere-page-nav-style-css'>`. So the
   duplicate below is redundant, not wrong; it is left in place because removing
   a shipped declaration to save nothing is not worth a deploy, and because this
   file's own header comment (written by WP-L3, before that helper existed) still
   says the hub keeps user-agent defaults. It does not. UX-7's citation-marker
   rule relies on the corrected reading and ships in this file only. */
[class*="wp-block-rere-"] { box-sizing: border-box; }

/* --- The jump list (deliverable 2) --------------------------------------- */

.wp-block-rere-page-nav {
	/* DS "Borders" names three jobs for border.soft and the table-of-contents
	   rail is one of them; it is decorative, and never the sole boundary of a
	   control, which a jump list is not. */
	border-inline-start: 1px solid var(--wp--custom--border--soft);
	padding-inline-start: var(--wp--preset--spacing--40);
}

.wp-block-rere-page-nav ul {
	/* A map of the page is not a bulleted list of prose, so the DS
	   TableOfContents reference drops the markers and lays the items out on a
	   gap instead of on list spacing. */
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	flex-wrap: wrap;
	/* Row-wrapped rather than the DS's vertical stack, and the difference is
	   the layout the DS assumed: it stacks these inside a 16rem sticky rail,
	   which A10 deferred as its own decision. In flow, eight stacked links push
	   the record down by most of a small viewport. The row still reads as
	   separate links and stacks on its own when the measure runs out.

	   One step on both axes since 2026-08-20 (UX-12): it was 20 down and 50
	   across, which was right while these were bare words and wrong the moment
	   they became pills — 24px of gap plus 12px of padding on each side reads as
	   36px between two labels, and the row stopped looking like one control set.
	   The pill's own padding is now what separates them. */
	gap: var(--wp--preset--spacing--20);
}

.wp-block-rere-page-nav a {
	/* A jump link is quiet at rest — `contrast-2` ink, no underline. That much
	   is the DS TableOfContents and it is unchanged.

	   **The rest of this rule is UX-12 (2026-08-20, R61-f), and it exists because
	   the quiet half had gone too far.** This was the only place on the site that
	   dropped the link underline. The justification was real — the links sit
	   inside a named `nav` landmark whose every child is a link, so nothing here
	   relied on colour alone to mark a word as clickable in running prose — and
	   the outcome was still that a reader could not tell these were controls.
	   Andres reported it as the third of three languages: buttons on the front
	   page, pills on the hub, plain text here.

	   So they take the same pill geometry as the other two and separate from them
	   by fill: `border.soft` at rest with no fill, and the fill arrives on hover
	   below. The hairline at rest is the load-bearing part — a pill with neither
	   fill nor rule until hover is, at rest, exactly the plain text this is
	   fixing, which is why the register's first sketch of this option was not
	   what shipped.

	   Measured on a country page at 1768, 768 and 375: each link goes from a
	   45x19 box to 71x33, which takes the smallest target from **19px to 33px**
	   and over the WCAG 2.2 AA 2.5.8 floor of 24 for the first time. The row
	   itself grows 23px to 33px at desktop and the block grows 85px to 115px at
	   375, where it wraps to three rows. No horizontal document scroll at any of
	   the three.

	   Departs from the DS TableOfContents, which says of its active item "No
	   pill, no fill" — recorded in that component's own prompt file rather than
	   left as drift, per R56-D-1a. */
	color: var(--wp--preset--color--contrast-2);
	text-decoration: none;
	display: inline-block;
	padding: var(--wp--preset--spacing--10) var(--wp--preset--spacing--30);
	border: 1px solid var(--wp--custom--border--soft);
	border-radius: var(--wp--custom--radius--pill);
}

.wp-block-rere-page-nav a:hover,
.wp-block-rere-page-nav a:focus {
	/* Hover fills the pill and firms the hairline, which is the same pair the
	   front page's family tiles already use for the same gesture — one hover
	   language across the site, not three. It replaces the underline this rule
	   used to add: an underline inside a bordered pill draws two lines around one
	   word. The focus ring is untouched and still arrives from the theme. */
	background: var(--wp--preset--color--surface-1);
	border-color: var(--wp--custom--border--muted);
}

/* --- Collapsible sections: the marker (deliverable 1) -------------------- */

.rere-section > summary {
	/* The disclosure control is the whole heading row, so say so. */
	cursor: pointer;
}

.rere-section > summary > :is(h2, h3, h4, h5, h6) {
	/* WP-H's open cosmetic, closed here. `<summary>` is a list-item and
	   `rere_heading()` emits a block-level heading, so the marker box took a
	   line of its own above it in both engines. Rendering the heading inline
	   puts marker and heading in one line box. Nothing else moves: the element,
	   its level, its text and the document outline are untouched, and the
	   heading keeps every typographic value theme.json gives it. */
	display: inline;
}

.rere-section > summary::marker {
	/* The user agent's own disclosure glyph, quieted to the DS's tertiary ink.
	   No icon asset is drawn or fetched: the self-hosted sprite is WP-L5's
	   deliverable and hard rule 7 forbids a remote one, so until it exists the
	   honest chevron is the one the browser already has. Sized off h-3 so it
	   stays proportionate to the fluid h-2 beside it at every viewport — at the
	   inherited body size it was a speck against a 2.5rem serif heading and
	   read as debris rather than a control (specimen: three sizes, both
	   engines, WP-L3 build). */
	color: var(--wp--preset--color--contrast-3);
	font-size: var(--wp--preset--font-size--h-3);
}

.rere-section[open] > summary {
	/* DS spacing: 40 between a heading and the body it introduces. A closed
	   section gets none — the card's own padding is the whole of its box. */
	margin-block-end: var(--wp--preset--spacing--40);
}

.rere-section > .rere-section__body {
	/* Deliverable 6. The fragment target has to sit in the details' second slot
	   for the user agent to reveal it (A10 measured that the wrapper and the
	   summary both fail), which puts the summary above the scroll position.
	   80 pulls the heading back into view across the whole fluid h-2 range.
	   Only inside a `<details>`: a section that never collapses carries its own
	   heading inside this wrapper and needs no offset. */
	scroll-margin-block-start: var(--wp--preset--spacing--80);
}

/* --- Section rhythm (deliverable 3) -------------------------------------- */

.rere-section__body > * {
	/* User-agent and core margins out, so the steps below are the only vertical
	   rhythm inside a record section and it is the DS's scale, not four
	   different stylesheets' opinions. */
	margin-block: 0;
}

.rere-section__body > * + * {
	/* DS "Spacing": 50 between components inside a component. */
	margin-block-start: var(--wp--preset--spacing--50);
}

.rere-section__body > * + :is(h2, h3, h4) {
	/* 60 before a sub-heading and 30 after it — the CountryProfileScreen
	   reference's H3 rhythm, which is what binds a heading to its own table
	   rather than floating it between two. */
	margin-block-start: var(--wp--preset--spacing--60);
}

.rere-section__body > :is(h2, h3, h4) + * {
	margin-block-start: var(--wp--preset--spacing--30);
}

.rere-section__body > p + p {
	/* Consecutive paragraphs are one passage, not two components; at 50 the
	   route-status explainer reads as a separate claim from the status. */
	margin-block-start: var(--wp--preset--spacing--30);
}

/* --- Citation markers (UX-7, audit finding K-adjacent) ------------------- */

/* The citation superscripts were the smallest text on the site at 11.67px, and
   there are 305 of them on /routes/investment/. They are the record's
   proof-of-work — the thing that separates this from a blog — so being the
   least legible thing on the page is the wrong ranking.

   The size came from neither of the two places a stylesheet would look. There
   is no `sup` rule anywhere in this plugin and no preset is involved: it is the
   user-agent default, `sup { font-size: smaller }`, which Blink resolves as
   0.8333 of the parent. A 14px table cell therefore gave 11.67px and a 17px
   paragraph 14.17px. That is why this is one declaration in a block stylesheet
   and not a theme.json change — the `xs` preset is not in the path, and would
   be the wrong instrument anyway: it is a flat 12px, which would *shrink* the
   marker in a paragraph while raising it in a cell.

   `em` and not a preset for the same reason. The marker has to stay
   proportionate to whatever text it annotates, and this plugin sets it in two
   sizes on one page.

   0.875 is measured, not picked. The layout cost of a bigger marker is
   quantised by the line box, so the candidate values fall into plateaus: 0.85em
   and 0.875em both cost +27px of document height on a country page, +11px on a
   route page and **0** on the hub, while 0.9em doubles it to +54/+23. 0.875em
   is the largest value in the cheapest plateau — 12.25px in a cell, above the
   12px floor, and 14.875px in a paragraph.

   `line-height` is deliberately not set, which is what keeps the surrounding
   text still. Measured across the 60 sup-bearing rows on a country page and a
   route page, the row-header text box is unchanged in every one; the only
   movement is rows that stack several marked lines growing by up to 7px.
   Pinning `line-height: 0` was tried and is worse, not better: it removes the
   line contribution the markers already make today, which moves rows by up to
   25.59px and takes 99px out of a country page. The smallest change is to
   leave the inherited ratio alone.

   Selector: the same handle UX-2 used at the top of this file, because the
   twelve wrappers still share no other class. It reaches all 305 markers on the
   hub, all 78 on a country page and all 56 on a route page — the hub included,
   because rere_enqueue_section_style() requests this stylesheet from the helper
   that emits a record section rather than from the nav, so a family hub carries
   it without carrying a page-nav. `rere_marks()` is the only thing in this
   codebase that emits a `<sup>`, so the broad descendant selector has exactly
   one consumer. */
[class*="wp-block-rere-"] sup { font-size: 0.875em; }

/* --- One label column on every record table (UX-6, audit finding F) ------ */

/* Nine tables on /countries/austria/blue-card-eu/ measured nine different first
   columns at 1768px — 281, 756, 184, 208, 141, 187, 195, 135, 465 — because
   every one of them is `table-layout: auto` and sizes itself from its own
   longest label. Scrolling one record page, the reader watches the label/value
   boundary move eight times; the rule that should read as the page's spine
   reads as noise. Measured after: one value, 319, on all nine, and on eight of
   the nine on a country page (the ninth is route-coverage, excluded below).

   Three rules, and the first one is not optional. `table-layout: fixed` on its
   own does nothing here: every table rere_table() builds carries a
   `screen-reader-text` caption (R39/F7), core's recipe for that class is
   `position: absolute`, and an out-of-flow caption makes Blink's fixed-layout
   algorithm discard the specified column widths and fall back to an equal
   split — 775 of 1550 for a field label. Measured, bisected and reproduced in
   a synthetic table on the same page: static or relative, 319; absolute or
   fixed, 775. `position: static` puts the caption back in flow as a 1px box
   that `clip-path: inset(50%)` and `overflow: hidden` still hide, so nothing
   becomes visible and nothing leaves the accessibility tree — the caption is
   the table's accessible name and stays exactly where it was. It costs 1px of
   table height each, 9px on a route page. Only Blink could be tested here.

   `min(19rem, 45vw)` for the column, and both halves are measured rather than
   chosen. 19rem: all 217 distinct row labels that the 16 countries and 240
   routes render were measured at this `th`'s own 700 14px Inter, and 19rem is
   the first step at which every recurring catalogue field label fits on one
   line — 18rem leaves `Years to permanent residence on this route` 4px short.
   The 22 that still wrap at 19rem are all rere/reference-figures names, quoted
   from the source and running to 121 characters (800px); that is a content
   shape and it is logged as one, not a width to chase. Nothing can overflow
   either way: the longest unbreakable run in the whole catalogue is 210px
   against a 290px content box, and its hyphens break shorter still. 45vw: the
   record card narrows faster than a label does, and one pixel above UX-5's
   stack the table is 503px, where a bare 19rem would take 63% of it. The cap
   only binds below 768px and every table on a page still reports one width at
   every viewport. It is `vw` and not `%` because a percentage inside `min()`
   is silently dropped by the fixed-layout algorithm — `min(19rem, 45%)`
   measured the same 775 equal split as no width at all, while `min(19rem,
   45vw)` measured 319. Same class of measured layout bound as WP-L4's `80vh`
   and UX-4's `min(100%, 22rem)`, not a design value.

   `:not(:has(thead))` is the two-column test UX-5 already uses in this file,
   and it is here for the same reason: rere/route-coverage is the one record
   table with a header row, its first column holds a route family name rather
   than a field label, and pinning it to a label's width would be the wrong
   reading of the row. It keeps its 104px. An engine without `:has()` drops all
   three rules and gets today's `auto` layout — the jumping spine, not a broken
   table.

   Outside UX-5's `(max-width: 37.5rem)` block and deliberately complementary
   to it, which is why the bound is a range query rather than a second
   breakpoint: below that width these tables are a stack with no columns to
   size, and a 19rem label line inside a 327px stack would be most of the row.
   An engine without range syntax drops this block and keeps `auto`. */
@media (width > 37.5rem) {
	.rere-section__body .wp-block-table:not(:has(thead)) > table > caption { position: static; }
	.rere-section__body .wp-block-table:not(:has(thead)) > table { table-layout: fixed; }
	.rere-section__body .wp-block-table:not(:has(thead)) tbody th[scope="row"] { width: min(19rem, 45vw); }
}

/* --- The coverage table's own geometry (UX-11, item 4.2) ----------------- */

/* `rere/route-coverage` is the one record table UX-6 deliberately excluded, so
   it stayed `table-layout: auto` — and auto sizes from content mass, which on a
   table holding one short status phrase in one column and a sourced note in the
   next is not a layout at all. Measured at 1768px across all sixteen published
   countries, the three columns came out as:

       greece    139 /  135 / 1274      routes column takes 82%
       austria   104 / 1204 /  241      coverage column takes 78%
       spain     106 /  996 /  448

   Sixteen countries, sixteen different tables. At 1024px it is 16 distinct
   geometries out of 16. Andres reported the Austria shape — "Coverage is too
   wide, pressing Routes to be too narrow" — and Greece is the same defect
   pointing the other way: one long cell anywhere in a column drags that whole
   column, and one 787-character note in Austria's `study` row is the entire
   cause. The reported symptom is a per-page accident; the defect is that the
   table has no geometry.

   `table-layout: fixed` with the first column pinned gives the other two an
   equal share by construction, which is what "more equally" asks for and needs
   no second width. Measured after, on all sixteen: **175 / 687 / 687, the same
   on every country**, zero family labels wrapping, no cell overflow.

   `10rem`, not the 12rem the eye reaches for: the seven family names are short —
   "Passive income" is the longest — and auto had been giving the column 101–139px
   unprompted. 10rem computes to 175 here and every name fits on one line at every
   width this block applies to.

   **On the thead cell, not the tbody one, and that is the whole reason this rule
   is not simply UX-6's copied down.** In a fixed layout the widths come from the
   FIRST row, and this is the one record table with a `<thead>` — so UX-6's
   `tbody th[scope="row"]` selector measured an equal three-way split (516/516/516,
   the family column given as much room as a sourced note) rather than the
   intended one. Bisected against both selectors on the same three pages.

   **UX-6's caption rule is deliberately absent, and it was tested rather than
   assumed.** That package found an out-of-flow `screen-reader-text` caption makes
   Blink discard specified column widths, and fixed it with `position: static`. It
   does not happen here: with the width on the thead row the caption's positioning
   makes no difference at all — 175/687/687 either way, measured on three pages —
   and leaving it absolute keeps it out of flow and saves the 1px of table height
   the static version costs. A future session should not "complete" this rule by
   adding the third declaration; it buys nothing on this table.

   **Bounded at 64rem, and the bound is the trade rather than a tidy number.** The
   equal split pays for itself on a wide screen and costs height on a narrow one,
   because a country whose coverage column holds one short phrase gives up a route
   list that was reading on one line. Measured across all sixteen countries, total
   table height: at 1024px **15 920 -> 14 807, 7% shorter** (five countries 17-29%
   shorter, two longer); at 768px **19 543 -> 20 164, 3% taller**, with four
   countries 28-56% taller. So it applies from 1024 up and stops there — `>=`, not
   `>`, because 1024 is the width the 7% was measured at and a strict bound would
   have excluded the very viewport that justified the rule. Between
   UX-5's 37.5rem stack and this bound the table keeps `auto`, which adapts to
   content and is what Andres said was acceptable — the honest cost is that the
   one-geometry guarantee is a desktop guarantee, and that is stated rather than
   implied. */
@media (width >= 64rem) {
	.wp-block-rere-route-coverage .wp-block-table > table { table-layout: fixed; }
	.wp-block-rere-route-coverage thead th:first-child { width: 10rem; }
}

/* --- Record tables on a phone (UX-5, audit finding B) -------------------- */

/* The one breakpoint the record surfaces have ever had. Twelve blocks render
   roughly thirty label/value tables on a country page and nine on a route page,
   and until this release every one of them rendered as a squeezed two-column
   grid at 375px: the label column took ~55px, the value column ~120px, and
   `Official name (local)` wrapped to three lines beside a value that wrapped to
   five. Measured worst label on /countries/austria/: seven lines.

   Below 37.5rem a record table is a stack — label line, value line, one field
   per row — which is the treatment `blocks/comparison-table/style.css` already
   gives a hub table at the same width, adapted for two columns. Simpler there
   in one way and harder in another: the label *is* the `th`, so no generated
   content is needed for it; but one record table, rere/route-coverage, has
   three columns and a `<thead>`, so the hub's `data-rere-label` mechanism is
   kept for that one. `role="table"`/`rowgroup`/`row`/`rowheader`/`cell` are on
   the markup from this release (rere-render.php, route-coverage/render.php):
   `display` stops making a table here, and without the roles the reader would
   lose the header/cell relationship along with it.

   Same media feature and the same 37.5rem as the comparison table — one phone
   breakpoint on this site, not two. */

@media (max-width: 37.5rem) {

	[class*="wp-block-rere-"].is-style-card-flat:not(.alignfull) {
		/* The card stops insetting (deliverable 2). 26% of a 375px screen went
		   to chrome — 24px page gutter plus 25px of card padding and hairline on
		   each side — and only the gutter half of that is correct. At this width
		   a flat card's job is to draw a top and a bottom edge, not to inset: the
		   inline padding, the inline hairline, the corner radius and the white
		   fill all go, the block borders stay, and the table underneath lands on
		   the same left edge as the `h1` above it. Measured at 375: the table
		   goes from L=49 W=277 to L=24 W=327.

		   `:not(.alignfull)` is the one exception and it is not cosmetic.
		   rere/route-coverage is composed full-bleed, so its box already runs
		   0…375 and its inline padding *is* the page gutter — dropping it would
		   put the reading column on the screen edge, which is the one thing the
		   audit said not to do. Its table already measures 325.

		   Nothing else loses its inset: notice-* is a status callout whose 3px
		   accent rule is a signal, and trust-strip-quiet is a filled band whose
		   fill needs the padding to read as one. Their tables still stack. */
		padding-inline: 0;
		border-inline-width: 0;
		border-radius: 0;
		background-color: transparent;
	}

	/* Core gives the figure `overflow-x: auto` for a table wider than its
	   container. A stack cannot be wider than its container — and three of
	   these tables were in fact scrolling sideways inside the card at 375,
	   rere/reference-figures worst at 306 in a 277 figure. Nothing left to
	   scroll, so no scrollport. */
	.rere-section__body .wp-block-table { overflow: visible; }

	.rere-section__body .wp-block-table > table {
		/* The table's own ring and white fill did the card's job on a wide
		   screen and are redundant once the card above has stopped drawing one:
		   two boxes around one stack, on the narrowest screen there is. The
		   hairlines between fields, below, separate the rows now. Width and
		   background only — `has-border-color` still feeds the cells. */
		border-width: 0;
		background-color: transparent;
	}

	/* The stack itself. `:not([hidden])` is carried over from the hub table
	   and is load-bearing for the same reason: without it this rule beats
	   the user agent's `[hidden] { display: none }`. No record cell is
	   hidden today, but the guard costs nothing and the next block that
	   hides one will not have to rediscover why. */
	.rere-section__body .wp-block-table :is(table, thead, tbody, tr, th, td):not([hidden]) { display: block; }

	.rere-section__body .wp-block-table thead {
		/* Only rere/route-coverage has one. Off-screen rather than removed, so
		   `role="columnheader"` keeps naming the cells in the accessibility
		   tree; the sighted label arrives from data-rere-label below. Identical
		   construction to the hub table's. */
		position: absolute;
		width: 1px;
		height: 1px;
		overflow: hidden;
		clip-path: inset(50%);
	}

	/* One field per block, on the DS's in-component step. */
	.rere-section__body .wp-block-table tbody tr { padding-block: var(--wp--preset--spacing--30); }

	/* The only separator left, on the soft hairline the DS uses inside a
	   card rather than the muted one that bounds it. */
	.rere-section__body .wp-block-table tbody tr + tr { border-block-start: 1px solid var(--wp--custom--border--soft); }

	/* Second and later value cells — route-coverage only — read as their own
	   field rather than as a continuation of the one above. */
	.rere-section__body .wp-block-table tbody td + td { margin-block-start: var(--wp--preset--spacing--20); }

	.rere-section__body .wp-block-table tbody :is(th, td) {
		/* The grid is gone, so the cell rules that drew it go with it, and the
		   cell padding that held the columns apart moves to the row above.
		   `text-align: start` because the user agent centres every `th`: in a
		   narrow two-column grid that reads as a column, in a stack it is
		   plainly wrong. `start` rather than `left` because the records carry
		   Greek and French strings already. Deliberately outside the `:has()`
		   rules below — an engine that cannot do `:has()` still must not centre
		   a label. */
		border-width: 0;
		padding: 0;
		text-align: start;
	}

	.rere-section__body .wp-block-table:not(:has(thead)) tbody th[scope="row"] {
		/* The field label, quiet above its value: the DS's secondary label ink
		   at the sm step, keeping the user agent's bold so label and value
		   differ by weight as well as by size and colour. Never by colour alone.

		   `:not(:has(thead))` is the two-column test. In a table with column
		   headers the row header is the row's *identity* — a route family name —
		   not a field label, and shrinking it would be the wrong reading. An
		   engine without `:has()` drops this rule and renders every label at the
		   value's size: flat, not broken, and still stacked and left-aligned. */
		font-size: var(--wp--preset--font-size--sm);
		color: var(--wp--preset--color--contrast-2);
	}

	/* The card header of a three-column row, held off the first field label
	   beneath it. */
	.rere-section__body .wp-block-table:has(thead) tbody th[scope="row"] { margin-block-end: var(--wp--preset--spacing--20); }

	.rere-section__body .wp-block-table tbody td[data-rere-label]::before {
		/* The column label the hidden header row no longer shows, read back from
		   the attribute route-coverage/render.php emits — the same approved
		   string the header renders, so no new reader-facing string exists here
		   (hard rule 2). The second `content` sets empty alternative text,
		   keeping the label out of the accessibility tree where the
		   columnheader already announces it; an engine without that syntax drops
		   the second declaration and keeps the label from the first. Identical
		   to the hub table's rule, and the attribute selector is what keeps the
		   two-column tables — which carry no such attribute — generating
		   nothing at all. */
		content: attr(data-rere-label);
		content: attr(data-rere-label) / "";
		display: block;
		color: var(--wp--preset--color--contrast-2);
		font-size: var(--wp--preset--font-size--sm);
	}
}
