/*
Theme Name: Codex Memoria
Theme URI: https://codex-memoria-wp.kaz.bzh/
Description: Thème de l'association Codex Memoria, enfant de Twenty Twenty-Five : identité « page annotée », typographies auto-hébergées, modes sombre et contraste renforcé.
Author: Codex Memoria
Template: twentytwentyfive
Version: 1.0.0
Requires at least: 7.1
Requires PHP: 7.4
License: GNU Affero General Public License v3
License URI: https://www.gnu.org/licenses/agpl-3.0.html
Text Domain: codex-memoria
*/

/*
 * Color modes. theme.json holds the light palette; dark and high-contrast modes
 * swap the same preset variables, so every block follows without per-block rules.
 * `html:root` outranks the `:root` rule printed by global styles.
 */
@media (prefers-color-scheme: dark) {
	html:root {
		--wp--preset--color--base: #0D1A26;
		--wp--preset--color--surface: #152434;
		--wp--preset--color--contrast: #E4EDF2;
		--wp--preset--color--soft: #A7B6C2;
		--wp--preset--color--line: #24384A;
		--wp--preset--color--primary: #4FC1C6;
		--wp--preset--color--on-primary: #0D1A26;
		--wp--preset--color--primary-soft: #15323A;
		--wp--preset--color--rubric: #E8A15A;
		--wp--preset--color--accent-1: #15323A;
		--wp--preset--color--accent-2: #152434;
		--wp--preset--color--accent-3: #4FC1C6;
		--wp--preset--color--accent-4: #A7B6C2;
		--wp--preset--color--accent-5: #152434;
		--wp--preset--color--accent-6: #24384A;
		color-scheme: dark;
	}
}

/*
 * High contrast wins over dark: chosen with the header toggle, or requested by the OS.
 * The two blocks are identical because CSS cannot share declarations between a selector and a media query.
 */
html:root[data-contrast="more"] {
	--wp--preset--color--base: #FFFFFF;
	--wp--preset--color--surface: #FFFFFF;
	--wp--preset--color--contrast: #0B0B0B;
	--wp--preset--color--soft: #333333;
	--wp--preset--color--line: #0B0B0B;
	--wp--preset--color--primary: #0B5357;
	--wp--preset--color--on-primary: #FFFFFF;
	--wp--preset--color--primary-soft: #E6F2F2;
	--wp--preset--color--brand: #0B5357;
	--wp--preset--color--rubric: #9A2A12;
	--wp--preset--color--accent-1: #E6F2F2;
	--wp--preset--color--accent-2: #FFFFFF;
	--wp--preset--color--accent-3: #0B5357;
	--wp--preset--color--accent-4: #333333;
	--wp--preset--color--accent-5: #FFFFFF;
	--wp--preset--color--accent-6: #0B0B0B;
	color-scheme: light;
}

@media (prefers-contrast: more) {
	html:root:not([data-contrast="normal"]) {
		--wp--preset--color--base: #FFFFFF;
		--wp--preset--color--surface: #FFFFFF;
		--wp--preset--color--contrast: #0B0B0B;
		--wp--preset--color--soft: #333333;
		--wp--preset--color--line: #0B0B0B;
		--wp--preset--color--primary: #0B5357;
		--wp--preset--color--on-primary: #FFFFFF;
		--wp--preset--color--primary-soft: #E6F2F2;
		--wp--preset--color--brand: #0B5357;
		--wp--preset--color--rubric: #9A2A12;
		--wp--preset--color--accent-1: #E6F2F2;
		--wp--preset--color--accent-2: #FFFFFF;
		--wp--preset--color--accent-3: #0B5357;
		--wp--preset--color--accent-4: #333333;
		--wp--preset--color--accent-5: #FFFFFF;
		--wp--preset--color--accent-6: #0B0B0B;
		color-scheme: light;
	}
}

/* Readability rule from the identity guide: no justified body paragraphs. */
p {
	text-align: start;
	text-wrap: pretty;
}

h1,
h2,
h3,
h4,
.wp-block-post-title {
	text-wrap: balance;
}

/* A long French compound wraps mid-word rather than overflow at 320px; hyphens appear only where typed (&shy;). */
h1,
h2,
h3,
h4 {
	overflow-wrap: break-word;
	hyphens: manual;
}

li,
figcaption,
.wp-block-post-excerpt__excerpt {
	text-wrap: pretty;
}

::selection {
	background: var(--wp--preset--color--primary-soft);
	color: var(--wp--preset--color--contrast);
}

/* Display size, reserved for the home manifesto: at 72px it needs tighter leading than the 52px page titles. */
.has-display-font-size {
	line-height: 1.04;
	letter-spacing: -0.015em;
}

/* Focus ring: a token per surface, so the ring contrasts with what surrounds the control (WCAG 2.4.7, 1.4.11). */
:root {
	--cm-focus: var(--wp--preset--color--contrast);
}

/* Set on the children, so a control that carries the surface class itself keeps the ring of the surface around it. */
.has-contrast-background-color > * {
	--cm-focus: var(--wp--preset--color--base);
}

.has-primary-background-color > * {
	--cm-focus: var(--wp--preset--color--on-primary);
}

/* :root lifts specificity to (0,2,0), above the theme.json button :focus rule whatever the load order. */
:root :where(a, button, input, select, textarea, summary, [tabindex]:not([tabindex="-1"])):focus-visible {
	outline: 2px solid var(--cm-focus);
	outline-offset: 3px;
}

/* The theme.json button :focus and the parent's .wp-site-blocks :focus rules also match mouse clicks. */
:root :focus:not(:focus-visible) {
	outline: none;
}

/* Skip link: core prints it server-side, so it works without JS; this restyles core's #eee box in the identity. */
:root .skip-link.screen-reader-text:focus {
	top: 12px;
	left: 12px;
	/* Core's .screen-reader-text keeps margin: -1px in its :focus state, which would shift the box to (11, 11). */
	margin: 0;
	display: inline-flex;
	align-items: center;
	min-height: 44px;
	padding: 0 16px;
	border-radius: 4px;
	background: var(--wp--preset--color--contrast);
	color: var(--wp--preset--color--base);
	font-family: var(--wp--preset--font-family--mono);
	font-size: var(--wp--preset--font-size--x-small);
	letter-spacing: 0.06em;
	text-transform: uppercase;
	z-index: 100001;
}

