/*
 * dP site chrome — the header, the mobile panel and the footer.
 *
 * A transcription of design-source/components/SiteHeader.dc.html and
 * SiteFooter.dc.html. As everywhere in this theme, the values are the design's
 * and only the delivery mechanism differs (CLAUDE.md §5); the file is written
 * against the design's own token names, and a --wp--preset--* name in here would
 * be a bug that assets/css/tokens.css exists to prevent.
 *
 * Two rules govern the whole file.
 *
 * **There is not one media query in it.** The design's Ledger rules them out and
 * digest §5.2 says where the thresholds actually are: they are component widths,
 * not viewport widths. `SiteHeader` switches at 720px of its own width, so
 * `.dp-header` is a container and everything that switches is a descendant of
 * it. A container cannot query itself, which is why the switch is always
 * expressed on children.
 *
 * **The mobile panel works with JavaScript switched off.** CLAUDE.md §1.7: every
 * page must be readable and navigable without it. A `<dialog>` that only opens
 * from `showModal()` fails that outright, so the panel opens from `:target` —
 * the hamburger is a real link to the panel's id, and the rule below overrides
 * the UA stylesheet's `display: none` on a closed dialog. assets/js/nav-panel.js
 * then upgrades it to a real modal, where the top layer gives Escape and the
 * focus trap for nothing. Both states are styled here; neither is the fallback
 * for the other's failure.
 */
/* stylelint-disable no-descending-specificity -- the rule compares only the last
   compound selector of a pair, so it reports every two unrelated components that
   happen to end in `a`, `p`, `li` or one of core's class names. Every finding in
   this file is a pair of that kind — a pagination link against a section head's
   action, a post row's `li` against a filter pill's — and no two of them can
   select the same element, so there is no cascade between them to get wrong.
   The rule stays on in blocks.css, where a post's blocks really do nest. */


/* -------------------------------------------------------------------------
 * Full-bleed chrome
 *
 * theme.json puts the gutter on the root, so `.wp-site-blocks` carries it and
 * `alignfull` is core's way back out to the viewport edge — which the header's
 * and the footer's rules need, since both draw a border across the whole
 * window. The block markup asks for `alignfull`; what is left here is the top
 * margin the root's blockGap would otherwise put above the footer. Two classes,
 * so it beats `.wp-site-blocks > *` on specificity rather than on load order.
 * ---------------------------------------------------------------------- */

.wp-site-blocks > .dp-footer,
.wp-site-blocks > .dp-header {
	margin-block-start: 0;
}

/* -------------------------------------------------------------------------
 * The brand mark
 *
 * `core/site-logo`, in all three places — the header bar, the mobile panel's
 * head, and the footer. It reads the `site_logo` option, so David swaps the
 * mark from the admin whenever he likes and nothing here has to change.
 *
 * This used to be a `background: url(…)` on a `core/site-title` whose text was
 * pushed off-screen, which meant the mark could only be changed by editing this
 * file and shipping a release. The image is now content; only its size is here.
 * `themes/dpaternina/assets/img/dp-mark-gradient-128.png` is still the default
 * and is still in the theme — `dp-core`'s seeder asks the theme for it through
 * `dp_brand_logo_path` and sets it as the site logo on a fresh site.
 *
 * The design's chrome uses the *gradient* mark, at 34px in the header and in
 * the mobile panel's head and at 30px, 0.85 opacity, in the footer.
 *
 * `design-source/assets/dp-mark-gradient*.png` is a broken export and stays
 * broken: both sizes carry only the top arc of the monogram. David supplied the
 * real file instead. It lives beside this stylesheet as
 * `assets/img/dp-mark-gradient.src.png` at 2000px, which is a master and not a
 * served asset; `dp-mark-gradient-128.png` is generated from it.
 * See assets/img/README.md.
 *
 * The white mark has not gone anywhere — `.dp-featured-art` still draws it over
 * the spectrum gradient, where a gradient mark on a gradient ground would not
 * read.
 *
 * Every selector below names `.wp-block-site-logo` as well as `.dp-brand`, for
 * the reason the button rules give: core's own block styles are
 * `.wp-block-site-logo img` and `.wp-block-site-logo.is-default-size img`, so a
 * rule at one or two classes here ties with them and is decided by load order —
 * which differs between the front end and the editor canvas (ADR-0008).
 * ---------------------------------------------------------------------- */

.dp-brand.wp-block-site-logo {
	margin: 0;
	flex: none;
	line-height: 0;
}

