/*
 * DuoDash theme styles.
 *
 * Every colour and measurement below resolves to a theme.json token. There are
 * no literal hex values in this file by design: the palette is defined once, in
 * theme.json, and "custom": false in that file prevents editors introducing
 * one-off colours through the UI.
 */

/* ---------------------------------------------------------------------------
 * Accessibility foundations
 * ------------------------------------------------------------------------ */

/*
 * A single visible focus style for everything. :focus-visible rather than
 * :focus so a mouse click on a button does not leave a ring behind, while
 * keyboard users always get one.
 */
:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
	outline: var(--wp--custom--focus-ring--width) solid var(--wp--custom--focus-ring--color);
	outline-offset: var(--wp--custom--focus-ring--offset);
	border-radius: var(--wp--custom--radius--sm);
}

/* Core injects the skip link for block themes; this makes it visible on focus. */
.skip-link:focus {
	position: fixed !important;
	top: var(--wp--preset--spacing--20);
	left: var(--wp--preset--spacing--20);
	z-index: 100000;
	clip: auto !important;
	clip-path: none;
	width: auto;
	height: auto;
	padding: 0.75rem 1.25rem;
	background: var(--wp--preset--color--accent);
	color: var(--wp--preset--color--accent-contrast);
	border-radius: var(--wp--custom--radius--sm);
	font-weight: 600;
	text-decoration: none;
}

/*
 * Honour the OS "reduce motion" preference. Animation on a product site is
 * decoration; for a visitor with a vestibular disorder it is a symptom trigger.
 */
@media (prefers-reduced-motion: reduce) {
	*,
	*::before,
	*::after {
		animation-duration: 0.01ms !important;
		animation-iteration-count: 1 !important;
		transition-duration: 0.01ms !important;
		scroll-behavior: auto !important;
	}
}

html {
	scroll-behavior: smooth;
}

/* Anchor targets clear the sticky header instead of hiding beneath it. */
:target {
	scroll-margin-top: calc(var(--wp--custom--header--height) + var(--wp--preset--spacing--30));
}

/*
 * Links inside running text must be underlined, not merely coloured.
 *
 * WCAG 1.4.1 (Use of Colour): when a link sits in a block of text, colour alone
 * is not a sufficient distinction — someone with a colour vision deficiency
 * cannot see it. theme.json keeps links undecorated globally so navigation,
 * buttons and card links stay clean; this restores the underline exactly where
 * the rule applies, which is links surrounded by other text.
 */
.entry-content p > a,
.entry-content li > a,
.wp-block-post-content p > a,
.wp-block-post-content li > a,
.duodash-issue-card p > a,
.duodash-consent p > a,
.duodash-faq-list p > a {
	text-decoration: underline;
	text-underline-offset: 0.2em;
	text-decoration-thickness: 1px;
}

/* Buttons and CTAs are shapes, not text links — an underline there is noise. */
.entry-content p > a.duodash-cta,
.entry-content li > a.duodash-cta,
.wp-block-post-content p > a.duodash-cta,
.wp-block-post-content li > a.duodash-cta,
.entry-content .wp-block-button__link,
.wp-block-post-content .wp-block-button__link {
	text-decoration: none;
}

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

.duodash-header {
	position: sticky;
	top: 0;
	z-index: 100;
	backdrop-filter: saturate(140%) blur(12px);
	-webkit-backdrop-filter: saturate(140%) blur(12px);
	border-bottom: 1px solid var(--wp--preset--color--border);
}

/* The admin bar is fixed at the top for logged-in users; the header has to
 * clear it or the two overlap. */
.admin-bar .duodash-header {
	top: 32px;
}

@media (max-width: 782px) {
	.admin-bar .duodash-header {
		top: 46px;
	}
}

.duodash-header .wp-block-navigation {
	font-size: var(--wp--preset--font-size--sm);
	font-weight: 500;
}

.duodash-header .wp-block-navigation a:where(:not(.wp-element-button)) {
	color: var(--wp--preset--color--muted);
	transition: color var(--wp--custom--transition--fast) ease;
}

.duodash-header .wp-block-navigation a:where(:not(.wp-element-button)):hover,
.duodash-header .wp-block-navigation .current-menu-item > a {
	color: var(--wp--preset--color--contrast);
	text-decoration: none;
}

/* Core's mobile overlay defaults to a light panel; match the dark shell. */
.wp-block-navigation__responsive-container.is-menu-open {
	background-color: var(--wp--preset--color--base);
	padding-top: var(--wp--preset--spacing--60);
}