a {
	text-underline-offset: 4px;
	text-decoration-thickness: 1px;
}

/*
 * State grammar: hover thickens a link or fills a button with ink, the current page is a 2px teal underline,
 * a press sinks 1px. Hover stays behind (hover: hover) so nothing sticks after a tap, which is why theme.json
 * restates the resting style on :hover. The parent sets a { text-decoration-thickness: 1px !important },
 * so every thickness here is !important too.
 */
@media (hover: hover) {
	a:where(:not(.wp-element-button)):hover {
		text-decoration-thickness: 2px !important;
	}

	.wp-block-post-title a:hover,
	.wp-block-breadcrumbs a:hover {
		text-decoration-line: underline;
	}

	.wp-element-button:hover {
		background-color: var(--wp--preset--color--contrast);
		color: var(--wp--preset--color--base);
	}

	.wp-block-button.is-style-outline > .wp-element-button:hover {
		border-color: var(--wp--preset--color--contrast);
		background-color: var(--wp--preset--color--contrast);
		color: var(--wp--preset--color--base);
	}

	.has-contrast-background-color .wp-block-button.is-style-outline > .wp-element-button:hover {
		border-color: var(--wp--preset--color--base);
		background-color: var(--wp--preset--color--base);
		color: var(--wp--preset--color--contrast);
	}
}

.wp-element-button:active,
.cm-contrast-toggle:active {
	translate: 0 1px;
}

@media (prefers-reduced-motion: no-preference) {
	.wp-element-button,
	.cm-contrast-toggle,
	.wp-block-group.is-style-card {
		transition-property: background-color, border-color, color, translate;
		transition-duration: 120ms;
		transition-timing-function: ease-out;
	}
}

@media (prefers-reduced-motion: reduce) {
	*,
	*::before,
	*::after {
		animation: none !important;
		transition: none !important;
		scroll-behavior: auto !important;
	}
}

/* Logo: inline SVG painted from the palette, so it follows every color mode. */
.cm-logo {
	display: inline-flex;
	align-items: center;
	color: inherit;
	text-decoration: none;
}

.cm-logo svg {
	display: block;
	height: 56px;
	width: auto;
}

.cm-logo .ink {
	fill: var(--wp--preset--color--contrast);
}

.cm-logo .brand {
	fill: var(--wp--preset--color--brand);
}

.cm-logo--mark svg {
	height: 64px;
}

/* Header: one row at every width; sticky, so anchors and focus use the scroll padding below. */
:root {
	--cm-header-bar: 72px;
}

.wp-site-blocks > header.wp-block-template-part {
	position: sticky;
	top: var(--wp-admin--admin-bar--height, 0px);
	z-index: 20;
}

.cm-header {
	border-bottom: 1px solid var(--wp--preset--color--line);
	background: var(--wp--preset--color--base);
}

.cm-header__bar {
	min-block-size: var(--cm-header-bar);
}

/* Anchors and keyboard focus land below the sticky bar (WCAG 2.4.11). */
html {
	scroll-padding-top: calc(var(--cm-header-bar) + 1px + var(--wp-admin--admin-bar--height, 0px) + var(--wp--preset--spacing--30));
}

/* The inline row needs about 880px; core only switches to the overlay below 600px. CSS cannot read a custom property in a media query. */
@media (max-width: 959px) {
	.cm-header .wp-block-navigation__responsive-container-open:not(.always-shown) {
		display: inline-flex;
	}

	.cm-header .wp-block-navigation__responsive-container:not(.hidden-by-default):not(.is-menu-open) {
		display: none;
	}
}

@media (max-width: 599px) {
	:root {
		--cm-header-bar: 64px;
	}

	/* The overlay carries Adhérer on phones. Core's .wp-block-buttons.is-layout-flex (0,2,0) sets display: flex. */
	.cm-header .cm-header__cta {
		display: none;
	}

	.cm-header .cm-logo svg {
		height: 44px;
	}
}

/* Up to 600px core positions the admin bar absolute, so it scrolls away and the bar sticks to the top. */
@media (max-width: 600px) {
	.admin-bar .wp-site-blocks > header.wp-block-template-part {
		top: 0;
	}
}

/* Short viewports (landscape phones, 400% zoom): a sticky bar would eat the page (WCAG 1.4.10). */
@media (max-height: 30em) {
	.wp-site-blocks > header.wp-block-template-part {
		position: static;
	}

	html {
		scroll-padding-top: var(--wp--preset--spacing--30);
	}
}

/* "Menu" and "Fermer" share one style so the label swaps in place.
   Each selector outweighs its core rule whatever the load order: the open button's tripled class (0,3,0), the close reset (0,1,0). */
:root .cm-header .wp-block-navigation__responsive-container-open:not(.always-shown),
.cm-overlay .cm-overlay__close {
	align-items: center;
	min-block-size: 44px;
	padding-inline: 14px;
	border: 1px solid currentColor;
	border-radius: 4px;
	font-family: var(--wp--preset--font-family--mono);
	font-size: var(--wp--preset--font-size--x-small);
	letter-spacing: 0.06em;
	text-transform: uppercase;
}

/* Menu hover keeps a 1px ink underline: !important lets it outweigh the 2px link hover, itself !important. */
.cm-header .wp-block-navigation-item__content {
	display: inline-flex;
	align-items: center;
	min-height: 44px;
	text-decoration-line: none;
	text-decoration-thickness: 1px !important;
	text-underline-offset: 8px;
}

/* aria-current is the source of truth, so the visual state and assistive tech always agree. */
.cm-header .wp-block-navigation-item__content[aria-current="page"] {
	text-decoration-line: underline;
	text-decoration-thickness: 2px !important;
	text-decoration-color: var(--wp--preset--color--primary);
}

@media (hover: hover) {
	.cm-header .wp-block-navigation-item__content:hover {
		text-decoration-line: underline;
	}
}

/* Mobile menu (parts/navigation-overlay.html): its bar mirrors the header bar, so "Menu" becomes "Fermer" in place. */
.cm-overlay {
	min-block-size: 100dvh;
}

/* The overlay renders inside the padded header, so core zeroes the global padding its constrained groups would get. */
.cm-overlay__bar,
.cm-overlay__body {
	padding-inline: var(--wp--style--root--padding-left) var(--wp--style--root--padding-right);
}