.dp-brand.wp-block-site-logo a {
	display: block;
	line-height: 0;
	text-decoration: none;
}

.dp-brand.wp-block-site-logo img {
	display: block;
	width: 34px;
	height: auto;
}

.dp-brand-sm.wp-block-site-logo img {
	width: 30px;
	opacity: 0.85;
}

/* -------------------------------------------------------------------------
 * Buttons
 *
 * The design's Button primitive. theme.json deliberately carries no button
 * styles — digest §5 says the primitives "become block styles and small
 * patterns" — so the appearance is here, on core's own `wp-element-button`
 * class, which every button block and every button-shaped link already has.
 *
 * **Each selector names an element or a second class on purpose.** Core's own
 * rule is `:root :where(.wp-element-button, .wp-block-button__link)`, which is
 * one pseudo-class of specificity — exactly the same as a bare
 * `.wp-element-button` here. Ties are broken by load order, the front end
 * prints the global styles first and the block editor injects them last, so a
 * one-class rule was teal on the site and core's default grey in the canvas.
 * That is the hazard ADR-0008 and the Phase 5b notes describe, and it applied
 * to every unadorned button on the site. The `.dp-button-*` variants below
 * already carry two classes, which is why only the base ever diverged.
 * ---------------------------------------------------------------------- */

a.wp-element-button,
button.wp-element-button,
input.wp-element-button,
.wp-block-button__link.wp-element-button {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: var(--control-gap-md);
	height: var(--control-h-md);
	padding: 0 20px;
	border: var(--border-width) solid transparent;
	border-radius: var(--radius-pill);
	background: var(--accent);
	box-shadow: var(--shadow-sm);
	color: var(--accent-contrast);
	font-family: var(--font-display);
	font-size: var(--fs-base);
	font-weight: var(--fw-semibold);
	line-height: 1;
	letter-spacing: var(--ls-tight);
	text-decoration: none;
	white-space: nowrap;
	transition:
		transform var(--dur-fast) var(--ease-standard),
		background var(--dur-base) var(--ease-standard),
		box-shadow var(--dur-base) var(--ease-standard),
		border-color var(--dur-base) var(--ease-standard);
}

a.wp-element-button:hover,
button.wp-element-button:hover,
input.wp-element-button:hover,
.wp-block-button__link.wp-element-button:hover {
	background: var(--accent-hover);
	box-shadow: var(--shadow-glow-teal);
	color: var(--accent-contrast);
}

a.wp-element-button:active,
button.wp-element-button:active,
input.wp-element-button:active,
.wp-block-button__link.wp-element-button:active {
	transform: scale(0.97);
}

.dp-button-secondary .wp-block-button__link {
	border-color: var(--border-strong);
	background: transparent;
	box-shadow: none;
	color: var(--text-primary);
}

.dp-button-secondary .wp-block-button__link:hover {
	border-color: var(--accent);
	background: color-mix(in srgb, var(--accent) 12%, transparent);
	box-shadow: none;
	color: var(--text-primary);
}

.dp-button-lg .wp-block-button__link {
	height: var(--control-h-lg);
	padding: 0 28px;
	font-size: var(--fs-md);
}

.dp-button-sm .wp-block-button__link {
	height: var(--target-min);
	padding: 0 14px;
	font-size: var(--fs-sm);
}

/* The design system's fourth Button variant, from Button.jsx: transparent, no
   border, `--text-secondary`, and a faint wash of the text colour on hover. The
   blog index's empty state is the only place the design reaches for it. */
.dp-button-ghost .wp-block-button__link {
	border-color: transparent;
	background: transparent;
	box-shadow: none;
	color: var(--text-secondary);
}

.dp-button-ghost .wp-block-button__link:hover {
	background: color-mix(in srgb, var(--text-primary) 8%, transparent);
	box-shadow: none;
	color: var(--text-secondary);
}

/* A link that is a link, not a button: the footer's columns and the design's
   mono caps "→" affordances. Same block, no chrome.

   It gives back one thing the pill above it needs and a span never has.
   `line-height: 1` centres a label inside a 44px control; on a control with
   `height: auto` it collapses the text box to the glyph size, which throws the
   baseline out in every flex row the design lines one up in — the work page's
   outro is one. The design declares no leading on any of these, so `normal` is
   what it renders (tests/e2e/design-parity.spec.ts, outro.action). */