.wp-block-navigation__responsive-container.is-menu-open a {
	color: var(--wp--preset--color--contrast);
	font-size: var(--wp--preset--font-size--lg);
}

/* ---------------------------------------------------------------------------
 * Product bar — the DuoDash section navigation
 *
 * A plain scrollable strip rather than core/navigation, so the Buy CTA can
 * never collapse into a hamburger (brief §4). On narrow screens the link list
 * scrolls horizontally while the brand and CTA stay put.
 * ------------------------------------------------------------------------ */

.duodash-productbar {
	border-top: 1px solid var(--wp--preset--color--border);
	background: var(--wp--preset--color--surface);
}

.duodash-productbar__inner {
	display: flex;
	align-items: center;
	gap: var(--wp--preset--spacing--30);
	max-width: 1360px;
	margin-inline: auto;
	padding: 0.55rem var(--wp--preset--spacing--30);
}

.duodash-productbar__brand {
	font-weight: 700;
	letter-spacing: -0.01em;
	color: var(--wp--preset--color--contrast);
	text-decoration: none;
	white-space: nowrap;
	flex: 0 0 auto;
}

.duodash-productbar__brand:hover {
	color: var(--wp--preset--color--accent);
	text-decoration: none;
}

.duodash-productbar__nav {
	flex: 1 1 auto;
	min-width: 0;
	overflow-x: auto;
	scrollbar-width: none;
}

.duodash-productbar__nav::-webkit-scrollbar {
	display: none;
}

.duodash-productbar__nav ul {
	display: flex;
	gap: var(--wp--preset--spacing--30);
	list-style: none;
	margin: 0;
	padding: 0;
}

.duodash-productbar__nav a {
	display: block;
	padding: 0.35rem 0;
	white-space: nowrap;
	font-size: var(--wp--preset--font-size--sm);
	color: var(--wp--preset--color--muted);
	text-decoration: none;
	border-bottom: 2px solid transparent;
	transition: color var(--wp--custom--transition--fast) ease;
}

.duodash-productbar__nav a:hover {
	color: var(--wp--preset--color--contrast);
	text-decoration: none;
}

/* "page" is the page itself; "true" is a section containing it — the developer
 * guide's child pages. Both read as current in the bar; only the first claims
 * to be the current page to a screen reader. */
.duodash-productbar__nav a[aria-current="page"],
.duodash-productbar__nav a[aria-current="true"] {
	color: var(--wp--preset--color--accent);
	border-bottom-color: var(--wp--preset--color--accent);
}

.duodash-productbar__cta {
	flex: 0 0 auto;
}

/* ---------------------------------------------------------------------------
 * Unset-setting placeholders
 *
 * Deliberately conspicuous. An invisible placeholder is how a {{TOKEN}} reaches
 * production; dashed amber monospace is not something anyone signs off.
 * ------------------------------------------------------------------------ */

.duodash-token--unset {
	display: inline-block;
	padding: 0.15em 0.5em;
	border: 1px dashed var(--wp--preset--color--status-warn);
	border-radius: var(--wp--custom--radius--sm);
	background: color-mix(in srgb, var(--wp--preset--color--status-warn) 12%, transparent);
	color: var(--wp--preset--color--status-warn);
	font-family: var(--wp--preset--font-family--mono);
	font-size: 0.85em;
	letter-spacing: 0.02em;
	white-space: nowrap;
}

.duodash-cta-wrap {
	display: inline-flex;
	flex-direction: column;
	gap: 0.4rem;
	align-items: flex-start;
}

.duodash-cta--unset {
	opacity: 0.6;
	cursor: not-allowed;
}

.duodash-cta__unset-note {
	font-size: var(--wp--preset--font-size--xs);
	color: var(--wp--preset--color--muted);
}

/* ---------------------------------------------------------------------------
 * Buttons
 * ------------------------------------------------------------------------ */

.duodash-cta {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 0.5rem;
	padding: 0.85rem 1.75rem;
	border: 1px solid transparent;
	border-radius: var(--wp--custom--radius--pill);
	font-weight: 600;
	font-size: var(--wp--preset--font-size--md);
	line-height: 1.2;
	text-decoration: none;
	cursor: pointer;
	transition: background-color var(--wp--custom--transition--base) ease,
		border-color var(--wp--custom--transition--base) ease,
		color var(--wp--custom--transition--base) ease;
}