/* The header draws its rule below the bar's height, so the overlay bar adds it to keep the logo in place. */
.cm-overlay__bar {
	min-block-size: calc(var(--cm-header-bar) + 1px);
	border-bottom: 1px solid var(--wp--preset--color--line);
}

/* Core gives the open button color: currentColor but leaves the close button on the user-agent button colour. */
.cm-overlay .cm-overlay__close {
	color: inherit;
}

/* Menu rows: the numbered gutter of the hero, one line number per destination. */
.cm-overlay__nav .wp-block-navigation__container {
	counter-reset: cm-nav;
	inline-size: 100%;
	gap: 0;
	border-top: 1px solid var(--wp--preset--color--line);
}

.cm-overlay__nav .wp-block-navigation-item {
	counter-increment: cm-nav;
	inline-size: 100%;
	border-bottom: 1px solid var(--wp--preset--color--line);
}

.cm-overlay__nav .wp-block-navigation-item__content {
	display: grid;
	grid-template-columns: 40px 1fr;
	column-gap: 16px;
	align-items: center;
	inline-size: 100%;
	min-block-size: 60px;
	font-family: var(--wp--preset--font-family--heading);
	font-size: var(--wp--preset--font-size--x-large);
	font-weight: 600;
	line-height: 1.2;
	text-decoration: none;
}

/* The header underlines its current and hovered links (0,3,0); here § marks the current row and hover underlines the label. */
.cm-overlay__nav :is(.wp-block-navigation-item__content[aria-current="page"], .wp-block-navigation-item__content:hover) {
	text-decoration: none;
}

/* The stretched gutter cell draws one continuous rule across the rows; the empty alt text keeps the number silent. */
.cm-overlay__nav .wp-block-navigation-item__content::before {
	content: counter(cm-nav, decimal-leading-zero);
	content: counter(cm-nav, decimal-leading-zero) / "";
	align-self: stretch;
	display: flex;
	align-items: center;
	justify-content: flex-end;
	padding-inline-end: 12px;
	border-inline-end: 1px solid var(--wp--preset--color--line);
	font-family: var(--wp--preset--font-family--mono);
	font-size: 13px;
	font-weight: 400;
	color: var(--wp--preset--color--soft);
}

.cm-overlay__nav .wp-block-navigation-item__content[aria-current="page"]::before {
	content: "§";
	content: "§" / "";
	color: var(--wp--preset--color--rubric);
}

@media (hover: hover) {
	.cm-overlay__nav .wp-block-navigation-item__content:hover .wp-block-navigation-item__label {
		text-decoration: underline 1px;
		text-underline-offset: 6px;
	}
}

.cm-overlay__actions .wp-block-button__link {
	inline-size: 100%;
	justify-content: center;
}

.cm-contrast-toggle {
	position: relative;
	flex: none;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 44px;
	height: 44px;
	padding: 0;
	border: 1.5px solid currentColor;
	border-radius: 50%;
	background: transparent;
	color: var(--wp--preset--color--contrast);
	cursor: pointer;
}

.cm-contrast-toggle[aria-pressed="true"] {
	background: var(--wp--preset--color--contrast);
	color: var(--wp--preset--color--base);
}

/* The label names the button and doubles as its tooltip; clip-path hides it visually but keeps it in the accessibility tree. */
.cm-contrast-toggle__label {
	position: absolute;
	top: calc(100% + 8px);
	right: 0;
	z-index: 30;
	padding: 6px 10px;
	border-radius: 3px;
	background: var(--wp--preset--color--contrast);
	color: var(--wp--preset--color--base);
	font-family: var(--wp--preset--font-family--mono);
	font-size: 13px;
	line-height: 1.4;
	white-space: nowrap;
	clip-path: inset(50%);
	pointer-events: none;
}

/* Bridge over the 8px gap, so the pointer can move onto the tooltip (WCAG 1.4.13 hoverable). */
.cm-contrast-toggle__label::before {
	content: "";
	position: absolute;
	inset: -8px 0 100%;
}

.cm-contrast-toggle:focus-visible:not([data-tip="hidden"]) .cm-contrast-toggle__label {
	clip-path: none;
	pointer-events: auto;
}

@media (hover: hover) {
	.cm-contrast-toggle:hover:not([data-tip="hidden"]) .cm-contrast-toggle__label {
		clip-path: none;
		pointer-events: auto;
	}
}

/* Forced colours drop the pressed fill; system colours keep the state visible. */
@media (forced-colors: active) {
	.cm-contrast-toggle[aria-pressed="true"] {
		forced-color-adjust: none;
		border-color: Highlight;
		background: Highlight;
		color: HighlightText;
	}

	/* The forced Canvas fill matches the page, so a border outlines the tooltip. */
	.cm-contrast-toggle__label {
		border: 1px solid CanvasText;
	}
}

/* Footer: columns of bare link lists, each link a 44px target. */
.cm-footer-links {
	margin: 0;
	padding: 0;
	list-style: none;
}

/* The parent theme.json spaces every list item 0.5rem apart; here the 44px boxes alone set the rhythm. */
.cm-footer-links > li {
	margin-block: 0;
}

.cm-footer-links a,
.cm-footer__legal a {
	display: inline-flex;
	align-items: center;
	min-block-size: 44px;
}

.cm-footer-links a {
	color: var(--wp--preset--color--contrast);
	text-decoration: none;
}

@media (hover: hover) {
	.cm-footer-links a:hover {
		text-decoration-line: underline;
	}
}

/* Running-text link in the soft ink: the underline is its non-colour cue (WCAG 1.4.1). */
.cm-footer__legal a {
	color: inherit;
	text-decoration-line: underline;
}

/* Mono voices: rubric marks sections (amber), label names things (uppercase), tag qualifies (chip). */

/* Block style: rubric, the mono section label ("§ 02", "Association loi 1901"). */
.is-style-rubric {
	font-family: var(--wp--preset--font-family--mono);
	font-size: var(--wp--preset--font-size--x-small);
	letter-spacing: 0.06em;
	color: var(--wp--preset--color--rubric);
}

/* Block style: label, the uppercase mono name of a column or a field. */
.is-style-label {
	font-family: var(--wp--preset--font-family--mono);
	font-size: var(--wp--preset--font-size--xx-small);
	font-weight: 400;
	line-height: 1.5;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--wp--preset--color--soft);
}