.dp-button-quiet .wp-block-button__link {
	height: auto;
	padding: 0;
	border: 0;
	border-radius: 0;
	background: none;
	box-shadow: none;
	color: var(--text-secondary);
	font-family: var(--font-body);
	font-size: var(--fs-sm);
	font-weight: var(--fw-regular);
	line-height: normal;
	letter-spacing: var(--ls-normal);
	white-space: normal;
}

.dp-button-quiet .wp-block-button__link:hover {
	background: none;
	box-shadow: none;
	color: var(--text-primary);
}

/* One of the theme's three computed links, with nothing behind it yet: it keeps
   its button and loses its href (DP\Theme\Blocks\DerivedLink, ADR-0008).
   Dimmed and unclickable, so it reads as "not wired up" rather than as a link
   that does nothing. ADR-0018 narrowed this to those three — every other link
   on the site is one David set in the site editor, and an unset one is simply a
   button with no link, which is what the editor shows him too. */
.dp-destination-unset {
	cursor: default;

	/* The design system's own disabled opacity — Button.jsx, `opacity: 0.45`. */
	opacity: 0.45;
	pointer-events: none;
}

/* -------------------------------------------------------------------------
 * The mono caps label, used everywhere the design sets one
 *
 * `font-mono / fs-xs / ls-caps`, which is the triple the design repeats on
 * every label it draws. Only the colour varies by role, and it varies through
 * the tone classes in components.css rather than here: --text-muted is the
 * quiet-metadata default, and a label that carries meaning gets --hue-* or
 * --accent-text on top of it.
 *
 * Named by element as well as by class, which is not decoration. WordPress
 * emits `:root :where(p) { font-size: … }` for the global styles, and that is
 * one class of specificity — the same as a bare `.dp-label`, so which one wins
 * is decided by stylesheet order. The front end prints global styles first and
 * the block editor injects them last, so a single-class rule here is correct on
 * the site and silently overridden in the canvas. Every other component in this
 * theme is already written `p.dp-badge`, `h3.dp-tile-title`, `ul.dp-filter-pills`
 * for the same reason; this one was the exception.
 * ---------------------------------------------------------------------- */

p.dp-label,
span.dp-label {
	margin: 0;
	color: var(--text-muted);
	font-family: var(--font-mono);
	font-size: var(--fs-xs);
	line-height: normal;
	letter-spacing: var(--ls-caps);
	text-transform: uppercase;
}

/* -------------------------------------------------------------------------
 * Header
 * ---------------------------------------------------------------------- */

.dp-header {
	position: sticky;
	z-index: 30;
	top: 0;
	container: dp-header / inline-size;
	border-bottom: var(--border-width) solid var(--border-subtle);
	background: var(--bg-page);
}

/*
 * The gap, the margin and the padding on every rule from here down name a
 * second class or an element on purpose, and it is the same purpose the button
 * rules above give. Core emits its layout styles as
 * `:root :where(.is-layout-flex) { gap: … }` and
 * `:root :where(.is-layout-flow) > * { margin-block-start: … }`, both one class
 * of specificity — the same as a bare `.dp-header-bar` or `.dp-footer-bar` — so
 * a single-class rule here ties and is settled by load order. The front end
 * prints the global styles first and the block editor injects them last, so
 * every one of these was the design's value on the site and core's 24px block
 * gap in the canvas. ADR-0011 has the sweep; ADR-0008 has the mechanism.
 */
.dp-header-bar.wp-block-group {
	gap: var(--space-6);
	max-width: var(--container-lg);
	margin-inline: auto;
	padding-block: 12px;
	padding-inline: var(--gutter);
}

/*
 * The two selectors below are doubled deliberately. Core emits its own layout
 * rule for every flex group — `.wp-block-group-is-layout-flex { display: flex }`
 * and `.wp-block-buttons-is-layout-flex` likewise — at one class of
 * specificity, so a single-class rule here ties with it and loses or wins by
 * whichever stylesheet the page happened to print last. The header is the
 * container either way, so naming it costs nothing and settles it.
 */
.dp-header .dp-header-wide {
	gap: 12px;
	flex: 1 1 auto;
	justify-content: flex-end;
}

.dp-header .dp-header-toggle {
	display: none;
}

/* `nav` for the same reason the panel's rule below carries it: the container
   `<ul>` inherits this block's classes, and a sizing declaration meant for the
   row must not be read a second time by the list inside it. */
nav.dp-nav.wp-block-navigation {
	flex: 0 1 auto;
	gap: 0;
	font-size: var(--fs-sm);
}