.duodash-cta--primary {
	background: var(--wp--preset--color--accent);
	color: var(--wp--preset--color--accent-contrast);
}

.duodash-cta--primary:hover:not([disabled]) {
	background: var(--wp--preset--color--contrast);
	color: var(--wp--preset--color--base);
	text-decoration: none;
}

.duodash-cta--secondary {
	background: transparent;
	border-color: var(--wp--preset--color--border);
	color: var(--wp--preset--color--contrast);
}

.duodash-cta--secondary:hover:not([disabled]) {
	border-color: var(--wp--preset--color--accent);
	color: var(--wp--preset--color--accent);
	text-decoration: none;
}

.duodash-cta--ghost {
	background: transparent;
	color: var(--wp--preset--color--accent);
	padding-left: 0;
	padding-right: 0;
}

/*
 * Header variant. Must never wrap: "Buy on Havoc" breaking across two lines
 * doubles the sticky header's height on a phone, and §4 requires the CTA stay
 * easy to find at every width without eating the viewport.
 */
.duodash-cta--compact {
	white-space: nowrap;
	padding: 0.6rem 1.15rem;
	font-size: var(--wp--preset--font-size--sm);
}

/* ---------------------------------------------------------------------------
 * Status badges
 *
 * Glyph + label + colour. Colour is the third, redundant channel — never the
 * only one (WCAG 1.4.1).
 * ------------------------------------------------------------------------ */

.duodash-badge {
	display: inline-flex;
	align-items: center;
	gap: 0.4em;
	padding: 0.2em 0.65em;
	border-radius: var(--wp--custom--radius--pill);
	border: 1px solid currentColor;
	font-size: var(--wp--preset--font-size--xs);
	font-weight: 600;
	line-height: 1.5;
	white-space: nowrap;
}

.duodash-badge__glyph {
	font-weight: 700;
}

.duodash-badge--ok      { color: var(--wp--preset--color--status-ok); }
.duodash-badge--warn    { color: var(--wp--preset--color--status-warn); }
.duodash-badge--bad     { color: var(--wp--preset--color--status-bad); }
.duodash-badge--info    { color: var(--wp--preset--color--status-info); }
.duodash-badge--neutral { color: var(--wp--preset--color--status-neutral); }

/* ---------------------------------------------------------------------------
 * Block style variations
 * ------------------------------------------------------------------------ */

/* Screenshot frame — a bezel that reads as a device, not a photo border. */
.wp-block-image.is-style-duodash-screenshot img,
.wp-block-image.is-style-duodash-headunit img,
.wp-block-image.is-style-duodash-phone img {
	border-radius: var(--wp--custom--screenshot--radius);
	display: block;
	width: 100%;
	height: auto;
}

.wp-block-image.is-style-duodash-screenshot,
.wp-block-image.is-style-duodash-headunit,
.wp-block-image.is-style-duodash-phone {
	padding: var(--wp--custom--screenshot--bezel);
	background: var(--wp--custom--screenshot--bezel-color);
	border: 1px solid var(--wp--preset--color--border);
	border-radius: calc(var(--wp--custom--screenshot--radius) + var(--wp--custom--screenshot--bezel));
	box-shadow: var(--wp--preset--shadow--card);
	overflow: hidden;
}

/*
 * Phone frame.
 *
 * The iPhone settings screenshots are 750 x 1334. Left to the screenshot frame
 * they would stretch to the full 720px content width and stand ~1280px tall —
 * taller than the viewport, and far larger than the copy beside them warrants.
 * Capping the width instead of forcing a ratio keeps the whole screen visible,
 * which is the same reason the head-unit frame refuses to crop.
 *
 * width, not max-width: the figure is a block-level flow item, so max-width
 * alone leaves it full-width until the image inside pulls it in, and the bezel
 * would still paint across the column.
 */
.wp-block-image.is-style-duodash-phone {
	width: min(100%, var(--wp--custom--screenshot--phone-width));
	margin-inline: auto;
}

/*
 * Head-unit frame.
 *
 * Deliberately NO forced aspect-ratio with object-fit:cover. Head units vary
 * from 16:9 to roughly 2.4:1, and cropping a real product screenshot to a fixed
 * ratio would silently cut off part of the UI — which the acceptance criteria
 * explicitly forbid ("product screenshots must not be distorted or wrongly
 * cropped"). The intrinsic width/height attributes on the img reserve the right
 * space, so there is no layout shift either way.
 */