/* Block style: tag, a small mono chip for licence, platform or version. */
.is-style-tag {
	display: inline-block;
	padding: 3px 8px;
	border: 1px solid var(--wp--preset--color--line);
	border-radius: 3px;
	font-family: var(--wp--preset--font-family--mono);
	font-size: var(--wp--preset--font-size--xx-small);
	line-height: 1.5;
}

/* Block style: card. Flat surface, hairline border, no shadow (identity rule). */
.wp-block-group.is-style-card {
	position: relative;
	padding: clamp(24px, 3vw, 36px);
	border: 1px solid var(--wp--preset--color--line);
	border-radius: 6px;
	background: var(--wp--preset--color--surface);
}

.wp-block-group.is-style-card.has-primary-soft-background-color {
	border-color: var(--wp--preset--color--primary);
}

/* Drawn arrow: no shipped font has U+2192, so a typed → renders from a system fallback. */
:root {
	--cm-arrow: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M2 8h11M9 4l4 4-4 4' fill='none' stroke='%23000' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}

/*
 * Block style: arrow, a standalone link to a listing, sized as a 44px target. A block box, not a flex one, so the
 * arrow follows the last word when the label wraps instead of standing alone at the right edge.
 */
.is-style-arrow a {
	display: inline-block;
	min-block-size: 44px;
	padding-block: calc((44px - 1lh) / 2);
	box-sizing: border-box;
	font-weight: 700;
}

.is-style-arrow a::after {
	display: inline-block;
	margin-inline-start: 0.4em;
	vertical-align: middle;
}

/* The SVG only masks: the arrow is painted with currentColor, so it follows the link in every mode and on the ink band. */
.is-style-arrow a::after,
.wp-block-post-navigation-link :is(.wp-block-post-navigation-link__arrow-previous, .wp-block-post-navigation-link__arrow-next) {
	content: "";
	inline-size: 1em;
	block-size: 1em;
	flex: none;
	background: currentColor;
	mask: var(--cm-arrow) center / contain no-repeat;
	transition: translate 150ms ease-out;
}

/*
 * Core types the arrow glyph in an aria-hidden span; a zero font size hides it, so sizes are set in rem.
 * It also collapses core's 1ch spacing and baseline alignment, hence the explicit margin and middle alignment.
 */
.wp-block-post-navigation-link :is(.wp-block-post-navigation-link__arrow-previous, .wp-block-post-navigation-link__arrow-next) {
	display: inline-block;
	font-size: 0;
	inline-size: 1rem;
	block-size: 1rem;
	vertical-align: middle;
}

.wp-block-post-navigation-link .wp-block-post-navigation-link__arrow-previous {
	margin-inline-end: 0.5rem;
	scale: -1 1;
}

.wp-block-post-navigation-link .wp-block-post-navigation-link__arrow-next {
	margin-inline-start: 0.5rem;
}

/*
 * Post neighbours: with linkLabel, core puts the label and the title inside the link, so both name it; the label is
 * the mono mention above the underlined title, and the link a 44px target like the other navigation controls.
 */
.wp-block-post-navigation-link {
	display: flex;
	align-items: center;
}

.wp-block-post-navigation-link a {
	display: inline-flex;
	flex-direction: column;
	justify-content: center;
	min-block-size: 44px;
	text-decoration-line: none;
}

.wp-block-post-navigation-link .post-navigation-link__label {
	font-family: var(--wp--preset--font-family--mono);
	font-size: var(--wp--preset--font-size--x-small);
	color: var(--wp--preset--color--soft);
}

.wp-block-post-navigation-link .post-navigation-link__title {
	text-decoration-line: underline;
	text-decoration-thickness: 1px;
}

@media (hover: hover) {
	.wp-block-post-navigation-link a:hover .post-navigation-link__title {
		text-decoration-thickness: 2px;
	}
}

@media (hover: hover) {
	.is-style-arrow a:hover::after {
		translate: 3px 0;
	}
}

.is-style-arrow a:focus-visible::after {
	translate: 3px 0;
}

/* Forced colours replace backgrounds with Canvas, which would erase a background painted through a mask. */
@media (forced-colors: active) {
	.is-style-arrow a::after,
	.wp-block-post-navigation-link :is(.wp-block-post-navigation-link__arrow-previous, .wp-block-post-navigation-link__arrow-next) {
		forced-color-adjust: none;
		background: LinkText;
	}
}

/*
 * Margin geometry shared by the hero gutter and every folio: rule at 52px, text at 72px from the wide edge. The folio
 * wide size is set at the root, so the page editor, which shows no folio, can take it too (functions.php).
 */
:root {
	--cm-gutter: 72px;
	--cm-gutter-rule: 52px;
	--cm-folio-wide: 53rem;
}

/* Below the core 782px breakpoint the rule stays as the mobile signature; numbers move inline. */
@media (max-width: 781px) {
	:root {
		--cm-gutter: 17px;
		--cm-gutter-rule: 0px;
	}
}

.wp-block-group.is-style-gutter,
.cm-folio {
	position: relative;
	padding-inline-start: var(--cm-gutter);
}

.wp-block-group.is-style-gutter::before,
.cm-folio::before {
	content: "";
	position: absolute;
	inset-block: 0;
	border-inline-start: 1px solid var(--wp--preset--color--line);
}

.wp-block-group.is-style-gutter::before {
	inset-inline-start: var(--cm-gutter-rule);
}

/*
 * Folio: every page sets its text from the gutter of the wide container, the edge the home hero and the news indexes
 * share, so content keeps one left edge across the site; the room right of the measure is the margin column.
 */
.cm-folio {
	isolation: isolate;
}

/* The rule passes behind the plates. */
.cm-folio::before {
	z-index: -1;
	inset-inline-start: var(--cm-gutter-rule);
}

/*
 * Only the post content breaks out, up to the folio wide size; a custom property, so the constrained sections nested
 * in it inherit it.
 */
.cm-folio > .wp-block-post-content {
	--wp--style--global--wide-size: var(--cm-folio-wide);
}

/*
 * A wide block is one plate in the page colour, hiding the rule; a wide section keeps its prose on the measure, so its
 * own wide blocks are the plates.
 */
.cm-folio .wp-block-post-content .alignwide:not(.is-layout-constrained) {
	background-color: var(--wp--preset--color--base);
}

/* Contents list of a folio: its § numbers echo the marks hanging in the gutter. */
.cm-contents__title {
	margin: 0 0 var(--wp--preset--spacing--20);
	font-family: var(--wp--preset--font-family--mono);
	font-size: var(--wp--preset--font-size--x-small);
	font-weight: 400;
	line-height: 1.4;
	letter-spacing: 0.06em;
	color: var(--wp--preset--color--soft);
}

.cm-contents__list {
	margin: 0;
	padding: 0;
	list-style: none;
	border-inline-start: 1px solid var(--wp--preset--color--line);
}

.cm-contents__list a {
	display: flex;
	align-items: center;
	gap: 0.75em;
	min-block-size: 44px;
	padding-inline-start: 16px;
	font-size: var(--wp--preset--font-size--small);
	line-height: 1.35;
	color: var(--wp--preset--color--contrast);
	text-decoration: none;
}

.cm-contents__list a:hover {
	text-decoration: underline;
}

.cm-contents__number {
	flex: none;
	font-family: var(--wp--preset--font-family--mono);
	font-size: var(--wp--preset--font-size--x-small);
	color: var(--wp--preset--color--rubric);
}

/* From 1280px the margin column right of the folio wide size holds the list, level with the breadcrumb. */
@media (min-width: 1280px) {
	.cm-folio > .cm-contents {
		position: absolute;
		inset-block-start: 0;
		inset-inline-end: 0;
		inline-size: min(240px, 100% - var(--cm-gutter) - var(--cm-folio-wide) - 2em);
		margin: 0;
	}
}

/* Block style: gutter, the numbered margin of a code editor (signature motif). */
@media (min-width: 782px) {
	.wp-block-group.is-style-gutter::before {
		content: "01\A 02\A 03\A 04\A 05\A 06" / "";
		inset-inline-start: 0;
		/* The extra pixel puts the border at x = --cm-gutter-rule, where the folio rule is drawn. */
		inline-size: calc(var(--cm-gutter-rule) + 1px);
		padding-inline-end: 12px;
		box-sizing: border-box;
		border-inline-start: 0;
		border-inline-end: 1px solid var(--wp--preset--color--line);
		font-family: var(--wp--preset--font-family--mono);
		font-size: 13px;
		line-height: 2;
		color: var(--wp--preset--color--soft);
		text-align: end;
		white-space: pre;
	}
}

.cm-folio__meta .wp-block-post-terms a {
	color: inherit;
	text-decoration: none;
}

/* Breadcrumb and category links are navigation controls, held to the identity's 44px targets like the menu. */
.wp-block-breadcrumbs a,
.wp-block-post-terms a {
	display: inline-flex;
	align-items: center;
	min-block-size: 44px;
}

/* Section marks: every flow h2 of a post is numbered; nested headings opt in with the section style. */
.wp-block-post-content {
	counter-reset: cm-section;
}

.wp-block-post-content > h2,
.wp-block-post-content h2.is-style-section {
	counter-increment: cm-section;
}

/*
 * Core makes grids inline-size containers, whose style containment would restart the counter inside them.
 * Core queries that container only to collapse spanning children, which grids holding sections do not have.
 */
.wp-block-post-content .is-layout-grid:has(h2.is-style-section) {
	container-type: normal;
}

/*
 * The empty alt text keeps screen readers from announcing « paragraph sign 01 »;
 * the first content declaration is the fallback for engines without alt text.
 */
.wp-block-post-content > h2::before,
.wp-block-post-content h2.is-style-section::before {
	content: "§\00a0" counter(cm-section, decimal-leading-zero);
	content: "§\00a0" counter(cm-section, decimal-leading-zero) / "";
	display: block;
	margin-block-end: var(--wp--preset--spacing--20);
	font-family: var(--wp--preset--font-family--mono);
	font-size: var(--wp--preset--font-size--x-small);
	font-weight: 400;
	line-height: 1.4;
	letter-spacing: 0;
	color: var(--wp--preset--color--rubric);
}

/*
 * Zero net width: the mark hangs in the gutter, right-aligned 12px before the rule, on the heading's first baseline.
 * A section group's heading hangs too; a card's stays inside the card.
 */
@media (min-width: 782px) {
	.cm-folio .wp-block-post-content > h2::before,
	.cm-folio .wp-block-post-content > .wp-block-group:not(.is-style-card) > h2.is-style-section::before {
		display: inline-block;
		inline-size: var(--cm-gutter);
		margin-inline-start: calc(-1 * var(--cm-gutter));
		margin-block-end: 0;
		padding-inline-end: calc(var(--cm-gutter) - var(--cm-gutter-rule) + 12px);
		box-sizing: border-box;
		text-align: end;
		line-height: 1;
	}
}

/* Section rhythm: 64 above a section, 40 above a subsection, 16 from a heading to its text. */
.wp-block-post-content > h2:not(:first-child) {
	margin-block-start: var(--wp--preset--spacing--60);
}

.wp-block-post-content > h3:not(:first-child) {
	margin-block-start: var(--wp--preset--spacing--50);
}

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

/*
 * Bordered list rows (news, links). Each row starts on the rule closing the one above, so its padding centres it: the
 * parent's list items and core's flow layout would add 0.5rem and the 24px block gap. The li selectors weigh (0,1,1)
 * over the parent's (0,1,0); .cm-rows > * + * ties with core's :root :where(.is-layout-flow) > * + * and comes later.
 */
.is-style-rows > li,
.is-style-links > li,
.cm-rows > * {
	padding-block: 20px;
	border-top: 1px solid var(--wp--preset--color--line);
}

.is-style-rows > li,
.is-style-links > li,
.cm-rows > * + * {
	margin-block-start: 0;
}

.is-style-rows,
.is-style-links {
	padding-inline-start: 0;
	list-style: none;
	border-bottom: 1px solid var(--wp--preset--color--line);
}

.cm-rows {
	border-bottom: 1px solid var(--wp--preset--color--line);
}

/* A lone card of a query grid spans its row instead of one column beside empty ones; its excerpt keeps the measure. */
.wp-block-post-template.is-layout-grid > li:only-child {
	grid-column: 1 / -1;
}

.wp-block-post-template.is-layout-grid > li:only-child .wp-block-post-excerpt {
	max-inline-size: var(--wp--style--global--content-size);
}

/* Query cards and news rows: the title link stretches over the item, so the item is one link and one Tab stop. */
.cm-rows > li {
	position: relative;
}

.is-style-card .wp-block-post-title a::after,
.cm-rows .wp-block-post-title a::after {
	content: "";
	position: absolute;
	inset: 0;
}

/* The ring follows the item's corners: the card's radius, and the 3px of link rows. */
.is-style-card .wp-block-post-title a::after {
	border-radius: 6px;
}

.cm-rows .wp-block-post-title a::after {
	border-radius: 3px;
}

/* Secondary links (category) stay clickable above the stretched area. */
.is-style-card .wp-block-post-terms a,
.cm-rows .wp-block-post-terms a {
	position: relative;
	z-index: 1;
}

/* As on link rows, the overlay carries the ring, so it surrounds the item without :has(). */
.is-style-card .wp-block-post-title a:focus-visible,
.cm-rows .wp-block-post-title a:focus-visible {
	outline: none;
}

.is-style-card .wp-block-post-title a:focus-visible::after,
.cm-rows .wp-block-post-title a:focus-visible::after {
	outline: 2px solid var(--cm-focus);
	outline-offset: 3px;
}

@media (hover: hover) {
	.wp-block-group.is-style-card:has(.wp-block-post-title a:hover) {
		border-color: var(--wp--preset--color--primary);
	}
}

/*
 * Numbered rows: an ordered rows list hangs mono numbers in a 3rem column, on the first baseline.
 * An inline-block, not a grid item: a grid would split « <strong>…</strong> text » into separate cells.
 */
ol.is-style-rows {
	counter-reset: cm-row;
}

ol.is-style-rows > li {
	counter-increment: cm-row;
	padding-inline-start: 3rem;
}

/* The empty alt text leaves the position to the list semantics, so the number is not read twice. */
ol.is-style-rows > li::before {
	content: counter(cm-row, decimal-leading-zero);
	content: counter(cm-row, decimal-leading-zero) / "";
	display: inline-block;
	inline-size: 3rem;
	margin-inline-start: -3rem;
	font-family: var(--wp--preset--font-family--mono);
	font-size: var(--wp--preset--font-size--x-small);
	line-height: 1;
	color: var(--wp--preset--color--soft);
}

/*
 * Link rows: <li><a>Label</a><br>One description line</li>. The first link covers the whole row,
 * so the target is the row (44px targets); the text after it is the row's soft description.
 */
.is-style-links > li {
	position: relative;
	min-block-size: 44px;
	padding-block: 16px;
	padding-inline-end: 2.5rem;
	font-size: var(--wp--preset--font-size--small);
	color: var(--wp--preset--color--soft);
	/* Pretty wrapping balances the label and the description as one paragraph, which can leave a blank line at the <br>. */
	text-wrap: wrap;
}

.is-style-links > li > a:first-child {
	font-size: var(--wp--preset--font-size--medium);
	font-weight: 700;
	color: var(--wp--preset--color--contrast);
	text-decoration: none;
}

.is-style-links > li > a:first-child::after {
	content: "";
	position: absolute;
	inset: 0;
	border-radius: 3px;
}

/* A link in the description stays clickable above the row overlay. */
.is-style-links > li > a:not(:first-child) {
	position: relative;
	z-index: 1;
}

/* One ring around the row: the overlay carries the link's focus ring, in the global ring's colour and offset. */
.is-style-links > li > a:first-child:focus-visible {
	outline: none;
}

.is-style-links > li > a:first-child:focus-visible::after {
	outline: 2px solid var(--cm-focus);
	outline-offset: 3px;
}

/*
 * The arrow sits on li::before, a::after being the overlay. It is centred on the label's first line,
 * whose box is the medium size at the body line height (1.6, theme.json).
 */
.is-style-links > li::before {
	content: "";
	position: absolute;
	inset-block-start: calc(16px + (var(--wp--preset--font-size--medium) * 1.6 - 1rem) / 2);
	inset-inline-end: 4px;
	inline-size: 1rem;
	block-size: 1rem;
	background: var(--wp--preset--color--primary);
	mask: var(--cm-arrow) center / contain no-repeat;
	transition: translate 150ms ease-out;
}

@media (hover: hover) {
	.is-style-links > li:hover > a:first-child {
		text-decoration: underline;
		/* The parent sets a { text-decoration-thickness: 1px !important }, which only !important outranks. */
		text-decoration-thickness: 2px !important;
	}

	.is-style-links > li:hover::before {
		translate: 4px 0;
	}
}

.is-style-links > li:focus-within::before {
	translate: 4px 0;
}

@media (forced-colors: active) {
	.is-style-links > li::before {
		forced-color-adjust: none;
		background: LinkText;
	}
}

/*
 * Social links as text, at the surrounding text size. Core renders no item for a link without URL;
 * the ul type selector outweighs the font size of core's icon-size classes, whatever the load order.
 */
ul.wp-block-social-links.is-style-text {
	flex-direction: column;
	align-items: flex-start;
	gap: 0;
	font-size: inherit;
}

.wp-block-social-links.is-style-text .wp-social-link {
	border-radius: 0;
	background: none;
	color: var(--wp--preset--color--contrast);
	transform: none;
}

/* Core paints the anchor in currentColor at higher specificity, so its colour comes from the item above. */
.wp-block-social-links.is-style-text .wp-block-social-link-anchor {
	display: inline-flex;
	align-items: center;
	min-block-size: 44px;
	min-inline-size: 44px;
	padding: 0;
	line-height: inherit;
}

.wp-block-social-links.is-style-text .wp-block-social-link-anchor:hover {
	text-decoration: underline;
}

/* Icons hide only beside visible labels, so no link is left empty. */
.wp-block-social-links.is-style-text.has-visible-labels svg {
	display: none;
}

.wp-block-social-links.is-style-text .wp-block-social-link-label:not(.screen-reader-text) {
	margin: 0;
	font-size: inherit;
}

/* Core keeps the list when every link lacks a URL and drops only the items; an empty list would be announced. */
.wp-block-social-links:not(:has(.wp-social-link)) {
	display: none;
}

/*
 * French lists: en dash for unordered, mono two-digit numbers for ordered.
 * Scoped to list blocks: core's post-template and social-links lists set list-style: none at equal specificity and load first.
 */
.wp-block-post-content :where(ul.wp-block-list:not(.is-style-rows, .is-style-links)) {
	list-style-type: "\2013\00a0\00a0";
}

.wp-block-post-content :where(ol.wp-block-list:not(.is-style-rows)) {
	list-style-type: decimal-leading-zero;
}

.wp-block-post-content .wp-block-list:not(.is-style-rows, .is-style-links) > li::marker {
	font-family: var(--wp--preset--font-family--mono);
	font-size: var(--wp--preset--font-size--x-small);
	color: var(--wp--preset--color--soft);
}

.wp-block-post-content .wp-block-list:not(.is-style-rows, .is-style-links) > li + li {
	margin-block-start: var(--wp--preset--spacing--20);
}

/*
 * Tables: label-voice headers, horizontal hairlines only, tabular figures.
 * Cell selectors weigh (0,1,2), above core's (0,1,1) borders and 3px thead rule whatever the load order.
 */
.wp-block-table table {
	border-collapse: collapse;
	font-variant-numeric: tabular-nums;
}

.wp-block-table table :is(th, td) {
	padding: 14px 20px 14px 0;
	border: 0;
	border-block-end: 1px solid var(--wp--preset--color--line);
	text-align: start;
	vertical-align: baseline;
}

.wp-block-table table :is(thead, tfoot) {
	border: 0;
}

.wp-block-table table th {
	font-family: var(--wp--preset--font-family--mono);
	font-size: var(--wp--preset--font-size--xx-small);
	font-weight: 500;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--wp--preset--color--soft);
}