.dp-nav .wp-block-navigation-item__content {
	position: relative;
	padding: 12px 16px;
	color: var(--text-secondary);
	font-weight: var(--fw-semibold);
	text-decoration: none;
	transition: color var(--dur-base) var(--ease-standard);
}

.dp-nav .wp-block-navigation-item__content:hover {
	color: var(--text-primary);
}

/* The active rule is derived in DP\Theme\Chrome\Navigation from the queried
   object — which is what makes Blog light up on a post, a category and a
   series as well as on the index itself (digest §2.1). Everything here reads
   the `aria-current` that derivation sets, so the marker and the underline
   cannot disagree with what a screen reader is told. */
.dp-nav .wp-block-navigation-item__content[aria-current] {
	color: var(--text-primary);
}

.dp-nav .wp-block-navigation-item__content[aria-current]::after {
	position: absolute;
	right: 16px;
	bottom: 4px;
	left: 16px;
	height: 2px;
	background: var(--dp-teal);
	content: "";
}

/* The hamburger. A link, because without JavaScript it navigates to the panel
   and that is how the panel opens; the icon is drawn rather than shipped so
   there is no second request for 20 pixels of chrome. */
.dp-menu-open .wp-block-button__link,
.dp-menu-close .wp-block-button__link {
	overflow: hidden;
	width: var(--target-comfortable);
	height: var(--target-comfortable);
	padding: 0;
	border: var(--border-width) solid var(--border-subtle);
	border-radius: var(--radius-circle);

	/*
	 * The glyph is a mask rather than an image, so the stroke is
	 * `currentColor` and the icon's colour stays a token. A data URI cannot
	 * read a custom property, and hardcoding the hex here would put a colour
	 * outside design-source/ (CLAUDE.md §5).
	 */
	background-color: currentcolor;
	box-shadow: none;
	color: var(--text-primary);
	mask-position: center;
	mask-repeat: no-repeat;
	mask-size: 20px 20px;
	text-indent: -100vw;
	transition: border-color var(--dur-base) var(--ease-standard), color var(--dur-base) var(--ease-standard);
}

.dp-menu-open .wp-block-button__link {
	mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='2' stroke-linecap='round'%3E%3Cpath d='M4 7h16'/%3E%3Cpath d='M4 12h16'/%3E%3Cpath d='M4 17h16'/%3E%3C/svg%3E");
}

.dp-menu-close .wp-block-button__link {
	mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='2' stroke-linecap='round'%3E%3Cpath d='M18 6 6 18'/%3E%3Cpath d='m6 6 12 12'/%3E%3C/svg%3E");
}

.dp-menu-open .wp-block-button__link:hover,
.dp-menu-close .wp-block-button__link:hover {
	border-color: var(--accent-text);
	background-color: currentcolor;
	box-shadow: none;
	color: var(--accent-text);
}

/* -------------------------------------------------------------------------
 * The 720px switch
 *
 * digest §5.2: `SiteHeader` — 720px — hamburger to full-screen panel. The
 * container is `.dp-header`; every rule below styles one of its descendants,
 * because an element cannot answer a query about itself.
 * ---------------------------------------------------------------------- */

@container dp-header (width < 720px) {

	.dp-header .dp-header-wide {
		display: none;
	}

	.dp-header .dp-header-toggle {
		display: flex;
	}

	/* Only inside the narrow container. Without this bound, landing on the
	   panel's URL fragment at 1400px would open a full-screen menu over a page
	   that already has a nav bar. The `[open]` state below needs no such guard:
	   nothing opens it but the hamburger, and the hamburger is not here. */
	.dp-panel:target {
		display: flex;
	}
}

/* -------------------------------------------------------------------------
 * The panel
 * ---------------------------------------------------------------------- */

dialog.dp-panel {
	position: fixed;
	z-index: 40;
	inset: 0;
	display: none;
	overflow: hidden;
	width: 100%;
	max-width: none;
	height: 100%;
	max-height: none;
	flex-direction: column;
	margin: 0;
	padding: 0;
	border: 0;
	background: var(--bg-page);
	color: var(--text-primary);
}

.dp-panel[open] {
	display: flex;
	animation: dp-panel-in var(--dur-base) var(--ease-out) both;
}

.dp-panel::backdrop {
	background: var(--bg-page);
}

@keyframes dp-panel-in {

	from {
		opacity: 0;
		transform: translateY(-8px);
	}

	to {
		opacity: 1;
		transform: none;
	}
}