.wp-block-image.is-style-duodash-headunit img {
	object-fit: contain;
}

/* Cards */
.wp-block-group.is-style-duodash-card {
	background: var(--wp--preset--color--surface);
	border: 1px solid var(--wp--preset--color--border);
	border-radius: var(--wp--custom--radius--lg);
	padding: var(--wp--preset--spacing--40);
}

/*
 * Cards in a columns row all match the tallest one. Without this each card
 * shrink-wraps its own copy, so a row of four reads as a ragged staircase.
 *
 * :only-child is load-bearing, not a refinement. The column stretches to the
 * row height, so `height: 100%` only means "fill the row" while the card is the
 * column's sole occupant. Stack two cards in one column and each claims the
 * full row height — 200% between them — and they overflow the section and land
 * on top of whatever follows. That is not a subtle misalignment: it renders the
 * next section straight through the cards.
 */
.wp-block-columns > .wp-block-column > .wp-block-group.is-style-duodash-card:only-child {
	height: 100%;
}

/* Callouts. The ::before glyph is what carries the meaning when colour is
 * unavailable. */
.wp-block-group.is-style-duodash-callout-info,
.wp-block-group.is-style-duodash-callout-warning,
.wp-block-group.is-style-duodash-callout-danger {
	position: relative;
	padding: var(--wp--preset--spacing--30);
	padding-left: calc(var(--wp--preset--spacing--40) + 1rem);
	border-radius: var(--wp--custom--radius--md);
	border-left: 3px solid;
	background: var(--wp--preset--color--surface);
}

.wp-block-group[class*="is-style-duodash-callout-"]::before {
	position: absolute;
	left: var(--wp--preset--spacing--30);
	top: var(--wp--preset--spacing--30);
	font-weight: 700;
	line-height: 1.4;
}

.wp-block-group.is-style-duodash-callout-info {
	border-left-color: var(--wp--preset--color--status-info);
}
.wp-block-group.is-style-duodash-callout-info::before {
	content: "i";
	color: var(--wp--preset--color--status-info);
}

.wp-block-group.is-style-duodash-callout-warning {
	border-left-color: var(--wp--preset--color--status-warn);
}
.wp-block-group.is-style-duodash-callout-warning::before {
	content: "!";
	color: var(--wp--preset--color--status-warn);
}

.wp-block-group.is-style-duodash-callout-danger {
	border-left-color: var(--wp--preset--color--status-bad);
}
.wp-block-group.is-style-duodash-callout-danger::before {
	content: "!";
	color: var(--wp--preset--color--status-bad);
}

/* Eyebrow / lead */
.wp-block-paragraph.is-style-duodash-eyebrow {
	text-transform: uppercase;
	letter-spacing: 0.12em;
	font-size: var(--wp--preset--font-size--xs);
	font-weight: 700;
	color: var(--wp--preset--color--accent);
	margin-bottom: var(--wp--preset--spacing--10);
}

/* The prose cap is meant to keep a lead SHORTER than the column, but 62ch is
 * measured in the lead's own font, which is a preset larger than body text and
 * fluid on top of that. Past roughly a 1200px viewport it overtakes the 720px
 * content width, and because the constrained layout still centres the element,
 * the lead grows out of the column by half the excess on each side — a lead
 * whose left edge drifts away from every heading and paragraph below it as the
 * window widens. Clamping to the content size keeps the intent and removes the
 * crossover. */
.wp-block-paragraph.is-style-duodash-lead {
	font-size: var(--wp--preset--font-size--lg);
	color: var(--wp--preset--color--muted);
	max-width: min(var(--wp--custom--max-width--prose), var(--wp--style--global--content-size));
}

/* Numbered install steps */
.wp-block-list.is-style-duodash-steps {
	list-style: none;
	counter-reset: duodash-step;
	padding-left: 0;
	display: grid;
	gap: var(--wp--preset--spacing--30);
}

.wp-block-list.is-style-duodash-steps > li {
	counter-increment: duodash-step;
	position: relative;
	padding-left: 3.25rem;
	min-height: 2.25rem;
}

.wp-block-list.is-style-duodash-steps > li::before {
	content: counter(duodash-step);
	position: absolute;
	left: 0;
	top: 0;
	width: 2.25rem;
	height: 2.25rem;
	display: grid;
	place-items: center;
	border-radius: 50%;
	background: var(--wp--preset--color--elevated);
	border: 1px solid var(--wp--preset--color--border);
	color: var(--wp--preset--color--accent);
	font-weight: 700;
	font-size: var(--wp--preset--font-size--sm);
	font-variant-numeric: tabular-nums;
}