/* The cell rule outweighs core's .has-text-align-* utilities, so the editor's column alignments are restated. */
.wp-block-table table .has-text-align-center {
	text-align: center;
}

.wp-block-table table .has-text-align-right {
	text-align: end;
}

/* Annotations: footnote calls in mono, notes closed by a hairline. */
.wp-block-post-content sup.fn a {
	font-family: var(--wp--preset--font-family--mono);
	font-size: var(--wp--preset--font-size--xx-small);
	text-decoration: none;
}

.wp-block-footnotes {
	margin-block-start: var(--wp--preset--spacing--60);
	padding-block-start: var(--wp--preset--spacing--40);
	border-block-start: 1px solid var(--wp--preset--color--line);
	list-style-type: decimal-leading-zero;
}

.wp-block-footnotes > li::marker {
	font-family: var(--wp--preset--font-family--mono);
}

sup,
sub {
	font-size: 0.75em;
	line-height: 0;
}

/* Quotes: the source opens on an em dash, silent to screen readers; opening marks hang outside the measure. */
.wp-block-quote {
	hanging-punctuation: first;
}

.wp-block-quote cite::before {
	content: "— ";
	content: "— " / "";
}

/* Buttons keep the 44px touch target. */
.wp-block-button__link {
	min-height: 48px;
	display: inline-flex;
	align-items: center;
	text-decoration: none;
}