.dp-panel-head {
	flex: none;
	padding-block: 12px;
	padding-inline: var(--gutter);
	border-bottom: var(--border-width) solid var(--border-subtle);
}

/*
 * `nav`, and the element selector is load-bearing.
 *
 * `core/navigation` stamps the block's whole class list onto the container
 * `<ul>` as well as onto the `<nav>`, so `.dp-panel-nav.wp-block-navigation`
 * matches both — and every declaration below is one that must not apply twice.
 * The list would take the gutter a second time (the items sat indented past
 * everything else in the panel), open a second scroller inside the first, and
 * grow to fill.
 *
 * That last one is what tore the menu apart. A menu carrying anything that is
 * not a navigation item renders as more than one `<ul>` — core closes the list
 * around whatever else is in there — and `flex: 1 1 auto` on each of them
 * splits the panel's height between them, which drew three links spread over a
 * whole phone screen with the gaps in between.
 */
nav.dp-panel-nav.wp-block-navigation {
	flex: 1 1 auto;
	min-height: 0;
	overflow-y: auto;
	padding-block: 8px 24px;
	padding-inline: var(--gutter);
	gap: 0;
}

.dp-panel-nav .wp-block-navigation__container {
	width: 100%;
	gap: 0;
}

.dp-panel-nav .wp-block-navigation-item {
	width: 100%;
}

/* `flex: 1 1 auto` because core makes the `<li>` a flex row, which leaves the
   anchor shrink-wrapped around its own label: the rule under each item stopped
   at the end of the word and `space-between` had no space to work with, so the
   HERE marker sat against the label instead of at the panel's edge. */
.dp-panel-nav .wp-block-navigation-item__content {
	display: flex;
	flex: 1 1 auto;
	align-items: center;
	justify-content: space-between;
	gap: 16px;
	min-height: var(--target-comfortable);
	padding-block: 16px;
	border-bottom: var(--border-width) solid var(--border-subtle);
	color: var(--text-primary);
	font-family: var(--font-display);
	font-size: var(--fs-xl);
	font-weight: var(--fw-bold);
	letter-spacing: var(--ls-tight);
	text-decoration: none;
}

.dp-panel-nav .wp-block-navigation-item__content[aria-current] {
	color: var(--accent);
}

/* The design's HERE marker. It is decoration, deliberately: `aria-current`
   already tells assistive technology which item this is, so drawing the word
   from CSS says the same thing to the eye without saying it twice to a screen
   reader. */
.dp-panel-nav .wp-block-navigation-item__content[aria-current]::after {
	color: var(--accent-text);
	content: "HERE";
	font-family: var(--font-mono);
	font-size: var(--fs-xs);
	font-weight: var(--fw-regular);
	letter-spacing: var(--ls-caps);
}

.dp-panel-foot {
	display: flex;
	flex: none;
	flex-direction: column;
	gap: 16px;
	padding-block: 20px calc(24px + env(safe-area-inset-bottom, 0px));
	padding-inline: var(--gutter);
	border-top: var(--border-width) solid var(--border-subtle);
}

.dp-panel-foot .wp-block-button__link {
	height: var(--control-h-lg);
	font-size: var(--fs-md);
}

p.dp-panel-wordmark {
	margin: 0;
	color: var(--text-muted);
	font-family: var(--font-mono);
	font-size: var(--fs-xs);
	letter-spacing: var(--ls-caps);
	text-transform: uppercase;
}

/* Scroll lock. The class is set by assets/js/nav-panel.js; without JavaScript
   the panel covers the page instead, which is the same outcome by a cruder
   route. */
.dp-panel-open {
	overflow: hidden;
}

/* -------------------------------------------------------------------------
 * Footer
 * ---------------------------------------------------------------------- */

.dp-footer {
	border-top: var(--border-width) solid var(--border-subtle);
	background: var(--band);
}

/*
 * Every child of the grid, of the footer itself, and of each column carries the
 * design's own spacing — the grid's `gap`, the columns' `gap`, the bar's
 * `border-top`. Core's block gap adds a second one on top of all three, which
 * showed as 24px of dead ground above the bottom bar and as a 64px row gap
 * whenever the columns wrapped. The design has no margins anywhere in this
 * stack.
 */
.dp-footer.wp-block-group > *,
.dp-footer-grid.wp-block-group > *,
.dp-footer-brand.wp-block-group > *,
.dp-footer-group.wp-block-group > * {
	margin-block-start: 0;
}