/* ---------------------------------------------------------------------------
 * Tables
 *
 * Wide compatibility matrices scroll inside their own container so the page
 * body never scrolls sideways. tabindex on the wrapper makes that scroll region
 * reachable by keyboard, which is a WCAG requirement people routinely miss.
 * ------------------------------------------------------------------------ */

.duodash-table-scroll {
	overflow-x: auto;
	-webkit-overflow-scrolling: touch;
	border: 1px solid var(--wp--preset--color--border);
	border-radius: var(--wp--custom--radius--md);
}

.duodash-table-scroll:focus-visible {
	outline: var(--wp--custom--focus-ring--width) solid var(--wp--custom--focus-ring--color);
	outline-offset: 0;
}

.duodash-table {
	width: 100%;
	border-collapse: collapse;
	font-size: var(--wp--preset--font-size--sm);
}

.duodash-table caption {
	caption-side: top;
	text-align: left;
	padding: var(--wp--preset--spacing--20) var(--wp--preset--spacing--30);
	font-weight: 600;
	color: var(--wp--preset--color--contrast);
	background: var(--wp--preset--color--elevated);
	border-bottom: 1px solid var(--wp--preset--color--border);
}

.duodash-table th,
.duodash-table td {
	padding: 0.75rem var(--wp--preset--spacing--30);
	text-align: left;
	border-bottom: 1px solid var(--wp--custom--table--border-color);
	vertical-align: top;
}

.duodash-table thead th {
	background: var(--wp--preset--color--elevated);
	font-size: var(--wp--preset--font-size--xs);
	text-transform: uppercase;
	letter-spacing: 0.08em;
	color: var(--wp--preset--color--muted);
	white-space: nowrap;
}

.duodash-table tbody tr:nth-child(even) {
	background: var(--wp--custom--table--stripe);
}

.duodash-table tbody tr:last-child td {
	border-bottom: 0;
}

/*
 * Empty state. EDITORS ONLY — the table blocks render nothing at all for a
 * visitor when they have no rows, so this frame is now an admin affordance
 * rather than public content. It keeps the dashed border precisely because it
 * should not be mistaken for something a visitor is meant to see.
 */
.duodash-table__empty {
	padding: var(--wp--preset--spacing--40);
	text-align: center;
	color: var(--wp--preset--color--muted);
	border: 1px dashed var(--wp--preset--color--border);
	border-radius: var(--wp--custom--radius--md);
	background: var(--wp--custom--table--stripe);
	margin: 0;
}

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

.duodash-footer {
	border-top: 1px solid var(--wp--preset--color--border);
	color: var(--wp--preset--color--muted);
	font-size: var(--wp--preset--font-size--sm);
}

.duodash-footer h2,
.duodash-footer h3 {
	font-size: var(--wp--preset--font-size--xs);
	text-transform: uppercase;
	letter-spacing: 0.1em;
	color: var(--wp--preset--color--muted);
	margin-bottom: var(--wp--preset--spacing--20);
}

.duodash-footer ul {
	list-style: none;
	padding: 0;
	margin: 0;
	display: grid;
	gap: 0.6rem;
}

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

.duodash-footer a:hover {
	color: var(--wp--preset--color--accent);
	text-decoration: underline;
}

/*
 * The Community column is a list of links like the three columns beside it —
 * except two of its rows are duodash/cta-button, which is a button first and
 * foremost. The ghost variant drops the background and the horizontal padding
 * but keeps the rest of the button metrics, so Discord and Havoc render at
 * md/600 with 0.85rem of vertical padding and a 1.2 line-height against the
 * footer's sm/400, its 1.65, and a 0.6rem grid gap: a size larger, a weight
 * heavier, wrapping sooner, and set further apart than the links they sit
 * next to. Inherit the column instead. Only the metrics are normalised — the
 * unset state keeps its disabled styling and its {{TOKEN}} note, which is the
 * whole reason these are CTA blocks rather than plain <a>s.
 */
.duodash-footer .duodash-cta--ghost {
	font-size: inherit;
	font-weight: inherit;
	line-height: inherit;
	padding: 0;
	/* The button's 1px transparent border is invisible but not free: it makes
	 * these two rows 2px taller than a plain link, and the column's grid gap
	 * then stacks that difference into a row pitch that no longer matches the
	 * columns beside it. */
	border: 0;
	border-radius: 0;
}