/*
 * Search field: soft border, because line (#D5DEE4) on base fails WCAG 1.4.11 for an input boundary. The palette
 * fill and ink replace the browser's field colours, which paint #3B3B3B under a dark color-scheme.
 */
.wp-block-search__input {
	background-color: var(--wp--preset--color--surface);
	color: var(--wp--preset--color--contrast);
	border: 1px solid var(--wp--preset--color--soft);
	border-radius: 4px;
	min-height: 48px;
}

/* Dark ink band (« Pourquoi une association ? »): links follow the band's text color. */
.has-contrast-background-color a {
	color: inherit;
}

/* The text spans two rows, so the model figure after it sits under the title on two columns and after the text on one. */
.cm-why__text {
	grid-row: span 2;
}

/*
 * Illustrations (assets/images/illustrations): inline SVG whose six classes take a palette preset, so each drawing
 * follows every colour mode. Each pattern sets the drawing's nominal width in --cm-illustration-width.
 */
.cm-illustration {
	--cm-illustration-ink: var(--wp--preset--color--contrast);
	--cm-illustration-soft: var(--wp--preset--color--soft);
	--cm-illustration-line: var(--wp--preset--color--line);
	--cm-illustration-brand: var(--wp--preset--color--brand);
	--cm-illustration-action: var(--wp--preset--color--primary);
	--cm-illustration-base: var(--wp--preset--color--base);
	max-inline-size: var(--cm-illustration-width);
}