.dp-footer-grid {
	display: grid;
	max-width: var(--container-lg);
	margin-inline: auto;
	padding-block: 56px 32px;
	padding-inline: var(--gutter);
	gap: 40px 32px;
	grid-template-columns: repeat(auto-fit, minmax(min(180px, 100%), 1fr));
}

/*
 * The one place this footer is not a transcription, and the reason is that the
 * design has nothing to transcribe here: `SiteFooter.dc.html` states the track
 * above and stops, so what a phone gets is whatever `auto-fit` decides. Two
 * 180px tracks and the 32px between them want 392px; a 390px phone has 351px
 * inside the gutter, so it misses by 41 and every group becomes a full-width
 * row. That is four stacked rows 40px apart under 56px of padding — a footer
 * 654px tall on an 844px screen, most of it empty.
 *
 * Two even columns instead, with the brand across the top of them: 451px, and
 * the same words. Held behind a query the design's own breakpoint never
 * reaches, so the layout it *did* draw is untouched at every width it drew.
 */
@media (max-width: 599px) {

	.dp-footer-grid {
		padding-block: 40px 24px;
		gap: 32px 24px;
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}

	.dp-footer-brand {
		grid-column: 1 / -1;
	}
}

.dp-footer-brand,
.dp-footer-group {
	display: flex;
	flex-direction: column;
	gap: 12px;
}

.dp-footer-brand {
	gap: 16px;
}

p.dp-footer-line {
	max-width: 26ch;
	margin: 0;
	color: var(--text-secondary);
	font-size: var(--fs-sm);
	line-height: var(--lh-relaxed);
}

/*
 * The footer's three groups are ordinary links, not a menu. Digest §2 lists
 * them as SITE / WRITING / MORE, and there was once one `core/navigation` block
 * with no `ref` in the first group — which meant the footer could only ever show
 * the same menu as the header, and the third group did not exist. A per-group
 * menu is not available to a theme: `ref` is a post ID, a template file cannot
 * name one, and a filter that supplies it on the server leaves the block editor
 * drawing a different menu from the one the front end renders. ADR-0011.
 *
 * Each is a `core/button` David gives a link, in the site editor, once
 * (ADR-0018). The theme ships the words and the styling and no URL.
 */
.dp-footer-links .wp-block-button__link,
.dp-footer-cats a {
	color: var(--text-secondary);
	font-size: var(--fs-sm);
	text-decoration: none;
	transition: color var(--dur-base) var(--ease-standard);
}

.dp-footer-links .wp-block-button__link:hover,
.dp-footer-cats a:hover {
	color: var(--text-primary);
}

/*
 * Scoped by its column rather than named by its element. `core/categories`
 * renders a `<ul>` today and a `<div>` wrapping a `<select>` the moment the
 * dropdown variant is chosen, and the block editor draws a placeholder of its
 * own while it fetches the terms — so `ul.dp-footer-cats` is a rule that is
 * right most of the time. Two classes reach every one of those shapes, and
 * still beat core's block gap.
 */
.dp-footer-group .dp-footer-cats {
	display: flex;
	flex-direction: column;
	gap: 12px;
	margin: 0;
	padding: 0;
	list-style: none;
}

.dp-footer-links.wp-block-buttons {
	gap: 12px;
}

.dp-footer-bar.wp-block-group {
	gap: 12px 24px;
	max-width: var(--container-lg);
	margin-inline: auto;
	padding-block: 20px 40px;
	padding-inline: var(--gutter);
	border-top: var(--border-width) solid var(--border-subtle);
	align-items: center;
}

/*
 * A group rather than one row of buttons, because one of the three links is not
 * a `core/button` at all: RSS is `dpaternina/feed-link`, which renders its own
 * `wp-block-buttons` wrapper (ADR-0018), and `core/buttons` admits `core/button`
 * and nothing else. So Privacy and Colophon share a `wp:buttons` and the feed
 * sits beside it, with the same 20px between all three either way.
 */
.dp-footer-meta.wp-block-group,
.dp-footer-meta .wp-block-buttons {
	gap: 20px;
}

.dp-footer-meta .wp-block-button__link {
	color: var(--text-muted);
	font-family: var(--font-mono);
	font-size: var(--fs-xs);
	letter-spacing: var(--ls-caps);
	text-transform: uppercase;
}

.dp-footer-meta .wp-block-button__link:hover {
	color: var(--text-secondary);
}