.duodash-social {
	display: inline-block;
}

/* ---------------------------------------------------------------------------
 * Breadcrumbs
 * ------------------------------------------------------------------------ */

.duodash-breadcrumb ol {
	list-style: none;
	display: flex;
	flex-wrap: wrap;
	gap: 0.5rem;
	padding: 0;
	margin: 0;
	font-size: var(--wp--preset--font-size--xs);
	color: var(--wp--preset--color--muted);
}

.duodash-breadcrumb li + li::before {
	content: "/";
	margin-right: 0.5rem;
	color: var(--wp--preset--color--border);
}

/* ---------------------------------------------------------------------------
 * Disclosure lists (FAQ, troubleshooting)
 *
 * Native <details>/<summary> via core/details. Keyboard operation, focus and
 * screen-reader semantics all come from the browser — there is no JavaScript
 * here and nothing to get wrong.
 * ------------------------------------------------------------------------ */

.duodash-faq-list {
	display: grid;
	gap: var(--wp--preset--spacing--20);
}

/* The constrained layout gives every child `margin-inline: auto !important`,
 * which in a grid container shrinks each row to its own text and centres it.
 * A full-width item leaves no free space for those margins to take. */
.duodash-faq-list .wp-block-details {
	width: 100%;
	border: 1px solid var(--wp--preset--color--border);
	border-radius: var(--wp--custom--radius--md);
	background: var(--wp--preset--color--surface);
	padding: 0;
	margin: 0;
}

.duodash-faq-list .wp-block-details > summary {
	cursor: pointer;
	list-style: none;
	padding: 1rem 3rem 1rem 1.25rem;
	font-weight: 600;
	position: relative;
	border-radius: var(--wp--custom--radius--md);
}

.duodash-faq-list .wp-block-details > summary::-webkit-details-marker {
	display: none;
}

/* Chevron built from a rotated caret so it needs no icon font or SVG. */
.duodash-faq-list .wp-block-details > summary::after {
	content: "";
	position: absolute;
	right: 1.25rem;
	top: 1.45rem;
	width: 0.5rem;
	height: 0.5rem;
	border-right: 2px solid var(--wp--preset--color--muted);
	border-bottom: 2px solid var(--wp--preset--color--muted);
	transform: rotate(45deg);
	transition: transform var(--wp--custom--transition--base) ease;
}

.duodash-faq-list .wp-block-details[open] > summary::after {
	transform: rotate(-135deg);
}

.duodash-faq-list .wp-block-details > summary:hover {
	color: var(--wp--preset--color--accent);
}

.duodash-faq-list .wp-block-details > :not(summary) {
	padding-inline: 1.25rem;
}

.duodash-faq-list .wp-block-details > :last-child:not(summary) {
	padding-bottom: 1.25rem;
}

/* ---------------------------------------------------------------------------
 * FAQ filter
 * ------------------------------------------------------------------------ */

.duodash-faq-filter {
	display: grid;
	gap: var(--wp--preset--spacing--20);
	margin-bottom: var(--wp--preset--spacing--30);
}

.duodash-faq-filter input[type="search"] {
	width: 100%;
	padding: 0.75rem 1rem;
	background: var(--wp--preset--color--surface);
	border: 1px solid var(--wp--preset--color--border);
	border-radius: var(--wp--custom--radius--md);
	color: var(--wp--preset--color--contrast);
	font-size: var(--wp--preset--font-size--md);
	font-family: inherit;
}

.duodash-faq-filter input[type="search"]::placeholder {
	color: var(--wp--preset--color--muted);
}

.duodash-faq-filter__count {
	font-size: var(--wp--preset--font-size--sm);
	color: var(--wp--preset--color--muted);
	margin: 0;
}

/* ---------------------------------------------------------------------------
 * Copy-template button
 * ------------------------------------------------------------------------ */

.duodash-copy {
	display: grid;
	gap: var(--wp--preset--spacing--20);
}

.duodash-copy__pre {
	background: var(--wp--preset--color--elevated);
	border: 1px solid var(--wp--preset--color--border);
	border-radius: var(--wp--custom--radius--md);
	padding: var(--wp--preset--spacing--30);
	font-family: var(--wp--preset--font-family--mono);
	font-size: var(--wp--preset--font-size--sm);
	line-height: 1.8;
	white-space: pre-wrap;
	overflow-x: auto;
	margin: 0;
}