/* Zero specificity: a figure drops its user-agent indent, and layout rules keep their block gaps. */
:where(figure.cm-illustration) {
	margin: 0;
}

/* The viewBox gives the height before paint, so the drawing never shifts the text. */
.cm-illustration svg {
	display: block;
	inline-size: 100%;
	block-size: auto;
}

.cm-illustration .ink {
	color: var(--cm-illustration-ink);
}

.cm-illustration .soft {
	color: var(--cm-illustration-soft);
}

.cm-illustration .line {
	color: var(--cm-illustration-line);
}

.cm-illustration .brand {
	color: var(--cm-illustration-brand);
}

.cm-illustration .action {
	color: var(--cm-illustration-action);
}

.cm-illustration .base {
	color: var(--cm-illustration-base);
}

.cm-illustration figcaption {
	margin-block-start: var(--wp--preset--spacing--30);
	font-size: var(--wp--preset--font-size--small);
	color: var(--cm-illustration-soft);
}

.cm-illustration figcaption > * {
	margin-block: 0;
}

.cm-illustration figcaption > * + * {
	margin-block-start: var(--wp--preset--spacing--20);
}

/*
 * On the ink band the drawing inverts with the text. The teal moves 30% toward the band's text, which keeps the disc
 * and its knocked-out braces above 4.5:1 against the band in every mode (2.2:1 unmixed in high contrast).
 * Screen only: paper drops the band's fill, so print keeps the page mapping.
 */
@media screen {
	.has-contrast-background-color .cm-illustration {
		--cm-illustration-ink: var(--wp--preset--color--base);
		--cm-illustration-soft: color-mix(in srgb, var(--wp--preset--color--base) 70%, var(--wp--preset--color--contrast));
		--cm-illustration-line: color-mix(in srgb, var(--wp--preset--color--base) 25%, var(--wp--preset--color--contrast));
		--cm-illustration-brand: color-mix(in srgb, var(--wp--preset--color--brand) 70%, var(--wp--preset--color--base));
		--cm-illustration-base: var(--wp--preset--color--contrast);
	}
}