.duodash-copy__status {
	font-size: var(--wp--preset--font-size--sm);
	color: var(--wp--preset--color--status-ok);
	min-height: 1.5em;
	margin: 0;
}

/* A photograph, as opposed to a device screenshot: rounded and centred, with no
 * bezel or frame around it. margin-inline: auto is what centres it when the
 * wide layout width exceeds the viewport and the figure falls back to the
 * content column. */
.wp-block-image.duodash-photo {
	margin-inline: auto;
	text-align: center;
}

.wp-block-image.duodash-photo img {
	width: 100%;
	height: auto;
	border-radius: var(--wp--custom--radius--lg);
}

/* ---------------------------------------------------------------------------
 * Release notes
 *
 * Modelled on a GitHub release body: a rule-topped section per kind of change,
 * the section name carrying the status colour, and bullets whose bolded lead-in
 * is the thing that changed. The colour is decoration only — the section is
 * already named in words, so nothing here is colour-dependent.
 * ------------------------------------------------------------------------ */

.duodash-release-section {
	margin-block: var(--wp--preset--spacing--40);
	border-top: 1px solid var(--wp--preset--color--border);
	padding-top: var(--wp--preset--spacing--20);
}

.duodash-release-section__title {
	font-size: var(--wp--preset--font-size--sm);
	text-transform: uppercase;
	letter-spacing: 0.1em;
	margin-bottom: var(--wp--preset--spacing--20);
	color: var(--wp--preset--color--muted);
}

.duodash-release-section--ok .duodash-release-section__title {
	color: var(--wp--preset--color--status-ok);
}
.duodash-release-section--info .duodash-release-section__title {
	color: var(--wp--preset--color--status-info);
}
.duodash-release-section--warn .duodash-release-section__title {
	color: var(--wp--preset--color--status-warn);
}

.duodash-release-list {
	display: grid;
	gap: 0.45rem;
	margin: 0;
	padding-left: 1.15rem;
}

.duodash-release-list > li {
	padding-left: 0.2rem;
}

/* The lead-in is the feature or component that changed. */
.duodash-release-list strong {
	font-weight: 600;
	color: var(--wp--preset--color--contrast);
}

/* ---------------------------------------------------------------------------
 * Known-issue list
 * ------------------------------------------------------------------------ */

.duodash-issues {
	display: grid;
	gap: var(--wp--preset--spacing--40);
}

.duodash-issues__group-title {
	font-size: var(--wp--preset--font-size--sm);
	text-transform: uppercase;
	letter-spacing: 0.1em;
	color: var(--wp--preset--color--muted);
	margin-bottom: var(--wp--preset--spacing--20);
}

.duodash-issue-card {
	background: var(--wp--preset--color--surface);
	border: 1px solid var(--wp--preset--color--border);
	border-radius: var(--wp--custom--radius--lg);
	padding: var(--wp--preset--spacing--30);
	display: grid;
	gap: var(--wp--preset--spacing--10);
}

.duodash-issue-card__head {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--wp--preset--spacing--20);
	justify-content: space-between;
}

.duodash-issue-card__title {
	margin: 0;
	font-size: var(--wp--preset--font-size--lg);
}

.duodash-issue-card__meta {
	font-size: var(--wp--preset--font-size--xs);
	color: var(--wp--preset--color--muted);
	margin: 0;
}

/* ---------------------------------------------------------------------------
 * Video demo
 * ------------------------------------------------------------------------ */

.duodash-video {
	position: relative;
	aspect-ratio: var(--wp--custom--screenshot--ratio);
	border-radius: var(--wp--custom--radius--lg);
	overflow: hidden;
	border: 1px solid var(--wp--preset--color--border);
	background: var(--wp--preset--color--surface);
}

.duodash-video iframe {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	border: 0;
}

.duodash-video__placeholder {
	position: absolute;
	inset: 0;
	display: grid;
	place-content: center;
	gap: var(--wp--preset--spacing--20);
	justify-items: center;
	text-align: center;
	padding: var(--wp--preset--spacing--30);
	color: var(--wp--preset--color--muted);
}

/* ---------------------------------------------------------------------------
 * Cookie consent
 * ------------------------------------------------------------------------ */

.duodash-consent {
	position: fixed;
	inset-inline: var(--wp--preset--spacing--20);
	bottom: var(--wp--preset--spacing--20);
	z-index: 9999;
	max-width: 34rem;
	margin-inline: auto;
	background: var(--wp--preset--color--elevated);
	border: 1px solid var(--wp--preset--color--border);
	border-radius: var(--wp--custom--radius--lg);
	box-shadow: var(--wp--preset--shadow--card);
	padding: var(--wp--preset--spacing--30);
	display: grid;
	gap: var(--wp--preset--spacing--20);
	font-size: var(--wp--preset--font-size--sm);
}

.duodash-consent[hidden] {
	display: none;
}

.duodash-consent__actions {
	display: flex;
	flex-wrap: wrap;
	gap: var(--wp--preset--spacing--20);
}

.duodash-consent p {
	margin: 0;
	color: var(--wp--preset--color--muted);
}

/* ---------------------------------------------------------------------------
 * Developer guide
 *
 * Five long reference pages: a contents list, checklists, and code blocks that
 * carry both API samples and ASCII architecture diagrams.
 * ------------------------------------------------------------------------ */

.duodash-doc-toc {
	border: 1px solid var(--wp--preset--color--border);
	border-radius: var(--wp--custom--radius--md);
	background: var(--wp--preset--color--surface);
	padding: var(--wp--preset--spacing--30);
}

.duodash-doc-toc > h2 {
	margin: 0 0 var(--wp--preset--spacing--20);
	color: var(--wp--preset--color--muted);
	text-transform: uppercase;
	letter-spacing: 0.08em;
}

.duodash-doc-toc ul {
	margin: 0;
	padding-left: 0;
	list-style: none;
	/* A flat jump list of 6–18 items is a column of stubs on a wide screen. */
	columns: 2;
	column-gap: var(--wp--preset--spacing--40);
}

.duodash-doc-toc li {
	break-inside: avoid;
	margin-bottom: 0.4rem;
}

@media (max-width: 600px) {
	.duodash-doc-toc ul {
		columns: 1;
	}
}

/* Cards linking to the four guide sections from the hub. */
.duodash-doc-index {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
	gap: var(--wp--preset--spacing--30);
}

.duodash-doc-index .wp-block-group {
	width: 100%;
	margin: 0;
	height: 100%;
}

/*
 * Checklist. The box is a ::before glyph rather than a real checkbox: these are
 * items to verify before shipping, not state this page can hold, and an input
 * would be a control that does nothing and still takes a tab stop.
 */
.wp-block-list.is-style-duodash-checklist {
	list-style: none;
	padding-left: 0;
	display: grid;
	gap: 0.6rem;
}

.wp-block-list.is-style-duodash-checklist > li {
	position: relative;
	padding-left: 2rem;
}

.wp-block-list.is-style-duodash-checklist > li::before {
	content: "";
	position: absolute;
	left: 0;
	top: 0.2em;
	width: 1.1rem;
	height: 1.1rem;
	border-radius: var(--wp--custom--radius--sm);
	border: 1px solid var(--wp--preset--color--border);
	background: var(--wp--preset--color--elevated);
}

/*
 * Code samples wrap; diagrams must not. An ASCII box diagram reflowed at
 * 380px is unreadable, so it scrolls inside its own container instead — the
 * page itself never scrolls sideways.
 *
 * DO NOT ADD max-width HERE. The constrained layout centres content with
 *
 *   .is-layout-constrained > :where(…) {
 *       max-width: var(--wp--style--global--content-size);
 *       margin-left: auto !important; margin-right: auto !important; }
 *
 * which is also one class of specificity, and this stylesheet loads AFTER
 * core-block-supports-inline-css — so any max-width here wins the tie, replaces
 * the 720px content size, and the auto margins are left with no free space to
 * centre. The block then goes full-bleed while the prose around it stays in the
 * column. overflow-x alone gives the scroll containment with none of that.
 */
.wp-block-code {
	overflow-x: auto;
}

.wp-block-code.is-style-duodash-diagram code {
	white-space: pre;
	/* Diagram glyphs only line up in a monospaced grid; 1.45 keeps the vertical
	 * runs of │ visually continuous without touching the line above. */
	line-height: 1.45;
	tab-size: 4;
}

/* ---------------------------------------------------------------------------
 * Utilities
 * ------------------------------------------------------------------------ */

.duodash-prose {
	max-width: var(--wp--custom--max-width--prose);
}

/* Long compatibility strings should not force a horizontal scrollbar. */
.duodash-table td,
.duodash-issue-card {
	overflow-wrap: anywhere;
}