/* Centred under an empty state's card; query-no-results has no layout to space its blocks. */
.cm-illustration--empty-state {
	margin: var(--wp--preset--spacing--40) auto 0;
}

/*
 * Decorative asides float right of the text column (core's alignright) from 1280px, where the 1200px container leaves
 * them room beside the measure, never wider than that room; below, the page is text alone.
 */
.cm-illustration--aside {
	display: none;
}

@media (min-width: 1280px) {
	.cm-illustration--aside {
		display: block;
		inline-size: min(var(--cm-illustration-width), 100% - var(--wp--style--global--content-size) - 2em);
	}

	/*
	 * In a folio the aside is a margin note: out of the flow, at its static block position, in the margin column right
	 * of the measure and flush with the container's edge; the folio (position: relative) is its containing block.
	 */
	.cm-folio .cm-illustration--aside {
		position: absolute;
		margin: 0;
		inset-inline-end: 0;
		inline-size: min(var(--cm-illustration-width), 100% - var(--cm-gutter) - var(--wp--style--global--content-size) - 2em);
	}

	/*
	 * The hero's 820px column is wider than the room its drawing leaves, so each of its blocks forms its own context and
	 * narrows evenly beside the float instead of wrapping under it. Zero specificity: the flex buttons keep their display.
	 */
	:where(.cm-illustration--hero ~ *) {
		display: flow-root;
	}
}

/* The aside floats out of flow, so the block after it opens the flow with no gap above, as a first block does. */
:root .cm-illustration--aside + * {
	margin-block-start: 0;
}

/* Forced colours: the system pair replaces the palette, base still knocking shapes out of the canvas. */
@media (forced-colors: active) {
	.cm-illustration,
	.has-contrast-background-color .cm-illustration {
		--cm-illustration-ink: CanvasText;
		--cm-illustration-soft: CanvasText;
		--cm-illustration-line: GrayText;
		--cm-illustration-brand: CanvasText;
		--cm-illustration-action: LinkText;
		--cm-illustration-base: Canvas;
	}

	.cm-illustration svg {
		forced-color-adjust: none;
	}
}

/*
 * Print edition: the annotated page as ink on white, link targets spelled out, screen controls left off.
 * Kept last: its root ties in specificity with the dark and high-contrast blocks and wins by order.
 */
@media print {
	@page {
		margin: 18mm 16mm 20mm;
	}

	/* (0,2,1), as html:root[data-contrast="more"]: paper stays ink on white whatever the screen mode. */
	html:root[lang] {
		--wp--preset--color--base: #FFFFFF;
		--wp--preset--color--surface: #FFFFFF;
		--wp--preset--color--contrast: #000000;
		--wp--preset--color--soft: #333333;
		--wp--preset--color--line: #8C8C8C;
		--wp--preset--color--primary: #000000;
		--wp--preset--color--on-primary: #FFFFFF;
		--wp--preset--color--primary-soft: #FFFFFF;
		--wp--preset--color--brand: #000000;
		--wp--preset--color--rubric: #000000;
		--wp--preset--color--accent-1: #FFFFFF;
		--wp--preset--color--accent-2: #FFFFFF;
		--wp--preset--color--accent-3: #000000;
		--wp--preset--color--accent-4: #333333;
		--wp--preset--color--accent-5: #FFFFFF;
		--wp--preset--color--accent-6: #8C8C8C;
		color-scheme: light;
	}

	body {
		font-size: 11pt;
		line-height: 1.45;
	}

	/* The page switches to print media live, so a card's 120ms colour transition would still show its screen fill. */
	*,
	*::before,
	*::after {
		transition: none !important;
	}

	.skip-link,
	.cm-header .wp-block-navigation,
	.cm-contrast-toggle,
	.wp-block-buttons,
	.wp-block-search,
	.wp-block-social-links,
	.wp-block-query-pagination,
	.wp-block-post-navigation-link,
	.wp-block-breadcrumbs,
	.cm-contents {
		display: none !important;
	}

	.wp-site-blocks > header.wp-block-template-part {
		position: static;
	}

	.cm-header {
		border: 0;
	}

	/* Decorative drawings stay off paper; captioned figures print in the paper palette. */
	.cm-illustration:not(figure) {
		display: none;
	}

	.cm-logo svg {
		height: 40px;
	}

	.cm-footer__grid > :not(:first-child) {
		display: none;
	}

	.has-background {
		background: none !important;
	}

	/* The band's text, and the headings its element styles paint in base, which the paper palette makes white. */
	.has-base-color,
	.has-contrast-background-color :is(h1, h2, h3, h4, h5, h6) {
		color: #000000 !important;
	}

	.has-contrast-background-color {
		border-block: 1pt solid #000000;
	}

	.cm-folio,
	.wp-block-group.is-style-gutter {
		padding-inline-start: 0;
	}

	.cm-folio::before,
	.wp-block-group.is-style-gutter::before,
	.is-style-links > li::before {
		display: none;
	}

	.cm-folio .wp-block-post-content > h2::before {
		display: inline;
		margin: 0 0.6em 0 0;
		padding: 0;
		inline-size: auto;
	}

	a {
		color: inherit;
		text-decoration: underline;
	}

	.is-style-arrow a::after {
		display: none;
	}

	/*
	 * In flow, so a link row's stretched overlay cannot print as an absolute box over the row.
	 * :root lifts it to (0,3,2), above the (0,2,3) row overlay.
	 */
	:root .wp-block-post-content a:is([href^="http"], [href^="mailto:"])::after {
		position: static;
		inset: auto;
		display: inline;
		content: " (" attr(href) ")";
		mask: none;
		background: none;
		inline-size: auto;
		block-size: auto;
		font-family: var(--wp--preset--font-family--mono);
		font-size: 8.5pt;
		overflow-wrap: anywhere;
	}

	h1,
	h2,
	h3,
	h4 {
		break-after: avoid;
	}

	p,
	li {
		orphans: 3;
		widows: 3;
	}

	.is-style-card,
	figure,
	blockquote,
	tr,
	.is-style-rows > li,
	.is-style-links > li {
		break-inside: avoid;
	}
}
